Intereting Posts
PHP: чтение config.ini для массива с файлом () Пользовательская команда IMAP в php Uncault Error: невозможно вызвать методы на странице до инициализации; попытался вызвать метод «bindRemove» Поиск пятна на изображении – математический способ? Каков наилучший способ защиты паролем папки / страницы с использованием php без db или имени пользователя utf8_ (en | de) код удален из php7? Многомерный массив PHP MYSQL Как я могу проверить покупку Google в приложении в php? Как шифровать / расшифровывать данные в php? Предупреждение: session_start () не удалось: нет такого файла или каталога «Неустранимая ошибка: класс не найден в ..», пакет композитора не распознан Стили не загружаются в пурпуре из-за неправильного URL-адреса, как это решить? PHP-CodeIgniter: как получить соответствующие значения строк таблицы html, которые будут удалены с помощью Javascript Не удается передать экземпляр класса в конструктор Ошибка Javascript в Ubuntu Uncaught ReferenceError: $ не определено

imagecopyresampled () вводит артефакты в прозрачном PNG

Я добавляю прозрачный водяной знак PNG к изображению. Водяной знак имеет высокое разрешение, поэтому, прежде чем накладывать его на исходное изображение, я изменяю его размер. Это, кажется, вносит некоторые артефакты в водяной знак, который я не нашел способа избежать.

Исходное изображение: введите описание изображения здесь

Измененное изображение (посмотрите на горизонтальную линию «грязь» между буквами »): введите описание изображения здесь

Масштабирование измененного изображения (непрозрачное), чтобы прояснить, что я подразумеваю под «грязью» между буквами. Область между «s» и «t», которую я очистил с помощью инструмента select и delete (открыть на новой вкладке, чтобы увидеть полный размер, где это более понятно): введите описание изображения здесь

Вот код, который я использую:

function resizeImage($image_filename, $out_filename, $width, $height){ // Get image info $image_info = @getimagesize($image_filename); if ($image_info == false) return false; $org_width = $image_info[0]; $org_height = $image_info[1]; $image_type = $image_info[2]; // Open image if ($image_type == IMAGETYPE_JPEG) $org_image = @imagecreatefromjpeg($image_filename); else if ($image_type == IMAGETYPE_GIF) $org_image = @imagecreatefromgif($image_filename); else if ($image_type == IMAGETYPE_PNG) $org_image = @imagecreatefrompng($image_filename); else return false; // Open stream for resized image $resized_image = @imagecreatetruecolor($width, $height); if ($resized_image == false) return false; // Handle transparency in PNGs if ($image_type == IMAGETYPE_PNG){ $transparent = imagecolorallocatealpha($resized_image, 255, 255, 255, 127); imagefilledrectangle($resized_image, 0, 0, $width, $height, $transparent); imagealphablending($resized_image, false); imagesavealpha($resized_image, true); } // Resize $resize_result = @imagecopyresampled($resized_image, $org_image, 0, 0, 0, 0, $width, $height, $org_width, $org_height); // Free original image @imagedestroy($org_image); // Save if ($image_type == IMAGETYPE_JPEG) $save_result = imagejpeg($resized_image, $out_filename, 90); // 90 = compression else if ($image_type == IMAGETYPE_GIF) $save_result = imagegif($resized_image, $out_filename); else if ($image_type == IMAGETYPE_PNG) $save_result = imagepng($resized_image, $out_filename, 0); // Free resized image if ($resize_result) @imagedestroy($resized_image); return ($resize_result && $save_result); } 

Любая идея о том, что вызывает артефакты?

Это, похоже, не происходит на черном фоне, поэтому другой взлом должен состоять в том, чтобы инвертировать изображение перед изменением размера и сделать это снова после

 imagefilter($org_image, IMG_FILTER_NEGATE); imagecopyresampled($resized_image, $org_image, 0, 0, 0, 0, $width, $height, $org_width, $org_height); imagefilter($resized_image, IMG_FILTER_NEGATE); 

Хорошо, в первую очередь, вот ваше «грязное» тестовое изображение с каналами RGB (выше) и альфа-каналом (ниже):

Грязное изображение разбито на каналы

Я заменил чистый белый ( #FFFFFF ) / 100% прозрачный синий, чтобы выделить пятнышки.

Как вы можете видеть, GD добавляет speckles как к каналам RGB, так и к альфа-каналу.

Не изучив GD-код, я предполагаю, что это вызвано ошибкой округления, в результате чего некоторые пиксели отключены на 1 или 2.

Я заметил, что у вас встроенный цветовой профиль в исходном PNG. Попробуйте удалить это; артефакты могут быть вызваны выполнением коррекции цвета GD. (В Photoshop вы должны использовать «Сохранить для Интернета»).

В противном случае я не могу предложить способ решить эту проблему, не исправляя код GD, однако я могу предложить грязное обходное решение, которое может работать:

Вместо того, чтобы изменять размер водяного знака до целевого размера изображения, затем накладывая его на целевое изображение, вы можете изменить размер целевого изображения на размер водяного знака, наложить водяной знак, сбросить альфа-канал и затем изменить размер до старого размера целевого изображения. Таким образом, вы избегаете изменения размера изображения, когда у него есть альфа-канал, который может избежать видимых артефактов.

Как я писал в своем комментарии в ответ на ответ Сёрен Лёборгс, похоже, что это просто проблема с GD / imagecopyresampled() которую нельзя легко избежать. Проблема GD Quality с прозрачными PNG имеет ту же проблему.

Можно использовать предложенный Søren Løvborgs способ обхода, просто имейте в виду, что он может ввести заметное снижение качества из-за изменения размера исходного изображения в два раза.

Я предлагаю использовать редактор фотографий для изменения размера водяного знака перед наложением. Это не так гибко, но оно сохранит качество изображения и не добавит шума.