#php #javascript #jquery
#php #JavaScript #jquery
Вопрос:
Как я могу автоматически обрезать изображение в процессе загрузки? Есть ли функция php для этого?
Я хочу, чтобы на моей веб-странице отображались изображения с одинаковым размером из разных размеров исходных изображений путем обрезки.
Или есть идеи?
Ответ №1:
Автоматическая обрезка была бы затруднена, если бы вы не знали, где находится объект. Может быть, вы можете попытаться получить внутренний прямоугольник с центром, как на картинке:
Первое, что нужно сделать, это найти исходные размеры изображения и тип файла. Вы не должны доверять расширению изображения и вместо этого использовать getimagesize
для этого. Несмотря на имя getimagesize
, возвращает не только размер, но и тип файла.
//width is at index 0, height at index 1, mime type at ['mime'] key
$original = getimagesize($filename);
Затем вы должны создать внутреннюю структуру данных PHP для хранения исходного изображения в памяти, чтобы вы могли манипулировать им, используя imagecreatefromjpeg
или imagecreatefrompng
или imagecreatefromgif
, в зависимости от типа изображения. Например:
$srcImage = imagecreatefromjpeg($filename);
Затем вы должны выделить другую структуру данных для хранения целевого изображения. В этом случае у нас нет изображения для начала, поэтому я выделяю пустое изображение.
$dstImage = imagecreatetruecolor($newWidth, $newHeight);
Далее вы должны скопировать часть исходного изображения в целевое изображение. Если вы не хотите изменять размер, используйте imagecopy
, в противном случае, если вы хотите обрезать и изменить размер, вы можете рассмотреть imagecopyresampled
.
imagecopy(dstImage, $srcImage, 0, 0, $srcX, $srcY, $srcW, $srcH);
Где $ srcX — начальная точка X в исходном изображении, $ srcY — начальная точка Y, $ srcW — ширина для копирования из начальной точки X, $ srcH — высота копируемой области.
Наконец, вы можете либо сохранить изображение с помощью:
imagejpeg($this->dstImage, $filename, 90);
или вы можете вывести его в браузер с помощью:
imagejpeg($this->dstImage);
Если вы сохраняете изображение, вам нужно подумать, в какой каталог его сохранить, если у вас много изображений (тысячи или больше), подумайте о том, как разделить их на несколько подкаталогов.
Если вы сохраняете исходное изображение, никогда не сохраняйте изображения с расширениями, которых нет в вашем списке разрешенных расширений, иначе это станет огромной дырой в безопасности, через которую злоумышленник может отправить и выполнить любой PHP-код на ваш сайт.
Основываясь на описанных концепциях, я написал небольшой класс:
class ImageCrop {
//Image resources
private $srcImage, $dstImage;
//original width and height
private $width, $height;
/**
* Read an image from disk.
* @return true in case of success, false otherwise.
*/
public function openImage($filename) {
if (!file_exists($filename)) {
return false;
}
$original = getimagesize($filename);
switch ($original['mime']) {
case 'image/jpeg':
$this->srcImage = imagecreatefromjpeg($filename);
break;
case 'image/png':
$this->srcImage = imagecreatefrompng($filename);
break;
case 'image/gif':
$this->srcImage = imagecreatefromgif($filename);
break;
default:
return false;
}
$this->width = $original[0];
$this->height = $original[1];
return true;
}
/**
* Crop an image to the new specified dimension trying to get an
* internal rectangle of the original image. No crop is done if the
* original dimension is already smaller than $newWidth or $newHeight.
*/
public function crop($newWidth, $newHeight) {
$this->dstImage = imagecreatetruecolor($newWidth, $newHeight);
$srcX = $srcY;
$srcW = $this->width;
$srcH = $this->height;
$extraWidth = $this->width - $newWidth;
if ($extraWidth > 0) {
$srcX = $extraWidth / 2;
}
$extraHeight = $this->height - $newHeight;
if ($extraHeight > 0) {
$srcY = $extraHeight / 2;
}
imagecopy($this->dstImage, $this->srcImage, 0, 0,
$srcX, $srcY, $srcW, $srcH);
}
/**
* Save the destination image, the crop function should have been
* called already.
*/
public function save($filename) {
imagejpeg($this->dstImage, $filename, 90);
}
/**
* Output the destination image to the browser.
*/
public function output() {
imagejpeg($this->dstImage);
}
}
Сохраните класс в ImageCrop.php , пример использования:
require_once 'ImageCrop.php';
$imageCrop = new ImageCrop();
if ($imageCrop->openImage('big.jpg')) {
$imageCrop->crop(200, 300); //newWidth, newHeight
$imageCrop->save('small.jpg');
}
или, чтобы отправить вывод непосредственно в браузер, используйте $imageCrop->output();
.
Комментарии:
1. Спасибо за редактирование моего поста, прошу прощения за мой плохой английский. 🙂 Нет, я не хочу изменять его размер, я просто хочу его обрезать. Поэтому, когда пользователь загружает изображение, размеры которого превышают разрешенные мной, оно будет обрезано автоматически. Не могли бы вы рассказать мне идею о «внутреннем прямоугольнике»? спасибо в расширенном.
2. Обновил свой пост, теперь я обрезаю внутренний прямоугольник с центром.
3. Хорошо, Стивло. Это кажется очень интересным, позвольте мне попробовать это на некоторое время. Я отправлю вам несколько ответов позже.
4. Привет, вот мое обещание. Стивло.. Хорошая работа! Я протестировал ваш класс, и он работает нормально. Спасибо большое. Ваш ответ очень хорош, потому что он сопровождается концепцией и прямой реализацией. Я проголосую за ваш ответ. 🙂
5. Я ценю ваш код stivlo и химию между вами, ребята, Philips Tel и stivlo … но единственная проблема, которую я вижу в этом коде, заключается в том, что вы должны указать ширину и высоту, чтобы обрезать реальное изображение, чтобы сгенерированное изображение могло быть искажено, в то время как мое вы должны указать максимальный размер (ширину или высоту), т.Е. Если вашконтейнер изображения имеет портретную ширину или, если он имеет альбомную форму, дает высоту. Вот и все…..
Ответ №2:
Скажите это как max_size.php
<?php header('Content-type: image/jpeg');
function resampleimage($maxsize, $sourcefile, $imgcomp=0){
$g_imgcomp=100-$imgcomp;
if(file_exists($sourcefile)){
$g_is=getimagesize($sourcefile);
if($g_is[0] <= $maxsize amp;amp; $g_is[1] <= $maxsize){
$new_width=$g_is[0];
$new_height=$g_is[1];
} else {
$w_adjust = ($maxsize / $g_is[0]);
$h_adjust = ($maxsize / $g_is[1]);
if($w_adjust <= $h_adjust){
$new_width=($g_is[0]*$w_adjust);
$new_height=($g_is[1]*$w_adjust);
} else {
$new_width=($g_is[0]*$h_adjust);
$new_height=($g_is[1]*$h_adjust);
}
}
$image_type = strtolower(strrchr($sourcefile, "."));
switch($image_type) {
case '.jpg':
$img_src = imagecreatefromjpeg($sourcefile);
break;
case '.jpeg':
$img_src = imagecreatefromjpeg($sourcefile);
break;
case '.png':
$img_src = imagecreatefrompng($sourcefile);
break;
case '.gif':
$img_src = imagecreatefromgif($sourcefile);
break;
default:
echo("Error Invalid Image Type");
die;
break;
}
$img_dst=imagecreatetruecolor($new_width,$new_height);
imagecopyresampled($img_dst, $img_src, 0, 0, 0, 0, $new_width, $new_height, $g_is[0], $g_is[1]);
imagejpeg($img_dst);
imagedestroy($img_dst);
return true;
} else {
return false;
}
}
resampleimage($_GET['maxsize'], $_GET['source']);
?>
На странице, где у вас есть изображение
<img id="img" src="max_size.php?maxsize=152amp;source=[some image path]" />
Комментарии:
1. Хм … Спасибо за быстрый ответ! Я думаю, что приведенный выше сценарий просто создает эскиз изображения с одинаковым размером как по высоте, так и по ширине. Тем не менее, это отличная идея. 🙂
2. Ваше первое утверждение верно. Он создает миниатюру правильно, но не одинаковой ширины и высоты.. Это похоже на то, что он создаст thumb, но в том же соотношении с источником только максимальный размер будет для ширины в альбомной ориентации, а в портретной — для высоты… Также вы хотели, чтобы что-то создавалось автоматически… Так или иначе, многие сценарии обрезки доступны для jquery, но не автоматические…
3. Большинство доступных сценариев обрезки, похоже, требуют, чтобы мы обрезали изображение вручную. Я думаю, что есть другие способы сделать это в «небе».