Sign in to follow this  
Tispe

Help with loading ICON data from memory

Recommended Posts

Hi

 

I have a file which contain a bunch of icons batched together. I load this file to a buffer and now I want to extract the images into IDirect3DTexture9 objects.

 

The icons are 32x32 pixels in size, they contain a XOR palette and an AND palette (atleat I think so after looking at it on a HexEditor). Both palettes are 1024 bytes each.

 

I have seen source code that reads this into a HBITMAP using a BITMAPINFO header.

 

HBITMAP hBitmap = CreateDIBSection(hDC, &bmi , DIB_RGB_COLORS, (void**)&pSrc, NULL, 0 );

But this requires alot of bitfidling and the image is upside down.

 

 

I need help porting this code in to a more conventient method, like D3DXLoadSurfaceFromMemory() that can be used in DX9.

 

Any input about ICO file format and loading is appreciated.

Edited by Tispe

Share this post


Link to post
Share on other sites

MSDN has a pretty complete description here: http://msdn.microsoft.com/en-us/library/ms997538.aspx

 

 

You won't be too happy as there's quite a few formats (no. of colors, etc.) that could possibly be used. It would probably really be easier to have LoadIcon or CreateDIBSection do the hard work and go from there.

 

Also, if you pass the height in as negative to CreateDIBSection the image will be in the correct orientation.

Edited by Endurion

Share this post


Link to post
Share on other sites

I did some more research and I figured that the Icons I am trying to read are in this format:

typdef struct
{
   BITMAPINFOHEADER   icHeader;      // DIB header
   RGBQUAD         icColors[1];   // Color table
   BYTE            icXOR[1];      // DIB bits for XOR mask
   BYTE            icAND[1];      // DIB bits for AND mask
} ICONIMAGE, *LPICONIMAGE;

I cast this structure the starting address of the buffer. The BITMAPINFOHEADER gets filled with data that is consistent with what I am interpreting in a HexEditor. 32x32, 256 colors, and BI_RGB uncompressed format.

 

 

Now that I have an ICONIMAGE, how can I turn that into surface I can plug into a IDirect3DTexture9?

Share this post


Link to post
Share on other sites

I am looking for a method for looping through the ICO layout (XOR, AND, Color, paletts) and get the pixel value. The problem is that the data is spread out, and I need to reassemble it.

Share this post


Link to post
Share on other sites

I am looking for a method for looping through the ICO layout (XOR, AND, Color, paletts) and get the pixel value. The problem is that the data is spread out, and I need to reassemble it.

FWIW, I wrote the ICO muxer for FFmpeg (I didn't write the demuxer, but if its source is helpful, it's here).

 

ICOs either have 1bit, 4bit, 8bit, 16bit, 24bit, or 32bit BMP or 32bit PNG stored inside of them (in the size range 1x1 up to 256x256 pixels). PNGs are written in ICOs as a complete byte-for-byte copy 'n' paste. BMPs, however, are a little different. They have no BITMAPFILEHEADER, have twice the height they used to (because the top half is the original image, and the bottom half is the bitmask). Assuming you have code to extract the bytes for each BMP image, you can then read each individual BMP image. The BMP image bytes are first a BITMAPINFOHEADER, followed by the pixel data. Remember, the image height reported in the BITMAPINFOHEADER will be twice the actual height. The pixel data will first be the normal BMP pixel data (its exact format depends on the values of the BITMAPINFOHEADER (i.e. what its depth is, whether it's palette based, etc.). After that, you get the bitmask.

 

That ICONIMAGE structure is basically what I'm talking about for a BMP image. First it's got the BITMAPINFOHEADER (but remember, the height is doubled). The icColors and icXOR are just pointers for the data that would normally follow a BMP. The icAND is the bitmask that immediately follows the pixel data.

 

I don't have time to write the actual code to iterate over all these things and extract them. But if you have any specific questions I can try to cover them.

 

Edit: The simplest way to do it is to read through the ICO and extract each image. If the image is a PNG, just read the bytes and use some library to decode the PNG. If its a BMP, add the BITMAPFILEHEADER back on, divide the height by two, and use some library to decode the BMP. Extract the bitmask separately from the BMP (that is, extract the BMP info and repair it to a normal BMP, then extract the bitmask separately). After some library decodes the BMP for you, you can use/apply the bitmask.

Edited by Cornstalks

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this