Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

"Исправление проблем альфа-канала при использовании TBitmap32 для полупрозрачных PNG с библиотекой GR32"

Delphi , Графика и Игры , Компоненты и Графика

Проблема, описанная пользователем, заключается в том, что при использовании метода загрузки полупрозрачного изображения формата 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, а затем устанавливает альфа-канал как отдельный слой, так что при рисовании альфа-канал будет применен снова.

Чтобы решить проблему, необходимо изменить код следующим образом:

  1. Удалить альфа-канал перед рисованием с помощью PNGObject.RemoveTransparency;.
  2. Перезагрузить изображение, чтобы восстановить альфа-канал.
  3. Применить изменения только для альфа-канала, которые были неглубоко реализованы в исходном файле и привели к проблемами с палитрой.

Дополнительное решение предлагается использовать 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, изображение теряет свою прозрачность и отображается некорректно.

Пример кода с проблемой:

tmp:= TBitmap32.Create;
LoadPNGintoBitmap32(tmp, ..., foo);
tmp.DrawMode:= dmBlend;
PaintBox321.Buffer.Draw(..., tmp);

Код выше работает неправильно из-за ошибки в функции 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 для работы с палитрными изображениями и их альфа-каналами.

Альтернативные варианты решения:

  1. Использование TPngImage из модуля Vcl.Imaging.pngimage для прямого рисования на целевом битмапе, сохраняя информацию о прозрачности.
  2. Применение GR32 PNG библиотеки, которая позволяет загружать PNG изображения прямо в TBitmap32 с корректной обработкой альфа-канала.

Используя вышеописанные методы и рекомендации, разработчикам будет проще избегать ошибок связанных с прозрачностью изображений при работе с библиотекой GR32 и компонентами Delphi для работы с графикой.

Создано по материалам из источника по ссылке.

Проблема заключается в неправильной обработке альфа-канала полупрозрачного изображения формата PNG при его загрузке в `TBitmap32` с использованием библиотеки GR32, что приводит к искажению прозрачности изображений.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




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


:: Главная :: Компоненты и Графика ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-19 13:29:56
2024-11-21 11:33:08/0.0066168308258057/1