Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (495)
Games in Android Showcase (114)
games submitted by our members
Games in WIP (563)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Fast RGBA <-> ARGB conversion ?  (Read 6042 times)
0 Members and 1 Guest are viewing this topic.
Offline javazoid

Junior Member




Where's Flender?


« Posted 2005-01-12 07:22:47 »

As the topic says, I'm looking for a fast way to convert from an RGBA array to an ARGB one and vice-versa.

As far as I know this color space conversion is not supported by OpenGL so it can only be made in software, but maybe someone here knows a nice way to make it very fast (i.e. by using MMX, etc).

Suggestions welcome.

Offline zparticle

Senior Member




Thick As A Brick


« Reply #1 - Posted 2005-01-12 16:43:37 »

you could try (shift and rotate)

argb = rgba <<< 8

rgba = argb <<< 24

Offline phazer

Junior Member




Come get some


« Reply #2 - Posted 2005-01-12 17:53:04 »

Quote
you could try (shift and rotate)

argb = rgba <<< 8

rgba = argb <<< 24


What programming language is this?

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline jbanes

JGO Coder


Projects: 1


"Java Games? Incredible! Mr. Incredible, that is!"


« Reply #3 - Posted 2005-01-12 18:36:30 »

Quote
What programming language is this?


Umm... that would be Java. Although it's odd, because the JLS shows the shift and rotate right operator, but no shift and rotate left. I'm pretty sure the later works, however. Go figure.

In case you've never seen this sort of bitwise operation, it basically works like a shift. In a shift, the bits are moved the specified number of positions left or right. However, if the bits at the extreme ends of the number are lost when they overflow the number of bit positions. That's why C programmers used to use "myvar <<= 32" as a really fast method for setting a variable to zero. The difference with shift and rotate, however, is that the bits get wrapped back around the other end of the variable. This results in being able to reshuffle the exact bit positions without losing any information.

Shift and rotate is closely related to the assembly code concept of shift with carry, where the carry flag/register is set to the last bit value shifted out of the variable.

Java Game Console Project
Last Journal Entry: 12/17/04
Offline tom
« Reply #4 - Posted 2005-01-12 19:31:49 »

There is no rotate operator in java. ">>" is signed shift left. ">>>" is unsigned shift left. The difference is wether a the sign bit is kept with negative numbers.

Offline jbanes

JGO Coder


Projects: 1


"Java Games? Incredible! Mr. Incredible, that is!"


« Reply #5 - Posted 2005-01-12 19:54:01 »

Quote
There is no rotate operator in java. ">>" is signed shift left. ">>>" is unsigned shift left. The difference is wether a the sign bit is kept with negative numbers.


Doh! Seems you're right. Oddly enough, I did a quick Google search before I posted, and got a result or two that said "<<<" was shift and rotate in Java. Guess it's time to "forget" one more thing. :-)

This code should produce a reasonable facsimile of a shift and rotate:

1  
2  
rgba = (argb << 8) | (argb >>> (32-8));
argb = (rgba >>> 8) | (rgba << (32-8));


Special thanks to the Java Glossary for that bit of info.

Edit: Here's the varmits who should be hanged by their pinky toes! From their page:

Quote
bitwise operators - Operators used on the byte data type to modify bit values. These include the bitwise and (&), or (|), not (!), exclusive or (^), shift left (<<), shift right (>>), and shift and rotate (<<<) operators.

Java Game Console Project
Last Journal Entry: 12/17/04
Offline javazoid

Junior Member




Where's Flender?


« Reply #6 - Posted 2005-01-13 05:35:05 »

Shifting is not rotating and operators like ROR.L  ROL.L  (68k asm)  are not in the JSL.

An operation like

argb = (rgba >>> Cool | (rgba << (32-8));

of course takes a lot more than a single bitwise rotation (which is a common CPU operation).

Sadly I'm not fluent in x86 asm. Maybe someone here can write a simple loop that makes the conversion.

It would be nice to have it in the LWJGL BufferUtils:

BufferUtils.toARGB(intarray);
BufferUtils.toRGBA(intarray);

these functions would be widely used to create OGL textures etc.


Mik



Offline princec

JGO Kernel


Medals: 378
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #7 - Posted 2005-01-13 10:07:44 »

This conversion is automatically performed by GL drivers. There is no need to convert a texture yourself. The drivers probably have a much faster implementation than Java can manage too.

Cas Smiley

Offline javazoid

Junior Member




Where's Flender?


« Reply #8 - Posted 2005-01-13 10:47:20 »

Quote
...automatically performed..


Do you mean that glReadPixels from a Pbuffer can give me ARGB instead of RGBA at hardware speed ? Would be fantastic..

Offline zparticle

Senior Member




Thick As A Brick


« Reply #9 - Posted 2005-01-13 12:45:31 »

Quote


Doh! Seems you're right. Oddly enough, I did a quick Google search before I posted, and got a result or two that said "<<<" was shift and rotate in Java. Guess it's time to "forget" one more thing. :-)


