Проблема, описанная пользователем, заключается в том, что при использовании метода загрузки полупрозрачного изображения формата PNG в TBitmap32 с помощью библиотеки GR32 происходит искажение альфа-канала. Это приводит к некорректному отображению прозрачности изображений.
Оригинальный заголовок:
Delphi, GR32 + PngObject: converting to Bitmap32 doesn't work as expected
Описание проблемы (вопрос):
Пользователь использует GR32 для рисования нескольких полупрозрачных PNG изображений. Он пытается перейти на метод, предложенный на сайте GR32, который включает загрузку PNG в TBitmap32, установку режима смешивания и последующий вывод изображения. Однако этот метод приводит к проблемам с альфа-каналом, что видно из сравнения с изображением, обработанным в Paint.NET.
Подтвержденный ответ:
Проблема заключается в том, что при загрузке PNG в TBitmap32 с помощью функции LoadPNGintoBitmap32, происходит двойное применение альфа-канала, что делает изображение более прозрачным и сероватым. В исходном коде LoadPNGintoBitmap32 используется метод, который сначала применяет альфа-канал к RGB, а затем устанавливает альфа-канал как отдельный слой, так что при рисовании альфа-канал будет применен снова.
Чтобы решить проблему, необходимо изменить код следующим образом:
Удалить альфа-канал перед рисованием с помощью PNGObject.RemoveTransparency;.
Перезагрузить изображение, чтобы восстановить альфа-канал.
Применить изменения только для альфа-канала, которые были неглубоко реализованы в исходном файле и привели к проблемами с палитрой.
Дополнительное решение предлагается использовать TPngImage из модуля Vcl.Imaging.pngimage, который позволяет рисовать на битмапах, сохраняя оригинальную прозрачность изображения. Также можно использовать GR32 PNG библиотеку, которая умеет загружать PNG напрямую в TBitmap32 с сохранением альфа-канала.
Пример кода для исправления проблемы:
procedure LoadPNGintoBitmap32(DstBitmap: TBitmap32; SrcStream: TStream; out AlphaChannelUsed: Boolean);
var
PNGObject, SaveAlpha: PByte;
begin
// ...
end;
В приведенном примере кода сохраняется альфа-канал перед его удалением и затем восстанавливается обратно на изображение.
Альтернативный ответ:
Проблема может быть связана с некорректным преобразованием PNG в TBitmap32, что приводит к потере информации об альфа-канале. Важно то, как загружается PNG в TBitmap32. Объект TPngImage из модуля Vcl.Imaging.pngimage (доступный начиная с Delphi XE2) может рисовать на битмапах, сохраняя прозрачность исходного изображения и используя альфа-канал PNG для комбинирования цветов. Однако он не позволяет легко конвертировать форматы PNG-прозрачности (включая палитрованные) во альфа-компонент каждого пикселя TBitmap32.
Заключение:
Для корректной работы с полупрозрачными PNG в Delphi и библиотеке GR32 важно правильно обрабатывать альфа-канал при загрузке изображений в TBitmap32. Использование предложенных решений позволит избежать проблем, связанных с искажением прозрачности.
Статья для сайта:
Исправление проблем альфа-канала при использовании TBitmap32 для полупрозрачных PNG с библиотекой GR32
Разработчики, работающие с графическими изображениями в среде Delphi и использующие библиотеку GR32, могут столкнуться с проблемами связанными с обработкой альфа-каналов. Особенно это актуально при работе с полупрозрачными PNG-изображениями. В данной статье мы рассмотрим типичную проблему, когда при преобразовании объекта PNGObject в TBitmap32, изображение теряет свою прозрачность и отображается некорректно.
Код выше работает неправильно из-за ошибки в функции LoadPNGintoBitmap32, которая загружает PNG изображение в объект TBitmap32 и одновременно применяет альфа-канал дважды, что приводит к потере качества изображения и искажению его прозрачных свойств.
Исключение проблемы:
// Изменения для правильной загрузки альфа канала в один проход
procedure LoadPNGintoBitmap32(DstBitmap: TBitmap32; SrcStream: TStream);
var
PNGObject, SaveAlpha, AlphaPtr: PByte;
begin
// Создание объекта TPngImage для чтения данных PNG файла
PNGObject := TPngImage.Create;
try
PNGObject.LoadFromStream(SrcStream);
// Сохранение альфа канала в память до его удаления
AlphaPtr := PByte(PNGObject.AlphaScanline[0]);
if Assigned(AlphaPtr) then begin
// Загрузка размера в переменную для использования ниже
DstBitmap.Assign(SaveSizeOfAlphaChannel(AlphaPtr, PNGObject));
PNGObject.RemoveTransparency;
// ...
end;
// Используем сохраненный альфа канал для обновления альфы каждого пикселя после рисования изображения в bitmap
UpdatePixelAlpha(DstBitmap, AlphaPtr);
finally
FreeAndNil(PNGObject);
end;
end;
// Функции SaveSizeOfAlphaChannel и UpdatePixelAlpha реализованы как описано далее для сохранения альфа канала до его изменения
// и приведения в соответствие с каждым пикселем DstBitmap после загрузки PNG изображения.
// Процедура SaveSizeOfAlphaChannel рассчитывает необходимый размер буфера для хранения альфы, ...
```pascal
// ... И копирует альфа канал в выделенный буфер до его удаления и последующего применения траспаренси (PNGObject.RemoveTransparency).
// Процедура UpdatePixelAlpha обновляет альфа каналы пикселей TBitmap32 после того, как PNG изображение было загружено без альфы
// (после вызова PNGObject.RemoveTransparency), используя сохраненный альфа канал.
```pascal
function SaveSizeOfAlphaChannel(const AlphaPtr: PByte; const PNGObject: TPngImage): Integer;
begin
Result := PNGObject.Width * PNGObject.Height;
end;
procedure UpdatePixelAlpha(var DstBitmap: TBitmap32; const AlphaPtr: PByte);
var
PixelPtr, AlphaPtr: Pointer;
begin
PixelPtr := @DstBitmap.Bits[0];
AlphaPtr := AlphaPtr;
for var I := 0 to SaveSizeOfAlphaChannel(@AlphaPtr^, PNGObject) - 1 do begin
// Восстанавливаем альфа канал для каждого пикселя, корректируя цвет на полную прозрачность альфы.
PixelPtr^ := ColorToARGB(PixelPtr^, AlphaPtr^);
Inc(PixelPtr);
Inc(AlphaPtr);
end;
end;
var
SaveMemSize: Integer = SizeOfAlphaChannel(PNGObject);
GetMem(SaveAlpha, SaveMemSize);
try
Move(AlphaPtr^, SaveAlpha^, SaveMemSize); // Сохраняем альфа канал в буфер до его использования позже.
finally
FreeMem(SaveAlpha, SaveMemSize); // Освобождаем выделенную память после применения альфы к каждому пикселю.
end;
Используйте следующие шаги для улучшения загрузки PNG изображений в TBitmap32:
1. Удалить прозрачность перед рисованием, чтобы можно было избежать двойного применения альфа канала.
2. Прочитать файл изображения еще раз, после его "очистки" от альфы, для восстановления альфа-канала.
3. Предоставьте процедуру для сохранения альфа-канала перед его удалением и использовать её для перезаписи альфы каждого пикселя напрямую в TBitmap32.
Важно знать, что приведенный выше код является упрощенным примером и требует реализации соответствующих вспомогательных функций. Кроме того, он не решает проблему с палитрой PNG изображений, которая может потребовать отдельного решения.
Подробное решение альфа-канала в один проход:
// Важно! Приведенный ниже метод предполагается быть уже реализованным и готовым к использованию.
procedure CorrectLoadPNGintoBitmap32(DstBitmap: TBitmap32; SrcStream: TStream);
var
PNGObject, SaveAlphaChannel, AlphaSize, I: NativeInt;
begin
// Создание объекта TPngImage для загрузки данных из потока в память.
PNGObject := TPngImage.Create;
try
PNGObject.LoadFromStream(SrcStream);
if Assigned(PNGObject.AlphaScanline[0]) then begin
AlphaSize := PNGObject.Width * PNGObject.Height;
GetMem(SaveAlphaChannel, AlphaSize);
Move(PNGObject.AlphaScanline[0], SaveAlphaChannel^, AlphaSize);
// Удаление альфа канала перед рисованием
PNGObject.RemoveTransparency;
DstBitmap.Assign(PNGObject);
DstBitmap.ResetAlpha;
var PixelPtr := PColor32(@DstBitmap.Bits[Low(DstBitmap)]);
for I := 0 to AlphaSize - 1 do begin
PixelPtr^ := ARGBToColor(PixelPtr^, SaveAlphaChannel[I], PNGObject.Pixels[I]);
Inc(PixelPtr);
end;
end else if PNGObject.TransparencyMode = ptmNone then begin
DstBitmap.Assign(PNGObject);
end else raise Exception.Create('Не поддерживаемые типы прозрачности PNG: палитрные изображения.');
finally
FreeAndNil(PNGObject);
if Assigned(SaveAlphaChannel) then FreeMem(SaveAlphaChannel, AlphaSize);
end;
end;
Сохраняем альфа канал в отдельный буфер до его удаления и затем восстанавливаем обратно на картинку после рисования изображения без прозрачности.
Данный метод предполагает реализацию вспомогательных функций ARGBToColor для комбинирования цвета пикселя с альфа каналом, что позволяет избежать потери информации о прозрачности при конвертации PNG в TBitmap32. Также полезно использовать функционал из библиотеки GR32 для работы с палитрными изображениями и их альфа-каналами.
Альтернативные варианты решения:
Использование TPngImage из модуля Vcl.Imaging.pngimage для прямого рисования на целевом битмапе, сохраняя информацию о прозрачности.
Применение GR32 PNG библиотеки, которая позволяет загружать PNG изображения прямо в TBitmap32 с корректной обработкой альфа-канала.
Используя вышеописанные методы и рекомендации, разработчикам будет проще избегать ошибок связанных с прозрачностью изображений при работе с библиотекой GR32 и компонентами Delphi для работы с графикой.
Проблема заключается в неправильной обработке альфа-канала полупрозрачного изображения формата PNG при его загрузке в `TBitmap32` с использованием библиотеки GR32, что приводит к искажению прозрачности изображений.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.