Example #1
0
 function DrawSquared()
 {
     // This will tell us if lines have already begun to be drawn.
     // It is an array to keep separate information for every line, for with a single
     // variable we could sometimes get "undefined offset" errors and no plot...
     $start_lines = array_fill(0, $this->records_per_group, FALSE);
     if ($this->data_type == 'text-data') {
         $lastx[0] = $this->xtr(0);
         $lasty[0] = $this->xtr(0);
     }
     for ($row = 0, $cnt = 0; $row < $this->num_data_rows; $row++) {
         $record = 1;
         // Skip record #0 (data label)
         if ($this->data_type == 'data-data') {
             // Do we have a value for X?
             $x_now = $this->data[$row][$record++];
         } else {
             $x_now = 0.5 + $cnt++;
         }
         // Place text-data at X = 0.5, 1.5, 2.5, etc...
         $x_now_pixels = $this->xtr($x_now);
         // Absolute coordinates
         if ($this->x_data_label_pos != 'none') {
             // Draw X Data labels?
             $this->DrawXDataLabel($this->data[$row][0], $x_now_pixels);
         }
         // notice there is no last param.
         // Draw Lines
         for ($idx = 0; $record < $this->num_recs[$row]; $record++, $idx++) {
             if (is_numeric($this->data[$row][$record])) {
                 // Allow for missing Y data
                 $y_now_pixels = $this->ytr($this->data[$row][$record]);
                 if ($start_lines[$idx] == TRUE) {
                     // Set line width, revert it to normal at the end
                     ImageSetThickness($this->img, $this->line_widths[$idx]);
                     if ($this->line_styles[$idx] == 'dashed') {
                         $this->SetDashedStyle($this->ndx_data_colors[$idx]);
                         ImageLine($this->img, $lastx[$idx], $lasty[$idx], $x_now_pixels, $lasty[$idx], IMG_COLOR_STYLED);
                         ImageLine($this->img, $x_now_pixels, $lasty[$idx], $x_now_pixels, $y_now_pixels, IMG_COLOR_STYLED);
                     } else {
                         ImageLine($this->img, $lastx[$idx], $lasty[$idx], $x_now_pixels, $lasty[$idx], $this->ndx_data_colors[$idx]);
                         ImageLine($this->img, $x_now_pixels, $lasty[$idx], $x_now_pixels, $y_now_pixels, $this->ndx_data_colors[$idx]);
                     }
                 }
                 $lastx[$idx] = $x_now_pixels;
                 $lasty[$idx] = $y_now_pixels;
                 $start_lines[$idx] = TRUE;
             } else {
                 if ($this->draw_broken_lines) {
                     $start_lines[$idx] = FALSE;
                 }
             }
         }
     }
     // end while
     ImageSetThickness($this->img, 1);
 }
 /**
  * Gets the line style of the element	 
  * @return int A GD linestyle representing the line style 
  * @see Image_Graph_Line
  * @access private
  */
 function _getLineStyle()
 {
     $this->_debug("Getting line style");
     if (is_numeric($this->_lineStyle)) {
         if (isset($GLOBALS['_Image_Graph_gd2'])) {
             ImageSetThickness($this->_canvas(), 1);
         }
         return $this->_color($this->_lineStyle);
     }
     elseif ($this->_lineStyle != null) {
         if (is_a($this->_lineStyle, "Image_Graph_Color")) {
             ImageSetThickness($this->_canvas(), 1);
             return $this->_lineStyle->_index;
         } else {
             return $this->_lineStyle->_getLineStyle();
         }
     } else {
         if (isset($GLOBALS['_Image_Graph_gd2'])) {
             ImageSetThickness($this->_canvas(), 1);
         }
         return $this->_color(IMAGE_GRAPH_BLACK);
     }
 }
 protected function DrawSquared()
 {
     if (!$this->CheckDataType('text-data, data-data')) {
         return FALSE;
     }
     // Flag array telling if the current point is valid, one element per plot line.
     // If start_lines[i] is true, then (lastx[i], lasty[i]) is the previous point.
     $start_lines = array_fill(0, $this->records_per_group, FALSE);
     for ($row = 0, $cnt = 0; $row < $this->num_data_rows; $row++) {
         $record = 1;
         // Skip record #0 (data label)
         if ($this->data_type == 'data-data') {
             // Do we have a value for X?
             $x_now = $this->data[$row][$record++];
         } else {
             $x_now = 0.5 + $cnt++;
         }
         // Place text-data at X = 0.5, 1.5, 2.5, etc...
         $x_now_pixels = $this->xtr($x_now);
         // Absolute coordinates
         if ($this->x_data_label_pos != 'none') {
             // Draw X Data labels?
             $this->DrawXDataLabel($this->data[$row][0], $x_now_pixels);
         }
         // notice there is no last param.
         // Draw Lines
         for ($idx = 0; $record < $this->num_recs[$row]; $record++, $idx++) {
             if (is_numeric($this->data[$row][$record])) {
                 // Allow for missing Y data
                 $y_now_pixels = $this->ytr($this->data[$row][$record]);
                 if ($start_lines[$idx] == TRUE) {
                     // Set line width, revert it to normal at the end
                     ImageSetThickness($this->img, $this->line_widths[$idx]);
                     if ($this->line_styles[$idx] == 'dashed') {
                         $this->SetDashedStyle($this->ndx_data_colors[$idx]);
                         ImageLine($this->img, $lastx[$idx], $lasty[$idx], $x_now_pixels, $lasty[$idx], IMG_COLOR_STYLED);
                         ImageLine($this->img, $x_now_pixels, $lasty[$idx], $x_now_pixels, $y_now_pixels, IMG_COLOR_STYLED);
                     } else {
                         ImageLine($this->img, $lastx[$idx], $lasty[$idx], $x_now_pixels, $lasty[$idx], $this->ndx_data_colors[$idx]);
                         ImageLine($this->img, $x_now_pixels, $lasty[$idx], $x_now_pixels, $y_now_pixels, $this->ndx_data_colors[$idx]);
                     }
                 }
                 $lastx[$idx] = $x_now_pixels;
                 $lasty[$idx] = $y_now_pixels;
                 $start_lines[$idx] = TRUE;
             } else {
                 if ($this->draw_broken_lines) {
                     $start_lines[$idx] = FALSE;
                 }
             }
         }
     }
     // end while
     ImageSetThickness($this->img, 1);
     return TRUE;
 }
