Java-Gaming.org Java4K winners: [ by our judges | by the community ]         
Featured games (67)
games approved by the League of Dukes
Games in Showcase (∞)
games submitted by our members



News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  Print  
  Endianness and row order for images  (Read 1284 times)
0 Members and 1 Guest are viewing this topic.
Offline invalidname

JGO n00b
*

Posts: 3


Do it wrong, not at all, or do it right.


« on: 2003-08-27 10:34:30 »

I'm reading in a gif with AWT/J2D and doing a color-space conversion from ARGB to RGBA (which JOGL likes better).  There are two things I can fix with bit-shifting and array-copying, but I figure there must be nicer approaches to:

1. The colors are right on Mac OS X, wrong on Windows.  I suspect that because I'm sending an int[] to glDrawPixels like this:
  gl.glDrawPixels (width, height, gl.GL_RGBA, gl.GL_UNSIGNED_BYTE, myIntArray);
that I'm suffering an endianness problem, ie, that on x86, the high 16 bits and low 16 bits of each integer trade places and I'm essentially sending "BARG" instead of "RGBA".
 I could test this with java.nio.ByteOrder.nativeOrder and go through the array rotating bits if little-endian, but is there a prettier approach?

2. My image is "upside down", presumably because the java graphics world has 0,0 at top left, and OpenGL has 0,0 at bottom left, so the order of rows is correct, it's just the coordinate space is different.  Again, easy to fix by copying rows in reverse order to create a more OpenGL-friendly array, but is there another common approach, like using a transformation?

Thanks for ideas...
--invalidname
Offline kevglass
« League of Dukes »

JGO Kernel
*****

Posts: 5214
Medals: 49


Mentally unstable, best avoided.


« Reply #1 on: 2003-08-27 10:38:45 »

You might want to have a read through this post:

http://www.java-gaming.org/cgi-bin/JGNetForums/YaBB.cgi?board=jogl;action=display;num=1058674409;start=45

About a generic texture loader that gregory pierce started. The latest versions that I know of are here:

http://www.informatik.uni-oldenburg.de/~troggan/bodo/Texture.java  
http://www.informatik.uni-oldenburg.de/~troggan/bodo/TextureLoader.java

There was some talk about getting them into the Jogl code base, but that doesn't seem to have happened. This loader supports all images by creating a buffered image of the right type and just drawImage() into it...

Hope this helps,

Kev

Offline Orangy Tang

JGO Kernel
*****

Posts: 2960
Medals: 37


Monkey for a head


« Reply #2 on: 2003-08-27 12:43:48 »

Quote

 Again, easy to fix by copying rows in reverse order to create a more OpenGL-friendly array, but is there another common approach, like using a transformation?


You can draw the image from one buffered image to another with an AffineTransform, set to a scale of (1, -1).

[ TriangularPixels.com - Play Growth Spurt, Rescue Squad and Snowman Village ] [ Rebirth - game resource library ]
Games published by our own members! Go get 'em!
Offline swpalmer

JGO Kernel
*****

Posts: 3438
Medals: 4


Where's the Kaboom?


« Reply #3 on: 2003-08-27 17:59:06 »

Quote


You can draw the image from one buffered image to another with an AffineTransform, set to a scale of (1, -1).


How could that change the endianness?
I think defining a custom pixel format for the destination image is one way.  But your transform will simply flip the image, not the RGB components.

Offline tom

JGO Neuromancer
****

Posts: 1113
Medals: 5



« Reply #4 on: 2003-08-27 19:41:15 »

Quote
2. My image is "upside down", presumably because the java graphics world has 0,0 at top left, and OpenGL has 0,0 at bottom left, so the order of rows is correct, it's just the coordinate space is different.  Again, easy to fix by copying rows in reverse order to create a more OpenGL-friendly array, but is there another common approach, like using a transformation?


You could set up the projection matrix in opengl so that 0,0 is top left instead of bottom left. Use this code instead of glu.perspective(...).

1  
2  
3  
4  
5  
6  
//gl.frustum(left, right, bot, top, near, far);
float near = 1;
float top = n/2f;
float bot = -top;
float aspect = viewPortWidth /  viewPortHeight;
gl.frustum(-near*aspect/2f, near*aspect/2f, bot, top, near, far);


This will of course turn everything up side down Smiley But I think it is more intuitive.

Offline Java Cool Dude

JGO Ninja
***

Posts: 680


Java forever


« Reply #5 on: 2003-08-27 20:10:19 »

This is my basic texture loader class, and I insist on the  term "basic"since it pales in comparaison to what Greg coded.
It also addresses the upside down symptom that you're having.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
class load_image
{
  java.awt.Image tex;
  byte[]         data;
  int            width,
                 height,
                 pixels[];

