Создать экскиз-превью по изображению в PHP – задача тривиальная, необходимо только воспользоваться встроенными функциями imagecopyresampled() и imagejpeg().
Однако есть две вещи, которые хочется улучшить в этом процессе:
Очень просто всё сделать становится с помощью этого класса:
/** * Пример использования: * <code> * $cover = new Cover("/images/cover.jpg"); * $img = $cover->getPreparedImage(); * imagejpeg($img, "/images/cover_preview.jpg", 96); * </code> * Либо сразу: * <code> * $cover = new Cover("/images/cover.jpg"); * $cover->prepareAndWrite("/images/cover_preview.jpg"); * </code> * * http://kremer.pro/ */ class Cover { /** * Сторона конечного изображения в пикселях по умолчанию. */ const PREVIEW_SIZE = 128; /** * Максимальный размер исходного изображения в пикселях * (Ограничение на работу с изображением). */ const MAX_ORIG_SIZE = 2000; const DEFAULT_JPEG_QUALITY = 92; private $size; /** * @param string $path путь к изображению * @param string $previewSize размер конечного изображения */ public function __construct($path, $previewSize = self::PREVIEW_SIZE) { $this->img = imagecreatefromjpeg($path); if (!$this->img) throw new Exception("Unable to create from jpeg"); $this->size = $previewSize; } public function __destruct() { imagedestroy($this->img); } /** * Шарпит изображение. */ private function sharpen() { $filter = array ( // стандартный вид шарп-матрицы array( 0, -1, 0), array(-1, 9, -1), array( 0, -1, 0), ); $divisor = array_sum(array_map('array_sum', $filter)); if (!imageconvolution($this->img, $filter, $divisor, 0)) throw new Exception("Unable to sharpen"); } /** * Создаёт незашарпленное квадратное превью. */ private function cropAndResize() { $img_preview = imagecreatetruecolor($this->size, $this->size); $width_orig = imagesx($this->img); $height_orig = imagesy($this->img); if ($width_orig <= self::PREVIEW_SIZE && $height_orig <= self::PREVIEW_SIZE) { // нет смысла растягивать, лучше сразу зашарпить маленькое return; } if ($width_orig > self::MAX_ORIG_SIZE || $height_orig > self::MAX_ORIG_SIZE) throw new Exception("Image too lagre to process it"); // генерируем квадратное изображение, обрезая либо полосы слева и справа, // либо серху и снизу: if ($width_orig > $height_orig) { $a = round(($width_orig - $height_orig)/2);//x координата, откуда режем if (!imagecopyresampled($img_preview, $this->img, 0, 0, $a, 0, $this->size, $this->size, $height_orig, $height_orig)) { throw new Exception("Unable to resample"); } } else { $a = round(($height_orig - $width_orig)/2);//y координата, откуда режем if (!imagecopyresampled ($img_preview, $this->img, 0, 0, 0, $a, $this->size, $this->size, $width_orig, $width_orig)) { throw new Exception("Unable to resample"); } } $this->img = $img_preview; // теперь в объекте уже превьюшка } /** * @return resource $img - сжатое и зашарпленное изображение. * Выбрасывает исключения в случаях, если обработать изображение не удалось. */ public function getPreparedImage() { $this->cropAndResize(); $this->sharpen(); return $this->img; } /** * Сразу делает превью и записывает его в файл. * Выбрасывает исключения в случаях, если обработать изображение не удалось. * После записи освобождает resource с изображением. */ public function prepareAndWrite($path, $q = self::DEFAULT_JPEG_QUALITY) { imagejpeg($this->getPreparedImage(), $path, $q); imagedestroy($this->img); } public function clear() { imagedestroy($this->img); } private $img; // resource изображение, с которым работаем }