При работе с графикой в среде Delphi иногда возникают проблемы, связанные с непрозрачностью битмапов. Одна из таких проблем заключается в невозможности комбинирования прозрачного цвета битмапа с функцией Canvas.Draw с параметром Opacity. В данной статье мы рассмотрим, как можно решить эту проблему, не прибегая к использованию WinAPI.
Описание проблемы
Пользователь столкнулся с проблемой, когда пытался нарисовать битмап на канвасе с прозрачностью, где битмап уже имел прозрачный цвет. При использовании функции Canvas.Draw с параметром Opacity для битмапа без прозрачного цвета, все работало корректно. Однако, когда использовался битмап с прозрачным цветом, параметр Opacity игнорировался.
Пример кода, вызывающего проблему
procedure TForm1.FormPaint(Sender: TObject);
var
b1, b2: TBitmap;
begin
// Пример работы opacity:
b1 := TBitmap.Create;
b1.SetSize(20, 20);
b1.Canvas.Brush.Color := clBlue;
b1.Canvas.Rectangle(0, 0, 20, 20);
Canvas.Draw(10, 10, b1, $FF); // Работает
Canvas.Draw(40, 10, b1, $66); // Работает
// Необходимо сочетание с TransparentColor:
b2 := TBitmap.Create;
b2.Transparent := True;
b2.TransparentColor := clFuchsia;
b2.Canvas.Brush.Color := clFuchsia;
b2.SetSize(20, 20);
b2.Canvas.Brush.Color := clBlue;
b2.Canvas.Ellipse(0, 0, 20, 20);
Canvas.Draw(10, 40, b2, $FF); // Работает (полная непрозрачность)
Canvas.Draw(40, 40, b2, $66); // Игнорируется $66 Opacity
end;
Подтвержденное решение
Чтобы решить проблему, необходимо использовать другой подход к настройке альфа-канала битмапа. В коде ниже приведен пример функции SetBitmapAlpha, которая позволяет установить альфа-канал для каждого пикселя битмапа:
procedure SetBitmapAlpha(ABitmap: TBitMap; Alpha: Byte);
var
pscanLine32: pRGBQuadArray;
nScanLineCount, nPixelCount: Integer;
begin
with ABitmap do
begin
PixelFormat := pf32Bit;
HandleType := bmDIB;
ignorepalette := true;
alphaformat := afDefined;
for nScanLineCount := 0 to Height - 1 do
begin
pscanLine32 := Scanline[nScanLineCount];
for nPixelCount := 0 to Width - 1 do
begin
with pscanLine32[nPixelCount] do
begin
rgbReserved := Alpha;
end;
end;
end;
end;
end;
Также необходимо создать функцию AdaptBitmapAlpha, которая будет устанавливать альфа-канал в зависимости от прозрачного цвета:
procedure AdaptBitmapAlpha(ABitmap, TranspBitmap: TBitmap);
begin
// ... (код функции)
end;
После этого можно использовать новый битмап b3, установить альфа-канал в 0, нарисовать битмап b2 с нужной прозрачностью на b3, установить альфа-канал в 255 для каждого пикселя, не совпадающего с прозрачным цветом в b2, и затем нарисовать полученный битмап с желаемой непрозрачностью.
Альтернативный ответ
В качестве альтернативного решения можно использовать класс TBitmapHelper с функцией TransparentMaskedDraw, которая позволяет нарисовать битмап с учетом маски и непрозрачности:
unit uBitmapHelper;
interface
uses
Vcl.Graphics;
type
TBitmapHelper = class Helper for TBitmap
private
type
TRgbaRec = packed record
r, g, b, a: Byte;
end;
PRgbaRec = ^TRgbaRec;
PRgbaRecArray = ^TRgbaRecArray;
TRgbaRecArray = array [0 .. 0] of TRgbaRec;
public
procedure TransparentMaskedDraw(ACanvas: TCanvas; AX, AY: Integer; AMask: TColor; AOpacity: Byte);
end;
implementation
{ TBitmapHelper }
procedure TBitmapHelper.TransparentMaskedDraw(ACanvas: TCanvas; AX, AY: Integer; AMask: TColor; AOpacity: Byte);
begin
// ... (код функции)
end;
end.
Это решение позволяет использовать битмап с прозрачным фоном, учитывая альфа-канал.
Заключение
Используя предложенные функции и классы, можно решить проблему с непрозрачностью битмапа в Delphi без использования WinAPI. Важно правильно настроить альфа-канал и использовать функции для работы с прозрачными пикселями.
В статье рассматривается проблема непрозрачности битмапа в среде Delphi, связанная с игнорированием параметра Opacity при наличии у битмапа прозрачного цвета, и предлагаются способы решения этой проблемы без использования WinAPI.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.