2011-03-21 27 views
5

TImage de Delphi 2006 no es totalmente compatible con PNG. Para tener imágenes con transparencia alfa en mis formularios, debo cargarlos en tiempo de ejecución. Puedo cargarlos en el momento del diseño, pero no sobreviven, creo que porque los PNG no se guardan en el archivo DFM. Estoy seguro de que todo esto es genial en el último Delphi, pero no puedo actualizarlo por el momento.Delphi 2006: asignación en tiempo de ejecución de PNG a TImage pierde transparencia alfa

De todos modos, yo estaba cargarlos en tiempo de ejecución con:

Image1.Picture.Assign (PngImageCollection1.Items [0].PNGImage) ; 

El componente PNGImageCollection tiene todos mis archivos PNG de diferentes tamaños (éstos se crean y se cargan en tiempo de diseño), y les asigna a los respectivos TImages en el evento FormCreate.

Esto funcionó bien, hasta que tuve un problema en el que intentaba volver a utilizar una de estas imágenes en otro lugar después de que se había utilizado en un formulario. Descubrí que el acto de asignar el TPicture lo había configurado en una imagen vacía como resultado de Assign. Esto estaba sucediendo en la rutina TPicture.ForceType, que AFAICT verifica el tipo de FGraphic, y si no es del tipo deseado, libera FGraphic y crea una nueva instancia del tipo solicitado.

OK. Así que después de un poco de rascarse alrededor, veo que tal vez yo realmente debería estar haciendo esto:

Image1.Picture.Bitmap.Assign (PngImageCollection1.Items [0].PNGImage) ; 

Esto hizo el truco, en el que el Asignar no Clobber la imagen, pero la imagen muestra ahora con la semi los bits transparentes como opacas, es decir:

TImage when assigned with Image1.Picture.Bitmap.Assign

en lugar de:

TImage when assigned with Image1.Picture.Assign

cómo cA n Obtengo esta imagen para mostrar los bits transparentes alfa correctamente? (y una pregunta complementaria: ¿Image1.Picture.Bitmap.Assignifica la forma correcta de hacerlo?).

Aquí está el código en un poco más de detalle:

En el código donde tuve el problema de "reutilización" un TImage, la secuencia fue:
En forma crear:

LogoImage.Picture.Assign (PngImageCollection1.Items [0].PNGImage) ; 

(PNGIMage es un logotipo de la empresa, LogoImage1 está en el formulario principal).

El encabezado del informe de impresión:

procedure PrintLogo (Report : TBaseReport) ; 

var 
    X1, Y1, LogoHeightMM : Double ; 

begin 
with Report do 
    begin 
    LogoHeightMM := CalcGraphicHeight (LogoWidthMM, MainForm.LogoImage.Picture.Graphic) ; 
    X1   := PageWidth - MarginRight - LogoWidthMM ; 
    Y1   := SectionBottom - LogoHeightMM ; 
    PrintBitmapRect (X1, Y1, X1 + LogoWidthMM, Y1 + LogoHeightMM, MainForm.LogoImage.Picture.Bitmap) ; 
    end ; 
end ; 

La primera vez que la rutina para imprimir el logotipo se llama ejecuta sin error, pero el LOGOIMAGE .Picture se deja borra después de la llamada a PrintBitmapRect. La próxima vez que se llame a la rutina del encabezado de impresión, la llamada a CalcGraphicHeight falla porque el ancho y el alto de la imagen son cero.

Cambiar la imagen. Asignar a una imagen. Bitmap.Assign corrige el RTE en la rutina de impresión del encabezado, pero cuando trasplanté el mismo "arreglo" a otras imágenes estáticas asignadas desde PNG (como los engranajes anteriores) perdí la canal aplha

+1

Sugiero renunciar a una de las etiquetas sobre la cuestión a favor de 'Delphi'. Debería haber desarrolladores que hayan usado versiones anteriores en el pasado pero que no estén viendo sus etiquetas actualmente ... –

+0

Lo mejor es tratar de reproducir en un caso de prueba muy pequeño, luego trabajar desde allí. Ayuda mucho si puedes publicar ese pequeño caso de prueba. –

Respuesta

5

No está mostrando la parte realmente relevante de su código: cómo está reutilizando la imagen que causaría que tenga un tipo particular.

Cuando asigna un TImage a un TPngObject, el gráfico de la imagen contiene un objeto png. Solo cuando solicite específicamente un mapa de bits, forzará su gráfico a ser de tipo bitmap. Por ejemplo, esto,

Bmp.Assign(Image1.Picture.Bitmap); 

obligará Image1 tener un gráfico de mapa de bits, si el gráfico era un objeto png que será liberado. Si bien esto,

Bmp.Assign(Image1.Picture.Graphic); 

no forzará Image1 tener un gráfico de mapa de bits, el objeto png llevará a cabo el trabajo y permanecer allí.

Los mapas de bits de Delphi (al menos hasta las versiones más recientes) no son compatibles con canales alfa, por lo que no debe utilizar Image1.Picture.Bitmap.Assign(.. para imágenes parcialmente transparentes.


Por cierto, en lugar de volver a utilizar el gráfico en la imagen, se podría utilizar probablemente la imagen en su colección de imágenes png como la fuente ..

+0

@Sertac ... vea las ediciones de la pregunta. – rossmcm

+0

@rossmcm - Es la línea PrintBitmapRect (.. 'que está causando que su imagen pierda el objeto png, porque está solicitando específicamente un mapa de bits:' MainForm.LogoImage.Picture.Bitmap'. Es exactamente el tipo de primer ejemplo como en la respuesta. Si 'PrintBitmapRect' requiere un mapa de bits, cree un mapa de bits temporal, establezca su tamaño, asígnelo usando el segundo ejemplo como en la respuesta, pase a 'PrintBitmapRect', luego libere el mapa de bits temporal. –

+0

Muchas gracias. El apoyo de PNG de terceros es muy frágil y fragmentado. Creo que valdría la pena echar mano a la versión actual de Delphi para poder deshacerme de esta mezcolanza de PNG. ¿Conoces algún conjunto razonable de unidades PNG desde un solo lugar? – rossmcm

Cuestiones relacionadas