static 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) * 0.016; $radius = abs(round(min(50, $radius) * 2)); // Only integers make sense. $threshold = min(255, $threshold); if ($radius == 0) { return true; } $w = ImageSX($img); $h = ImageSY($img); $imgCanvas = ImageCreateTrueColor($w, $h); $imgBlur = ImageCreateTrueColor($w, $h); // Gaussian blur matrix: // // 1 2 1 // 2 4 2 // 1 2 1 // ////////////////////////////////////////////////// if (function_exists('imageconvolution')) { // PHP >= 5.1 $matrix = array(array(1, 2, 1), array(2, 4, 2), array(1, 2, 1)); ImageCopy($imgBlur, $img, 0, 0, 0, 0, $w, $h); ImageConvolution($imgBlur, $matrix, 16, 0); } else { // 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, $img, 0, 0, 1, 0, $w - 1, $h); // left ImageCopyMerge($imgBlur, $img, 1, 0, 0, 0, $w, $h, 50); // right ImageCopyMerge($imgBlur, $img, 0, 0, 0, 0, $w, $h, 50); // center ImageCopy($imgCanvas, $imgBlur, 0, 0, 0, 0, $w, $h); ImageCopyMerge($imgBlur, $imgCanvas, 0, 0, 0, 1, $w, $h - 1, 33.33333); // up ImageCopyMerge($imgBlur, $imgCanvas, 0, 1, 0, 0, $w, $h, 25); // down } } if ($threshold > 0) { // Calculate the difference between the blurred pixels and the original // and set the pixels for ($x = 0; $x < $w - 1; $x++) { // each row for ($y = 0; $y < $h; $y++) { // each pixel $rgbOrig = ImageColorAt($img, $x, $y); $rOrig = $rgbOrig >> 16 & 0xff; $gOrig = $rgbOrig >> 8 & 0xff; $bOrig = $rgbOrig & 0xff; $rgbBlur = ImageColorAt($imgBlur, $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); } } } } else { for ($x = 0; $x < $w; $x++) { // each row for ($y = 0; $y < $h; $y++) { // each pixel $rgbOrig = ImageColorAt($img, $x, $y); $rOrig = $rgbOrig >> 16 & 0xff; $gOrig = $rgbOrig >> 8 & 0xff; $bOrig = $rgbOrig & 0xff; $rgbBlur = ImageColorAt($imgBlur, $x, $y); $rBlur = $rgbBlur >> 16 & 0xff; $gBlur = $rgbBlur >> 8 & 0xff; $bBlur = $rgbBlur & 0xff; $rNew = min(255, max(0, $amount * ($rOrig - $rBlur) + $rOrig)); $gNew = min(255, max(0, $amount * ($gOrig - $gBlur) + $gOrig)); $bNew = min(255, max(0, $amount * ($bOrig - $bBlur) + $bOrig)); $rgbNew = ($rNew << 16) + ($gNew << 8) + $bNew; ImageSetPixel($img, $x, $y, $rgbNew); } } } ImageDestroy($imgCanvas); ImageDestroy($imgBlur); return true; }
/** * Generates a resized version of an image and saves it in the image cache folder. * * @param string $source_file The original image to be resized. * @param string $cache_file The target file where the resized version will be cached. * @param int $resolution The resolution breakpoint at which the given image is to be resized. * @param int $jpg_quality The JPEG quality that will be used for resizing the images. * @param bool $sharpen Whether to sharpen the resized images or not. * * @return array Associative array( bool: success, string: message) with the result of the image cache generation. */ function adaptive_images_script_generate_image($source_file, $cache_file, $resolution, $jpg_quality, $sharpen) { // Get original image dimensions. $dimensions = @GetImageSize($source_file); $width = $dimensions[0]; $height = $dimensions[1]; // Calculate resized image dimensions. $ratio = $height / $width; $new_width = $resolution; $new_height = ceil($new_width * $ratio); // Start creating the resized image with a blank true color canvas. $destination = @ImageCreateTrueColor($new_width, $new_height); $extension = adaptive_images_script_get_file_extension($source_file); switch ($extension) { case 'png': $source = @ImageCreateFromPng($source_file); break; case 'gif': $source = @ImageCreateFromGif($source_file); break; default: $source = @ImageCreateFromJpeg($source_file); break; } // PNG images generation. if ($extension == 'png') { // Create a transparent color and fill the blank canvas with it. $rbga_color = @ImageColorAllocateAlpha($destination, 0, 0, 0, 127); @ImageColorTransparent($destination, $rbga_color); @ImageFill($destination, 0, 0, $rbga_color); // Copy source image to destination image with interpolation. @ImageCopyResampled($destination, $source, 0, 0, 0, 0, $new_width, $new_height, $width, $height); // Convert true colour image to pallette image to achieve PNG-8 compression. $dither = TRUE; @ImageTrueColorToPalette($destination, $dither, 255); // Save alpha (transparency) of destination image. $save_alpha = TRUE; @ImageSaveAlpha($destination, $save_alpha); // Disable blending of destination image to allow for alpha (transparency) above. $enable_alpha_blending = FALSE; @ImageAlphaBlending($destination, $enable_alpha_blending); } // GIF images generation. if ($extension == 'gif') { // Create a transparent color and fill the blank canvas with it. $rbga_color = @ImageColorAllocateAlpha($destination, 0, 0, 0, 127); @ImageColorTransparent($destination, $rbga_color); @ImageFill($destination, 0, 0, $rbga_color); // Copy source image to destination image with interpolation. @ImageCopyResampled($destination, $source, 0, 0, 0, 0, $new_width, $new_height, $width, $height); // Convert true colour image to pallette image to achieve PNG8 compression. $dither = TRUE; @ImageTrueColorToPalette($destination, $dither, 255); // Enable alpha blending of destination image. $enable_alpha_blending = TRUE; @ImageAlphaBlending($destination, $enable_alpha_blending); } // JPEG images generation. if ($extension == 'jpg' || $extension == 'jpeg') { // Enable JPEG interlacing. ImageInterlace($destination, TRUE); // Interpolates source image to destination image to make it more clear for JPGs. @ImageCopyResampled($destination, $source, 0, 0, 0, 0, $new_width, $new_height, $width, $height); } // Cleanup source image from memory. @ImageDestroy($source); // Do sharpening if requested. if ($sharpen && function_exists('imageconvolution')) { $sharpness_factor = adaptive_images_script_sharpness_factor($width, $new_width); $sharpness_transformation_matrix = array(array(-1, -2, -1), array(-2, $sharpness_factor + 12, -2), array(-1, -2, -1)); // OR // $sharpenMatrix = array // ( // array(-1.2, -1, -1.2), // array(-1, 20, -1), // array(-1.2, -1, -1.2) // ); // $divisor = array_sum(array_map('array_sum', $sharpenMatrix)); // OR // $sharpen = array( // array(0.0, -1.0, 0.0), // array(-1.0, 5.0, -1.0), // array(0.0, -1.0, 0.0) // ); // $divisor = array_sum(array_map('array_sum', $sharpen)); // OR // $matrix = array( // array(-1, -1, -1), // array(-1, 16, -1), // array(-1, -1, -1), // ); // $divisor = array_sum(array_map('array_sum', $matrix)); @ImageConvolution($destination, $sharpness_transformation_matrix, $sharpness_factor, 0); } // Check and ensure that cache directory is setup OK. $cache_path = dirname($cache_file); if (!adaptive_images_script_ensure_cache_directory_ready($cache_path)) { return array('success' => false, 'message' => 'Cache directory for image not accessible or writeable.'); } // Save resized image in cache. switch ($extension) { case 'png': $png_compression_level = 6; $image_saved = @ImagePng($destination, $cache_file, $png_compression_level, PNG_FILTER_NONE); break; case 'gif': $image_saved = @ImageGif($destination, $cache_file); break; default: $image_saved = @ImageJpeg($destination, $cache_file, $jpg_quality); break; } // Cleanup destination image from memory. @ImageDestroy($destination); // Check if all OK. if (!$image_saved && !file_exists($cache_file)) { return array('success' => false, 'message' => 'Resized image could not be created.'); } // Return file of resized and cached image. return array('success' => true, 'message' => $cache_file); }