Sign in to follow this  

Create bitmap with sdl or load one from memory.

This topic is 3307 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have some files which contains informations on how to build an image (for example a map tile). I did a little c++ program that reads that file, read every pixel color/position and with the support of CImage i "draw" the bitmap (using the function SetPixelRGB). After that i saved it as an image. Now my problem is: how can i create a bitmap with SDL in the same way i did with CImage (so have a bitmap object that can be loaded by SDL)? I don't want to load it from file but from memory. Edit: Forgot to say that i'm making a SDL game as a start, but then i want to use also OpenGL, so if there's a faster/better solution with OpenGL it's ok ;).

Share this post


Link to post
Share on other sites
I may be misunderstanding what you want, but it sounds like you want to use SDL to create a empty image, and place the pixels on the image yourself.

If that's so, to create a empty image, you use SDL_CreateRGBSurface.

Unfortunately, SDL doesn't have any functions for placing and retrieving pixels from a surface, but it's not too hard to make your own. See here for information.

You must use SDL_LockSurface to lock the empty image first before placing pixels, if the surface requires it.

Share this post


Link to post
Share on other sites
Upon re-reading your post, I see that I did infact misunderstand you. [grin]

You already have a bitmap in memory, and you want to turn it into a SDL_Surface?

If it's a BMP file in memory, use SDL_LoadBMP_RW. If you are using the SDL_image library, and you have a JPEG/PNG file in memory, you can use SDL_LoadIMG_RW. If it's raw pixel data, use SDL_CreateRGBSurfaceFrom.

I've never done it personally, so I can't give details, but if you google those function names, you should find information informing you how to use them. This GPWiki page ought to help you get started.

Share this post


Link to post
Share on other sites
Quote:
Original post by Servant of the Lord
Upon re-reading your post, I see that I did infact misunderstand you. [grin]

You already have a bitmap in memory, and you want to turn it into a SDL_Surface?

If it's a BMP file in memory, use SDL_LoadBMP_RW. If you are using the SDL_image library, and you have a JPEG/PNG file in memory, you can use SDL_LoadIMG_RW. If it's raw pixel data, use SDL_CreateRGBSurfaceFrom.

I've never done it personally, so I can't give details, but if you google those function names, you should find information informing you how to use them. This GPWiki page ought to help you get started.


Your first post has the answer to my question.
Anyway i have to create a bitmap object handled by SDL drawing it pixel by pixel, and i was asking if there's a way to do it with SDL or a way to load with SDL a bitmap object created from scratch with another method (for example using my previos code which uses CImage, or using OpenGL because it's more performant).
Now i check SDL_CreateRGBSurface etc, thnx.

Share this post


Link to post
Share on other sites
Now i have problems with color :
The file which contains information about pixel etc store each pixel color as a 16bit color, with URGB format (U beacuse that bit is unused).

This is what i did with the previous program:


struct SColor
{
union
{
unsigned int ARGB;
struct
{
unsigned char B;
unsigned char G;
unsigned char R;
unsigned char A;
};
};
};

[...]

// Buffer to load all pixels
unsigned short buffer[1024];

// Read all image pixels
Artmul.read((char*)&buffer, 2048);

[...] // Here starts a loop, but suppose i'm getting the color of the first pixel only
counter = 0;

SColor color;

color.ARGB =
(((buffer[counter] >> 10) & 0x1F) << 19) | // RED
(((buffer[counter] >> 5) & 0x1F) << 11) | // GREEN
(((buffer[counter] ) & 0x1F) << 3); // BLUE

// Set pixel color on CImage, using color.R, color.G, color.B




That way it's all ok, and when i save the image it has the right colors.

But with my SDL program what i'm supposed to do?

I already tried to write something:


[...]
SDL_Surface *temp, *image;

Uint32 rmask, gmask, bmask;

/* SDL interprets each pixel as a 32-bit number, so our masks must depend
on the endianness (byte order) of the machine */

#if SDL_BYTEORDER == SDL_BIG_ENDIAN
rmask = 0xff000000;
gmask = 0x00ff0000;
bmask = 0x0000ff00;
#else <- it enters here
rmask = 0x000000ff;
gmask = 0x0000ff00;
bmask = 0x00ff0000;
#endif

temp = SDL_CreateRGBSurface(SDL_HWSURFACE, 44, 44, 32,
rmask, gmask, bmask, 0);

