Hello.
Well, a few days ago I was asking for some help here regarding this subject, but I backed out, as I hate asking for help as much as most people abhor giving it. Since then I have gone through the docs and turned my brain to pineapple pulp trying to figure this out. I have only had limited success. Yes, there is a similar thread around here, but it is not specifically what I am doing. Sorry about that!
So… please help!
THE OBJECTIVE:
- Load a 32 bit BMP into an SDL_Surface structure.
- Recover the data on the image (format, bytes_pp, width, height, depth, etcetera).
- Save the pixel data from the surface (cast Uint32*) to a binary file with SDL_RWops.
- Create a new pixel array, identical to the one saved.
- Load the pixel data into it with SDL_RWops.
- Create a new SDL_Surface with SDL_CreateRGBSurfaceWithFormatFrom(), using the new array pixel data.
When I finally got some results, the data (pixel position and abgr8888) seems to be all mangled, as if there is some keying that I am not applying, or something. Or maybe the array I am storing the data in is inadequate for the format expected? I cannot find any deeper details on that (*pixels), it is a bit vague in the docs. In the printf output, I am noticing there is no consistency in the color order. I notice this because I see the alpha jumping around, from array element to array element.
I am baffled. Is what I am trying to do even possible with SDL?
Anyway, for posterity, here is the code.
#include <SDL.h>
#include <stdio.h>
typedef enum { false, true } bool;
int main(int argc, char* argv[])
{
if (SDL_Init(SDL_INIT_VIDEO) != 0)
{
return -1;
}
SDL_RWops* the_file = NULL;
SDL_Surface* new_surface = NULL;
SDL_Surface* remake_surface = NULL;
const char* new_image = "bird.bmp";
new_surface = SDL_LoadBMP_RW(SDL_RWFromFile(new_image, "rb"), 1);
Uint8 image_bytes_pp = new_surface->format->BytesPerPixel;
int image_pitch = new_surface->pitch;
int image_width = new_surface->w;
int image_height = new_surface->h;
int image_size = image_width * image_height;
Uint8 image_depth = new_surface->format->BitsPerPixel;
SDL_PixelFormat* image_pixel_format = new_surface->format;
Uint32 pixel_format_enum = new_surface->format->format;
const char* pixel_format_name = SDL_GetPixelFormatName(pixel_format_enum);
SDL_Color abgr;
int x = 0;
int y = 0;
int i = 0;
int x_coord_address_index = x * image_pitch;
int y_coord_address_index = y * image_bytes_pp;
int coord_address_index = x_coord_address_index + y_coord_address_index;
Uint8* pixel_array_channels = NULL;
Uint8* pixel_address_ptr = NULL;
printf("%s\n", SDL_GetPixelFormatName(pixel_format_enum));
printf("%u\n", image_bytes_pp);
printf("%u\n", image_depth);
printf("%d\n", image_pitch);
printf("%d\n", coord_address_index);
printf("Should this surface be locked? %s", SDL_MUSTLOCK(new_surface) == 0 ? "NO" : "YES");
SDL_Delay(3500);
Uint32* pixel_array = SDL_calloc(image_size, sizeof(Uint32));
//for(y = 0; y < image_height; y++)
//for (x = 0; x < image_width; x++)
//for (x = (image_width - 1); x > -1; x--)
for (y = (image_height - 1); y > -1; y--)
{
//for (x = 0; x < image_width; x++)
//for (y = 0; y < image_height; y++)
//for (y = (image_height - 1); y > -1; y--)
for (x = (image_width - 1); x > -1; x--)
{
x_coord_address_index = x * image_pitch;
y_coord_address_index = y * image_bytes_pp;
coord_address_index = x_coord_address_index + y_coord_address_index;
pixel_address_ptr = (Uint8*)new_surface->pixels + coord_address_index;
// Something weird is happening here with the following function...
SDL_GetRGBA(*(Uint32*)pixel_address_ptr, image_pixel_format, &abgr.r, &abgr.g, &abgr.b, &abgr.a);
if (pixel_array != NULL)
{
// Or something weird is happening here. Debugger is not placing it as it is not a programming error,
// but a format order and/or scanline storage error, it would seem.
pixel_array_channels = (Uint8*)&pixel_array[i];
pixel_array_channels[0] = (Uint8)abgr.r;
pixel_array_channels[1] = (Uint8)abgr.g;
pixel_array_channels[2] = (Uint8)abgr.b;
pixel_array_channels[3] = (Uint8)abgr.a;
// The order of the
printf("Red: 0x%02x, ", pixel_array_channels[0]);
printf("Green: 0x%02x, ", pixel_array_channels[1]);
printf("Blue: 0x%02x, ", pixel_array_channels[2]);
printf("Alpha: 0x%02x\n", pixel_array_channels[3]);
printf("Pixel: 0x%08x\n", pixel_array[i]);
i++;
}
else
{
return -1;
}
}
}
i = 0;
const char* file_name = "new_bird.bin";
the_file = SDL_RWFromFile(file_name, "w+b");
if (the_file != NULL)
{
SDL_RWwrite(the_file, pixel_array, sizeof(Uint32), image_size);
SDL_RWclose(the_file);
the_file = NULL;
}
// There is one last possibility here, though I doubt it.
// Perhaps the data is getting mangled between the writing and the reading.
// I assume that SDL_RWread is configured to "read" as SDL_RWwrite "writes".
// It would not make any sense if it did not, but I do not know.
Uint32* new_pixel_array = SDL_calloc(image_size, sizeof(Uint32));
the_file = SDL_RWFromFile(file_name, "r+b");
if (the_file != NULL)
{
SDL_RWread(the_file, new_pixel_array, sizeof(Uint32), image_size);
SDL_RWclose(the_file);
}
remake_surface = SDL_CreateRGBSurfaceWithFormatFrom((Uint32*)new_pixel_array,
image_width, image_height, (int)image_depth, image_pitch, pixel_format_enum);
SDL_Window* local_window = NULL;
SDL_Surface* local_window_surface = NULL;
local_window = SDL_CreateWindow("Image",
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
image_width, image_height, SDL_WINDOW_SHOWN);
local_window_surface = SDL_GetWindowSurface(local_window);
SDL_BlitSurface(remake_surface, NULL, local_window_surface, NULL);
SDL_UpdateWindowSurface(local_window);
bool quit = false;
SDL_Event loop_event;
while (quit == false)
{
while (SDL_PollEvent(&loop_event) != true)
{
if (loop_event.type == SDL_QUIT)
{
quit = true;
}
}
}
SDL_FreeSurface(new_surface);
SDL_FreeSurface(remake_surface);
SDL_FreeSurface(local_window_surface);
SDL_DestroyWindow(local_window);
SDL_free(pixel_array);
SDL_free(new_pixel_array);
SDL_Quit();
return 0;
}
Here is the image I want to store, on the left. The results, after being put through the program, are on the right. Kind of getting there, after many failures, but not quite there yet…
Is there a trick? Any ideas?
My sincere thanks in advance, if you can spare a little time to de-fuddle me.