El problema puede ser que el PNG se haya convertido incorrectamente a TBitmap32, perdiendo la información de transparencia en tránsito. Es un caso común con imágenes PNG con paleta. De lo contrario, no tendría que usar "Bitmap.DrawMode: = dmTransparent" y "OuterColor". Si la información transparencry de PNG se hubiera transferido correctamente a TBitmpa32, DrawMode: = dmBlend habría funcionado, sin la necesidad de establecer OuterColor.
Lo que más importa es cómo cargar un archivo PNG en el TBitmap32. El TPngImage desde Vcl.Imaging.La unidad pngimage (implementada en Delphi XE2 y posterior) puede dibujar transparentemente en mapas de bits, preservando lo que estaba en esos mapas de bits, combinando colores usando la capa alfa PNG, etc., pero no permite convertir fácilmente varios formatos de transparencia PNG (incluida la paleta) en el componente alfa de cada píxel de TBitmap32. Una vez que TPngImage ha dibujado una imagen, obtienes el RGB combinado para cada píxel, pero el componente alfa no se transfiere al mapa de bits objetivo.
Hay rutinas de ayuda disponibles que intenta cargar un archivo PNG en un TBitmap32 con transparencia, pero tienen inconvenientes:
(1) “LoadPNGintoBitmap32” de http://graphics32.org/wiki/FAQ/ImageFormatRelated - se aplica la transparencia en dos ocasiones, por lo que las imágenes con los valores alfa distintos de 0 o 255 se verán de forma diferente que en otro software (más notable en las imágenes translúcidas con efectos de cristal). Este código primero aplicará alfa a RGB y luego establecer alfa como una capa separada, por lo que cuando pintes, alfa se aplicará nuevamente. Puede encontrar más información sobre este tema aquí: Delphi, GR32 + PngObject: converting to Bitmap32 doesn't work as expected . Además de eso, no convierte correctamente la transparencia de las imágenes con paleta en la capa alfa de TBitmap32. Establecen manualmente la transparencia alfa para los píxeles de un cierto color del mapa de bits de salida (renderizado a RGB) en lugar de hacerlo a RGB, por lo que la transparencia real se pierde como en su imagen de muestra cuando todos los píxeles blancos son transparentes.
(2) “LoadBitmap32FromPNG” de la biblioteca gr32ex: https://code.google.com/archive/p/gr32ex/ - una implementación ligeramente diferente del mismo algoritmo que (1), y tiene los mismos problemas que (1).
Por lo tanto, las soluciones son:
- No utilice TBitmap32; use Vcl.Imaging.pngimage.TPngImage dibuje directamente en el mapa de bits del objetivo (pantalla, etc.): esta es la forma más compatible que maneja correctamente varios formatos PNG.
- Use un enrutador auxiliar para transferir información de transparencia de Vcl.Imaging.pngimage.TPngImage a TBitmap32.
- Utilice la biblioteca GR32 PNG que puede cargar de forma nativa un archivo PNG en TBitmap32 https://sourceforge.net/projects/gr32pnglibrary/ Dado que ahora tiene toda la información sobre este tema, puede obtener la solución adecuada para usted.
cómo cargar la capa alfa en una sola pasada
Heinrich Ulbricht hizo una buena sugerencia para eliminar la capa de transparencia antes de doler y después de leer la imagen de nuevo. Para evitar cargar la imagen dos veces, puede guardar la capa alfa antes de llamar a PNGObject.RemoveTransparency. Aquí está el código que aplica correctamente la capa alfa y carga la imagen solo una vez. Desafortunadamente, no funciona con imágenes con paleta. Si sabe cómo rellenar correctamente la capa alfa de TBitmap32 desde cualquier imagen con paleta, sin los efectos descritos en Transparent Png to TBitmap32, por favor avíseme.
procedure LoadPNGintoBitmap32(DstBitmap: TBitmap32; SrcStream: TStream; out AlphaChannelUsed: Boolean);
var
PNGObject: TPngImage;
PixelPtr: PColor32;
AlphaPtr: PByte;
SaveAlpha: PByte;
I, AlphaSize: Integer;
begin
AlphaChannelUsed := False;
PNGObject := TPngImage.Create;
try
PNGObject.LoadFromStream(SrcStream);
AlphaPtr := PByte(PNGObject.AlphaScanline[0]);
if Assigned(AlphaPtr) then
begin
AlphaSize := PNGObject.Width * PNGObject.Height;
if AlphaSize <= 0 then raise Exception.Create('PNG files with zero dimensions are not supported to be loaded to TBitmap32');
GetMem(SaveAlpha, AlphaSize);
try
Move(AlphaPtr^, SaveAlpha^, AlphaSize);
PNGObject.RemoveTransparency;
DstBitmap.Assign(PNGObject);
DstBitmap.ResetAlpha;
PixelPtr := PColor32(@DstBitmap.Bits[0]);
AlphaPtr := SaveAlpha;
for I := 0 to AlphaSize-1 do
begin
PixelPtr^ := (PixelPtr^ and $00FFFFFF) or (TColor32(AlphaPtr^) shl 24);
Inc(PixelPtr);
Inc(AlphaPtr);
end;
finally
FreeMem(SaveAlpha, AlphaSize);
end;
AlphaChannelUsed := True;
end else
if PNGObject.TransparencyMode = ptmNone then
begin
DstBitmap.Assign(PNGObject);
end else
begin
raise Exception.Create('Paletted PNG images are not supported in LoadPNGintoBitmap32, transparency cannot be stored to TBitmap32');
end;
finally
FreeAndNil(PNGObject);
end;
end;
supongo que es debido a la "opacidad", también se ha configurado "tmp.DrawMode: = dmBlend;", no he utilizado GR32, pero yo supongo que la diferencia se debe a la opacidad. – ComputerSaysNo
@Dorin Duminica, no lo es. El ejemplo en su sitio web muestra que el modo debe ser dmBlend si hay alguna transparencia en la imagen PNG cargada. Como sé que todas mis imágenes son transparentes, no tengo que verificarlo. – migajek