Sorry guys I didn't mean to send anyone in the wrong direction, I think I was looking at the same page jbanes was.

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline jbanes

JGO Coder


Projects: 1


"Java Games? Incredible! Mr. Incredible, that is!"


« Reply #10 - Posted 2005-01-13 13:37:11 »

Quote

An operation like

argb = (rgba >>> Cool | (rgba << (32-8));

of course takes a lot more than a single bitwise rotation (which is a common CPU operation).


Bah! 2 shifts and an or shouldn't strain the CPU in the slightest. In fact, each one should cost no more than 1 cycle a piece. This makes the cost of converting a 256x256 image 256x256x3 = 196,608 cycles. Do that 60 times a second, and you've got 117,964,480 cycles per second. That works out to requiring a 118MHz processor. Of course, one would hope that you don't actually need to do that 60 times a second. :-)

FWIW, the assembly instructions for shift and rotate are ROL (left) and ROR (right). These come at a cost of 1 to 3 cycles per execution. I don't have enough documentation in front of me to determine the situation when it takes one or the other.

Java Game Console Project
Last Journal Entry: 12/17/04
Offline javazoid

Junior Member




Where's Flender?


« Reply #11 - Posted 2005-01-13 13:53:54 »

Well, I'm sure you're not talking of java bytecode.

Did you measure a java for() loop doing the above conversion of an int array ? I think it should be several times slower that the x86 asm counterpart.

From the cpu clock cycles side, I remember that 68020 and above had "barrel shifters" (1clk for sure, but on 040 you can have some "free instructions" depending on the execution order: 1 clk -> several instructions) and surely modern cpus would make even better. So how can you be so sure about the Mhz you need ?


Offline jbanes

JGO Coder


Projects: 1


"Java Games? Incredible! Mr. Incredible, that is!"


« Reply #12 - Posted 2005-01-13 14:23:55 »

Quote
Did you measure a java for() loop doing the above conversion of an int array ? I think it should be several times slower that the x86 asm counterpart.


I wouldn't be so certain about that. The bounds checks would certainly suck, yes, and there is overhead for the for loop. However, if this code executes often enough, HotSpot will take notice and optimize it. You could easily expect that HotSpot would eliminate the bounds checking, unroll the loop a bit, and do a few other optimizations that would make it blaze. With any luck, it should be very close in performance to an assembly version.

Quote
From the cpu clock cycles side, I remember that 68020 and above had "barrel shifters" (1clk for sure, but on 040 you can have some "free instructions" depending on the execution order: 1 clk -> several instructions) and surely modern cpus would make even better. So how can you be so sure about the Mhz you need ?


I think what you're referring to is Out Of Order instructions and SuperScalar execution. (The two are closely related.) And yes, it would be great if the processor gave better than 1 cycle per instruction. However, it's always best to plan for worst case rather than best case. :-)

Java Game Console Project
Last Journal Entry: 12/17/04
Offline princec

JGO Kernel


Medals: 378
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #13 - Posted 2005-01-13 19:21:28 »

The Pentium 4 no longer has a barrel shifter :/

Cas Smiley

Offline javazoid

Junior Member




Where's Flender?


« Reply #14 - Posted 2005-01-14 05:04:27 »

Apart from the P4 implementation (no barrel shifter ? fantastic  :-/). I would make you all concentrate on the main topic and go back to the RGBA-ARGB conversion.
Don't you think that such a feature would be nice inside LWJGL ? This feature could be easily included in the native code and people would use it instead of their implementation. LWJGL implementors could also put a processor-optimized version of the functions. Consider this a kind of RFE.

Offline Matzon

JGO Knight


Medals: 19
Projects: 1


I'm gonna wring your pants!


« Reply #15 - Posted 2005-01-14 05:51:40 »

FWIW, I don't actually see any reason whatsoever in implementing this in lwjgl... Why would any game have to convert between ARGB and RGBA ? One must assume that all content is in the same order.

Offline javazoid

Junior Member




Where's Flender?


« Reply #16 - Posted 2005-01-14 06:42:56 »

For people like me ? ;-)

More seriously:

I develop Java2D desktop video applications at full time. I've recently discovered LWJGL and I'm developing a Java2D-like library that will allow me to easily move from Java2D to a faster implementation.
After playing with LWJGL for about five days I already have a working implementation (call it a proof of concept) that can handle AffineTransforms, images, composite and some primitives. More to come. Through the use of Pbuffers I can create several contexts (i.e Graphics2D) and draw my offscreen graphics there.

Of course I must integrate the LWJGL-based rendering with the Java2D counterpart, so I think that a pair of nicely optimized methods like BufferUtils.toARGB(fb)  andBufferUtils.toRGBA(fb) would be a "standard" and fast bridge between OpenGL and Java2D pixel formats.
Maybe I'm wrong, but I don't think I'm the only one that uses LWJGL in this way.

Cheers,

