Identify pixel data format in SDL - opengl

Running on OS X, I've loaded a texture in OpenGL using SDL_Image library (using IMG_LOAD() which returns SDL_Surface*). It appeared that the color channels have been swapped, i.e. I had to set GL_BGRA as a pixel format parameter in glTexImage2D().
Is there a way to determine the correct data format (BGRA or RGBA or etc...) without just simply compiling and checking the texture? And what is the reason that SDL swaps these color channels?

Yes. Following link has code examples of how to determine the channel shift for each component: http://wiki.libsdl.org/SDL_PixelFormat#Code_Examples
From the site:
SDL_PixelFormat *fmt;
SDL_Surface *surface;
Uint32 temp, pixel;
Uint8 red, green, blue, alpha;
.
.
.
fmt = surface->format;
SDL_LockSurface(surface);
pixel = *((Uint32*)surface->pixels);
SDL_UnlockSurface(surface);
/* Get Red component */
temp = pixel & fmt->Rmask; /* Isolate red component */
temp = temp >> fmt->Rshift; /* Shift it down to 8-bit */
temp = temp << fmt->Rloss; /* Expand to a full 8-bit number */
red = (Uint8)temp;
You should be able to sort the Xmasks by value. Then you may determine if its RGBA or BGRA. If Xmask == 0 then the color channel does not exist.
I have no idea why the swaps occur.
Edit: Changed from Xshift to Xmask as the latter may be used to determine both location AND existance of color channels.

Related

What are this properties in libjpeg and in libpng?

I'm actually using the libjpeg to read and save JPEG images.
So first what are the possibilities of pixel size (info.output_components;) ?
What are the possibilities of color space (info.out_color_space;) ?
And can a JPEG image have an alpha channel ?
I'm using the libpng too.
So first what is the bit depth (png_get_bit_depth(png, info);) ?
And what is the color type (png_get_color_type(png, info);) ?
Thanks !
So first what are the possibilities of pixel size (info.output_components;) ?
From the doc
output_components is 1 (a colormap index) when quantizing colors; otherwise it
equals out_color_components. It is the number of JSAMPLE values that will be
emitted per pixel in the output arrays.
int out_color_components; /* # of color components in out_color_space */
int output_components; /* # of color components returned */
/* output_components is 1 (a colormap index) when quantizing colors;
* otherwise it equals out_color_components.
What are the possibilities of color space (info.out_color_space;) ?
From the source
JCS_UNKNOWN, /* error/unspecified */
JCS_GRAYSCALE, /* monochrome */
JCS_RGB, /* red/green/blue as specified by the RGB_RED,
RGB_GREEN, RGB_BLUE, and RGB_PIXELSIZE macros */
JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */
JCS_CMYK, /* C/M/Y/K */
JCS_YCCK, /* Y/Cb/Cr/K */
JCS_EXT_RGB, /* red/green/blue */
JCS_EXT_RGBX, /* red/green/blue/x */
JCS_EXT_BGR, /* blue/green/red */
JCS_EXT_BGRX, /* blue/green/red/x */
JCS_EXT_XBGR, /* x/blue/green/red */
JCS_EXT_XRGB, /* x/red/green/blue */
/* When out_color_space it set to JCS_EXT_RGBX, JCS_EXT_BGRX, JCS_EXT_XBGR,
or JCS_EXT_XRGB during decompression, the X byte is undefined, and in
order to ensure the best performance, libjpeg-turbo can set that byte to
whatever value it wishes. Use the following colorspace constants to
ensure that the X byte is set to 0xFF, so that it can be interpreted as an
opaque alpha channel. */
JCS_EXT_RGBA, /* red/green/blue/alpha */
JCS_EXT_BGRA, /* blue/green/red/alpha */
JCS_EXT_ABGR, /* alpha/blue/green/red */
JCS_EXT_ARGB, /* alpha/red/green/blue */
JCS_RGB565 /* 5-bit red/6-bit green/5-bit blue */
And can a JPEG image have an alpha channel ?
As you can see from the source code above, libjpeg-turbo does support alpha channel for jpegs.
So first what is the bit depth (png_get_bit_depth(png, info);) ?
Simply put, number of bits used to represent each pixel in an image. The higher the bit depth, the more colors each pixel can contain.
From the PNG Spec:
Color type is a single-byte integer that describes the interpretation of the image data. Color type codes represent sums of the following values: 1 (palette used), 2 (color used), and 4 (alpha channel used). Valid values are 0, 2, 3, 4, and 6.
Color Allowed Interpretation
Type Bit Depths
0 1,2,4,8,16 Each pixel is a grayscale sample.
2 8,16 Each pixel is an R,G,B triple.
3 1,2,4,8 Each pixel is a palette index;
a PLTE chunk must appear.
4 8,16 Each pixel is a grayscale sample,
followed by an alpha sample.
6 8,16 Each pixel is an R,G,B triple,
followed by an alpha sample.

How to go from raw Bitmap data to SDL Surface or Texture?

