Прозрачность PNG в проектах Lazarus ...
Модератор: Модераторы
QT в крапинку 
Ага, маска ему не понравилась, а с хандела в GTK вытянуть альфу не возможно
Вот более чистый вариант
Заменяем только процедуру TRasterImage.Draw в rasterimage.inc
Вот более чистый вариант
Заменяем только процедуру TRasterImage.Draw в rasterimage.inc
Код: Выделить всё
procedure TRasterImage.Draw(DestCanvas: TCanvas; const DestRect: TRect);
var
UseMaskHandle: HBitmap;
SrcDC: hDC;
DestDC: hDC;
DstBmp:TBitmap;
RShift, GShift, BShift, AShift, DstRShift, DstGShift, DstBShift:Integer;
RWidth, RHeight:integer;
ix, iy, iyStartByte, dstiyStartByte:integer;
srcdata, dstdata: PByteArray;
tmpdc:HDC;
bmp, old: HBitmap;
msk: HBitmap;
FinishX:Integer;
FinishY:Integer;
DP, SP:integer;
SrcPR, DstPR:byte;
SrcWidthPR,SrcHeightPR:single;
begin
if (Width=0) or (Height=0)
then Exit;
BitmapHandleNeeded;
if not BitmapHandleAllocated then Exit;
if Masked then
UseMaskHandle:=MaskHandle
else
UseMaskHandle:=0;
DestCanvas.Changing;
DestDC := DestCanvas.GetUpdatedHandle([csHandleValid]);
if ((WidgetSet.LCLPlatform = lpGtk) or (WidgetSet.LCLPlatform = lpGtk2)) and
(PixelFormat = pf32bit) and (RawImage.Description.BitsPerPixel = 32) and
(RawImage.Description.Format = ricfRGBA) then
begin
RWidth:= DestRect.Right-DestRect.Left;
RHeight:= DestRect.Bottom-DestRect.Top;
DstBmp := TBitmap.Create;
DstBmp.PixelFormat:=pf32bit;
DstBmp.SetSize(RWidth,RHeight);
DstBmp.Canvas.CopyRect(rect(0,0,DstBmp.Width,DstBmp.Height),DestCanvas,DestRect);
try
srcdata:=PByteArray(RawImage.Data);
dstdata:=PByteArray(DstBmp.RawImage.Data);
RShift:=RawImage.Description.RedShift div 8;
GShift:=RawImage.Description.GreenShift div 8;
BShift:=RawImage.Description.BlueShift div 8;
AShift:=RawImage.Description.AlphaShift div 8;
DstRShift:=DstBmp.RawImage.Description.RedShift div 8;
DstGShift:=DstBmp.RawImage.Description.GreenShift div 8;
DstBShift:=DstBmp.RawImage.Description.BlueShift div 8;
FinishY:=min(rHeight,DstBmp.RawImage.Description.Height);
FinishX:=min(rWidth,DstBmp.RawImage.Description.Width);
if (Height = rHeight)and(Width = rWidth) then
begin
for iy := 0 to FinishY-1 do
begin
iyStartByte := iy*RawImage.Description.Width;
dstiyStartByte := iy*dstBmp.RawImage.Description.Width;
for ix := 0 to FinishX-1 do
begin
DP :=((ix+dstiyStartByte)*4);
SP :=((ix+iyStartByte)*4);
SrcPR:=srcdata^[SP+AShift];
DstPR:=255-SrcPR;
dstdata^[DP+DstRShift]:=((srcdata^[SP+RShift]*SrcPR)+(dstdata^[DP+DstRShift]*DstPR)) div 255;
dstdata^[DP+DstGShift]:=((srcdata^[SP+GShift]*SrcPR)+(dstdata^[DP+DstGShift]*DstPR)) div 255;
dstdata^[DP+DstBShift]:=((srcdata^[SP+BShift]*SrcPR)+(dstdata^[DP+DstBShift]*DstPR)) div 255;
end;
end;
end else
begin
SrcWidthPR:=Width/RWidth;
SrcHeightPR:=Height/RHeight;
for iy := 0 to FinishY-1 do
begin
iyStartByte := trunc(iy*SrcHeightPR)*RawImage.Description.Width;
dstiyStartByte := iy*dstBmp.RawImage.Description.Width;
for ix := 0 to FinishX-1 do
begin
DP :=((ix+dstiyStartByte)*4);
SP :=((trunc(ix*SrcWidthPR)+iyStartByte)*4);
SrcPR:=srcdata^[SP+AShift];
DstPR:=255-SrcPR;
dstdata^[DP+RShift]:=((srcdata^[SP+RShift]*SrcPR)+(dstdata^[DP+RShift]*DstPR))div 255;
dstdata^[DP+GShift]:=((srcdata^[SP+GShift]*SrcPR)+(dstdata^[DP+GShift]*DstPR))div 255;
dstdata^[DP+BShift]:=((srcdata^[SP+BShift]*SrcPR)+(dstdata^[DP+BShift]*DstPR))div 255;
end;
end;
end;
WidgetSet.RawImage_CreateBitmaps(dstBmp.RawImage, bmp, msk, false);
tmpDC := CreateCompatibleDC(DestDC);
old := SelectObject(tmpDC, bmp);
StretchMaskBlt(DestDC, DestRect.Left, DestRect.Top, DstBmp.RawImage.Description.Width, DstBmp.RawImage.Description.Height, TmpDC, 0, 0, DstBmp.RawImage.Description.Width, DstBmp.RawImage.Description.Height,
0, 0,0,DestCanvas.CopyMode);
finally
DeleteObject(SelectObject(tmpDC, old));
DeleteObject(msk);
DeleteDC(tmpDC);
DstBmp.Free;
end;
end else
begin
SrcDC := Canvas.GetUpdatedHandle([csHandleValid]);
StretchMaskBlt(DestDC,
DestRect.Left,DestRect.Top,
DestRect.Right-DestRect.Left,DestRect.Bottom-DestRect.Top,
SrcDC,0,0,Width,Height, UseMaskHandle,0,0,DestCanvas.CopyMode);
end;
DestCanvas.Changed;
end;
Последний раз редактировалось carrots 02.08.2009 05:35:43, всего редактировалось 1 раз.
Работает.
Хотя это и не поддерживает идеологию разработчиков, но на данный момент нормальное решение, всеравно GTK скоро в корне переработают и нужно будет искать новые решения.
Хотя это и не поддерживает идеологию разработчиков, но на данный момент нормальное решение, всеравно GTK скоро в корне переработают и нужно будет искать новые решения.
carrots писал(а):... под suse, mandriva, debian, под gnome и KDE, везде работает, так что причина наверное в старом lazarus и FPC
Возможно действительно это из-за того, что я использую 0.9.26,.. еще немного повожусь и если не получится, то попробую обновиться до версии 0.9.27 из SVN.
Andreich писал(а):Возможно действительно это из-за того, что я использую 0.9.26,..
Проверил, действительно в 0.9.26 рисует мусор на фоне.
Logo писал(а):Работает.
Хотя это и не поддерживает идеологию разработчиков, но на данный момент нормальное решение
Как понять не поддерживает идеологию разработчиков?
Не в виджетсете написано?
Для того чтоб сделать по принципу разработчиков нужно будет добавить новый параметр в существующую процедуру или создать новую процедуру переноса изображений, ради чего придется вносить изменения во все виджетсеты, это не удобной и не нужно.
GTK 3 будет отдельной историей которая будет поддерживаться помимо 1 и 2.
В lazarus 9.26 возвращаться нет смысла, так что работает под ним или нет не имеет особого значения.
carrots писал(а):Не в виджетсете написано?
Ага, - не кошерно. Хотя я лично пользуюсь твоей заплаткой, за что ОГРОМНОЕ СПАСИБО!!!
carrots писал(а):В lazarus 9.26 возвращаться нет смысла, так что работает под ним или нет не имеет особого значения.
Согласен, слишком уж много улучшений в 0.9.27, чтобы возвращаться к прошлому. ВПЕРЕД и только ВПЕРЕД!!!
Уже 0.2.29 делают, а прозрачности как не было так и нет.
До сих пор приходится патчить.
Интересно они вообще собираются эту проблему решать?
До сих пор приходится патчить.
Интересно они вообще собираются эту проблему решать?
-
Павел Ишенин
- постоялец
- Сообщения: 475
- Зарегистрирован: 24.03.2007 09:16:52
Интересно они вообще собираются эту проблему решать?
Проблем как всегда много. За всеми не угонишься. Прозрачностью будет заниматься Marc Weustink после возвращения из отпуска. Эту тему я ему показывал.
carrots писал(а):Уже 0.2.29 делают, а прозрачности как не было так и нет.
До сих пор приходится патчить.![]()
Интересно они вообще собираются эту проблему решать?
Не нервничай, чем патч не нравится? Работает нормально, а по-правилам потом сделают. Тем более, что при обновлении с SVN пропатченый модуль остается не тронутым - все Ок!
- AbakAngelSoft
- постоялец
- Сообщения: 273
- Зарегистрирован: 06.08.2008 19:28:26
- Откуда: Краснодар
- Контактная информация:
carrots писал(а):Ага, маска ему не понравилась, а с хандела в GTK вытянуть альфу не возможно
Вот более чистый вариант
Заменяем только процедуру TRasterImage.Draw в rasterimage.incКод: Выделить всё
procedure TRasterImage.Draw(DestCanvas: TCanvas; const DestRect: TRect);
var
UseMaskHandle: HBitmap;
SrcDC: hDC;
DestDC: hDC;
DstBmp:TBitmap;
RShift, GShift, BShift, AShift, DstRShift, DstGShift, DstBShift:Integer;
RWidth, RHeight:integer;
ix, iy, iyStartByte, dstiyStartByte:integer;
srcdata, dstdata: PByteArray;
tmpdc:HDC;
bmp, old: HBitmap;
msk: HBitmap;
FinishX:Integer;
FinishY:Integer;
DP, SP:integer;
SrcPR, DstPR:byte;
SrcWidthPR,SrcHeightPR:single;
begin
if (Width=0) or (Height=0)
then Exit;
BitmapHandleNeeded;
if not BitmapHandleAllocated then Exit;
if Masked then
UseMaskHandle:=MaskHandle
else
UseMaskHandle:=0;
DestCanvas.Changing;
DestDC := DestCanvas.GetUpdatedHandle([csHandleValid]);
if ((WidgetSet.LCLPlatform = lpGtk) or (WidgetSet.LCLPlatform = lpGtk2)) and
(PixelFormat = pf32bit) and (RawImage.Description.BitsPerPixel = 32) and
(RawImage.Description.Format = ricfRGBA) then
begin
RWidth:= DestRect.Right-DestRect.Left;
RHeight:= DestRect.Bottom-DestRect.Top;
DstBmp := TBitmap.Create;
DstBmp.PixelFormat:=pf32bit;
DstBmp.SetSize(RWidth,RHeight);
DstBmp.Canvas.CopyRect(rect(0,0,DstBmp.Width,DstBmp.Height),DestCanvas,DestRect);
try
srcdata:=PByteArray(RawImage.Data);
dstdata:=PByteArray(DstBmp.RawImage.Data);
RShift:=RawImage.Description.RedShift div 8;
GShift:=RawImage.Description.GreenShift div 8;
BShift:=RawImage.Description.BlueShift div 8;
AShift:=RawImage.Description.AlphaShift div 8;
DstRShift:=DstBmp.RawImage.Description.RedShift div 8;
DstGShift:=DstBmp.RawImage.Description.GreenShift div 8;
DstBShift:=DstBmp.RawImage.Description.BlueShift div 8;
FinishY:=min(rHeight,DstBmp.RawImage.Description.Height);
FinishX:=min(rWidth,DstBmp.RawImage.Description.Width);
if (Height = rHeight)and(Width = rWidth) then
begin
for iy := 0 to FinishY-1 do
begin
iyStartByte := iy*RawImage.Description.Width;
dstiyStartByte := iy*dstBmp.RawImage.Description.Width;
for ix := 0 to FinishX-1 do
begin
DP :=((ix+dstiyStartByte)*4);
SP :=((ix+iyStartByte)*4);
SrcPR:=srcdata^[SP+AShift];
DstPR:=255-SrcPR;
dstdata^[DP+DstRShift]:=((srcdata^[SP+RShift]*SrcPR)+(dstdata^[DP+DstRShift]*DstPR)) div 255;
dstdata^[DP+DstGShift]:=((srcdata^[SP+GShift]*SrcPR)+(dstdata^[DP+DstGShift]*DstPR)) div 255;
dstdata^[DP+DstBShift]:=((srcdata^[SP+BShift]*SrcPR)+(dstdata^[DP+DstBShift]*DstPR)) div 255;
end;
end;
end else
begin
SrcWidthPR:=Width/RWidth;
SrcHeightPR:=Height/RHeight;
for iy := 0 to FinishY-1 do
begin
iyStartByte := trunc(iy*SrcHeightPR)*RawImage.Description.Width;
dstiyStartByte := iy*dstBmp.RawImage.Description.Width;
for ix := 0 to FinishX-1 do
begin
DP :=((ix+dstiyStartByte)*4);
SP :=((trunc(ix*SrcWidthPR)+iyStartByte)*4);
SrcPR:=srcdata^[SP+AShift];
DstPR:=255-SrcPR;
dstdata^[DP+RShift]:=((srcdata^[SP+RShift]*SrcPR)+(dstdata^[DP+RShift]*DstPR))div 255;
dstdata^[DP+GShift]:=((srcdata^[SP+GShift]*SrcPR)+(dstdata^[DP+GShift]*DstPR))div 255;
dstdata^[DP+BShift]:=((srcdata^[SP+BShift]*SrcPR)+(dstdata^[DP+BShift]*DstPR))div 255;
end;
end;
end;
WidgetSet.RawImage_CreateBitmaps(dstBmp.RawImage, bmp, msk, false);
tmpDC := CreateCompatibleDC(DestDC);
old := SelectObject(tmpDC, bmp);
StretchMaskBlt(DestDC, DestRect.Left, DestRect.Top, DstBmp.RawImage.Description.Width, DstBmp.RawImage.Description.Height, TmpDC, 0, 0, DstBmp.RawImage.Description.Width, DstBmp.RawImage.Description.Height,
0, 0,0,DestCanvas.CopyMode);
finally
DeleteObject(SelectObject(tmpDC, old));
DeleteObject(msk);
DeleteDC(tmpDC);
DstBmp.Free;
end;
end else
begin
SrcDC := Canvas.GetUpdatedHandle([csHandleValid]);
StretchMaskBlt(DestDC,
DestRect.Left,DestRect.Top,
DestRect.Right-DestRect.Left,DestRect.Bottom-DestRect.Top,
SrcDC,0,0,Width,Height, UseMaskHandle,0,0,DestCanvas.CopyMode);
end;
DestCanvas.Changed;
end;
Правильно ли я понимаю:
Необходимо этот код вставить в файл /usr/lib/lazarus/0.9.28.2/lcl/include/rasterimage.inc вместо имеющейся там TRasterImage.Draw и собрать lazarus?
После этих действий png изображение с альфа каналом загруженное в TImage или TImageList должно отображаться без "лесенки" по краям, как и в gimp-е?
Если да, то почему после указанных действий в "Ubuntu 10.04 x64" + "Lazarus 0.9.28.2-8ubuntu1 бета" изображения остаются "лесенкой"?
- AbakAngelSoft
- постоялец
- Сообщения: 273
- Зарегистрирован: 06.08.2008 19:28:26
- Откуда: Краснодар
- Контактная информация:
Неужели никто не сталкивался с указанными проблемами?
... Руки у меня что ли не от туда растут
...
... Руки у меня что ли не от туда растут
