Bitwise puzzle in com.sun.glass.ui.monocle.Framebuffer

John Neffenger john at status6.com
Mon Nov 5 18:20:13 UTC 2018


I am completely puzzled by the bitwise operations in the Framebuffer 
class (package com.sun.glass.ui.monocle). I'm overriding its methods to 
support a "Y8" 8-bit grayscale frame buffer, yet I have no idea why it's 
doing what it's doing. Can anyone shed light on its complexity?

The Framebuffer class converts a buffer with 32-bit pixels in ARGB32 
format into a buffer with 16-bit pixels in RGB565 format, as illustrated 
below for one pixel.

aaaa aaaa  rrrr rrrr  gggg gggg  bbbb bbbb
     --> rrrr rggg  gggb bbbb

I would convert the pixels with a method like the following:

void copyNextPixel(IntBuffer source, ShortBuffer target) {
     int pixel32 = source.get();
     int r = (pixel32 >> 8) & 0xF800;
     int g = (pixel32 >> 5) & 0x07E0;
     int b = (pixel32 >> 3) & 0x001F;
     int pixel16 = r | g | b;
     target.put((short) pixel16);
}

The JavaFX Framebuffer class converts the pixels like this:

void copyNextPixelOriginal(IntBuffer source, ShortBuffer target) {
     int pixel32 = source.get();
     int r = ((((pixel32 >> 19) & 31) * 539219) >> 8) & (31 << 11);
     int g = ((((pixel32 >> 10) & 63) * 265395) >> 13) & (63 << 5);
     int b = (((pixel32 >> 3) & 31) * 539219) >> 19;
     int pixel16 = r | g | b;
     target.put((short) pixel16);
}

Both of these methods produce identical results when tested against all 
16,777,216 possible 24-bit RGB values. To understand what is happening, 
I show each step in the creation and positioning of the 5-bit red color 
value for both algorithms below (best viewed in a monospaced font).

My version
     int r = (pixel32 >> 8) & 0xF800;

____ ____  xxxx xxxx  ____ ____  ____ ____  pixel32 (x = red)
____ ____  ____ ____  xxxx xxxx  ____ ____  >> 8
0000 0000  0000 0000  xxxx x000  0000 0000  & 0xF800

JavaFX version
     int r = ((((pixel32 >> 19) & 31) * 539219) >> 8) & (31 << 11);

____ ____  xxxx xxxx  ____ ____  ____ ____  pixel32 (x = red)
____ ____  ____ ____  ____ ____  ___x xxxx  >> 19
0000 0000  0000 0000  0000 0000  000x xxxx  & 31 = 0x1F
0000 0000  xxxx x___  ____ ____  ____ ____  * 539219 = 2^19 + 14931
0000 0000  0000 0000  xxxx x___  ____ ____  >> 8
0000 0000  0000 0000  xxxx x000  0000 0000  & (31 << 11) = 0xF800

Why all the back and forth? Why introduce varying bits to the right of 
the red color value (* 539219), only to clear those bits later? The last 
three steps could be replaced with a single logical shift left operation 
(<< 11).

The Framebuffer class was added to the repository on January 21, 2014, 
by Daniel Blaukopf.

Thank you,
John



More information about the openjfx-dev mailing list