SDL_LockSurface(temp);
if(temp == NULL) {
fprintf(stderr, "CreateRGBSurface failed: %s\n", SDL_GetError());
exit(1);
}
[...]

void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel)
{
int bpp = surface->format->BytesPerPixel;
/* Here p is the address to the pixel we want to set */
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;

switch(bpp) {
case 1:
*p = pixel;
break;

case 2:
*(Uint16 *)p = pixel;
break;

case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
p[0] = (pixel >> 16) & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = pixel & 0xff;
} else {
p[0] = pixel & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = (pixel >> 16) & 0xff;
}
break;

case 4:
*(Uint32 *)p = pixel;
break;
}
}




Now what i'm supposed to do?
I mean, already tried to use the previous method, passing color.ARGB to function putpixel but it gives me a horrible image :D.

I'm a little confused on how to convert the color in the right way for SDL.

[Edited by - Smjert on December 28, 2008 6:05:55 AM]

Share this post


Link to post
Share on other sites
I solved in this way:


struct SColor
{
union
{
unsigned int ARGB;
struct
{
unsigned char B;
unsigned char G;
unsigned char R;
unsigned char A;
};
};
};


SColor scolor;

scolor.ARGB =
(((buffer[counter] >> 10) & 0x1F) << 19) | // RED
(((buffer[counter] >> 5) & 0x1F) << 11) | // GREEN
(((buffer[counter] ) & 0x1F) << 3); // BLUE

color = SDL_MapRGB(temp->format, scolor.R, scolor.G, scolor.B);





the next step is to understand if there's another way to get the color without struct and union..

Share this post


Link to post
Share on other sites
Now, I've never done much bitshifting work, so I can't check up on your math there, but like I mentioned in my second post, the function SDL_CreateRGBSurfaceFrom is used to make images from raw pixel data. You aren't required to manually place each pixel.

SDL_Surface *myNewImage = SDL_CreateRGBSurfaceFrom(myPixelBuffer, myImageWidth, myImageHeight, 16 /*bits per pixel*/, ..., 
rmask, gmask, bmask, amask);


If your format is URGB, then I think in your post you have the byte masks wrong. Granted, I said I don't do bit shifting much, but shouldn't it be...?
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
amask = 0xff000000;
rmask = 0x00ff0000;
gmask = 0x0000ff00;
bmask = 0x000000ff;
#else
amask = 0x000000ff;
rmask = 0x0000ff00;
gmask = 0x00ff0000;
bmask = 0xff000000;
#endif

It looks like you had the masks lined up for RGBA, not ARGB (or URGB, or whatever)

Ofcourse, my masks in that code right there are for a 32 bit pixel, I wouldn't know how to align them for a 16 bit one, I was just pointing out you had your Alpha/Unused after the RGB instead of before it like you said your pixels were stored in.

This might help a little also.

Also, SDL_GetRGB's documentation says this:
Quote:
This function uses the entire 8-bit [0..255] range when converting color components from pixel formats with less than 8-bits per RGB component (e.g., a completely white pixel in 16-bit RGB565 format would return [0xff, 0xff, 0xff] not [0xf8, 0xfc, 0xf8]).


Hopefully that helps you figure out how to do what you want; I can't help any farther than that, because I have no experience in 16 bit surfaces. Maybe someone else can help.

Share this post


Link to post
Share on other sites
First of all i want to say that my code works :P
Because with right shift it takes the single components (R then G then B), it make sure that it takes only 5 bits (with & 1F) and left shift the color to "transform" it in a 32bit color.

SDL_CreateRGBSurfaceFrom is a bit confusing, how is the format of the pixel buffer i have to pass (and if is simply an array of colour, one for pixel, in wich order i have to pass them?, because in my case the image is a square, but rotated 45 degree).

However the mask for the surface is BGRA (and is chosen by SDL_BYTEORDER, so i don't think it's good to use RGB mask for the surface), but when i put pixels i use the RGB color format, and it works... dont' ask me why :\.
The strange thing is that i need to use union because if i use the shifted color component (from above) the image has the wrong colors.

EDIT: oh wait, i know why it works, with a BGRA mask and RGB color... because i use the function SDL_MapRGB that reads what format has the surface and out a BGR color.

[Edited by - Smjert on December 28, 2008 3:37:11 PM]

Share this post


Link to post
Share on other sites
Sign in to follow this