SFML community forums

Help => Graphics => Topic started by: Prominence256 on January 27, 2011, 03:26:45 am

Title: Loading an image from a .rc file
Post by: Prominence256 on January 27, 2011, 03:26:45 am
I'm trying to upgrade my screensaver from using Shapes to using actual images. I have it working and everything, but I was wondering if there was a way to set an sf::Image from an image saved in a .rc file, that way my screensaver's just one file.
Title: Loading an image from a .rc file
Post by: Laurent on January 27, 2011, 07:38:10 am
Get a pointer to the contents of your resource and use LoadFromMemory.
Title: Loading an image from a .rc file
Post by: Prominence256 on January 27, 2011, 11:03:30 pm
Do you have an example of this? This is what I tried and it didn't work:
Code: [Select]
Image zero;
HBITMAP img = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BITMAP0));
zero.LoadFromMemory((const char*) img, sizeof(img));
Title: Loading an image from a .rc file
Post by: Laurent on January 27, 2011, 11:16:17 pm
I don't know how to do, but it's a little bit more complicated than this. Read carefully the MSDN doc and tutorials.
Title: Loading an image from a .rc file
Post by: Groogy on January 27, 2011, 11:49:31 pm
my guess is that the "sizeof" is wrong. The BITMAP variable is more or less a pointer/reference to the data. Just like if you would use sizeof(sf::Image) you would not get the amount of bytes the image data consist of but you would get the byte size of the instance sf::Image.

You'll have to acquire the size somehow else.

Never used BITMAP myself before, just an educated guess ^^
Title: Loading an image from a .rc file
Post by: JAssange on January 28, 2011, 01:59:54 am
Bitmaps are stored in memory like this (http://en.wikipedia.org/wiki/BMP_file_format#DIBs_in_memory) under Windows.
Title: Loading an image from a .rc file
Post by: Disch on January 29, 2011, 11:16:02 pm
Acquiring a pointer to resource data is a multi-step process.

1)  FindResource to find it
2)  LoadReourse to get a handle to it
3)  LockResource to get the data pointer


After that I'm not sure how you free the resource as there doesn't seem to be an UnlockResource function.  You can search MSDN for details on all these functions.
Title: Loading an image from a .rc file
Post by: Prominence256 on January 30, 2011, 02:10:36 am
Thanks, and according to MSDN LockResource doens't actually lock anything as of XP.

But now my issue is what to put for the SizeInBytes in LoadFromMemory.
Title: Loading an image from a .rc file
Post by: JAssange on January 30, 2011, 02:31:32 am
Quote from: "Prominence256"
Thanks, and according to MSDN LockResource doens't actually lock anything as of XP.

But now my issue is what to put for the SizeInBytes in LoadFromMemory.

Width * Height *4
Title: Loading an image from a .rc file
Post by: Disch on January 30, 2011, 03:27:16 am
Quote from: "JAssange"

Width * Height *4


No, he needs the size of the bitmap/whatever file.

To get the size of a resource,use SizeofResource:

http://msdn.microsoft.com/en-us/library/ms648048%28v=vs.85%29.aspx
Title: Loading an image from a .rc file
Post by: Prominence256 on January 30, 2011, 03:56:19 am
I tried all of this together and the image showed up as a little white dot on the screen, also SFML printed this to the console:
Quote from: "SFML"
Failed to load image from memory. Reason : Image not of any known type, or corrupt

This was my code:
Code: [Select]
Image zeroimg;
HRSRC hresource = FindResource(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BITMAP1), RT_BITMAP);
HGLOBAL hglobal = LoadResource(GetModuleHandle(NULL), hresource);
LPVOID lpvoid = LockResource(hglobal);
zeroimg.LoadFromMemory((const char*) lpvoid, SizeofResource(GetModuleHandle(NULL), hresource));

Here's (http://www.filedropper.com/file_73) a link to the picture, I couldn't find an image host that doesn't convert the image to a png.
Title: Loading an image from a .rc file
Post by: JAssange on January 30, 2011, 04:05:30 am
Quote from: "Disch"
Quote from: "JAssange"

Width * Height *4


No, he needs the size of the bitmap/whatever file.

To get the size of a resource,use SizeofResource:

http://msdn.microsoft.com/en-us/library/ms648048%28v=vs.85%29.aspx

But he said LoadFromMemory so I assume he means the SFML function, which only takes the pixels in ARGB format, which would be w*h*4.
Title: Loading an image from a .rc file
Post by: Prominence256 on January 30, 2011, 04:12:11 am
I did mean the SFML function, but I get the same result with both width*height*4 and SizeofResource().
Title: Loading an image from a .rc file
Post by: JAssange on January 30, 2011, 05:25:27 am
Quote from: "Prominence256"
I did mean the SFML function, but I get the same result with both width*height*4 and SizeofResource().

Then the pointer isn't to ARGB formatted pixel data. You can't just take the handle of the Bitmap resource, it has a DIB header and a color table, its a completely different format. You need to parse it into an array of ARGB bytes.
Title: Loading an image from a .rc file
Post by: Laurent on January 30, 2011, 10:16:56 am
LoadFromMemory takes a pointer to a bitmap file in memory (the same thing that you would have on your hard drive).

LoadFromPixels takes a pointer to an array of RGBA pixels.

Use the one that suits what your resource is ;)
Title: Loading an image from a .rc file
Post by: Disch on January 30, 2011, 04:54:18 pm
Quote from: "Laurent"
LoadFromMemory takes a pointer to a bitmap file in memory (the same thing that you would have on your hard drive).


This is what I was thinking.  If that's the case, then the size of the resource will almost certainly not be equal to width*height*4
Title: Loading an image from a .rc file
Post by: JAssange on January 30, 2011, 05:02:17 pm
LoadFromMemory wants the bytes of a normal BMP file, not a Windows DIB.

