Convert any IImage to A8R8G8B8

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
eye776
Posts: 94
Joined: Sun Dec 28, 2008 11:07 pm

Convert any IImage to A8R8G8B8

Post by eye776 »

If anyone ever needed to draw inside a texture, but couldn't because of Color format differences, heres' a short snippet on how to convert any IImage that Irrlicht can load to 32-bit ARGB.

Code: Select all


IImage* getARGBImage(stringc filename)
{
IImage* srcImage = System::Driver->createImageFromFile(filename);
IImage* bmpImage = NULL;

	if(srcImage->getColorFormat() != ECF_A8R8G8B8) {
		printf("Image color format doesn't match, converting!\n");
		dimension2du dim = srcImage->getDimension();
		void* load_pixels = malloc((dim.Width * dim.Height) << 2);
		switch(srcImage->getColorFormat())
		{
		case ECF_A1R5G5B5:
			convert_A1R5G5B5toA8R8G8B8(srcImage->lock(), (dim.Width * dim.Height), load_pixels);
			break;
		case ECF_R5G6B5:
			convert_R5G6B5toA8R8G8B8(srcImage->lock(), (dim.Width * dim.Height), load_pixels);
			break;
		case ECF_R8G8B8:
		        convert_R8G8B8toA8R8G8B8(srcImage->lock(), (dim.Width * dim.Height), load_pixels);
			break;
		}
		bmpImage = System::Driver->createImageFromData(ECF_A8R8G8B8, dim, load_pixels, false, true);
		free(load_pixels);
		srcImage->drop();
                return bmpImage;
       } else {
                return srcImage;
       }
}
You then use:

Code: Select all

IImage* newImage = getARGBImage(filename);
ITexture* newTexture = IVideoDriver::addTexture(filename, newImage);
You can now use (u32*)newTexture->lock(); and draw inside it as you please using SColor::color.

PS: convert_A1R5G5B5toA8R8G8B8, convert_A1R5G5B5toA8R8G8B8, convert_R8G8B8toA8R8G8B8 are found in CColorConverter.cpp (in the irrlicht sources).
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Check latest SVN trunk for a properly exported conversion function. This will redue the code to basically a few lines and works even on non-linux systems.
eye776
Posts: 94
Joined: Sun Dec 28, 2008 11:07 pm

Post by eye776 »

Okay. What's the function called like?

PS: Is this it?

Code: Select all

IVideoDriver::convertColor(const void* sP, ECOLOR_FORMAT sF, s32 sN, void* dP, ECOLOR_FORMAT dF)
PS2: The code I wrote was tested on win32 with VC9 express
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Yes, that's the function. However, I cannot see how you can access the functions which are buried inside the dll. There's no public interface for them, so they are largely inaccessible.
slavik262
Posts: 753
Joined: Sun Nov 22, 2009 9:25 pm
Location: Wisconsin, USA

Post by slavik262 »

Could you expose that function? It would be incredibly useful to a lot of people.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

As you can see from the code snippet above, it will be exposed in Irrlicht 1.8. The convertColor function subsumes all the specialised convertColorAtoColorB functions via the color format parameters. So you basically only need one such function, which will be part of the video driver interface.
slavik262
Posts: 753
Joined: Sun Nov 22, 2009 9:25 pm
Location: Wisconsin, USA

Post by slavik262 »

Awesome. Can't wait to see it!
eye776
Posts: 94
Joined: Sun Dec 28, 2008 11:07 pm

Post by eye776 »

So the code would become (in irrlicht 1.8):

Code: Select all

IImage* getARGBImage(stringc filename) 
{ 
IImage* srcImage = IVideoDriver::createImageFromFile(filename); 
IImage* bmpImage = NULL; 

   if(srcImage->getColorFormat() != ECF_A8R8G8B8) { 
      printf("Image color format doesn't match, converting!\n"); 
      bmpImage = System::Driver->createImage(ECF_A8R8G8B8, srcImage->getDimension()); 
      IVideoDriver::convertColor(srcImage->lock(), srcImage->getColorFormat(), (srcImage->getDimension().Width * srcImage->getDimension().Height), bmpImage->lock(), ECF_A8R8G8B8);
      srcImage->unlock();
      srcImage->drop();
      bmpImage->unlock();
      return bmpImage; 
  } else {
       return srcImage; 
  }

}
EDIT: Edited according to what hybrid stated below.
Last edited by eye776 on Fri Jun 04, 2010 9:11 am, edited 8 times in total.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

You can avoid the additional alloc/free and data copy by creating an empty image with the proper dimension and color format, lock it, and use that pointer as parameter for convert destination.
Post Reply