  load_image(){

    destroy();
  }

  void generate_texture_info(String texture_name, int type){

    try{
      tex = java.awt.Toolkit.getDefaultToolkit().getImage(texture_name);
    }
    catch(NullPointerException e){
      System.out.println(e);
    }

    while(width <= 0 || height <= 0){
      width      = tex.getWidth(null);
      height     = tex.getHeight(null);
    }

    pixels     = new int[width*height];
    extract_pixels();

    int pointer =0;

    switch(type){
      case  net.java.games.jogl.GL.GL_RGB:

        data = new byte[pixels.length*3];
        for(int y = height -1; y>=0; y--)
        for(int x = 0; x<width; x++){
          data[pointer+0] = (byte)((pixels[y*width + x] >> 16) & 0xFF);
          data[pointer+1] = (byte)((pixels[y*width + x] >>  8) & 0xFF);
          data[pointer+2] = (byte) (pixels[y*width + x]        & 0xFF);
          pointer+=3;
        }
      break;
      case net.java.games.jogl.GL.GL_RGBA:

        data = new byte[pixels.length*4];
        for(int y = height -1; y>=0; y--)
        for(int x = 0; x<width; x++){
          data[pointer+3] = (byte)((pixels[y*width + x] >> 24) & 0xFF);
          data[pointer+0] = (byte)((pixels[y*width + x] >> 16) & 0xFF);
          data[pointer+1] = (byte)((pixels[y*width + x] >>  8) & 0xFF);
          data[pointer+2] = (byte)( pixels[y*width + x]        & 0xFF);
          pointer+=4;
        }
      break;
      default: System.out.println("Unrecognized GL mode or not supported yet ^_^");
    }
  }

  void destroy(){

    tex    = null;
    data   = null;
    width  = -1;
    height = -1;
    pixels = null;
  }

  void extract_pixels(){

    try{
      new java.awt.image.PixelGrabber(tex,0,0,width,height,pixels,0,width).grabPixels();
    }
    catch (InterruptedException e) {}
  }
}


And this is how I call/use it in my demos:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
  load_image     texture_loader = new load_image();
  String         texture_name[] = {"textures/floor.png",
                                   "textures/wall.png",
                                   "textures/ceiling.jpg"};
  float          x, y, z;
  int            index,
                 texture_id[] = new int[3];

    gl.glGenTextures(3, texture_id);

    for(int i =0; i<3; i++){

      texture_loader.generate_texture_info(texture_name[i], gl.GL_RGB);
      gl.glBindTexture(gl.GL_TEXTURE_2D, texture_id[i]);
      gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, 3,texture_loader.width, texture_loader.height,
                      0,gl.GL_RGB, gl.GL_UNSIGNED_BYTE, texture_loader.data);
      gl.glTexParameteri(gl.GL_TEXTURE_2D,gl.GL_TEXTURE_MIN_FILTER,gl.GL_LINEAR);
      gl.glTexParameteri(gl.GL_TEXTURE_2D,gl.GL_TEXTURE_MAG_FILTER,gl.GL_LINEAR);
      texture_loader.destroy();
    }
Offline Orangy Tang

JGO Kernel
*****

Posts: 2960
Medals: 37


Monkey for a head


« Reply #6 on: 2003-08-28 02:08:33 »

Quote

How could that change the endianness?
I think defining a custom pixel format for the destination image is one way.  But your transform will simply flip the image, not the RGB components.


I wasn't giving a solution to the endianness :P But as InvalidName mentions, if you're assuming that openGL has a coord system with the origin at the bottom left your textures will appear flipped. The affine transform is just an easy way to shuffle the rows around without doing it manually.

[ TriangularPixels.com - Play Growth Spurt, Rescue Squad and Snowman Village ] [ Rebirth - game resource library ]
Offline invalidname

JGO n00b
*

Posts: 3


Do it wrong, not at all, or do it right.


« Reply #7 on: 2003-08-28 13:46:55 »

Thanks guys (and gals?).  The suggestions were great.  Greg's texture-loader code made me realize I should use an interleaved color model, not direct/packed ARGB in an int[].  Also, the image flip (via a scale and translate AffineTransform) works for me.  Maybe slower than munging arrays directly, but if it's only done once, why not be a little pretty?  (if nothing else, get it right and optimize last)  So, both problems solved.

--invalidname
Pages: [1]
  Print  
 
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.16 | SMF © 2011, Simple Machines Valid XHTML 1.0! Valid CSS!
Page created in 0.187 seconds with 21 queries.