Quote
This is what I was thinking. If that's the case, then the size of the resource will almost certainly not be equal to width*height*4

Sorry, was thinking of LoadFromPixels.
Title: Loading an image from a .rc file
Post by: Laurent on January 30, 2011, 05:54:36 pm
Quote
LoadFromMemory wants the bytes of a normal BMP file, not a Windows DIB.

I'm just wondering, isn't DIB the same thing that is inside bitmap files?
Title: Loading an image from a .rc file
Post by: JAssange on January 30, 2011, 06:00:24 pm
Quote from: "Laurent"
Quote
LoadFromMemory wants the bytes of a normal BMP file, not a Windows DIB.

I'm just wondering, isn't DIB the same thing that is inside bitmap files?

As far as I know they use a modified header.
Title: Loading an image from a .rc file
Post by: Disch on January 30, 2011, 07:27:20 pm
I wasn't aware there was any difference, either
Title: Loading an image from a .rc file
Post by: Prominence256 on January 30, 2011, 07:35:26 pm
Okay, I replaced
Code: [Select]
zeroimg.LoadFromMemory((const char*) lpvoid, SizeofResource(GetModuleHandle(NULL), hresource));with
Code: [Select]
zeroimg.LoadFromPixels(128, 128, (const Uint8*) lpvoid);
Now it shows a messed up version of the picture:
(http://www.freeimagehosting.net/uploads/8b45ccc9bf.png)
Title: Loading an image from a .rc file
Post by: Groogy on January 30, 2011, 07:49:18 pm
So the image is flipped? That's not messed up, your just a step away from having it working :)
Title: Loading an image from a .rc file
Post by: Prominence256 on January 30, 2011, 08:39:13 pm
It's not that it's flipped it's that it attached part of the right side to the left edge of the image. This, is what's getting drawn to the screen:
(http://www.freeimagehosting.net/uploads/e71c544c33.png)
Title: Loading an image from a .rc file
Post by: devlin on January 30, 2011, 09:06:38 pm
Seems to me you have a 10-40 byte (depending on bitdepth) header you're not removing before sending it to LoadFromPixels. It's not the stride or it would be diagonal.
Title: Loading an image from a .rc file
Post by: Prominence256 on January 30, 2011, 10:20:09 pm
How do I get rid of the header?
Title: Loading an image from a .rc file
Post by: devlin on January 30, 2011, 10:23:17 pm
Well, you could try it the hackish way and do:

zeroimg.LoadFromPixels(128, 128, ((const Uint8*) lpvoid) + 10); // or rather +30/+40 depending on bitdepth.
Title: Loading an image from a .rc file
Post by: Prominence256 on January 31, 2011, 01:54:34 am
I'm using 40 as the color depth, and that problems fixed. But now it's still upside down:
(http://www.freeimagehosting.net/uploads/df8a71d7f9.png)
Title: Loading an image from a .rc file
Post by: devlin on January 31, 2011, 10:18:51 am
Yes, that is normal for DIBs.

From Wikipedia:
Quote
The Pixel Array is a block of 32-bit DWORDs, that describes the image pixel by pixel. Normally pixels are stored "upside-down" with respect to normal image raster scan order, starting in the lower left corner, going from left to right, and then row by row from the bottom to the top of the image.[1]
Uncompressed Windows bitmaps also can be stored from the top to bottom, when the Image Height value is negative.
Title: Loading an image from a .rc file
Post by: Groogy on January 31, 2011, 11:48:18 am
You could before passing the pointer to the image create a temporary array where you copy each pixel but just make sure that you flip them. Then pass the array to the image and your done :)
Title: Loading an image from a .rc file
Post by: Disch on January 31, 2011, 04:40:12 pm
Wait... why did you switch to LoadFromPixels?  Was LoadFromMemory not working?

Loading from pixels seems like a really bad idea here.  I mean you already have a header and everything -- why not just load the image normally?
Title: Loading an image from a .rc file
Post by: devlin on January 31, 2011, 05:25:40 pm
Because LoadFromMemory doesn't support DIBs (nor should it, really), and the header differs between BMP and DIBs? :)
Title: Loading an image from a .rc file
Post by: Prominence256 on February 01, 2011, 12:36:56 am
Okay, I just used sf::Sprite::FlipY and everything's just fine. Thanks for all the help everybody! :D
Title: Loading an image from a .rc file
Post by: Disch on February 01, 2011, 05:09:46 am
Quote
Because LoadFromMemory doesn't support DIBs (nor should it, really), and the header differs between BMP and DIBs?


Is that even true?

I really didn't think there was any difference between the two.  Bitmaps are bitmaps.  It's a pretty standard format, I thought.

Quote
Okay, I just used sf::Sprite::FlipY and everything's just fine. Thanks for all the help everybody!


Blech.  This isn't a solution.  It's a hack, and you shouldn't be the least bit satisfied with it.

The obvious solution here would be to just use a supported image format.  Is there any reason you can't?
Title: Loading an image from a .rc file
Post by: Prominence256 on February 01, 2011, 06:14:22 pm
Well, is there any way to load a png from a .rc file using FindResource, LoadResource, and LockResource?

And according to wikipedia dib's and bmp's do have different headers.
Title: Loading an image from a .rc file
Post by: Disch on February 01, 2011, 06:29:06 pm
Quote from: "Prominence256"
Well, is there any way to load a png from a .rc file using FindResource, LoadResource, and LockResource?


Yes.

Find/Load/Lock the resource, then sf::Image::LoadFromMemory

Quote
And according to wikipedia dib's and bmp's do have different headers.


Interesting.  Learn something new every day I guess.