function ImageCreateFromStringReplacement(&$RawImageData, $DieOnErrors = false) { // there are serious bugs in the non-bundled versions of GD which may cause // PHP to segfault when calling ImageCreateFromString() - avoid if at all possible // when not using a bundled version of GD2 if (!phpthumb_functions::gd_version()) { if ($DieOnErrors) { if (!headers_sent()) { // base64-encoded error image in GIF format $ERROR_NOGD = 'R0lGODlhIAAgALMAAAAAABQUFCQkJDY2NkZGRldXV2ZmZnJycoaGhpSUlKWlpbe3t8XFxdXV1eTk5P7+/iwAAAAAIAAgAAAE/vDJSau9WILtTAACUinDNijZtAHfCojS4W5H+qxD8xibIDE9h0OwWaRWDIljJSkUJYsN4bihMB8th3IToAKs1VtYM75cyV8sZ8vygtOE5yMKmGbO4jRdICQCjHdlZzwzNW4qZSQmKDaNjhUMBX4BBAlmMywFSRWEmAI6b5gAlhNxokGhooAIK5o/pi9vEw4Lfj4OLTAUpj6IabMtCwlSFw0DCKBoFqwAB04AjI54PyZ+yY3TD0ss2YcVmN/gvpcu4TOyFivWqYJlbAHPpOntvxNAACcmGHjZzAZqzSzcq5fNjxFmAFw9iFRunD1epU6tsIPmFCAJnWYE0FURk7wJDA0MTKpEzoWAAskiAAA7'; header('Content-Type: image/gif'); echo base64_decode($ERROR_NOGD); } else { echo '*** ERROR: No PHP-GD support available ***'; } exit; } else { $this->DebugMessage('ImageCreateFromStringReplacement() failed: gd_version says "' . phpthumb_functions::gd_version() . '"', __FILE__, __LINE__); return false; } } if (phpthumb_functions::gd_is_bundled()) { $this->DebugMessage('ImageCreateFromStringReplacement() calling built-in ImageCreateFromString()', __FILE__, __LINE__); return @ImageCreateFromString($RawImageData); } if ($this->issafemode) { $this->DebugMessage('ImageCreateFromStringReplacement() failed: cannot create temp file in SAFE_MODE', __FILE__, __LINE__); return false; } switch (substr($RawImageData, 0, 3)) { case 'GIF': $ICFSreplacementFunctionName = 'ImageCreateFromGIF'; break; case "ÿØÿ": $ICFSreplacementFunctionName = 'ImageCreateFromJPEG'; break; case "‰" . 'PN': $ICFSreplacementFunctionName = 'ImageCreateFromPNG'; break; default: $this->DebugMessage('ImageCreateFromStringReplacement() failed: unknown fileformat signature "' . phpthumb_functions::HexCharDisplay(substr($RawImageData, 0, 3)) . '"', __FILE__, __LINE__); return false; break; } if ($tempnam = $this->phpThumb_tempnam()) { if ($fp_tempnam = @fopen($tempnam, 'wb')) { fwrite($fp_tempnam, $RawImageData); fclose($fp_tempnam); if ($ICFSreplacementFunctionName == 'ImageCreateFromGIF' && !function_exists($ICFSreplacementFunctionName)) { // Need to create from GIF file, but ImageCreateFromGIF does not exist ob_start(); if (!@(include_once dirname(__FILE__) . '/phpthumb.gif.php')) { $ErrorMessage = 'Failed to include required file "' . dirname(__FILE__) . '/phpthumb.gif.php" in ' . __FILE__ . ' on line ' . __LINE__; $this->DebugMessage($ErrorMessage, __FILE__, __LINE__); } ob_end_clean(); // gif_loadFileToGDimageResource() cannot read from raw data, write to file first if ($tempfilename = $this->phpThumb_tempnam()) { if ($fp_tempfile = @fopen($tempfilename, 'wb')) { fwrite($fp_tempfile, $RawImageData); fclose($fp_tempfile); $gdimg_source = gif_loadFileToGDimageResource($tempfilename); $this->DebugMessage('gif_loadFileToGDimageResource(' . $tempfilename . ') completed', __FILE__, __LINE__); $this->DebugMessage('deleting "' . $tempfilename . '"', __FILE__, __LINE__); unlink($tempfilename); return $gdimg_source; // break; } else { $ErrorMessage = 'Failed to open tempfile in ' . __FILE__ . ' on line ' . __LINE__; $this->DebugMessage($ErrorMessage, __FILE__, __LINE__); } } else { $ErrorMessage = 'Failed to open generate tempfile name in ' . __FILE__ . ' on line ' . __LINE__; $this->DebugMessage($ErrorMessage, __FILE__, __LINE__); } } elseif (function_exists($ICFSreplacementFunctionName) && ($gdimg_source = @$ICFSreplacementFunctionName($tempnam))) { // great $this->DebugMessage($ICFSreplacementFunctionName . '(' . $tempnam . ') succeeded', __FILE__, __LINE__); $this->DebugMessage('deleting "' . $tempnam . '"', __FILE__, __LINE__); unlink($tempnam); return $gdimg_source; } else { // GD functions not available, or failed to create image $this->DebugMessage($ICFSreplacementFunctionName . '(' . $tempnam . ') ' . (function_exists($ICFSreplacementFunctionName) ? 'failed' : 'does not exist'), __FILE__, __LINE__); if (isset($_GET['phpThumbDebug'])) { $this->phpThumbDebug(); } } } else { $ErrorMessage = 'Failed to fopen(' . $tempnam . ', "wb") in ' . __FILE__ . ' on line ' . __LINE__ . "\n" . 'You may need to set $PHPTHUMB_CONFIG[temp_directory] in phpThumb.config.php'; if ($this->issafemode) { $ErrorMessage = 'ImageCreateFromStringReplacement() failed in ' . __FILE__ . ' on line ' . __LINE__ . ': cannot create temp file in SAFE_MODE'; } $this->DebugMessage($ErrorMessage, __FILE__, __LINE__); } $this->DebugMessage('deleting "' . $tempnam . '"', __FILE__, __LINE__); @unlink($tempnam); } else { $ErrorMessage = 'Failed to generate phpThumb_tempnam() in ' . __FILE__ . ' on line ' . __LINE__ . "\n" . 'You may need to set $PHPTHUMB_CONFIG[temp_directory] in phpThumb.config.php'; if ($this->issafemode) { $ErrorMessage = 'ImageCreateFromStringReplacement() failed in ' . __FILE__ . ' on line ' . __LINE__ . ': cannot create temp file in SAFE_MODE'; } } if ($DieOnErrors && $ErrorMessage) { return $this->ErrorImage($ErrorMessage); } return false; }
public function Smooth(&$gdimg, $amount = 6) { $amount = min(25, max(0, $amount)); if ($amount == 0) { return true; } if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { if (ImageFilter($gdimg, IMG_FILTER_SMOOTH, $amount)) { return true; } $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_SMOOTH, ' . $amount . ')', __FILE__, __LINE__); // fall through and try it the hard way } // currently not implemented "the hard way" $this->DebugMessage('FAILED: phpthumb_filters::Smooth($gdimg, ' . $amount . ') [function not implemented]', __FILE__, __LINE__); return false; }
function applyUnsharpMask(&$img, $amount, $radius, $threshold) { // $img is an image that is already created within php using // imgcreatetruecolor. No url! $img must be a truecolor image. // Attempt to calibrate the parameters to Photoshop: $amount = min($amount, 500); $amount = $amount * 0.016; if ($amount == 0) { return true; } $radius = min($radius, 50); $radius = $radius * 2; $threshold = min($threshold, 255); $radius = abs(round($radius)); // Only integers make sense. if ($radius == 0) { return true; } $w = ImageSX($img); $h = ImageSY($img); $imgCanvas = ImageCreateTrueColor($w, $h); $imgCanvas2 = ImageCreateTrueColor($w, $h); ImageCopy($imgCanvas, $img, 0, 0, 0, 0, $w, $h); ImageCopy($imgCanvas2, $img, 0, 0, 0, 0, $w, $h); $builtinFilterSucceeded = false; if ($radius == 1) { if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { if (ImageFilter($imgCanvas, IMG_FILTER_GAUSSIAN_BLUR) && ImageFilter($imgCanvas2, IMG_FILTER_GAUSSIAN_BLUR)) { $builtinFilterSucceeded = true; } } } if (!$builtinFilterSucceeded) { $imgBlur = ImageCreateTrueColor($w, $h); $imgBlur2 = ImageCreateTrueColor($w, $h); /////////////////////////// // // Gaussian blur matrix: // 1 2 1 // 2 4 2 // 1 2 1 // /////////////////////////// // Move copies of the image around one pixel at the time and merge them with weight // according to the matrix. The same matrix is simply repeated for higher radii. for ($i = 0; $i < $radius; $i++) { ImageCopy($imgBlur, $imgCanvas, 0, 0, 1, 1, $w - 1, $h - 1); // up left ImageCopyMerge($imgBlur, $imgCanvas, 1, 1, 0, 0, $w, $h, 50); // down right ImageCopyMerge($imgBlur, $imgCanvas, 0, 1, 1, 0, $w - 1, $h, 33.33333); // down left ImageCopyMerge($imgBlur, $imgCanvas, 1, 0, 0, 1, $w, $h - 1, 25); // up right ImageCopyMerge($imgBlur, $imgCanvas, 0, 0, 1, 0, $w - 1, $h, 33.33333); // left ImageCopyMerge($imgBlur, $imgCanvas, 1, 0, 0, 0, $w, $h, 25); // right ImageCopyMerge($imgBlur, $imgCanvas, 0, 0, 0, 1, $w, $h - 1, 20); // up ImageCopyMerge($imgBlur, $imgCanvas, 0, 1, 0, 0, $w, $h, 16.666667); // down ImageCopyMerge($imgBlur, $imgCanvas, 0, 0, 0, 0, $w, $h, 50); // center ImageCopy($imgCanvas, $imgBlur, 0, 0, 0, 0, $w, $h); // During the loop above the blurred copy darkens, possibly due to a roundoff // error. Therefore the sharp picture has to go through the same loop to // produce a similar image for comparison. This is not a good thing, as processing // time increases heavily. ImageCopy($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h); ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 50); ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 33.33333); ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 25); ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 33.33333); ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 25); ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 20); ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 16.666667); ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 50); ImageCopy($imgCanvas2, $imgBlur2, 0, 0, 0, 0, $w, $h); } ImageDestroy($imgBlur); ImageDestroy($imgBlur2); } // Calculate the difference between the blurred pixels and the original // and set the pixels for ($x = 0; $x < $w; $x++) { // each row for ($y = 0; $y < $h; $y++) { // each pixel $rgbOrig = ImageColorAt($imgCanvas2, $x, $y); $rOrig = $rgbOrig >> 16 & 0xff; $gOrig = $rgbOrig >> 8 & 0xff; $bOrig = $rgbOrig & 0xff; $rgbBlur = ImageColorAt($imgCanvas, $x, $y); $rBlur = $rgbBlur >> 16 & 0xff; $gBlur = $rgbBlur >> 8 & 0xff; $bBlur = $rgbBlur & 0xff; // When the masked pixels differ less from the original // than the threshold specifies, they are set to their original value. $rNew = abs($rOrig - $rBlur) >= $threshold ? max(0, min(255, $amount * ($rOrig - $rBlur) + $rOrig)) : $rOrig; $gNew = abs($gOrig - $gBlur) >= $threshold ? max(0, min(255, $amount * ($gOrig - $gBlur) + $gOrig)) : $gOrig; $bNew = abs($bOrig - $bBlur) >= $threshold ? max(0, min(255, $amount * ($bOrig - $bBlur) + $bOrig)) : $bOrig; if ($rOrig != $rNew || $gOrig != $gNew || $bOrig != $bNew) { $pixCol = ImageColorAllocate($img, $rNew, $gNew, $bNew); ImageSetPixel($img, $x, $y, $pixCol); } } } ImageDestroy($imgCanvas); ImageDestroy($imgCanvas2); return true; }