Endian?

Hello,

I use SDL (trough ocamlsdl) under Mac Os X (on ppc).
When I use Image loader, everytime I try to read a png file, SDL
invert red and blue channel. This does not occure on png with
colormap. I think it is a problem of endianness, and I see that
this seems to be a common error
(by google some keywords, I saw that this problem seems to
happen oftenly).
So is my question : Do I make some mistake (but when I use
imageloader, I just give the filename, so I don’t have a lots of
choices…), or is there some fix that will be published soon ?

Thank you, SDL is very useful to make cross plateform things !!

Hello, this sounds strange to me.
1-Can you show (only) the part where you load ans display the image.
2-Can you load the image with another computer or/and another application correctly.

Christophe Papazian wrote:> Hello,

I use SDL (trough ocamlsdl) under Mac Os X (on ppc).
When I use Image loader, everytime I try to read a png file, SDL
invert red and blue channel. This does not occure on png with
colormap. I think it is a problem of endianness, and I see that
this seems to be a common error
(by google some keywords, I saw that this problem seems to
happen oftenly).
So is my question : Do I make some mistake (but when I use
imageloader, I just give the filename, so I don’t have a lots of
choices…), or is there some fix that will be published soon ?

Thank you, SDL is very useful to make cross plateform things !!


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

Here is the code :

let l = List.map (fun s -> s, Sdlloader.load_image s)
[“datas/red.gif”;“datas/red.png”;“datas/red.jpg”;
“datas/red.tif”;“datas/red.bmp”] in
List.iter (fun (n,s) -> let i = Sdlvideo.get_pixel s 0 0 in
let r,g,b = Sdlvideo.get_RGB s i in
Printf.printf “%20s : %3i %3i %3i\n” n r g b) l

(Sorry, it is ocaml code !)

It is a test. I create 5 picture, 16x16 pixels of plain red (255,0,0) with GIMP.
% file datas/*
datas/red.bmp: PC bitmap data, Windows 3.x format, 16 x 16 x 24
datas/red.gif: GIF image data, version 87a, 16 x 16
datas/red.jpg: JPEG image data, JFIF standard 1.01
datas/red.png: PNG image data, 16 x 16, 8-bit/color RGB, non-interlaced
datas/red.tif: TIFF image data, big-endian

  • WEIRD 1 *

I load them using Sdlimage, and i get the color of the first pixel,
and I print it.
Under macosx, I get this weird result :

SDL v1.2.10 initialized (Quartz)
datas/red.gif : 255 0 0
datas/red.png : 0 0 255 // weird
datas/red.jpg : 0 0 254 // weird
datas/red.tif : 255 0 0
datas/red.bmp : 0 0 255 // weird

So it is wrong on png, jpg and bmp (it gives plain blue !!). However, any other
applications show plain red on all those files (not only Gimp !)

  • WEIRD 2* (the normal behaviour comes back)

What is really strange, is that when i try to show this surfaces on screen.
When I use Sdlvideo
blit_surface, this work fine, every pictures appears correctly in red.
This is not the same, when I try to show them under OpenGl…

  • WEIRD 3*

I use opengl and create texture from previous sdlsurfaces I load…
Tif appears like a rainbow, BMP appears plain blue, and I can’t get gif
to appears at all…
PNG and JPG looks fine (plain red)…
This last strange behaviour could come from ocamlsdl wrapper,
because some code
is required to get sdl and OpenGl together under OCaml
But I think that the first two points are not caml-dependant,
but OSX dependant.
Could someone try it ?

thank you !

I will try the same code under another platform, but i have no pc at home,
so it will take some time !

Christophe Papazian wrote:

I load them using Sdlimage, and i get the color of the first pixel,
and I print it.
Under macosx, I get this weird result

What is really strange, is that when i try to show this surfaces on screen.
When I use Sdlvideo
blit_surface, this work fine, every pictures appears correctly in red.
This is not the same, when I try to show them under OpenGl…

That sounds like a) the code you use to “get the color of the first
pixel” and b) your OpenGL pixel format are broken (don’t take into
account the surface’s pixel format).

For a), it seems that the “Sdlvideo.get_pixel” or "Sdlvideo.get_RGB"
functions are to blame (if I understand that ocaml code correctly), do
you perchance have access to their implementation (in C, I suppose) to
post it (or a link to it) here?

For b), what are the arguments of your glTexImage2D (or equivalent) call?

-Christian

This is the same code I use, but I remove all ocaml,
and just extract C code from wrapper…
Is there something wrong ?

I compile with
gcc -L/usr/local/lib -lSDLmain -lSDL -lSDL_image -Wl,-framework,Cocoa test.c
(under MacOSX)

I will inspect my problem with OpenGL soon, but later…

########### test.c ##################
#include “SDL/SDL.h”
#include “SDL/SDL_image.h”

char *files[] = { “datas/red.gif”,“datas/red.png”,“datas/red.jpg”,
“datas/red.tif”,“datas/red.bmp”};

Uint32 getpixel(SDL_Surface *surface, int x, int y)
{
int bpp = surface->format->BytesPerPixel;
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;

switch(bpp) {
case 1: return *p;
case 2: return *(Uint16 *)p;
case 3: {
  unsigned int shift;
  Uint32 color=0;
  shift = surface->format->Rshift;
  color = *(p+shift/8)<<shift;
  shift = surface->format->Gshift;
  color|= *(p+shift/8)<<shift;
  shift = surface->format->Bshift;
  color|= *(p+shift/8)<<shift;
  shift = surface->format->Ashift;
  color|= *(p+shift/8)<<shift;
  return color;
}
case 4: return *(Uint32 *)p;
default: 
  return 0;       /* shouldn't happen, but avoids warnings */
}

}

