2009-07-20 15 views
31

Tengo un formulario con un TImage grande como fondo. El problema es que esto se almacena directamente en el DFM como un mapa de bits, que ocupa unos 3 MB. El archivo PNG original es ~ 250K. Me gustaría tratar de reducir la hinchazón insertando el PNG en un recurso, y luego hacer que el formulario lo cargue durante OnCreate. Puedo hacerlo ahora que Delphi 2009 incluye soporte PNG, excepto que no sé cómo crear un archivo de recursos con un archivo PNG. Alguien sabe cómo se hace eso?¿Cómo hago un recurso PNG?

Respuesta

50

Ejemplo de archivo de texto (llamado myres.rc):

MYPNG RCDATA mypng.png 

añadida al proyecto:

{$R 'myres.res' 'myres.rc'} 

Ejemplo de carga en tiempo de ejecución:

uses 
    PngImage; 

var 
    Png: TPngImage; 
begin 
    Png := TPngImage.Create; 
    try 
    Png.LoadFromResourceName(HInstance, 'MYPNG'); 
    Image1.Picture.Graphic := Png; // Image1: TImage on the form 
    finally 
    Png.Free; 
    end; 
end; 
+0

¿Es 'RCDATA' realmente el tipo de recurso más específico disponible para ese tipo de gráfico? No hay 'RT_PNG', por ejemplo? –

+2

Buena pregunta, Rob. Mi Platform SDK instalado actualmente es para Windows Server 2003 R2, y no pude encontrar una constante específica de PNG en WinUser.h. Aunque no estoy seguro. Puede ser declarado en otro lugar, tal vez en una versión posterior de Platform SDK. –

+11

LoadFromResourceName busca específicamente un recurso de tipo RCDATA. –

1

Si está utilizando Delphi 2009, TImage debe almacenar su archivo PNG como PNG en el archivo DFM. El DFM será más grande porque el contenido binario de la propiedad Picture.Data del objeto TImage está codificado en el DFM como texto hexadecimal. Pero cuando el DFM se compila en su EXE, se compila en un recurso binario. Su imagen debería ocupar el mismo espacio dentro del recurso RCDATA del formulario, ya que almacenaría el PNG en su propio recurso RCDATA.

Acabo de probar esto abriendo uno de mis propios archivos DFM Delphi 2009 que tienen un componente TImage con una imagen PNG cargada en tiempo de diseño en un editor de texto, copiando el contenido de la propiedad Picture.Data y pegándolos en un editor hexadecimal El editor hexadecimal me muestra que la propiedad Picture.Data almacena un archivo PNG real con un prefijo de 10 bytes. El primer byte es $ 09 y el siguiente hechizo de 9 bytes TPngImage. Si elimino esos 10 bytes y guardo el archivo en el editor hexadecimal, obtengo un archivo PNG apropiado.

Si está utilizando Delphi 2009, simplemente cargue la imagen PNG en un componente TImage en el momento del diseño.

+0

Interesante, pero ¿qué pasa con el caso donde una imagen se reutiliza en múltiples formularios? ¿Delphi es lo suficientemente inteligente como para almacenar solo una copia, o almacena la imagen n veces, donde n es el número de componentes TImage cargados? :) – Drarok

+3

Cada componente de TImage almacena su imagen independientemente de cualquier otra instancia de TImage.Por lo tanto, si carga la misma imagen en n instancias de TImage, la misma imagen se almacena n veces. Una forma de resolver esto es usar la herencia de formas. Cree una forma base con el TImage y cargue la imagen en ella. A continuación, obtenga todas las formas que necesiten tener el mismo TImage de esa forma. Cualquier propiedad que no se modifique en formularios descendientes solo se almacena en el DFM de la forma ancestral. Eso incluye los datos de imagen de un TImage. –

2

Para aquellos que utilizan C++ Builder este código funciona para mí:

En el archivo de ResourceTest.rc

IMG_BMP BITMAP "Ressources\\myimage.bmp"; 
IMG_PNG RCDATA "Ressources\\myimage.png"; 

En el archivo ResourceTest.rh

#ifndef ResourceTestRH 
#define ResourceTestRH 

#define IMG_BMP "IMG_BMP" 
#define IMG_PNG "IMG_PNG" 

#endif 

En el archivo ResourceTest.cpp

#include "pngimage.hpp" 

// Loading bmp image from resource 
Graphics::TBitmap *bmpImage = new Graphics::TBitmap(); 
bmpImage->LoadFromResourceName((int)HInstance, IMG_BMP); 

// Loading png image from resource 
TPngImage *pngImage = new TPngImage(); 
pngImage->LoadFromResourceName((int)HInstance, IMG_PNG); 
Cuestiones relacionadas