Mik


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  
      public BufferedImage screenShot()
      {
            BufferedImage image = null;
           
            // allocate space for RBGA pixels
           ByteBuffer fb = BufferUtils.createByteBuffer(width * height * 4);
            int[] pixels = new int[width * height];
            int bindex;

            GL11.glReadBuffer(GL11.GL_FRONT);

            // grab a copy of the current frame contents as RGBA
           GL11.glReadPixels(0, 0, width, height, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, fb);

            // convert RGBA data in ByteBuffer to integer array
           for (int i = 0; i < pixels.length; i++)
            {
                  bindex = i * 4;
                  int a = fb.get(bindex + 3) & 0xff;
                  int r = fb.get(bindex + 0) & 0xff;
                  int g = fb.get(bindex + 1) & 0xff;
                  int b = fb.get(bindex + 2) & 0xff;
                  pixels[i] = (a << 24) | (r << 16) | (g << 8) | (b);
            }

            // Create a BufferedImage with the RGBA pixels
           try
            {
                  image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
                  image.setRGB(0, 0, width, height, pixels, 0, width);
            }
            catch (Exception e)
            {
                  System.out.println("ScreenShot() exception: " + e);
            }
            return image;
      }


would read as:

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  
      public BufferedImage screenShot()
      {
            BufferedImage image = null;
           
            // allocate space for RBGA pixels
           ByteBuffer fb = BufferUtils.createByteBuffer(width * height * 4);
            int[] pixels = new int[width * height];
            int bindex;

            GL11.glReadBuffer(GL11.GL_FRONT);

            // grab a copy of the current frame contents as RGBA
           GL11.glReadPixels(0, 0, width, height, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, fb);

            // convert
           BufferUtils.toARGB(fb);

            // Create a BufferedImage with the RGBA pixels
           try
            {
                  image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
                  image.setRGB(0, 0, width, height, pixels, 0, width);
            }
            catch (Exception e)
            {
                  System.out.println("ScreenShot() exception: " + e);
            }
            return image;
      }


Offline princec

JGO Kernel


Medals: 378
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #17 - Posted 2005-01-14 07:17:18 »

As I say, this is built into all OpenGL drivers. It's not a function that will ever make it into LWJGL.

Cas Smiley

Offline javazoid

Junior Member




Where's Flender?


« Reply #18 - Posted 2005-01-14 07:22:21 »

I'm sorry for my ignorance, but... can you make an example, an how-to that shows how to do RGBA-ARGB with OpenGL ?

Of course don't assume we're onscreen. Just think you want to get a BufferedImage from the pixels you read with glReadPixels().

Offline princec

JGO Kernel


Medals: 378
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #19 - Posted 2005-01-14 07:40:34 »

Simply pass in the required format into glReadPixels()... eg. GL_EXT_bgra or GL_EXT_rbga. Make sure the extension is supported first. Nearly all drivers support this conversion.

Cas Smiley

Offline Spasi
« Reply #20 - Posted 2005-01-14 07:59:13 »

Quote
can you make an example, an how-to that shows how to do RGBA-ARGB with OpenGL ?


You don't need to do an RGBA-ARGB conversion. First of all, you should be using TYPE_4BYTE_ABGR for your BufferedImages. This makes it straightforward:

1  
2  
3  
4  
5  
6  
7  
glReadPixels(0, 0, w, h, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buffer);

byte[] pixels = new byte[IMAGE_SIZE];
buffer.get(pixels);

BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_4BYTE_ABGR);
image.getRaster().setDataElements(0, 0, w, h, pixels);


Make sure you cache the temp byte[] and BufferedImage if you do this often.
Offline javazoid

Junior Member




Where's Flender?


« Reply #21 - Posted 2005-01-14 08:27:44 »

Nice suggestions, thanks.

One thing for CAS:

ahem..how to use extensions in LWJGL ?
I couldn't find the define for GL_EXT_bgra.

For spasi:

Yes, Java2D is so flexible.
My video-out framebuffer is not! It will never understand other than ARGB..


--ADDENDUM--

Found it: EXTBgra.GL_BGRA_EXT
Result: it works at hardware speed (FX5700)!
Finally: many thanks CAS, Spasi.

Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

Dwinin (23 views)
2014-09-12 09:08:26

Norakomi (56 views)
2014-09-10 13:57:51

TehJavaDev (69 views)
2014-09-10 06:39:09

Tekkerue (34 views)
2014-09-09 02:24:56

mitcheeb (56 views)
2014-09-08 06:06:29

BurntPizza (40 views)
2014-09-07 01:13:42

Longarmx (25 views)
2014-09-07 01:12:14

Longarmx (31 views)
2014-09-07 01:11:22

Longarmx (31 views)
2014-09-07 01:10:19

mitcheeb (38 views)
2014-09-04 23:08:59
List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06

List of Learning Resources
by SilverTiger
2014-07-31 11:54:12

HotSpot Options
by dleskov
2014-07-08 01:59:08
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!