Example #4
0
 /**
  * Resets the canvas.
  *
  * Include fillstyle, linestyle, thickness and polygon
  * @access private
  */
 function _reset()
 {
     if ($this->_gd2) {
         ImageSetThickness($this->_canvas, 1);
     }
     if ($this->_tileImage != null) {
         ImageDestroy($this->_tileImage);
         $this->_tileImage = null;
     }
     parent::_reset();
     $this->_font = array('font' => 1, 'color' => 'black');
 }
Example #5
0
 protected function DrawSquared()
 {
     if (!$this->CheckDataType('text-data, data-data')) {
         return FALSE;
     }
     // Flag array telling if the current point is valid, one element per plot line.
     // If start_lines[i] is true, then (lastx[i], lasty[i]) is the previous point.
     if ($this->data_columns > 0) {
         $start_lines = array_fill(0, $this->data_columns, FALSE);
     }
     $gcvars = array();
     // For GetDataColor, which initializes and uses this.
     // Data Value Labels?
     $do_dvls = $this->CheckDataValueLabels($this->y_data_label_pos, $dvl);
     for ($row = 0; $row < $this->num_data_rows; $row++) {
         $record = 1;
         // Skip record #0 (data label)
         if ($this->datatype_implied) {
             // Implied X values?
             $x_now = 0.5 + $row;
         } else {
             $x_now = $this->data[$row][$record++];
         }
         // Read it, advance record index
         $x_now_pixels = $this->xtr($x_now);
         // Absolute coordinates
         if ($this->x_data_label_pos != 'none') {
             // Draw X Data labels?
             $this->DrawXDataLabel($this->data[$row][0], $x_now_pixels, $row);
         }
         // Draw Lines
         for ($idx = 0; $record < $this->num_recs[$row]; $record++, $idx++) {
             if (is_numeric($y_now = $this->data[$row][$record])) {
                 // Allow for missing Y data
                 $y_now_pixels = $this->ytr($y_now);
                 if ($start_lines[$idx]) {
                     // Set line width, revert it to normal at the end
                     ImageSetThickness($this->img, $this->line_widths[$idx]);
                     // Select the color:
                     $this->GetDataColor($row, $idx, $gcvars, $data_color);
                     // Select solid color or dashed line
                     $style = $this->SetDashedStyle($data_color, $this->line_styles[$idx] == 'dashed');
                     // Draw the step
                     ImageLine($this->img, $lastx[$idx], $lasty[$idx], $x_now_pixels, $lasty[$idx], $style);
                     ImageLine($this->img, $x_now_pixels, $lasty[$idx], $x_now_pixels, $y_now_pixels, $style);
                 }
                 // Draw data value labels?
                 if ($do_dvls) {
                     $this->DrawDataValueLabel('y', $row, $idx, $x_now, $y_now, $y_now, $dvl);
                 }
                 $lastx[$idx] = $x_now_pixels;
                 $lasty[$idx] = $y_now_pixels;
                 $start_lines[$idx] = TRUE;
             } elseif ($this->draw_broken_lines) {
                 // Y data missing, leave a gap.
                 $start_lines[$idx] = FALSE;
             }
         }
     }
     ImageSetThickness($this->img, 1);
     return TRUE;
 }
 function ImageBorder()
 {
     if (isset($this->bw)) {
         // optional image border and fixed-dimension images (regardless of aspect ratio)
         $this->config_background_hexcolor = !empty($this->bg) ? $this->bg : $this->config_background_hexcolor;
         $this->config_border_hexcolor = !empty($this->bc) ? $this->bc : $this->config_border_hexcolor;
         if (!eregi('^[0-9A-F]{6}$', $this->config_background_hexcolor)) {
             $this->ErrorImage('Invalid hex color string "' . $this->config_background_hexcolor . '" for parameter "bg"');
         }
         if (!eregi('^[0-9A-F]{6}$', $this->config_border_hexcolor)) {
             $this->ErrorImage('Invalid hex color string "' . $this->config_border_hexcolor . '" for parameter "bc"');
         }
         $background_color = phpthumb_functions::ImageHexColorAllocate($this->gdimg_output, $this->config_background_hexcolor);
         $border_color = phpthumb_functions::ImageHexColorAllocate($this->gdimg_output, $this->config_border_hexcolor);
         ImageFilledRectangle($this->gdimg_output, 0, 0, $this->thumbnail_width, $this->thumbnail_height, $background_color);
         if ($this->bw > 0) {
             // ImageRectangle() draws a rectangle centred on the coordinates given,
             // so coordinates must be offset by half the line thickness
             if ($this->bw > 1 && @ImageSetThickness($this->gdimg_output, $this->bw)) {
                 // better way (for lines > 1px thick), but requires GD v2.0.1+
                 ImageRectangle($this->gdimg_output, floor($this->bw / 2), floor($this->bw / 2), $this->thumbnail_width - ceil($this->bw / 2), $this->thumbnail_height - ceil($this->bw / 2), $border_color);
             } else {
                 for ($i = 0; $i < $this->bw; $i++) {
                     ImageRectangle($this->gdimg_output, $i, $i, $this->thumbnail_width - $i - 1, $this->thumbnail_height - $i - 1, $border_color);
                 }
             }
         }
         if (!empty($this->brx) && !empty($this->bry) && $this->bw > 0) {
             // if 'bw' > 0 then leave the image rectangular and have a rounded border line around the edges of the image
             // if 'bw' == 0 then round off the corners of the image itself (see RoundedImageCorners())
             ImageFilledRectangle($this->gdimg_output, 0, 0, $this->brx, $this->bry, $background_color);
             ImageFilledRectangle($this->gdimg_output, $this->thumbnail_width - $this->brx, 0, $this->thumbnail_width, $this->bry, $background_color);
             ImageFilledRectangle($this->gdimg_output, $this->thumbnail_width - $this->brx, $this->thumbnail_height - $this->bry, $this->thumbnail_width, $this->thumbnail_height, $background_color);
             ImageFilledRectangle($this->gdimg_output, 0, $this->thumbnail_height - $this->bry, $this->brx, $this->thumbnail_height, $background_color);
             // PHP bug: ImageArc() with thicknesses > 1 give bad/undesirable/unpredicatable results
             // Solution: Draw multiple 1px arcs side-by-side.
             if (phpthumb_functions::gd_version(false) >= 2) {
                 // imagesetthickness(): requires GD 2.0 or later
                 // GD1 always has line thickness of 1
                 ImageSetThickness($this->gdimg_output, 1);
             }
             for ($thickness_offset = 0; $thickness_offset < $this->bw; $thickness_offset++) {
                 // Problem: parallel arcs give strange/ugly antialiasing problems
                 // Solution: draw non-parallel arcs, from one side of the line thickness at the start angle
                 //   to the opposite edge of the line thickness at the terminating angle
                 if ($this->bw > 1) {
                     ImageArc($this->gdimg_output, $this->brx, $thickness_offset - 1 + $this->bry, $this->brx * 2, $this->bry * 2, 180, 270, $border_color);
                     // top-left
                     ImageArc($this->gdimg_output, $thickness_offset - 1 + $this->brx, $this->bry, $this->brx * 2, $this->bry * 2, 180, 270, $border_color);
                     // top-left
                     ImageArc($this->gdimg_output, $this->thumbnail_width - $this->brx, $thickness_offset - 1 + $this->bry, $this->brx * 2, $this->bry * 2, 270, 360, $border_color);
                     // top-right
                     ImageArc($this->gdimg_output, $this->thumbnail_width - $thickness_offset - $this->brx, $this->bry, $this->brx * 2, $this->bry * 2, 270, 360, $border_color);
                     // top-right
                     ImageArc($this->gdimg_output, $this->thumbnail_width - $this->brx, $this->thumbnail_height - $thickness_offset - $this->bry, $this->brx * 2, $this->bry * 2, 0, 90, $border_color);
                     // bottom-right
                     ImageArc($this->gdimg_output, $this->thumbnail_width - $thickness_offset - $this->brx, $this->thumbnail_height - $this->bry, $this->brx * 2, $this->bry * 2, 0, 90, $border_color);
                     // bottom-right
                     ImageArc($this->gdimg_output, $this->brx, $this->thumbnail_height - $thickness_offset - $this->bry, $this->brx * 2, $this->bry * 2, 90, 180, $border_color);
                     // bottom-left
                     ImageArc($this->gdimg_output, $thickness_offset - 1 + $this->brx, $this->thumbnail_height - $this->bry, $this->brx * 2, $this->bry * 2, 90, 180, $border_color);
                     // bottom-left
                 } else {
                     ImageArc($this->gdimg_output, $this->brx, $thickness_offset + $this->bry, $this->brx * 2, $this->bry * 2, 180, 270, $border_color);
                     // top-left
                     ImageArc($this->gdimg_output, $this->thumbnail_width - $this->brx, $this->bry, $this->brx * 2, $this->bry * 2, 270, 360, $border_color);
                     // top-right
                     ImageArc($this->gdimg_output, $this->thumbnail_width - $this->brx, $this->thumbnail_height - $this->bry, $this->brx * 2, $this->bry * 2, 0, 90, $border_color);
                     // bottom-right
                     ImageArc($this->gdimg_output, $this->brx, $this->thumbnail_height - $this->bry, $this->brx * 2, $this->bry * 2, 90, 180, $border_color);
                     // bottom-left
                 }
             }
             ImageArc($this->gdimg_output, $this->brx, $this->bry, $this->brx * 2, $this->bry * 2, 180, 270, $border_color);
             ImageArc($this->gdimg_output, $this->thumbnail_width - $this->brx, $this->bry, $this->brx * 2, $this->bry * 2, 270, 360, $border_color);
             ImageArc($this->gdimg_output, $this->thumbnail_width - $this->brx, $this->thumbnail_height - $this->bry, $this->brx * 2, $this->bry * 2, 0, 90, $border_color);
             ImageArc($this->gdimg_output, $this->brx, $this->thumbnail_height - $this->bry, $this->brx * 2, $this->bry * 2, 90, 180, $border_color);
         }
     }
     return true;
 }