int main(int argc, char *argv[]) {
SDL_Surface *surface;
int i;
Uint8 r,g,b;
SDL_PixelFormat fmt;
SDL_Init(SDL_INIT_EVERYTHING);

for(i=0;i<5;i++) {
SDL_Surface *surface = IMG_Load(files[i]);
SDL_GetRGB(getpixel(surface,0,0),surface->format,&r,&g,&b);
printf("%12s : %3i,%3i,%3i\n",files[i],r,g,b); }

return 0;
}

######### end of test.c #############

Output :

% ./a.out
datas/red.gif : 255, 0, 0
datas/red.png : 0, 0,255
datas/red.jpg : 0, 0,249
datas/red.tif : 255, 0, 0
datas/red.bmp : 0, 0,255

This is the same code I use, but I remove all ocaml,
and just extract C code from wrapper…
Is there something wrong ?

There is something looking bad. It doesn’t take into account the R/G/Bmask nor
R/G/Bloss fields of the SDL_PixelFormat struct. When I look into the sources of
SDL (1.2.7 but I guess there is no change), I have this:

void SDL_GetRGB(Uint32 pixel, SDL_PixelFormat *fmt, Uint8 *r,Uint8 *g,Uint8 b)
{
if ( fmt->palette == NULL ) {
/
the note for SDL_GetRGBA above applies here too */
unsigned v;
v = (pixel & fmt->Rmask) >> fmt->Rshift;
*r = (v << fmt->Rloss) + (v >> (8 - (fmt->Rloss << 1)));
v = (pixel & fmt->Gmask) >> fmt->Gshift;
*g = (v << fmt->Gloss) + (v >> (8 - (fmt->Gloss << 1)));
v = (pixel & fmt->Bmask) >> fmt->Bshift;
*b = (v << fmt->Bloss) + (v >> (8 - (fmt->Bloss << 1)));
} else {
*r = fmt->palette->colors[pixel].r;
*g = fmt->palette->colors[pixel].g;
*b = fmt->palette->colors[pixel].b;
}
}

I don’t know about ocaml / C wrapper, but I wonder why it doesn’t call this
code. You should check around, good luck!

########### test.c ##################
[…]
unsigned int shift;
Uint32 color=0;
shift = surface->format->Rshift;
color = *(p+shift/8)<<shift;
shift = surface->format->Gshift;
color|= *(p+shift/8)<<shift;
shift = surface->format->Bshift;
color|= *(p+shift/8)<<shift;
shift = surface->format->Ashift;
color|= *(p+shift/8)<<shift;
return color;
[…]

And stolen from the downloadable doc (1.2.7), there is an example of the
getpixel() function… I think there should be no use of the SDL_PixelFormat
stuct when you extract the Uint32 pixel!

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

switch(bpp) {
case 1:
    return *p;

case 2:
    return *(Uint16 *)p;

case 3:
    if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
        return p[0] << 16 | p[1] << 8 | p[2];
    else
        return p[0] | p[1] << 8 | p[2] << 16;

case 4:
    return *(Uint32 *)p;

default:
    return 0;       /* shouldn't happen, but avoids warnings */
}

}

thank you Nuage,
it seems the wrapper is a little bit old… and needs some rewriting !