PNG из Bitmap с переносом альфа-канала. И наоборот

bmp-to-png

Стандартными средствами Delphi можно создать PNG из Bitmap, но альфа канал при этом не переносится. Что за PNG без альфа-канала? Исправим это вопиющее безобразие. Заодно рассмотрим нюансы получения Bitmap из TGraphic.

PNG из Bitmap

Если требуются пояснения по коду, пишите в комментариях, с удовольствием отвечу.

Перенос альфа-канала из PNG в Bitmap

Переносить альфа-канал можно на что угодно. Например, у нас есть PNG с чуть размытым по Гауссу содержимым.

Рис.1. PNG с альфа-каналом

И некий абстрактный фон. Допустим, такой jpg.

Рис.2. JPG с абстрактным содержимым

Теперь, если преобразовать JPG с рисунка 2 в битмап и перенести в этот битмап альфа-канал из рисунка 1, то получится следующее:

Рис.3. Перенос альфа-канала в битмап

Получить Bitmap из TGraphic. Способ 1

Битмап в графике нужен всегда. Для обработки и анализа изображения. Для переноса данных из одного формата в другой. Просто для отрисовки. Все графические форматы рисуют не себя, а битмап, который формируется на основании данных, хранящихся в нем.

Не всегда графический формат согласен отдать свой внутренний битмап. Использование Assign также может не дать желаемого результата. Поэтому будем просто рисовать на битмапе искомый TGraphic.

Почему закомментирован вызов SetPngAlphaToBitmap. Потому что не всегда нужно переносить альфа-канал. Если это необходимо, вполне можно вызвать после LoadBitmapFromGraphic.

Для работы с альфа-каналом у нас есть отдельная функция.

Получить Bitmap из TGraphic. Способ 2. Альфа-канал

Метод Assign для потомков TGraphic вещь универсальная. В силу этого не всегда делает то, что хочется. Поэтому чуть модифицируем и дополним.

Почему закомментирована последняя строка. Свойство AlphaFormat следует устанавливать после всех операция с альфа-байтами. После вызова функции LoadBitmapFromGraphic, возможно, захочется еще что-то поделать с битмапом. Если свойство AlphaFormat уже будет выставлено, результаты будут крайне забавными.

Что тут происходит. Дело в том, что достаточно часто возникает ситуация, когда мы применили Assign, сделали PixelFormat = pf32bit и выставили AlphaFormat = afDefined, и в результате при отрисовке видим… пустоту! Чистый лист. Нетронутый холст. Такое ощущение, что произошла ошибка.

Но ошибки нет. Просто у нас везде альфа-канал равен 0. Непрозрачная исходная картинка, альфа-канала в ней нет. Мы перенесли данные и заказав 32 бита получили в 4-м байте пикселя 0. То есть прозрачный пиксель. И рисует все правильно — просто битмап абсолютно прозрачный.

Поэтому делаем проверку. Если у нас все альфа-байты в битмапе нулевые — это однозначно непрозрачная картинка. Если это так, выставляем все альфа-байты в 255.

Пример использования

У нас есть два TImage. Image1 отвечает за прозрачный PNG, Image2 — за фон. Открываем графические файлы и вставляем из буфера как было описано ранее.

Полный текст лучше посмотреть в исходниках по ссылке ниже. Что тут происходит. Если в Image1 находится TPNGImage, то используем Assign. Если что-то другое, а при вставке из буфера нам прилетает TBitmap, используем LoadBitmapFromGraphic из способа 2.

Обработчик события OnPaint компонента pb: TPaintBox выглядит следующим образом:

Здесь мы воспользовались функцией LoadBitmapFromGraphic из способа 1. Мы преобразовали TGraphic, который находится в Image2, в Bitmap. Затем сделали его полностью прозрачным функцией SetBitmapAlpha. Потом перенесли альфа-канал из ранее подготовленного PNG функцией SetPngAlphaToBitmap. И только после всех манипуляция с альфа-каналом установили формат AlphaFormat = afDefined.

В конце просто нарисовали этот битмап.

Таким образом, протестирована работа функций:

  • BitmapToPNG — сделать PNG из Bitmap с переносом альфа-канала;
  • SetPngAlphaToBitmap — перенос альфа-канала из PNG в Bitmap;
  • LoadBitmapFromGraphic 1 — получить Bitmap из TGraphic с масштабированием;
  • LoadBitmapFromGraphic 2 — получить Bitmap из TGraphic с анализом альфа-канала;

Скачать

Cпасибо за внимание!

Надеюсь, материал был полезен.

Подписывайтесь на телегу, задавайте вопросы, пишите комментарии.

Отвечу на все вопросы, выслушаю любую конструктивную критику.


Исходники (Delphi XE 7-10) 282 Кб

Исполняемый файл (zip) 1.18 Мб


5 4 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest
2 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
Олег
Олег
4 месяцев назад

Роман, весьма полезная статья! Благодарю, пригодится в хозяйстве.

2
0
Не нашли ответ на свой вопрос? Задайте его здесь!...x
()
x