Render to bitmap

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
guest22
Posts: 5
Joined: Mon Mar 12, 2007 2:55 pm

Render to bitmap

Post by guest22 »

Hi,

I want to render a scene, and later use it as a Win32 HBITMAP.
I have the following Qs.

1) This is I want to use it:

Code: Select all

void* pixels = rt->lock();
...
HBITMAP hbmp = foo(pixels);
...
Is there a code in irrlicht which is doing the "foo" ?

2) Currently I'm using a texture as target, as described in http://irrlicht.sourceforge.net/tut013.html
Is there a way to get a CImage object from video::ITexture ?

10x,
g22.
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

If you have an video::IImage or a video::ITexture it should not be very difficult to create an MFC CImage from it. The CImage class has a Create() method that takes a height, width and bit depth. You would need to create your image based on the size and type of the source image. Then you'd need to copy bits from the source image to the destination.

The easiest way might just be to use getPixel() and SetPixel().

Code: Select all

const core::dimension2di dim(src->getDimension());

// if height is negative, the bitmap is a top-down DIB and its origin is the upper left corner
CImage img;
img.Create(dim.Width, -dim.Height, src->getBytesPerPixel() * 8);

u32 x, y;
for (y = 0; y < dim.Height; ++y)
{
  for (x = 0; x < dim.Width; ++x)
  {
    video::SColor pixel = src->getPixel(x, y);

    // video::SColor stores color in 0xaarrggbb format and 
    // COLORREF stores color in 0x00bbggrr format so we must
    // reverse the rr and bb parts
    COLORREF clr;
    clr = ((pixel.color & 0x000000ff) << 16) |
            ((pixel.color & 0x0000ff00)) |
            ((pixel.color & 0x00ff0000) >> 16);
    img.SetPixel(x, y, clr);

    //// this should be equivalent to the code above, but probably slower
    //img.SetPixel(x, y, RGB(pixel.getRed(), pixel.getGreen(), pixel.getBlue());
  }
}
Now you could get fancy and copy the image in its native format by locking the image and copying each row of pixels. This would be faster, but you have to write more special case code.

Travis
guest22
Posts: 5
Joined: Mon Mar 12, 2007 2:55 pm

Post by guest22 »

Hi Travis,

10x, but I actually meant the CImage used in irrlicht, and not MFC CImage.

Maybe I should have asked
Is there any way to go from video::ITexture to video::IImage ?
Or is it possible to use IImage as rendering target ?

Regarding Q1, I think I know how to do it (similar to your solution for MFC),
but I thought maybe there is a code in irrlicht which already does it which I couldn't find (newbieness).

10x.
g22.
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

I assumed you meant the MFC CImage because you want an HBITMAP handle to the data. There was that and the fact that the Irrlicht CImage class is not public. It is not directly accessible to the user because it is not exported from the Irrlicht library. You can only really access an IImage interface for a CImage that is created by the driver.

I don't know of any code to copy from an ITexture to a IImage. You can write it yourself pretty easily, much like the above code. As I mentioned, it would be faster to memcpy each row of color instead of copying each pixel one at a time. If you have an ITexture you can easily create an IImage with the same color format and size. Once you've done that, you can just memcpy the data from each line of the the texture to the image.

Of course if you need an HBITMAP you should create one directly from the ITexture pixel datat instead of going through the steps of creating and copying an intermediary IImage.

If you just want to get the last rendered image as an IImage you should be able to use the createScreenShot() method of the video driver for that. There is even code in there for writing the IImage to disk.

Travis
Post Reply