Example #7
0
     }
     // draw grid on y
     for ($i = $rand_func(6, 20); $i < $height * 2; $i += $rand_func(10, 25)) {
         ImageSetThickness($temp_bg, $rand_func(2, 6));
         $text_r = $rand_func(100, 150);
         $text_g = $rand_func(100, 150);
         $text_b = $rand_func(100, 150);
         $text_colour3 = ImageColorAllocate($temp_bg, $text_r, $text_g, $text_b);
         ImageLine($temp_bg, 0, $i, $width * 2, $i, $text_colour3);
     }
 } else {
     if ($bg_type == 2) {
         // draw squiggles!
         $bg3 = ImageColorAllocate($im3, 255, 255, 255);
         ImageFill($im3, 0, 0, $bg3);
         ImageSetThickness($temp_bg, 4);
         for ($i = 0; $i < strlen($word) + 1; $i++) {
             $text_r = $rand_func(100, 150);
             $text_g = $rand_func(100, 150);
             $text_b = $rand_func(100, 150);
             $text_colour3 = ImageColorAllocate($temp_bg, $text_r, $text_g, $text_b);
             $points = array();
             // draw random squiggle for each character
             // the longer the loop, the more complex the squiggle
             // keep random so OCR can't say "if found shape has 10 points, ignore it"
             // each squiggle will, however, be a closed shape, so OCR could try to find
             // line terminations and start from there. (I don't think they're that advanced yet..)
             for ($j = 1; $j < $rand_func(5, 10); $j++) {
                 $points[] = $rand_func(1 * (20 * ($i + 1)), 1 * (50 * ($i + 1)));
                 $points[] = $rand_func(30, $height + 30);
             }
Example #8
0
        $polygon = array_merge($polygon, $quad);
        for ($i = 2; $i < $n - 5; $i += 2) {
            //ctxx.bezierCurveTo(cp[2*i-2],cp[2*i-1],cp[2*i],cp[2*i+1],pts[i+2],pts[i+3]);
            $p1 = array($pts[$i], $pts[$i + 1]);
            $p2 = array($cp[2 * $i - 2], $cp[2 * $i - 1]);
            $p3 = array($cp[2 * $i], $cp[2 * $i + 1]);
            $p4 = array($pts[$i + 2], $pts[$i + 3]);
            $bez = Bezier_convert($p1, $p2, $p3, $p4, $t);
            $polygon = array_merge($polygon, $bez);
        }
        //ctxx.quadraticCurveTo(cp[2*n-10],cp[2*n-9],pts[n-2],pts[n-1]); // last arc
        $quad = quadBezier($polygon[count($polygon) - 2], $polygon[count($polygon) - 1], $cp[2 * $n - 10], $cp[2 * $n - 9], $pts[$n - 2], $pts[$n - 1]);
        $polygon = array_merge($polygon, $quad);
    }
    return $polygon;
}
$p = drawSpline(array(50, 250, 550, 250, 550, 750));
//print_r($p); exit;
$img = imagecreatetruecolor(80, 80);
$img2 = imagecreatetruecolor(800, 800);
$bg = ImageColorAllocate($img2, 255, 255, 255);
$fg = ImageColorAllocate($img2, 0, 0, 0);
imagefill($img2, 0, 0, $bg);
imageantialias($img2, true);
ImageSetThickness($img2, 5);
ImagePolygon($img2, $p, count($p) / 2, $fg);
imagearc($img2, 400, 400, 200, 200, 0, 350, $fg);
for ($i = 0; $i < 0; $i++) {
    imagefilter($img2, IMG_FILTER_GAUSSIAN_BLUR);
}
ImagePng($img2);
Example #9
0
    ImageSetThickness($im, mt_rand(1, 2));
    ImageLine($im, $vx, $vy, $ux, $uy, $linecolor);
    $vx = $ux;
    $vy = $uy;
}
ImageLine($im, $vx, $vy, $x, $y2, $linecolor);
// Triangle
ImageSetThickness($im, 3);
$ux = mt_rand($x2 - 10, $x2 + 10);
$uy = mt_rand($y2 - 10, $y2 - 30);
ImageLine($im, mt_rand(10, $x2 - 20), $y, $ux, $uy, $linecolor);
ImageSetThickness($im, 1);
ImageLine($im, mt_rand($x2 + 20, $x - 10), $y, $ux, $uy, $linecolor);
ImageSetThickness($im, 1);
// Border
ImageSetThickness($im, 1);
ImageLine($im, 0, 0, 0, $y, $bordercolor);
// left
ImageLine($im, 0, 0, $x, 0, $bordercolor);
// top
ImageLine($im, 0, $y - 1, $x, $y - 1, $bordercolor);
// bottom
ImageLine($im, $x - 1, 0, $x - 1, $y - 1, $bordercolor);
// right
for ($i = $x / $clen; $i < $x; $i += $x / $clen) {
    ImageLine($im, $i, 0, $i, $y, $bordercolor);
}
switch ($c_imgtype) {
    case 'jpeg':
        Header("Content-Type: image/jpeg");
        ImageJPEG($im, "", 75);
Example #10
0
 /**
  * Gets the line style of the element	 
  * @return int A GD linestyle representing the line style 
  * @see Image_Graph_Line
  * @access private
  */
 function _getLineStyle()
 {
     if (isset($GLOBALS['_Image_Graph_gd2'])) {
         ImageSetThickness($this->_canvas(), $this->_thickness);
     }
     return $this->_color->_index;
 }
Example #11
0
function _drawxaxis() {

        $maxlabwid = $this->_maxlab();
        $x0 = $this->lm;
        $y0 = $this->tm + $this->cheight;
        $x1 = $x0 + $this->cwidth;
        $y1 = $y0;
        $div = $this->xgridint;
        imageline($this->image,$x0,$y0,$x1,$y1,$this->gridcol);
        $gry = $this->xgrid ? $this->tm : $this->tm + $this->cheight + 3 ;
        $ii=0;
        for ($x=$x1,$i=$this->xcount-1; $x>$x0+3; $x -= $div, $i--, $ii++) {
                if ($this->xdashed) {
                        for ($xd=$gry;$xd<=$y0; $xd=$xd+4) {
                                imagesetpixel($this->image,$x,$xd,$this->gridcol);
                        }
                } else {
                        imageline($this->image,$x,$gry,$x,$y0,$this->gridcol);
                }
                imageline($this->image,$x,$y0-4,$x,$y0+3,$this->txtcol);
                $v = $this->xlabels[$i];
                $tw = strlen("$v")*imagefontwidth(2);
                $th = imagefontheight(2);

                if (!($ii%$this->xstep)) {
                        if ($this->xdelta) { if (!$delta) { $delta=12; } else { $delta=0; } } else { $delta=0; }

                        $this->_writestring($this->image,2,$x - ($div+$tw)/2, $y0 + 5 + $delta, $v, $this->txtcol,0,0);
                }
        }
        $y = $this->height - 30;
        $tw = strlen($this->xtitle)*imagefontwidth(3);
        $x = ($this->lm + $this->cwidth + $this->lm - $tw)/2;
        $this->_writestring($this->image,3,$this->lm + $this->cwidth+2,$y0-20,$this->xtitle,$this->txtcol,1,0);

        if ($this->xstr) {
                $points[0] = $this->lm + $this->cwidth+10;
                $points[1] = $y0-3;
                $points[2] = $points[0]+15;
                $points[3] = $points[1]+3;
                $points[4] = $points[2]-15;
                $points[5] = $points[3]+3;
                $points[6] = $points[4]+3;
                $points[7] = $points[5]-3;
                ImageSetThickness($this->image, $this->xline);
                imageline($this->image,$x0,$y0,$x1+15,$y1,$this->txtcol);
                ImageSetThickness($this->image, 1);
                ImageFilledPolygon($this->image,$points,4,$this->txtcol);
        }
}
Example #12
0
 /**
  * Generate noisy background
  *
  * @param int $width: width of the image in pixels
  * @param int $height: width of the image in pixels
  * @param string $word: the captcha word
  * @param string $backgroundType (see constants)
  * @param array $backgroundImages: array of background image file names
  * @param boolean $morphBackground: if TRUE, the background will be morphed
  * @param boolean $blurBackground: if TRUE, the background will be blurred
  * @return string GD image identifier of noisy background
  */
 public static function generateNoisyBackground($width, $height, $word, $backgroundType, $backgroundImages = array(), $morphBackground = TRUE, $blurBackground = TRUE)
 {
     $image = ImageCreateTrueColor($width, $height);
     if ($backgroundType != self::BACKGROUND_TYPE_TRANSPARENT) {
         // Generate noisy background, to be merged with CAPTCHA later
         // any suggestions on how best to do this much appreciated
         // sample code would be even better!
         // I'm not an OCR expert (hell, I'm not even an image expert; puremango.co.uk was designed in MsPaint)
         // so the noise models are based around my -guesswork- as to what would make it hard for an OCR prog
         // ideally, the character obfuscation would be strong enough not to need additional background noise
         // in any case, I hope at least one of the options given here provide some extra security!
         $tempBackground = ImageCreateTrueColor($width * 1.5, $height * 1.5);
         $background = ImageColorAllocate($image, 255, 255, 255);
         ImageFill($image, 0, 0, $background);
         $tempBackgroundColor = ImageColorAllocate($tempBackground, 255, 255, 255);
         ImageFill($tempBackground, 0, 0, $tempBackgroundColor);
         // We draw all noise onto tempBackground
         // then if we're morphing, merge from tempBackground to image
         // or if not, just copy a $width x $height portion of $tempBackground to $image
         // tempBackground is much larger so that when morphing, the edges retain the noise.
         switch ($backgroundType) {
             case self::BACKGROUND_TYPE_WHITE_WITH_GRID:
                 // Draw grid on x
                 for ($i = RandomContentUtility::getRandomNumberInRange(6, 20); $i < $width * 2; $i += RandomContentUtility::getRandomNumberInRange(10, 25)) {
                     ImageSetThickness($tempBackground, RandomContentUtility::getRandomNumberInRange(2, 6));
                     $textColor = RandomContentUtility::getRandomColor(100, 150);
                     $textColor2 = ImageColorAllocate($tempBackground, $textColor[0], $textColor[1], $textColor[2]);
                     ImageLine($tempBackground, $i, 0, $i, $height * 2, $textColor2);
                 }
                 // Draw grid on y
                 for ($i = RandomContentUtility::getRandomNumberInRange(6, 20); $i < $height * 2; $i += RandomContentUtility::getRandomNumberInRange(10, 25)) {
                     ImageSetThickness($tempBackground, RandomContentUtility::getRandomNumberInRange(2, 6));
                     $textColor = RandomContentUtility::getRandomColor(100, 150);
                     $textColor2 = ImageColorAllocate($tempBackground, $textColor[0], $textColor[1], $textColor[2]);
                     ImageLine($tempBackground, 0, $i, $width * 2, $i, $textColor2);
                 }
                 break;
             case self::BACKGROUND_TYPE_WHITE_WITH_SQUIGGLES:
                 ImageSetThickness($tempBackground, 4);
                 for ($i = 0; $i < strlen($word) + 1; $i++) {
                     $textColor = RandomContentUtility::getRandomColor(100, 150);
                     $textColor2 = ImageColorAllocate($tempBackground, $textColor[0], $textColor[1], $textColor[2]);
                     $points = array();
                     // Draw random squiggle for each character
                     // the longer the loop, the more complex the squiggle
                     // keep random so OCR can't say "if found shape has 10 points, ignore it"
                     // each squiggle will, however, be a closed shape, so OCR could try to find
                     // line terminations and start from there. (I don't think they're that advanced yet..)
                     for ($j = 1; $j < RandomContentUtility::getRandomNumberInRange(5, 10); $j++) {
                         $points[] = RandomContentUtility::getRandomNumberInRange(1 * (20 * ($i + 1)), 1 * (50 * ($i + 1)));
                         $points[] = RandomContentUtility::getRandomNumberInRange(30, $height + 30);
                     }
                     ImagePolygon($tempBackground, $points, intval(sizeof($points) / 2), $textColor2);
                 }
                 break;
             case self::BACKGROUND_TYPE_MORPHED_IMAGE_BLOCKS:
                 // Take random chunks of $backgroundImages and paste them onto the background
                 for ($i = 0; $i < sizeof($backgroundImages); $i++) {
                     // Read each image and its size
                     $tempImages[$i] = ImageCreateFromJPEG(GeneralUtility::getFileAbsFileName($backgroundImages[$i]));
                     $tempWidths[$i] = imagesx($tempImages[$i]);
                     $tempHeights[$i] = imagesy($tempImages[$i]);
                 }
                 $blocksize = RandomContentUtility::getRandomNumberInRange(20, 60);
                 for ($i = 0; $i < $width * 2; $i += $blocksize) {
                     // Could randomise blocksize here... hardly matters
                     for ($j = 0; $j < $height * 2; $j += $blocksize) {
                         $imageIndex = RandomContentUtility::getRandomNumberInRange(0, sizeof($tempImages) - 1);
                         $cut_x = RandomContentUtility::getRandomNumberInRange(0, $tempWidths[$imageIndex] - $blocksize);
                         $cut_y = RandomContentUtility::getRandomNumberInRange(0, $tempHeights[$imageIndex] - $blocksize);
                         ImageCopy($tempBackground, $tempImages[$imageIndex], $i, $j, $cut_x, $cut_y, $blocksize, $blocksize);
                     }
                 }
                 // Cleanup
                 for ($i = 0; $i < sizeof($tempImages); $i++) {
                     ImageDestroy($tempImages[$i]);
                 }
                 break;
         }
         if ($morphBackground) {
             // Morph background
             // We do this separately to the main text morph because:
             // a) the main text morph is done char-by-char, this is done across whole image
             // b) if an attacker could un-morph the background, it would un-morph the CAPTCHA
             // hence background is morphed differently to text
             // why do we morph it at all? it might make it harder for an attacker to remove the background
             // morph_chunk 1 looks better but takes longer
             // this is a different and less perfect morph than the one we do on the CAPTCHA
             // occasonally you get some dark background showing through around the edges
             // it doesn't need to be perfect as it's only the background.
             $morph_chunk = RandomContentUtility::getRandomNumberInRange(1, 5);
             $morph_y = 0;
             for ($x = 0; $x < $width; $x += $morph_chunk) {
                 $morph_chunk = RandomContentUtility::getRandomNumberInRange(1, 5);
                 $morph_y += RandomContentUtility::getRandomNumberInRange(-1, 1);
                 ImageCopy($image, $tempBackground, $x, 0, $x + 30, 30 + $morph_y, $morph_chunk, $height * 2);
             }
             ImageCopy($tempBackground, $image, 0, 0, 0, 0, $width, $height);
             $morph_x = 0;
             for ($y = 0; $y <= $height; $y += $morph_chunk) {
                 $morph_chunk = RandomContentUtility::getRandomNumberInRange(1, 5);
                 $morph_x += RandomContentUtility::getRandomNumberInRange(-1, 1);
                 ImageCopy($image, $tempBackground, $morph_x, $y, 0, $y, $width, $morph_chunk);
             }
         } else {
             // Just copy tempBackground onto $image
             ImageCopy($image, $tempBackground, 0, 0, 30, 30, $width, $height);
         }
         // Cleanup
         ImageDestroy($tempBackground);
         if ($blurBackground) {
             $image = self::blurImage($image);
         }
     }
     return $image;
 }