I'm using a library called Awesomium and it has the following function:
void Awesomium::BitmapSurface::CopyTo ( unsigned char * dest_buffer, // output
int dest_row_span, // input that I can select
int dest_depth, // input that I can select
bool convert_to_rgba, // input that I can select
bool flip_y // input that I can select
) const
Copy this bitmap to a certain destination. Will also set the dirty bit to False.
Parameters
dest_buffer A pointer to the destination pixel buffer.
dest_row_span The number of bytes per-row of the destination.
dest_depth The depth (number of bytes per pixel, is usually 4 for BGRA surfaces and 3 for BGR surfaces).
convert_to_rgba Whether or not we should convert BGRA to RGBA.
flip_y Whether or not we should invert the bitmap vertically.
This is great because it gives me an unsigned char * dest_buffer which contains raw bitmap data. I've been trying for several hours to convert this raw bitmap data into some sort of usable format that I can use in SDL but I'm having trouble. =[ Is there any way I can load it into a SDL texture or surface? It would be ideal to have examples for both but if I only get one example (either texture or surface), that is sufficient and I will be very grateful. :) I tried to use SDL_LoadBMP_RW but that crashed. I'm not even sure if I should be using that method.
SDL_LoadBMP_RW is for loading an image in the BMP file format. And it expects an SDL_RWops*, which is a file stream, not a pixel buffer. The function you want is SDL_CreateRGBSurfaceFrom. I believe this call should work for your purposes:
SDL_Surface* surface =
SDL_CreateRGBSurfaceFrom(
pixels, // dest_buffer from CopyTo
width, // in pixels
height, // in pixels
depth, // in bits, so should be dest_depth * 8
pitch, // dest_row_span from CopyTo
Rmask, // RGBA masks, see docs
Gmask,
Bmask,
Amask
);

how to acces colour of individual pixels using SOIL in cpp

I would like to access the RGB valuas from individual pixels. I know I can get an unsigned char array by calling
unsigned char* pixels = SOIL_load_image(picturename.c_str(), &_w, &_h, 0, SOIL_LOAD_RGB);
However I dont understand what these chars mean. The documentation says:
// The return value from an image loader is an 'unsigned char *' which points
// to the pixel data. The pixel data consists of *y scanlines of *x pixels,
// with each pixel consisting of N interleaved 8-bit components; the first
// pixel pointed to is top-left-most in the image. There is no padding between
// image scanlines or between pixels, regardless of format. The number of
// components N is 'req_comp' if req_comp is non-zero, or *comp otherwise.
// If req_comp is non-zero, *comp has the number of components that _would_
// have been output otherwise. E.g. if you set req_comp to 4, you will always
// get RGBA output, but you can check *comp to easily see if it's opaque.
However when I load an 10 by 10 pixels image to test it i get an huge ammound of chars in the array (almost 54000) this seems way too much. How do i get the individual pixel colour that I can do something like this:
int colourvalue = pixel[y*width+x];
i cant seem to find this

Rendering pixels from array of RGB values in SDL 1.2?

I'm working on a NES emulator right now and I'm having trouble figuring out how to render the pixels. I am using a 3 dimensional array to hold the RGB value of each pixel. The array definition looks like this for the 256 x 224 screen size:
byte screenData[224][256][3];
For example, [0][0][0] holds the blue value, [0][0][1] holds the green values and [0][0][2] holds the red value of the pixel at screen position [0][0].
When the vblank flag goes high, I need to render the screen. When SDL goes to render the screen, the screenData array will be full of the RGB values for each pixel. I was able to find a function named SDL_CreateRGBSurfaceFrom that looked like it may work for what I want to do. However, all of the examples I have seen use 1 dimensional arrays for the RGB values and not a 3 dimensional array.
What would be the best way for me to render my pixels? It would also be nice if the function allowed me to resize the surface somehow so I didn't have to use a 256 x 224 window size.
You need to store the data as an unidimensional char array:
int channels = 3; // for a RGB image
char* pixels = new char[img_width * img_height * channels];
// populate pixels with real data ...
SDL_Surface *surface = SDL_CreateRGBSurfaceFrom((void*)pixels,
img_width,
img_height,
channels * 8, // bits per pixel = 24
img_width * channels, // pitch
0x0000FF, // red mask
0x00FF00, // green mask
0xFF0000, // blue mask
0); // alpha mask (none)
In 2.0, use SDL_Texture + SDL_TEXTUREACCESS_STREAMING + SDL_RenderCopy, it's faster than SDL_RenderPoint.
See:
official example: http://hg.libsdl.org/SDL/file/e12c38730512/test/teststreaming.c
my derived example which does not require blob data and compares both methods: https://github.com/cirosantilli/cpp-cheat/blob/0607da1236030d2e1ec56256a0d12cadb6924a41/sdl/plot2d.c
Related: Why do I get bad performance with SDL2 and SDL_RenderCopy inside a double for loop over all pixels?

OpenGL - Getting The Display Color Bits

I'm looking at the LWJGL wiki for taking a screenshot (found here) and I noticed the comment Assuming a 32-bit display with a byte each for red, green, blue, and alpha. in this code:
GL11.glReadBuffer(GL11.GL_FRONT);
int width = Display.getDisplayMode().getWidth();
int height= Display.getDisplayMode().getHeight();
int bpp = 4; // Assuming a 32-bit display with a byte each for red, green,
//blue, and alpha.
ByteBuffer buffer = BufferUtils.createByteBuffer(width * height * bpp);
GL11.glReadPixels(0, 0, width, height, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buffer );
How would I change the var bpp based off of the current system?
In case you're still looking for an answer:
You can get the bytes per pixel of the current display mode by getting it from LWJGL's Display class. It would look something like this:
int bpp = Display.getDisplayMode().getBitsPerPixel()/4