/** * @param Thumbnail $thumbnail * @return void * @throws Exception\NoThumbnailAvailableException */ public function refresh(Thumbnail $thumbnail) { try { $filenameWithoutExtension = pathinfo($thumbnail->getOriginalAsset()->getResource()->getFilename(), PATHINFO_FILENAME); $temporaryLocalCopyFilename = $thumbnail->getOriginalAsset()->getResource()->createTemporaryLocalCopy(); $documentFile = sprintf(in_array($thumbnail->getOriginalAsset()->getResource()->getFileExtension(), $this->getOption('paginableDocuments')) ? '%s[0]' : '%s', $temporaryLocalCopyFilename); $width = $thumbnail->getConfigurationValue('width') ?: $thumbnail->getConfigurationValue('maximumWidth'); $height = $thumbnail->getConfigurationValue('height') ?: $thumbnail->getConfigurationValue('maximumHeight'); $im = new \Imagick(); $im->setResolution($this->getOption('resolution'), $this->getOption('resolution')); $im->readImage($documentFile); $im->setImageFormat('png'); $im->setImageBackgroundColor('white'); $im->setImageCompose(\Imagick::COMPOSITE_OVER); $im->setImageAlphaChannel(\Imagick::ALPHACHANNEL_RESET); $im->thumbnailImage($width, $height, true); $im->flattenImages(); // Replace flattenImages in imagick 3.3.0 // @see https://pecl.php.net/package/imagick/3.3.0RC2 // $im->mergeImageLayers(\Imagick::LAYERMETHOD_MERGE); $resource = $this->resourceManager->importResourceFromContent($im->getImageBlob(), $filenameWithoutExtension . '.png'); $im->destroy(); $thumbnail->setResource($resource); $thumbnail->setWidth($width); $thumbnail->setHeight($height); } catch (\Exception $exception) { $filename = $thumbnail->getOriginalAsset()->getResource()->getFilename(); $sha1 = $thumbnail->getOriginalAsset()->getResource()->getSha1(); $message = sprintf('Unable to generate thumbnail for the given document (filename: %s, SHA1: %s)', $filename, $sha1); throw new Exception\NoThumbnailAvailableException($message, 1433109652, $exception); } }
/** * @param null|string $backgroundColor * * @throws ProcessorException * * @returns $this */ public function removeAlpha($backgroundColor = null) { $backgroundColor = $backgroundColor === null ? 'white' : $backgroundColor; try { $this->im->setBackgroundColor($backgroundColor); $this->im->setImageAlphaChannel($this->getLibraryConstant('ALPHACHANNEL_REMOVE', null, 11)); } catch (\Exception $e) { throw new ProcessorException('Could not remove alpha channel: %s', null, $e, (string) $e->getMessage()); } return $this; }
/** * @param string $file * * @throws \ManaPHP\Image\Adapter\Exception */ public function __construct($file) { if (!extension_loaded('imagick')) { throw new ImagickException('Imagick is not installed, or the extension is not loaded'); } $this->_file = realpath($this->alias->resolve($file)); if (!$this->_file) { throw new ImagickException('`:file` file is not exists', ['file' => $file]); } $this->_image = new \Imagick(); if (!$this->_image->readImage($this->_file)) { throw new ImagickException('Imagick::readImage `:file` failed', ['file' => $file]); } if ($this->_image->getNumberImages() !== 1) { throw new ImagickException('not support multiple iterations: `:file`', ['file' => $file]); } if (!$this->_image->getImageAlphaChannel()) { $this->_image->setImageAlphaChannel(\Imagick::ALPHACHANNEL_SET); } $this->_width = $this->_image->getImageWidth(); $this->_height = $this->_image->getImageHeight(); }
/** * Resize image to a given size. Use only to shrink an image. * If an image is smaller than specified size it will be not resized. * * @param int $size Max width/height size * @param string $filename Output filename * @param boolean $browser_compat Convert to image type displayable by any browser * * @return mixed Output type on success, False on failure */ public function resize($size, $filename = null, $browser_compat = false) { $result = false; $rcube = rcube::get_instance(); $convert = $rcube->config->get('im_convert_path', false); $props = $this->props(); if (empty($props)) { return false; } if (!$filename) { $filename = $this->image_file; } // use Imagemagick if ($convert || class_exists('Imagick', false)) { $p['out'] = $filename; $p['in'] = $this->image_file; $type = $props['type']; if (!$type && ($data = $this->identify())) { $type = $data[0]; } $type = strtr($type, array("jpeg" => "jpg", "tiff" => "tif", "ps" => "eps", "ept" => "eps")); $p['intype'] = $type; // convert to an image format every browser can display if ($browser_compat && !in_array($type, array('jpg', 'gif', 'png'))) { $type = 'jpg'; } // If only one dimension is greater than the limit convert doesn't // work as expected, we need to calculate new dimensions $scale = $size / max($props['width'], $props['height']); // if file is smaller than the limit, we do nothing // but copy original file to destination file if ($scale >= 1 && $p['intype'] == $type) { $result = $this->image_file == $filename || copy($this->image_file, $filename) ? '' : false; } else { $valid_types = "bmp,eps,gif,jp2,jpg,png,svg,tif"; if (in_array($type, explode(',', $valid_types))) { // Valid type? if ($scale >= 1) { $width = $props['width']; $height = $props['height']; } else { $width = intval($props['width'] * $scale); $height = intval($props['height'] * $scale); } // use ImageMagick in command line if ($convert) { $p += array('type' => $type, 'quality' => 75, 'size' => $width . 'x' . $height); $result = rcube::exec($convert . ' 2>&1 -flatten -auto-orient -colorspace sRGB -strip' . ' -quality {quality} -resize {size} {intype}:{in} {type}:{out}', $p); } else { try { $image = new Imagick($this->image_file); try { // it throws exception on formats not supporting these features $image->setImageBackgroundColor('white'); $image->setImageAlphaChannel(11); $image->mergeImageLayers(Imagick::LAYERMETHOD_FLATTEN); } catch (Exception $e) { // ignore errors } $image->setImageColorspace(Imagick::COLORSPACE_SRGB); $image->setImageCompressionQuality(75); $image->setImageFormat($type); $image->stripImage(); $image->scaleImage($width, $height); if ($image->writeImage($filename)) { $result = ''; } } catch (Exception $e) { rcube::raise_error($e, true, false); } } } } if ($result === '') { @chmod($filename, 0600); return $type; } } // do we have enough memory? (#1489937) if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN' && !$this->mem_check($props)) { return false; } // use GD extension if ($props['gd_type']) { if ($props['gd_type'] == IMAGETYPE_JPEG && function_exists('imagecreatefromjpeg')) { $image = imagecreatefromjpeg($this->image_file); $type = 'jpg'; } else { if ($props['gd_type'] == IMAGETYPE_GIF && function_exists('imagecreatefromgif')) { $image = imagecreatefromgif($this->image_file); $type = 'gif'; } else { if ($props['gd_type'] == IMAGETYPE_PNG && function_exists('imagecreatefrompng')) { $image = imagecreatefrompng($this->image_file); $type = 'png'; } else { // @TODO: print error to the log? return false; } } } if ($image === false) { return false; } $scale = $size / max($props['width'], $props['height']); // Imagemagick resize is implemented in shrinking mode (see -resize argument above) // we do the same here, if an image is smaller than specified size // we do nothing but copy original file to destination file if ($scale >= 1) { $result = $this->image_file == $filename || copy($this->image_file, $filename); } else { $width = intval($props['width'] * $scale); $height = intval($props['height'] * $scale); $new_image = imagecreatetruecolor($width, $height); if ($new_image === false) { return false; } // Fix transparency of gif/png image if ($props['gd_type'] != IMAGETYPE_JPEG) { imagealphablending($new_image, false); imagesavealpha($new_image, true); $transparent = imagecolorallocatealpha($new_image, 255, 255, 255, 127); imagefilledrectangle($new_image, 0, 0, $width, $height, $transparent); } imagecopyresampled($new_image, $image, 0, 0, 0, 0, $width, $height, $props['width'], $props['height']); $image = $new_image; // fix rotation of image if EXIF data exists and specifies rotation (GD strips the EXIF data) if ($this->image_file && $type == 'jpg' && function_exists('exif_read_data')) { $exif = exif_read_data($this->image_file); if ($exif && $exif['Orientation']) { switch ($exif['Orientation']) { case 3: $image = imagerotate($image, 180, 0); break; case 6: $image = imagerotate($image, -90, 0); break; case 8: $image = imagerotate($image, 90, 0); break; } } } if ($props['gd_type'] == IMAGETYPE_JPEG) { $result = imagejpeg($image, $filename, 75); } elseif ($props['gd_type'] == IMAGETYPE_GIF) { $result = imagegif($image, $filename); } elseif ($props['gd_type'] == IMAGETYPE_PNG) { $result = imagepng($image, $filename, 6, PNG_ALL_FILTERS); } } if ($result) { @chmod($filename, 0600); return $type; } } // @TODO: print error to the log? return false; }
/** * Process an image. * * Returns an array of the $file, $results, $converted to tell us if an image changes formats, and the $original file if it did. * * @param string $file Full absolute path to the image file * @param int $gallery_type 1=wordpress, 2=nextgen, 3=flagallery, 4=aux_images, 5=image editor, 6=imagestore * @param boolean $converted tells us if this is a resize and the full image was converted to a new format * @param boolean $new tells the optimizer that this is a new image, so it should attempt conversion regardless of previous results * @param boolean $fullsize tells the optimizer this is a full size image * @returns array */ function ewww_image_optimizer($file, $gallery_type = 4, $converted = false, $new = false, $fullsize = false) { ewwwio_debug_message('<b>' . __FUNCTION__ . '()</b>'); // if the plugin gets here without initializing, we need to run through some things first if (!defined('EWWW_IMAGE_OPTIMIZER_CLOUD')) { ewww_image_optimizer_cloud_init(); } session_write_close(); $bypass_optimization = apply_filters('ewww_image_optimizer_bypass', false, $file); if (true === $bypass_optimization) { // tell the user optimization was skipped $msg = __("Optimization skipped", EWWW_IMAGE_OPTIMIZER_DOMAIN); ewwwio_debug_message("optimization bypassed: {$file}"); // send back the above message return array(false, $msg, $converted, $file); } // initialize the original filename $original = $file; $result = ''; // check that the file exists if (FALSE === file_exists($file)) { // tell the user we couldn't find the file $msg = sprintf(__('Could not find %s', EWWW_IMAGE_OPTIMIZER_DOMAIN), $file); ewwwio_debug_message("file doesn't appear to exist: {$file}"); // send back the above message return array(false, $msg, $converted, $original); } // check that the file is writable if (FALSE === is_writable($file)) { // tell the user we can't write to the file $msg = sprintf(__('%s is not writable', EWWW_IMAGE_OPTIMIZER_DOMAIN), $file); ewwwio_debug_message("couldn't write to the file {$file}"); // send back the above message return array(false, $msg, $converted, $original); } if (function_exists('fileperms')) { $file_perms = substr(sprintf('%o', fileperms($file)), -4); } $file_owner = 'unknown'; $file_group = 'unknown'; if (function_exists('posix_getpwuid')) { $file_owner = posix_getpwuid(fileowner($file)); $file_owner = $file_owner['name']; } if (function_exists('posix_getgrgid')) { $file_group = posix_getgrgid(filegroup($file)); $file_group = $file_group['name']; } ewwwio_debug_message("permissions: {$file_perms}, owner: {$file_owner}, group: {$file_group}"); $type = ewww_image_optimizer_mimetype($file, 'i'); if (strpos($type, 'image') === FALSE && strpos($type, 'pdf') === FALSE) { ewwwio_debug_message('could not find any functions for mimetype detection'); //otherwise we store an error message since we couldn't get the mime-type return array(false, __('Unknown type: ' . $type, EWWW_IMAGE_OPTIMIZER_DOMAIN), $converted, $original); $msg = __('Missing finfo_file(), getimagesize() and mime_content_type() PHP functions', EWWW_IMAGE_OPTIMIZER_DOMAIN); return array(false, $msg, $converted, $original); } if (!EWWW_IMAGE_OPTIMIZER_CLOUD) { // check to see if 'nice' exists $nice = ewww_image_optimizer_find_nix_binary('nice', 'n'); if (!defined('EWWW_IMAGE_OPTIMIZER_NOEXEC')) { // Check if exec is disabled if (ewww_image_optimizer_exec_check()) { define('EWWW_IMAGE_OPTIMIZER_NOEXEC', true); ewwwio_debug_message('exec seems to be disabled'); ewww_image_optimizer_disable_tools(); // otherwise, query the php settings for safe mode } elseif (ewww_image_optimizer_safemode_check()) { define('EWWW_IMAGE_OPTIMIZER_NOEXEC', true); ewwwio_debug_message('safe mode appears to be enabled'); ewww_image_optimizer_disable_tools(); } else { define('EWWW_IMAGE_OPTIMIZER_NOEXEC', false); } } } $skip = ewww_image_optimizer_skip_tools(); // if the user has disabled the utility checks if (EWWW_IMAGE_OPTIMIZER_CLOUD) { $skip['jpegtran'] = true; $skip['optipng'] = true; $skip['gifsicle'] = true; $skip['pngout'] = true; $skip['pngquant'] = true; $skip['webp'] = true; } if (ewww_image_optimizer_get_option('ewww_image_optimizer_metadata_skip_full') && $fullsize) { $keep_metadata = true; } else { $keep_metadata = false; } if (ewww_image_optimizer_get_option('ewww_image_optimizer_lossy_skip_full') && $fullsize) { $skip_lossy = true; } else { $skip_lossy = false; } if (ini_get('max_execution_time') < 90 && ewww_image_optimizer_stl_check()) { set_time_limit(0); } // if the full-size image was converted if ($converted) { ewwwio_debug_message('full-size image was converted, need to rebuild filename for meta'); $filenum = $converted; // grab the file extension preg_match('/\\.\\w+$/', $file, $fileext); // strip the file extension $filename = str_replace($fileext[0], '', $file); // grab the dimensions preg_match('/-\\d+x\\d+(-\\d+)*$/', $filename, $fileresize); // strip the dimensions $filename = str_replace($fileresize[0], '', $filename); // reconstruct the filename with the same increment (stored in $converted) as the full version $refile = $filename . '-' . $filenum . $fileresize[0] . $fileext[0]; // rename the file rename($file, $refile); ewwwio_debug_message("moved {$file} to {$refile}"); // and set $file to the new filename $file = $refile; $original = $file; } // get the original image size $orig_size = filesize($file); ewwwio_debug_message("original filesize: {$orig_size}"); if ($orig_size < ewww_image_optimizer_get_option('ewww_image_optimizer_skip_size')) { // tell the user optimization was skipped $msg = __("Optimization skipped", EWWW_IMAGE_OPTIMIZER_DOMAIN); ewwwio_debug_message("optimization bypassed due to filesize: {$file}"); // send back the above message return array(false, $msg, $converted, $file); } if ($type == 'image/png' && ewww_image_optimizer_get_option('ewww_image_optimizer_skip_png_size') && $orig_size > ewww_image_optimizer_get_option('ewww_image_optimizer_skip_png_size')) { // tell the user optimization was skipped $msg = __("Optimization skipped", EWWW_IMAGE_OPTIMIZER_DOMAIN); ewwwio_debug_message("optimization bypassed due to filesize: {$file}"); // send back the above message return array($file, $msg, $converted, $file); } // initialize $new_size with the original size, HOW ABOUT A ZERO... //$new_size = $orig_size; $new_size = 0; // set the optimization process to OFF $optimize = false; // toggle the convert process to ON $convert = true; // allow other plugins to mangle the image however they like prior to optimization do_action('ewww_image_optimizer_pre_optimization', $file, $type); // run the appropriate optimization/conversion for the mime-type switch ($type) { case 'image/jpeg': $png_size = 0; // if jpg2png conversion is enabled, and this image is in the wordpress media library if (ewww_image_optimizer_get_option('ewww_image_optimizer_jpg_to_png') && $gallery_type == 1 || !empty($_GET['ewww_convert'])) { // generate the filename for a PNG // if this is a resize version if ($converted) { // just change the file extension $pngfile = preg_replace('/\\.\\w+$/', '.png', $file); // if this is a full size image } else { // get a unique filename for the png image list($pngfile, $filenum) = ewww_image_optimizer_unique_filename($file, '.png'); } } else { // otherwise, set it to OFF $convert = false; $pngfile = ''; } // check for previous optimization, so long as the force flag is on and this isn't a new image that needs converting if (empty($_REQUEST['ewww_force']) && !($new && $convert)) { if ($results_msg = ewww_image_optimizer_check_table($file, $orig_size)) { return array($file, $results_msg, $converted, $original); } } if (ewww_image_optimizer_get_option('ewww_image_optimizer_jpg_level') > 10) { list($file, $converted, $result, $new_size) = ewww_image_optimizer_cloud_optimizer($file, $type, $convert, $pngfile, 'image/png', $skip_lossy); if ($converted) { // check to see if the user wants the originals deleted if (ewww_image_optimizer_get_option('ewww_image_optimizer_delete_originals') == TRUE) { // delete the original JPG unlink($original); } $converted = $filenum; ewww_image_optimizer_webp_create($file, $new_size, 'image/png', null, $orig_size != $new_size); } else { ewww_image_optimizer_webp_create($file, $new_size, $type, null, $orig_size != $new_size); } break; } if ($convert) { $tools = ewww_image_optimizer_path_check(!$skip['jpegtran'], !$skip['optipng'], false, !$skip['pngout'], !$skip['pngquant'], !$skip['webp']); } else { $tools = ewww_image_optimizer_path_check(!$skip['jpegtran'], false, false, false, false, !$skip['webp']); } // if jpegtran optimization is disabled if (ewww_image_optimizer_get_option('ewww_image_optimizer_jpg_level') == 0) { // store an appropriate message in $result $result = __('JPG optimization is disabled', EWWW_IMAGE_OPTIMIZER_DOMAIN); // otherwise, if we aren't skipping the utility verification and jpegtran doesn't exist } elseif (!$skip['jpegtran'] && !$tools['JPEGTRAN']) { // store an appropriate message in $result $result = sprintf(__('%s is missing', EWWW_IMAGE_OPTIMIZER_DOMAIN), '<em>jpegtran</em>'); // otherwise, things should be good, so... } else { // set the optimization process to ON $optimize = true; } // if optimization is turned ON if ($optimize) { ewwwio_debug_message('attempting to optimize JPG...'); // generate temporary file-names: $tempfile = $file . ".tmp"; //non-progressive jpeg $progfile = $file . ".prog"; // progressive jpeg // check to see if we are supposed to strip metadata (badly named) if (ewww_image_optimizer_get_option('ewww_image_optimizer_jpegtran_copy') && !$keep_metadata) { // don't copy metadata $copy_opt = 'none'; } else { // copy all the metadata $copy_opt = 'all'; } // run jpegtran - non-progressive exec("{$nice} " . $tools['JPEGTRAN'] . " -copy {$copy_opt} -optimize -outfile " . ewww_image_optimizer_escapeshellarg($tempfile) . " " . ewww_image_optimizer_escapeshellarg($file)); // run jpegtran - progressive exec("{$nice} " . $tools['JPEGTRAN'] . " -copy {$copy_opt} -optimize -progressive -outfile " . ewww_image_optimizer_escapeshellarg($progfile) . " " . ewww_image_optimizer_escapeshellarg($file)); // check the filesize of the non-progressive JPG $non_size = ewww_image_optimizer_filesize($tempfile); // check the filesize of the progressive JPG $prog_size = ewww_image_optimizer_filesize($progfile); ewwwio_debug_message("optimized JPG (non-progresive) size: {$non_size}"); ewwwio_debug_message("optimized JPG (progresive) size: {$prog_size}"); if ($non_size === false || $prog_size === false) { $result = __('Unable to write file', EWWW_IMAGE_OPTIMIZER_DOMAIN); $new_size = 0; } elseif (!$non_size || !$prog_size) { $result = __('Optimization failed', EWWW_IMAGE_OPTIMIZER_DOMAIN); $new_size = 0; } else { // if the progressive file is bigger if ($prog_size > $non_size) { // store the size of the non-progessive JPG $new_size = $non_size; if (is_file($progfile)) { // delete the progressive file unlink($progfile); } // if the progressive file is smaller or the same } else { // store the size of the progressive JPG $new_size = $prog_size; // replace the non-progressive with the progressive file rename($progfile, $tempfile); } } ewwwio_debug_message("optimized JPG size: {$new_size}"); // if the best-optimized is smaller than the original JPG, and we didn't create an empty JPG if ($orig_size > $new_size && $new_size != 0 && ewww_image_optimizer_mimetype($tempfile, 'i') == $type) { // replace the original with the optimized file rename($tempfile, $file); // store the results of the optimization $result = "{$orig_size} vs. {$new_size}"; // if the optimization didn't produce a smaller JPG } else { if (is_file($tempfile)) { // delete the optimized file unlink($tempfile); } // store the results $result = 'unchanged'; $new_size = $orig_size; } // if conversion and optimization are both turned OFF, finish the JPG processing } elseif (!$convert) { ewww_image_optimizer_webp_create($file, $orig_size, $type, $tools['WEBP']); break; } // if the conversion process is turned ON, or if this is a resize and the full-size was converted if ($convert) { ewwwio_debug_message("attempting to convert JPG to PNG: {$pngfile}"); if (empty($new_size)) { $new_size = $orig_size; } // convert the JPG to PNG if (ewww_image_optimizer_gmagick_support()) { try { $gmagick = new Gmagick($file); $gmagick->stripimage(); $gmagick->setimageformat('PNG'); $gmagick->writeimage($pngfile); } catch (Exception $gmagick_error) { ewwwio_debug_message($gmagick_error->getMessage()); } $png_size = ewww_image_optimizer_filesize($pngfile); } if (!$png_size && ewww_image_optimizer_imagick_support()) { try { $imagick = new Imagick($file); $imagick->stripImage(); $imagick->setImageFormat('PNG'); $imagick->writeImage($pngfile); } catch (Exception $imagick_error) { ewwwio_debug_message($imagick_error->getMessage()); } $png_size = ewww_image_optimizer_filesize($pngfile); } if (!$png_size) { $convert_path = ''; // retrieve version info for ImageMagick if (PHP_OS != 'WINNT') { $convert_path = ewww_image_optimizer_find_nix_binary('convert', 'i'); } elseif (PHP_OS == 'WINNT') { $convert_path = ewww_image_optimizer_find_win_binary('convert', 'i'); } if (!empty($convert_path)) { ewwwio_debug_message('converting with ImageMagick'); exec($convert_path . " " . ewww_image_optimizer_escapeshellarg($file) . " -strip " . ewww_image_optimizer_escapeshellarg($pngfile)); $png_size = ewww_image_optimizer_filesize($pngfile); } } if (!$png_size && ewww_image_optimizer_gd_support()) { ewwwio_debug_message('converting with GD'); imagepng(imagecreatefromjpeg($file), $pngfile); $png_size = ewww_image_optimizer_filesize($pngfile); } // if lossy optimization is ON and full-size exclusion is not active if (ewww_image_optimizer_get_option('ewww_image_optimizer_png_level') == 40 && $tools['PNGQUANT'] && !$skip_lossy) { ewwwio_debug_message('attempting lossy reduction'); exec("{$nice} " . $tools['PNGQUANT'] . " " . ewww_image_optimizer_escapeshellarg($pngfile)); $quantfile = preg_replace('/\\.\\w+$/', '-fs8.png', $pngfile); if (is_file($quantfile) && filesize($pngfile) > filesize($quantfile)) { ewwwio_debug_message("lossy reduction is better: original - " . filesize($pngfile) . " vs. lossy - " . filesize($quantfile)); rename($quantfile, $pngfile); } elseif (is_file($quantfile)) { ewwwio_debug_message("lossy reduction is worse: original - " . filesize($pngfile) . " vs. lossy - " . filesize($quantfile)); unlink($quantfile); } else { ewwwio_debug_message('pngquant did not produce any output'); } } // if optipng isn't disabled if (!ewww_image_optimizer_get_option('ewww_image_optimizer_disable_optipng')) { // retrieve the optipng optimization level $optipng_level = (int) ewww_image_optimizer_get_option('ewww_image_optimizer_optipng_level'); if (ewww_image_optimizer_get_option('ewww_image_optimizer_jpegtran_copy') && preg_match('/0.7/', ewww_image_optimizer_tool_found($tools['OPTIPNG'], 'o')) && !$keep_metadata) { $strip = '-strip all '; } else { $strip = ''; } // if the PNG file was created if (file_exists($pngfile)) { ewwwio_debug_message('optimizing converted PNG with optipng'); // run optipng on the new PNG exec("{$nice} " . $tools['OPTIPNG'] . " -o{$optipng_level} -quiet {$strip} " . ewww_image_optimizer_escapeshellarg($pngfile)); } } // if pngout isn't disabled if (!ewww_image_optimizer_get_option('ewww_image_optimizer_disable_pngout')) { // retrieve the pngout optimization level $pngout_level = (int) ewww_image_optimizer_get_option('ewww_image_optimizer_pngout_level'); // if the PNG file was created if (file_exists($pngfile)) { ewwwio_debug_message('optimizing converted PNG with pngout'); // run pngout on the new PNG exec("{$nice} " . $tools['PNGOUT'] . " -s{$pngout_level} -q " . ewww_image_optimizer_escapeshellarg($pngfile)); } } $png_size = ewww_image_optimizer_filesize($pngfile); ewwwio_debug_message("converted PNG size: {$png_size}"); // if the PNG is smaller than the original JPG, and we didn't end up with an empty file if ($new_size > $png_size && $png_size != 0 && ewww_image_optimizer_mimetype($pngfile, 'i') == 'image/png') { ewwwio_debug_message("converted PNG is better: {$png_size} vs. {$new_size}"); // store the size of the converted PNG $new_size = $png_size; // check to see if the user wants the originals deleted if (ewww_image_optimizer_get_option('ewww_image_optimizer_delete_originals') == TRUE) { // delete the original JPG unlink($file); } // store the location of the PNG file $file = $pngfile; // let webp know what we're dealing with now $type = 'image/png'; // successful conversion and we store the increment $converted = $filenum; } else { ewwwio_debug_message('converted PNG is no good'); // otherwise delete the PNG $converted = FALSE; if (is_file($pngfile)) { unlink($pngfile); } } } ewww_image_optimizer_webp_create($file, $new_size, $type, $tools['WEBP'], $orig_size != $new_size); break; case 'image/png': $jpg_size = 0; // png2jpg conversion is turned on, and the image is in the wordpress media library if ((ewww_image_optimizer_get_option('ewww_image_optimizer_png_to_jpg') || !empty($_GET['ewww_convert'])) && $gallery_type == 1 && !$skip_lossy && (!ewww_image_optimizer_png_alpha($file) || ewww_image_optimizer_jpg_background())) { ewwwio_debug_message('PNG to JPG conversion turned on'); // if the user set a fill background for transparency $background = ''; if ($background = ewww_image_optimizer_jpg_background()) { // set background color for GD $r = hexdec('0x' . strtoupper(substr($background, 0, 2))); $g = hexdec('0x' . strtoupper(substr($background, 2, 2))); $b = hexdec('0x' . strtoupper(substr($background, 4, 2))); // set the background flag for 'convert' $background = "-background " . '"' . "#{$background}" . '"'; } else { $r = ''; $g = ''; $b = ''; } // if the user manually set the JPG quality if ($quality = ewww_image_optimizer_jpg_quality()) { // set the quality for GD $gquality = $quality; // set the quality flag for 'convert' $cquality = "-quality {$quality}"; } else { $cquality = ''; $gquality = '92'; } // if this is a resize version if ($converted) { // just replace the file extension with a .jpg $jpgfile = preg_replace('/\\.\\w+$/', '.jpg', $file); // if this is a full version } else { // construct the filename for the new JPG list($jpgfile, $filenum) = ewww_image_optimizer_unique_filename($file, '.jpg'); } } else { ewwwio_debug_message('PNG to JPG conversion turned off'); // turn the conversion process OFF $convert = false; $jpgfile = ''; $r = null; $g = null; $b = null; $gquality = null; } // check for previous optimization, so long as the force flag is on and this isn't a new image that needs converting if (empty($_REQUEST['ewww_force']) && !($new && $convert)) { if ($results_msg = ewww_image_optimizer_check_table($file, $orig_size)) { return array($file, $results_msg, $converted, $original); } } if (ewww_image_optimizer_get_option('ewww_image_optimizer_png_level') >= 20 && ewww_image_optimizer_get_option('ewww_image_optimizer_cloud_key')) { list($file, $converted, $result, $new_size) = ewww_image_optimizer_cloud_optimizer($file, $type, $convert, $jpgfile, 'image/jpeg', $skip_lossy, array('r' => $r, 'g' => $g, 'b' => $b, 'quality' => $gquality)); if ($converted) { // check to see if the user wants the originals deleted if (ewww_image_optimizer_get_option('ewww_image_optimizer_delete_originals') == TRUE) { // delete the original JPG unlink($original); } $converted = $filenum; ewww_image_optimizer_webp_create($file, $new_size, 'image/jpeg', null, $orig_size != $new_size); } else { ewww_image_optimizer_webp_create($file, $new_size, $type, null, $orig_size != $new_size); } break; } if ($convert) { $tools = ewww_image_optimizer_path_check(!$skip['jpegtran'], !$skip['optipng'], false, !$skip['pngout'], !$skip['pngquant'], !$skip['webp']); } else { $tools = ewww_image_optimizer_path_check(false, !$skip['optipng'], false, !$skip['pngout'], !$skip['pngquant'], !$skip['webp']); } // if pngout and optipng are disabled if (ewww_image_optimizer_get_option('ewww_image_optimizer_disable_optipng') && ewww_image_optimizer_get_option('ewww_image_optimizer_disable_pngout') || ewww_image_optimizer_get_option('ewww_image_optimizer_png_level') == 0) { // tell the user all PNG tools are disabled $result = __('PNG optimization is disabled', EWWW_IMAGE_OPTIMIZER_DOMAIN); // if the utility checking is on, optipng is enabled, but optipng cannot be found } elseif (!$skip['optipng'] && !$tools['OPTIPNG']) { // tell the user optipng is missing $result = sprintf(__('%s is missing', EWWW_IMAGE_OPTIMIZER_DOMAIN), '<em>optipng</em>'); // if the utility checking is on, pngout is enabled, but pngout cannot be found } elseif (!$skip['pngout'] && !$tools['PNGOUT']) { // tell the user pngout is missing $result = sprintf(__('%s is missing', EWWW_IMAGE_OPTIMIZER_DOMAIN), '<em>pngout</em>'); } else { // turn optimization on if we made it through all the checks $optimize = true; } // if optimization is turned on if ($optimize) { // if lossy optimization is ON and full-size exclusion is not active if (ewww_image_optimizer_get_option('ewww_image_optimizer_png_level') == 40 && $tools['PNGQUANT'] && !$skip_lossy) { ewwwio_debug_message('attempting lossy reduction'); exec("{$nice} " . $tools['PNGQUANT'] . " " . ewww_image_optimizer_escapeshellarg($file)); $quantfile = preg_replace('/\\.\\w+$/', '-fs8.png', $file); if (is_file($quantfile) && filesize($file) > filesize($quantfile) && ewww_image_optimizer_mimetype($quantfile, 'i') == $type) { ewwwio_debug_message("lossy reduction is better: original - " . filesize($file) . " vs. lossy - " . filesize($quantfile)); rename($quantfile, $file); } elseif (is_file($quantfile)) { ewwwio_debug_message("lossy reduction is worse: original - " . filesize($file) . " vs. lossy - " . filesize($quantfile)); unlink($quantfile); } else { ewwwio_debug_message('pngquant did not produce any output'); } } $tempfile = $file . '.tmp.png'; copy($file, $tempfile); // if optipng is enabled if (!ewww_image_optimizer_get_option('ewww_image_optimizer_disable_optipng')) { // retrieve the optimization level for optipng $optipng_level = (int) ewww_image_optimizer_get_option('ewww_image_optimizer_optipng_level'); if (ewww_image_optimizer_get_option('ewww_image_optimizer_jpegtran_copy') && preg_match('/0.7/', ewww_image_optimizer_tool_found($tools['OPTIPNG'], 'o')) && !$keep_metadata) { $strip = '-strip all '; } else { $strip = ''; } // run optipng on the PNG file exec("{$nice} " . $tools['OPTIPNG'] . " -o{$optipng_level} -quiet {$strip} " . ewww_image_optimizer_escapeshellarg($tempfile)); } // if pngout is enabled if (!ewww_image_optimizer_get_option('ewww_image_optimizer_disable_pngout')) { // retrieve the optimization level for pngout $pngout_level = (int) ewww_image_optimizer_get_option('ewww_image_optimizer_pngout_level'); // run pngout on the PNG file exec("{$nice} " . $tools['PNGOUT'] . " -s{$pngout_level} -q " . ewww_image_optimizer_escapeshellarg($tempfile)); } // retrieve the filesize of the temporary PNG $new_size = ewww_image_optimizer_filesize($tempfile); // if the new PNG is smaller if ($orig_size > $new_size && $new_size != 0 && ewww_image_optimizer_mimetype($tempfile, 'i') == $type) { // replace the original with the optimized file rename($tempfile, $file); // store the results of the optimization $result = "{$orig_size} vs. {$new_size}"; // if the optimization didn't produce a smaller PNG } else { if (is_file($tempfile)) { // delete the optimized file unlink($tempfile); } // store the results $result = 'unchanged'; $new_size = $orig_size; } // if conversion and optimization are both disabled we are done here } elseif (!$convert) { ewwwio_debug_message('calling webp, but neither convert or optimize'); ewww_image_optimizer_webp_create($file, $orig_size, $type, $tools['WEBP']); break; } // retrieve the new filesize of the PNG $new_size = ewww_image_optimizer_filesize($file); // if conversion is on and the PNG doesn't have transparency or the user set a background color to replace transparency //if ( $convert && ( ! ewww_image_optimizer_png_alpha( $file ) || ewww_image_optimizer_jpg_background() ) ) { if ($convert) { ewwwio_debug_message("attempting to convert PNG to JPG: {$jpgfile}"); if (empty($new_size)) { $new_size = $orig_size; } $magick_background = ewww_image_optimizer_jpg_background(); if (empty($magick_background)) { $magick_background = '000000'; } // convert the PNG to a JPG with all the proper options if (ewww_image_optimizer_gmagick_support()) { try { if (ewww_image_optimizer_png_alpha($file)) { $gmagick_overlay = new Gmagick($file); $gmagick = new Gmagick(); $gmagick->newimage($gmagick_overlay->getimagewidth(), $gmagick_overlay->getimageheight(), '#' . $magick_background); $gmagick->compositeimage($gmagick_overlay, 1, 0, 0); } else { $gmagick = new Gmagick($file); } $gmagick->setimageformat('JPG'); $gmagick->setcompressionquality($gquality); $gmagick->writeimage($jpgfile); } catch (Exception $gmagick_error) { ewwwio_debug_message($gmagick_error->getMessage()); } $jpg_size = ewww_image_optimizer_filesize($jpgfile); } if (!$jpg_size && ewww_image_optimizer_imagick_support()) { try { $imagick = new Imagick($file); if (ewww_image_optimizer_png_alpha($file)) { $imagick->setImageBackgroundColor(new ImagickPixel('#' . $magick_background)); $imagick->setImageAlphaChannel(11); } $imagick->setImageFormat('JPG'); $imagick->setCompressionQuality($gquality); $imagick->writeImage($jpgfile); } catch (Exception $imagick_error) { ewwwio_debug_message($imagick_error->getMessage()); } $jpg_size = ewww_image_optimizer_filesize($jpgfile); } if (!$jpg_size) { // retrieve version info for ImageMagick $convert_path = ewww_image_optimizer_find_nix_binary('convert', 'i'); if (!empty($convert_path)) { ewwwio_debug_message('converting with ImageMagick'); ewwwio_debug_message("using command: {$convert_path} {$background} -alpha remove {$cquality} {$file} {$jpgfile}"); exec("{$convert_path} {$background} -alpha remove {$cquality} " . ewww_image_optimizer_escapeshellarg($file) . " " . ewww_image_optimizer_escapeshellarg($jpgfile)); $jpg_size = ewww_image_optimizer_filesize($jpgfile); } } if (!$jpg_size && ewww_image_optimizer_gd_support()) { ewwwio_debug_message('converting with GD'); // retrieve the data from the PNG $input = imagecreatefrompng($file); // retrieve the dimensions of the PNG list($width, $height) = getimagesize($file); // create a new image with those dimensions $output = imagecreatetruecolor($width, $height); if ($r === '') { $r = 255; $g = 255; $b = 255; } // allocate the background color $rgb = imagecolorallocate($output, $r, $g, $b); // fill the new image with the background color imagefilledrectangle($output, 0, 0, $width, $height, $rgb); // copy the original image to the new image imagecopy($output, $input, 0, 0, 0, 0, $width, $height); // output the JPG with the quality setting imagejpeg($output, $jpgfile, $gquality); } $jpg_size = ewww_image_optimizer_filesize($jpgfile); if ($jpg_size) { ewwwio_debug_message("converted JPG filesize: {$jpg_size}"); } else { ewwwio_debug_message('unable to convert to JPG'); } // next we need to optimize that JPG if jpegtran is enabled if (ewww_image_optimizer_get_option('ewww_image_optimizer_jpg_level') == 10 && file_exists($jpgfile)) { // generate temporary file-names: $tempfile = $jpgfile . ".tmp"; //non-progressive jpeg $progfile = $jpgfile . ".prog"; // progressive jpeg // check to see if we are supposed to strip metadata (badly named) if (ewww_image_optimizer_get_option('ewww_image_optimizer_jpegtran_copy') && !$keep_metadata) { // don't copy metadata $copy_opt = 'none'; } else { // copy all the metadata $copy_opt = 'all'; } // run jpegtran - non-progressive exec("{$nice} " . $tools['JPEGTRAN'] . " -copy {$copy_opt} -optimize -outfile " . ewww_image_optimizer_escapeshellarg($tempfile) . " " . ewww_image_optimizer_escapeshellarg($jpgfile)); // run jpegtran - progressive exec("{$nice} " . $tools['JPEGTRAN'] . " -copy {$copy_opt} -optimize -progressive -outfile " . ewww_image_optimizer_escapeshellarg($progfile) . " " . ewww_image_optimizer_escapeshellarg($jpgfile)); // check the filesize of the non-progressive JPG $non_size = ewww_image_optimizer_filesize($tempfile); ewwwio_debug_message("non-progressive JPG filesize: {$non_size}"); // check the filesize of the progressive JPG $prog_size = ewww_image_optimizer_filesize($progfile); ewwwio_debug_message("progressive JPG filesize: {$prog_size}"); // if the progressive file is bigger if ($prog_size > $non_size) { // store the size of the non-progessive JPG $opt_jpg_size = $non_size; if (is_file($progfile)) { // delete the progressive file unlink($progfile); } ewwwio_debug_message('keeping non-progressive JPG'); // if the progressive file is smaller or the same } else { // store the size of the progressive JPG $opt_jpg_size = $prog_size; // replace the non-progressive with the progressive file rename($progfile, $tempfile); ewwwio_debug_message('keeping progressive JPG'); } // if the best-optimized is smaller than the original JPG, and we didn't create an empty JPG if ($jpg_size > $opt_jpg_size && $opt_jpg_size != 0) { // replace the original with the optimized file rename($tempfile, $jpgfile); // store the size of the optimized JPG $jpg_size = $opt_jpg_size; ewwwio_debug_message('optimized JPG was smaller than un-optimized version'); // if the optimization didn't produce a smaller JPG } elseif (is_file($tempfile)) { // delete the optimized file unlink($tempfile); } } ewwwio_debug_message("converted JPG size: {$jpg_size}"); // if the new JPG is smaller than the original PNG if ($new_size > $jpg_size && $jpg_size != 0 && ewww_image_optimizer_mimetype($jpgfile, 'i') == 'image/jpeg') { // store the size of the JPG as the new filesize $new_size = $jpg_size; // if the user wants originals delted after a conversion if (ewww_image_optimizer_get_option('ewww_image_optimizer_delete_originals') == TRUE) { // delete the original PNG unlink($file); } // update the $file location to the new JPG $file = $jpgfile; // let webp know what we're dealing with now $type = 'image/jpeg'; // successful conversion, so we store the increment $converted = $filenum; } else { $converted = FALSE; if (is_file($jpgfile)) { // otherwise delete the new JPG unlink($jpgfile); } } } ewww_image_optimizer_webp_create($file, $new_size, $type, $tools['WEBP'], $orig_size != $new_size); break; case 'image/gif': // if gif2png is turned on, and the image is in the wordpress media library if ((ewww_image_optimizer_get_option('ewww_image_optimizer_gif_to_png') || !empty($_GET['ewww_convert'])) && $gallery_type == 1 && !ewww_image_optimizer_is_animated($file)) { // generate the filename for a PNG // if this is a resize version if ($converted) { // just change the file extension $pngfile = preg_replace('/\\.\\w+$/', '.png', $file); // if this is the full version } else { // construct the filename for the new PNG list($pngfile, $filenum) = ewww_image_optimizer_unique_filename($file, '.png'); } } else { // turn conversion OFF $convert = false; $pngfile = ''; } // check for previous optimization, so long as the force flag is on and this isn't a new image that needs converting if (empty($_REQUEST['ewww_force']) && !($new && $convert)) { if ($results_msg = ewww_image_optimizer_check_table($file, $orig_size)) { return array($file, $results_msg, $converted, $original); } } if (ewww_image_optimizer_get_option('ewww_image_optimizer_cloud_key') && ewww_image_optimizer_get_option('ewww_image_optimizer_gif_level') == 10) { list($file, $converted, $result, $new_size) = ewww_image_optimizer_cloud_optimizer($file, $type, $convert, $pngfile, 'image/png', $skip_lossy); if ($converted) { // check to see if the user wants the originals deleted if (ewww_image_optimizer_get_option('ewww_image_optimizer_delete_originals') == TRUE) { // delete the original JPG unlink($original); } $converted = $filenum; ewww_image_optimizer_webp_create($file, $new_size, 'image/png', null, $orig_size != $new_size); } break; } if ($convert) { $tools = ewww_image_optimizer_path_check(false, !$skip['optipng'], !$skip['gifsicle'], !$skip['pngout'], !$skip['pngquant'], !$skip['webp']); } else { $tools = ewww_image_optimizer_path_check(false, false, !$skip['gifsicle'], false, false, false); } // if gifsicle is disabled if (ewww_image_optimizer_get_option('ewww_image_optimizer_gif_level') == 0) { // return an appropriate message $result = __('GIF optimization is disabled', EWWW_IMAGE_OPTIMIZER_DOMAIN); // if utility checking is on, and gifsicle is not installed } elseif (!$skip['gifsicle'] && !$tools['GIFSICLE']) { // return an appropriate message $result = sprintf(__('%s is missing', EWWW_IMAGE_OPTIMIZER_DOMAIN), '<em>gifsicle</em>'); } else { // otherwise, turn optimization ON $optimize = true; } // if optimization is turned ON if ($optimize) { $tempfile = $file . '.tmp'; //temporary GIF output // run gifsicle on the GIF exec("{$nice} " . $tools['GIFSICLE'] . " -O3 --careful -o {$tempfile} " . ewww_image_optimizer_escapeshellarg($file)); // retrieve the filesize of the temporary GIF $new_size = ewww_image_optimizer_filesize($tempfile); // if the new GIF is smaller if ($orig_size > $new_size && $new_size != 0 && ewww_image_optimizer_mimetype($tempfile, 'i') == $type) { // replace the original with the optimized file rename($tempfile, $file); // store the results of the optimization $result = "{$orig_size} vs. {$new_size}"; // if the optimization didn't produce a smaller GIF } else { if (is_file($tempfile)) { // delete the optimized file unlink($tempfile); } // store the results $result = 'unchanged'; $new_size = $orig_size; } // if conversion and optimization are both turned OFF, we are done here } elseif (!$convert) { break; } // get the new filesize for the GIF $new_size = ewww_image_optimizer_filesize($file); // if conversion is ON and the GIF isn't animated if ($convert && !ewww_image_optimizer_is_animated($file)) { if (empty($new_size)) { $new_size = $orig_size; } // if optipng is enabled if (!ewww_image_optimizer_get_option('ewww_image_optimizer_disable_optipng') && $tools['OPTIPNG']) { // retrieve the optipng optimization level $optipng_level = (int) ewww_image_optimizer_get_option('ewww_image_optimizer_optipng_level'); if (ewww_image_optimizer_get_option('ewww_image_optimizer_jpegtran_copy') && preg_match('/0.7/', ewww_image_optimizer_tool_found($tools['OPTIPNG'], 'o')) && !$keep_metadata) { $strip = '-strip all '; } else { $strip = ''; } // run optipng on the GIF file exec("{$nice} " . $tools['OPTIPNG'] . " -out " . ewww_image_optimizer_escapeshellarg($pngfile) . " -o{$optipng_level} -quiet {$strip} " . ewww_image_optimizer_escapeshellarg($file)); } // if pngout is enabled if (!ewww_image_optimizer_get_option('ewww_image_optimizer_disable_pngout') && $tools['PNGOUT']) { // retrieve the pngout optimization level $pngout_level = (int) ewww_image_optimizer_get_option('ewww_image_optimizer_pngout_level'); // if $pngfile exists (which means optipng was run already) if (file_exists($pngfile)) { // run pngout on the PNG file exec("{$nice} " . $tools['PNGOUT'] . " -s{$pngout_level} -q " . ewww_image_optimizer_escapeshellarg($pngfile)); } else { // run pngout on the GIF file exec("{$nice} " . $tools['PNGOUT'] . " -s{$pngout_level} -q " . ewww_image_optimizer_escapeshellarg($file) . " " . ewww_image_optimizer_escapeshellarg($pngfile)); } } // retrieve the filesize of the PNG $png_size = ewww_image_optimizer_filesize($pngfile); // if the new PNG is smaller than the original GIF if ($new_size > $png_size && $png_size != 0 && ewww_image_optimizer_mimetype($pngfile, 'i') == 'image/png') { // store the PNG size as the new filesize $new_size = $png_size; // if the user wants original GIFs deleted after successful conversion if (ewww_image_optimizer_get_option('ewww_image_optimizer_delete_originals') == TRUE) { // delete the original GIF unlink($file); } // update the $file location with the new PNG $file = $pngfile; // let webp know what we're dealing with now $type = 'image/png'; // normally this would be at the end of the section, but we only want to do webp if the image was successfully converted to a png ewww_image_optimizer_webp_create($file, $new_size, $type, $tools['WEBP'], $orig_size != $new_size); // successful conversion (for now), so we store the increment $converted = $filenum; } else { $converted = FALSE; if (is_file($pngfile)) { unlink($pngfile); } } } break; case 'application/pdf': if (empty($_REQUEST['ewww_force'])) { if ($results_msg = ewww_image_optimizer_check_table($file, $orig_size)) { return array($file, $results_msg, false, $original); } } if (ewww_image_optimizer_get_option('ewww_image_optimizer_pdf_level') > 0) { list($file, $converted, $result, $new_size) = ewww_image_optimizer_cloud_optimizer($file, $type); } break; default: // if not a JPG, PNG, or GIF, tell the user we don't work with strangers return array($file, __('Unknown type: ' . $type, EWWW_IMAGE_OPTIMIZER_DOMAIN), $converted, $original); } // allow other plugins to run operations on the images after optimization. // NOTE: it is recommended to do any image modifications prior to optimization, otherwise you risk un-optimizing your images here. do_action('ewww_image_optimizer_post_optimization', $file, $type); // if their cloud api license limit has been exceeded if ($result == 'exceeded') { return array($file, __('License exceeded', EWWW_IMAGE_OPTIMIZER_DOMAIN), $converted, $original); } if (!empty($new_size)) { // Set correct file permissions $stat = stat(dirname($file)); $perms = $stat['mode'] & 0666; //same permissions as parent folder, strip off the executable bits @chmod($file, $perms); $results_msg = ewww_image_optimizer_update_table($file, $new_size, $orig_size, $new); ewwwio_memory(__FUNCTION__); return array($file, $results_msg, $converted, $original); } ewwwio_memory(__FUNCTION__); // otherwise, send back the filename, the results (some sort of error message), the $converted flag, and the name of the original image return array($file, $result, $converted, $original); }
/** * Fill the image background. * @param integer $r * @param integer $g * @param integer $b * @param integer $opacity */ protected function _background($r, $g, $b, $opacity) { $background = new \Imagick(); $background->newImage($this->width, $this->height, new \ImagickPixel(sprintf('rgb(%d, %d, %d)', $r, $g, $b))); if (!$background->getImageAlphaChannel()) { $background->setImageAlphaChannel(\Imagick::ALPHACHANNEL_SET); } $background->setImageBackgroundColor(new \ImagickPixel('transparent')); $background->evaluateImage(\Imagick::EVALUATE_MULTIPLY, $opacity / 100, \Imagick::CHANNEL_ALPHA); $background->setColorspace($this->im->getColorspace()); if ($background->compositeImage($this->im, \Imagick::COMPOSITE_DISSOLVE, 0, 0)) { $this->im = $background; } }
protected function _do_reflection($height, $opacity, $fade_in) { // Clone the current image and flip it for reflection $reflection = $this->im->clone(); $reflection->flipImage(); // Crop the reflection to the selected height $reflection->cropImage($this->width, $height, 0, 0); $reflection->setImagePage($this->width, $height, 0, 0); // Select the fade direction $direction = array('transparent', 'black'); if ($fade_in) { // Change the direction of the fade $direction = array_reverse($direction); } // Create a gradient for fading $fade = new Imagick(); $fade->newPseudoImage($reflection->getImageWidth(), $reflection->getImageHeight(), vsprintf('gradient:%s-%s', $direction)); // Apply the fade alpha channel to the reflection $reflection->compositeImage($fade, Imagick::COMPOSITE_DSTOUT, 0, 0); // NOTE: Using setImageOpacity will destroy alpha channels! $reflection->evaluateImage(Imagick::EVALUATE_MULTIPLY, $opacity / 100, Imagick::CHANNEL_ALPHA); // Create a new container to hold the image and reflection $image = new Imagick(); $image->newImage($this->width, $this->height + $height, new ImagickPixel()); // Force the image to have an alpha channel $image->setImageAlphaChannel(Imagick::ALPHACHANNEL_SET); // Force the background color to be transparent // $image->setImageBackgroundColor(new ImagickPixel('transparent')); // Match the colorspace between the two images before compositing $image->setColorspace($this->im->getColorspace()); // Place the image and reflection into the container if ($image->compositeImage($this->im, Imagick::COMPOSITE_SRC, 0, 0) and $image->compositeImage($reflection, Imagick::COMPOSITE_OVER, 0, $this->height)) { // Replace the current image with the reflected image $this->im = $image; // Reset the width and height $this->width = $this->im->getImageWidth(); $this->height = $this->im->getImageHeight(); return TRUE; } return FALSE; }
private function _mergeSingleImg($margedImagePath) { switch ($this->imageProcessLib) { case 'gd': $watermarkInfo = getimagesize($this->watermarkPath); if ($watermarkInfo["mime"] == "image/png") { $watermark = imagecreatefrompng($this->watermarkPath); } else { $watermark = imagecreatefromjpeg($this->watermarkPath); } $imageInfo = getimagesize($this->imagePath); if ($imageInfo["mime"] == "image/png") { $image = imagecreatefrompng($this->imagePath); } else { $image = imagecreatefromjpeg($this->imagePath); } imagesavealpha($image, true); imagesavealpha($watermark, true); imagealphablending($image, false); imagealphablending($watermark, false); if ($watermarkInfo[0] > $imageInfo[0] || $watermarkInfo[1] > $imageInfo[1]) { $kWidth = $watermarkInfo[0] / $imageInfo[0]; $kHeight = $watermarkInfo[0] / $imageInfo[0]; if ($kWidth > $kHeight) { // Масштабируем по ширине $watermarkInfo[0] = $watermarkInfo[0] / $kWidth; $watermarkInfo[1] = $watermarkInfo[1] / $kWidth; } else { // Масштабируем по высоте $watermarkInfo[0] = $watermarkInfo[0] / $kHeight; $watermarkInfo[1] = $watermarkInfo[1] / $kHeight; } imagecopyresampled($watermark, $watermark, 0, 0, 0, 0, $watermarkInfo[0], $watermarkInfo[1], imagesx($watermark), imagesy($watermark)); } imagecopy($image, $watermark, $this->watermarkOfsetX, $this->watermarkOfsetY, 0, 0, $watermarkInfo[0], $watermarkInfo[1]); if ($imageInfo["mime"] == "image/png") { imagepng($image, $margedImagePath); } else { imagejpeg($image, $margedImagePath); } imagedestroy($image); imagedestroy($watermark); break; case 'imagick': $image = new Imagick(); $image->readImage($this->imagePath); $watermark = new Imagick(); $watermark->readImage($this->watermarkPath); if (!$watermark->getImageAlphaChannel()) { $watermark->setImageAlphaChannel(1); } if ($watermark->getImageWidth() > $image->getImageWidth() || $watermark->getImageHeight() > $image->getImageHeight()) { $kWidth = $watermark->getImageWidth() / $image->getImageWidth(); $kHeight = $watermark->getImageHeight() / $image->getImageHeight(); if ($kWidth > $kHeight) { // Масштабируем по ширине $watermark->scaleImage($watermark->getImageWidth() / $kWidth, $watermark->getImageHeight() / $kWidth); } else { // Масштабируем по высоте $watermark->scaleImage($watermark->getImageWidth() / $kHeight, $watermark->getImageHeight() / $kHeight); } } $watermark->evaluateImage(Imagick::EVALUATE_MULTIPLY, $this->watermarkTransparency, Imagick::CHANNEL_ALPHA); $image->compositeImage($watermark, imagick::COMPOSITE_OVER, $this->watermarkOfsetX, $this->watermarkOfsetY); $image->writeImage($margedImagePath); break; default: echo json_encode(array('status' => 'error', 'errorId' => '1-6', 'errorText' => 'An invalid image processing library'), JSON_FORCE_OBJECT); exit; break; } return true; }
/** * @desc Create a thumbnail of the picture and save it * @param $size The size requested */ private function createThumbnail($width, $height = false, $format = 'jpeg') { if (!in_array($format, array_keys($this->_formats))) { $format = 'jpeg'; } if (!$height) { $height = $width; } $path = $this->_path . md5($this->_key) . '_' . $width . $this->_formats[$format]; $im = new Imagick(); try { $im->readImageBlob($this->_bin); $im->setImageFormat($format); if ($format == 'jpeg') { $im->setImageCompression(Imagick::COMPRESSION_JPEG); $im->setImageAlphaChannel(11); // Put 11 as a value for now, see http://php.net/manual/en/imagick.flattenimages.php#116956 //$im->setImageAlphaChannel(Imagick::ALPHACHANNEL_REMOVE); $im->setImageBackgroundColor('#ffffff'); $im = $im->mergeImageLayers(Imagick::LAYERMETHOD_FLATTEN); } //$crop = new CropEntropy; //$crop->setImage($im); $geo = $im->getImageGeometry(); $im->cropThumbnailImage($width, $height); if ($width > $geo['width']) { $factor = floor($width / $geo['width']); $im->blurImage($factor, 10); } //$im = $crop->resizeAndCrop($width, $height); $im->setImageCompressionQuality(85); $im->setInterlaceScheme(Imagick::INTERLACE_PLANE); $im->writeImage($path); $im->clear(); } catch (ImagickException $e) { error_log($e->getMessage()); } }
protected function _background($r, $g, $b, $opacity) { $color = sprintf("rgb(%d, %d, %d)", $r, $g, $b); $pixel1 = new \ImagickPixel($color); $opacity = $opacity / 100; $pixel2 = new \ImagickPixel("transparent"); $background = new \Imagick(); $this->_image->setIteratorIndex(0); while (true) { $background->newImage($this->_width, $this->_height, $pixel1); if (!$background->getImageAlphaChannel()) { $background->setImageAlphaChannel(constant("Imagick::ALPHACHANNEL_SET")); } $background->setImageBackgroundColor($pixel2); $background->evaluateImage(constant("Imagick::EVALUATE_MULTIPLY"), $opacity, constant("Imagick::CHANNEL_ALPHA")); $background->setColorspace($this->_image->getColorspace()); $background->compositeImage($this->_image, constant("Imagick::COMPOSITE_DISSOLVE"), 0, 0); if (!$this->_image->nextImage()) { break; } } $this->_image->clear(); $this->_image->destroy(); $this->_image = $background; }
echo 'Error: Format not supported. Supported format: dds, jpeg, png, bmp.'; exit; } /*if ($icon_width > 200 or $icon_height > 200) { echo 'Error: The size of your picture is too big. Should be under 200*200'; exit; }*/ if ($icon_width < 150 or $icon_height < 150) { echo 'Error: The size of your picture is too small. Should be above 150*150'; exit; } if ($icon_format != 'PNG') { $icon->setImageFormat('png'); } $icon->setImageAlphaChannel(Imagick::ALPHACHANNEL_ACTIVATE); // Resizing if ($icon_width != $icon_height) { $min = min($icon_width, $icon_height); $icon->resizeImage($min, $min, Imagick::FILTER_BOX, 1, true); $icon_width = $icon->getImageWidth(); $icon_height = $icon->getImageHeight(); } $wanted_size = 176; $icon->resizeImage($wanted_size, $wanted_size, Imagick::FILTER_BOX, 1); $iterator = $icon->getPixelIterator(); foreach ($iterator as $row => $pixels) { foreach ($pixels as $col => $pixel) { $color = $pixel->getColor(); // values are 0-255 $alpha = $pixel->getColor(true);
break; } $image->setImageFormat('jpeg'); $image->setImageCompression(Imagick::COMPRESSION_JPEG); $image->setImageCompressionQuality($cq); } else { $image->setImageFormat('png'); $compress[] = $file; } if (isset($size[SPLASH_ROTATE])) { $image->rotateImage(new ImagickPixel('none'), $size[SPLASH_ROTATE]); } $image->cropThumbnailImage($size[SPLASH_WIDTH], $size[SPLASH_HEIGHT]); $image->setImageResolution($size[SPLASH_DPI], $size[SPLASH_DPI]); $image->setImageUnits(imagick::RESOLUTION_PIXELSPERINCH); $image->setImageAlphaChannel(11); $image->writeImage($file); } } if ($_POST['compression'] && count($compress) > 0) { switch ($_POST['compression']) { case 'low': $o = 1; break; case 'medium': $o = 2; break; case 'high': $o = 3; break; }
function online($db) { $db->exec(<<<'EOS' -- CREATE TABLE `document` ( id INTEGER PRIMARY KEY, slug CHAR(128) NOT NULL UNIQUE, titre CHAR(128) NOT NULL, description TEXT NULL, auteur CHAR(512) NULL, suffixe CHAR(8), date DATETIME ); INSERT INTO document (slug, titre, suffixe, date) SELECT id, titre, suffixe, date FROM documents ORDER BY ROWID; DROP TABLE documents; CREATE TABLE `unite_document` ( id INTEGER PRIMARY KEY, unite INTEGER NOT NULL REFERENCES unite(id), document INTEGER NOT NULL REFERENCES document(id), UNIQUE (unite, document) ); INSERT INTO `unite_document` (document, unite) SELECT document.id, unite.id FROM doc_unite JOIN document ON document.slug = doc_unite.document JOIN unite ON unite.slug = doc_unite.unite; DROP TABLE doc_unite; CREATE VIEW vdocuments AS SELECT document.id, unite.slug, document.slug, document.suffixe FROM document JOIN unite_document ON unite_document.document = document.id JOIN unite ON unite.id = unite_document.unite ORDER BY document.date; ALTER TABLE activite_document RENAME TO tmp; CREATE TABLE `activite_document` ( id INTEGER PRIMARY KEY, activite INTEGER NOT NULL REFERENCES activite(id), document INTEGER NOT NULL REFERENCES document(id), UNIQUE (activite, document) ); INSERT INTO activite_document (activite, document) SELECT tmp.activite, document.id FROM tmp JOIN document ON document.slug = document; DROP TABLE tmp; CREATE VIEW vpiecesjointes AS SELECT document.id, activite.slug, document.slug, document.suffixe FROM document JOIN activite_document ON activite_document.document = document.id JOIN activite ON activite.id = activite_document.activite ORDER BY activite.debut; EOS ); error_log("Génération des vignettes des documents"); $stmt = $db->query("SELECT * FROM document"); foreach ($stmt as $row) { if ($row['suffixe'] != 'pdf') { continue; } $document = 'data/documents/' . $row['slug'] . '.' . $row['suffixe']; $vignette = 'data/documents/' . $row['slug'] . '-vignette.jpeg'; $im = new Imagick($document . '[0]'); $im->setImageAlphaChannel(Imagick::ALPHACHANNEL_RESET); $im->setImageFormat('jpg'); $im->setBackgroundColor('white'); $im->thumbnailImage(0, 256); $im->writeImage($vignette); } }
/** * Efficiently resize the current image * * This is a WordPress specific implementation of Imagick::thumbnailImage(), * which resizes an image to given dimensions and removes any associated profiles. * * @since 4.5.0 * @access protected * * @param int $dst_w The destination width. * @param int $dst_h The destination height. * @param string $filter_name Optional. The Imagick filter to use when resizing. Default 'FILTER_TRIANGLE'. * @param bool $strip_meta Optional. Strip all profiles, excluding color profiles, from the image. Default true. * @return bool|WP_Error */ protected function thumbnail_image($dst_w, $dst_h, $filter_name = 'FILTER_TRIANGLE', $strip_meta = true) { $allowed_filters = array('FILTER_POINT', 'FILTER_BOX', 'FILTER_TRIANGLE', 'FILTER_HERMITE', 'FILTER_HANNING', 'FILTER_HAMMING', 'FILTER_BLACKMAN', 'FILTER_GAUSSIAN', 'FILTER_QUADRATIC', 'FILTER_CUBIC', 'FILTER_CATROM', 'FILTER_MITCHELL', 'FILTER_LANCZOS', 'FILTER_BESSEL', 'FILTER_SINC'); /** * Set the filter value if '$filter_name' name is in our whitelist and the related * Imagick constant is defined or fall back to our default filter. */ if (in_array($filter_name, $allowed_filters) && defined('Imagick::' . $filter_name)) { $filter = constant('Imagick::' . $filter_name); } else { $filter = defined('Imagick::FILTER_TRIANGLE') ? Imagick::FILTER_TRIANGLE : false; } /** * Filters whether to strip metadata from images when they're resized. * * This filter only applies when resizing using the Imagick editor since GD * always strips profiles by default. * * @since 4.5.0 * * @param bool $strip_meta Whether to strip image metadata during resizing. Default true. */ if (apply_filters('image_strip_meta', $strip_meta)) { $this->strip_meta(); // Fail silently if not supported. } try { /* * To be more efficient, resample large images to 5x the destination size before resizing * whenever the output size is less that 1/3 of the original image size (1/3^2 ~= .111), * unless we would be resampling to a scale smaller than 128x128. */ if (is_callable(array($this->image, 'sampleImage'))) { $resize_ratio = $dst_w / $this->size['width'] * ($dst_h / $this->size['height']); $sample_factor = 5; if ($resize_ratio < 0.111 && ($dst_w * $sample_factor > 128 && $dst_h * $sample_factor > 128)) { $this->image->sampleImage($dst_w * $sample_factor, $dst_h * $sample_factor); } } /* * Use resizeImage() when it's available and a valid filter value is set. * Otherwise, fall back to the scaleImage() method for resizing, which * results in better image quality over resizeImage() with default filter * settings and retains backward compatibility with pre 4.5 functionality. */ if (is_callable(array($this->image, 'resizeImage')) && $filter) { $this->image->setOption('filter:support', '2.0'); $this->image->resizeImage($dst_w, $dst_h, $filter, 1); } else { $this->image->scaleImage($dst_w, $dst_h); } // Set appropriate quality settings after resizing. if ('image/jpeg' == $this->mime_type) { if (is_callable(array($this->image, 'unsharpMaskImage'))) { $this->image->unsharpMaskImage(0.25, 0.25, 8, 0.065); } $this->image->setOption('jpeg:fancy-upsampling', 'off'); } if ('image/png' === $this->mime_type) { $this->image->setOption('png:compression-filter', '5'); $this->image->setOption('png:compression-level', '9'); $this->image->setOption('png:compression-strategy', '1'); $this->image->setOption('png:exclude-chunk', 'all'); } /* * If alpha channel is not defined, set it opaque. * * Note that Imagick::getImageAlphaChannel() is only available if Imagick * has been compiled against ImageMagick version 6.4.0 or newer. */ if (is_callable(array($this->image, 'getImageAlphaChannel')) && is_callable(array($this->image, 'setImageAlphaChannel')) && defined('Imagick::ALPHACHANNEL_UNDEFINED') && defined('Imagick::ALPHACHANNEL_OPAQUE')) { if ($this->image->getImageAlphaChannel() === Imagick::ALPHACHANNEL_UNDEFINED) { $this->image->setImageAlphaChannel(Imagick::ALPHACHANNEL_OPAQUE); } } // Limit the bit depth of resized images to 8 bits per channel. if (is_callable(array($this->image, 'getImageDepth')) && is_callable(array($this->image, 'setImageDepth'))) { if (8 < $this->image->getImageDepth()) { $this->image->setImageDepth(8); } } if (is_callable(array($this->image, 'setInterlaceScheme')) && defined('Imagick::INTERLACE_NO')) { $this->image->setInterlaceScheme(Imagick::INTERLACE_NO); } } catch (Exception $e) { return new WP_Error('image_resize_error', $e->getMessage()); } }
/** * Convert a transparent PNG to JPG, with specified background color * * @param string $id Attachment ID * @param string $file File Path Original Image * @param string $meta Attachment Meta * @param string $size Image size. set to 'full' by default * * @return array Savings and Updated Meta */ function convert_tpng_to_jpg($id = '', $file = '', $meta = '', $size = 'full') { global $wpsmush_settings; $result = array('meta' => $meta, 'savings' => ''); //Flag: Whether the image was converted or not if ('full' == $size) { $result['converted'] = false; } //If any of the values is not set if (empty($id) || empty($file) || empty($meta)) { return $result; } //Get the File name without ext $n_file = pathinfo($file); if (empty($n_file['dirname']) || empty($n_file['filename'])) { return $result; } $n_file['filename'] = wp_unique_filename($n_file['dirname'], $n_file['filename'] . '.jpg'); //Updated File name $n_file = path_join($n_file['dirname'], $n_file['filename']); $transparent_png = $wpsmush_settings->get_setting(WP_SMUSH_PREFIX . 'transparent_png'); /** * Filter Background Color for Transparent PNGs */ $bg = apply_filters('wp_smush_bg', $transparent_png['background'], $id, $size); $quality = $this->get_quality($file); if ($this->supports_imagick()) { try { $imagick = new Imagick($file); $imagick->setImageBackgroundColor(new ImagickPixel('#' . $bg)); $imagick->setImageAlphaChannel(11); $imagick->setImageFormat('JPG'); $imagick->setCompressionQuality($quality); $imagick->writeImage($n_file); } catch (Exception $e) { error_log("WP Smush PNG to JPG Conversion error in " . __FILE__ . " at " . __LINE__ . " " . $e->getMessage()); return $result; } } else { //Use GD for conversion //Get data from PNG $input = imagecreatefrompng($file); //Width and Height of image list($width, $height) = getimagesize($file); //Create New image $output = imagecreatetruecolor($width, $height); // set background color for GD $r = hexdec('0x' . strtoupper(substr($bg, 0, 2))); $g = hexdec('0x' . strtoupper(substr($bg, 2, 2))); $b = hexdec('0x' . strtoupper(substr($bg, 4, 2))); //Set the Background color $rgb = imagecolorallocate($output, $r, $g, $b); //Fill Background imagefilledrectangle($output, 0, 0, $width, $height, $rgb); //Create New image imagecopy($output, $input, 0, 0, 0, 0, $width, $height); //Create JPG imagejpeg($output, $n_file, $quality); } //Replace file, and get savings $result = $this->replace_file($file, $result, $n_file); if (!empty($result['savings'])) { if ('full' == $size) { $result['converted'] = true; } //Update the File Details. and get updated meta $result['meta'] = $this->update_image_path($id, $file, $n_file, $meta, $size); /** * Perform a action after the image URL is updated in post content */ do_action('wp_smush_image_url_changed', $id, $file, $n_file, $size); } return $result; }
protected function _do_background($r, $g, $b, $opacity) { // Create a RGB color for the background $color = sprintf('rgb(%d, %d, %d)', $r, $g, $b); // Create a new image for the background $background = new Imagick(); $background->newImage($this->width, $this->height, new ImagickPixel($color)); if (!$background->getImageAlphaChannel()) { // Force the image to have an alpha channel $background->setImageAlphaChannel(Imagick::ALPHACHANNEL_SET); } // Clear the background image $background->setImageBackgroundColor(new ImagickPixel('transparent')); // NOTE: Using setImageOpacity will destroy current alpha channels! $background->evaluateImage(Imagick::EVALUATE_MULTIPLY, $opacity / 100, Imagick::CHANNEL_ALPHA); // Match the colorspace between the two images before compositing $background->setColorspace($this->im->getColorspace()); if ($background->compositeImage($this->im, Imagick::COMPOSITE_DISSOLVE, 0, 0)) { // Replace the current image with the new image $this->im = $background; return TRUE; } return FALSE; }
$save_image_link = 'imagick-crop-1920x1281-rotate-from-original-source.gif'; $save_result = $Imagick->writeImage($processed_images_fullpath . $save_image_link); $Imagick->clear(); var_dump($save_result); echo '<a href="' . $processed_images_folder . $save_image_link . '">rotated image</a>' . "\n"; echo '<hr>' . "\n\n"; // resize 6 (save to .png) $Imagick = new \Imagick(realpath($source_image_gif)); $Imagick->resizeImage($new_width1, $new_height1, \Imagick::FILTER_LANCZOS, 1); $Imagick->setImagePage(0, 0, 0, 0); // required to resize NON animated gif $save_image_link = 'imagick-resize-900x600-from-gif.png'; // convert transparency gif to white before save to another extension $Imagick->setImageBackgroundColor('white'); // convert from transparent to white. for GIF source $Imagick->setImageAlphaChannel(\Imagick::ALPHACHANNEL_REMOVE); // convert from transparent to white. for GIF source $Imagick = $Imagick->mergeImageLayers(\Imagick::LAYERMETHOD_FLATTEN); // convert from transparent to white. for GIF source // ----------------------------------------------------------------------------------------------- $save_result = $Imagick->writeImage($processed_images_fullpath . $save_image_link); var_dump($save_result); echo '<a href="' . $processed_images_folder . $save_image_link . '">resized image</a>' . "\n"; $image_data = getimagesize($processed_images_folder . $save_image_link); echo '<pre>' . print_r($image_data, true) . '</pre>'; echo '<hr>' . "\n\n"; // resize 7 (save to .jpg) $save_image_link = 'imagick-resize-900x600-from-gif.jpg'; // convert transparency gif to white before save to another extension $Imagick->setImageBackgroundColor('white'); // convert from transparent to white. for GIF source