K
Krishan
hi,
maybe i've been looking at this for too long, but i think i found a
strange thing in the JDK. take the color class and use the method
getRGB() on a color, you get an integer with the color samples in ARGB
(high order bits first) format, e.g.
Color.RED.getRGB(); gives 0xffff0000
then take the raster class with say the SinglePixelPackedSampleModel
(the following line gives u a raster with a databuffer holding width x
height x 4 samples while 4 samples represent the color value for a
stored pixel -- so it's SinglePixelPacked since the 4 color bands each
have a depth of 8bit, that makes 32bit/pixel and the databuffer's
integral type (TYPE_INT) matches this lovely)
Raster ras = Raster.createPackedRaster(DataBuffer.TYPE_INT,width,height,4,8,null);
the raster methods (setPixel) basically don't care about the color
format, as long as it's some 32bit value they'll eat it, same with the
setSample methods - they just navigate you through the bitmaze, ähm
array
so it's somebody else's task to interpret the values in the raster
right, let me introduce BufferedImage which enables you to command
exactly that, here's the code
BufferedImage bImg = new
BufferedImage(ras.getWidth(),ras.getHeight(),BufferedImage.TYPE_INT_ARGB);
along TYPE_INT_ARGB there are other types, those of interest here are
just
TYPE_INT_ARGB - MISLEADING, it's really ABGR (high order first), or
RGBA (low order first), like the api help will tell you
TYPE_4BYTE_ABGR - CONSISTENT at once, this actually interprets ABGR
(low order bits first, or RGBA (high order first)
(now low order bits first
why can't i just tell a java BufferedImage (colorformats either RGBA,
or ABGR) to take an java Color (colorformat BGRA) and display it
right, this sucks
there are two ways around this, but my guts tell me one shouldn't have
to bother with this and be changed in the api design
1) take the 32 bit value from getRGB(), left shifting it by 8 and
putting the alpha value in the low order 8bits of the integer
int color = Color.RED.geRGB();
color <<= 8;
color |= (optalpha & 0xFF);
now put the value in the raster and tell your buffered image to
interpret the data as TYPE_4BYTE_ABGR - WOW you've done it, thanks
SUN, this is really easy
2) tell the raster to switch things around - u use a different
constructor for that purpose
Raster ras = Raster.createPackedRaster(DataBuffer.TYPE_INT,r.width,r.height,new
int[]{0xFF<<16,0xFF<<8,0xFF<<0,0xFF<<24},null);
this switches your BGRA color class output into RGBA style (both low
order bits first), so that one can safely use TYPE_INT_ARGB for the
BufferedImage (which actually is RGBA as discussed above)
of course if u design your own 4-band integer array, u have to
consider this and do it the way the getRGB() method spits out it's
Color value - u want to put RED at (x,y) (3,3) on the raster, use
ras.getSampleModel().setPixel(3,3,new int[]{BLUEVAL, GREENVAL, REDVAL,
ALPHAVAL}, ras.getDataBuffer());
this doesn't apply to the first solution - there it's lovely ARGB for
arrays, just like the BufferedImageType
=============================================================================
next thing: there is a setPixel method in the SampleModelMethods that
takes a float array, just gorgeous u think - it'll propaply behave
like the Color constructor that takes float arguments - and scale your
fractional values between [0.0,1.0] to range [0,255]
of course all it does is casting away the fractional part and putting
that as the value for a color-band-sample
=============================================================================
if u know better, please tell me!
is it on purpose or is it just a designflaw?
i also appreciate any better solutions
what i'm doing?
implementing stuff that's already there - like drawing antialiasing
lines for study - works wonderfully, but i realized that this get's
really sloooow (no wonder, there's no setpixel operation in
java.awt.graphics, so one had to cripple drawLine(x1,y1,x2,y2) to
drawLine(x1,y1,x1,y1))
now i'm working offscreen on this raster and then blitting it to the
screen
is there a better way to intersect the (re-)drawing process in java
for such low level algorithms, making it even faster?
i also tried getting SurfaceData surData =
((SunGraphics2D)g).getSurfaceData().getRaster()...
but this feature isn't implemented yet, SUN tells me via Exception
thx in advance
maybe i've been looking at this for too long, but i think i found a
strange thing in the JDK. take the color class and use the method
getRGB() on a color, you get an integer with the color samples in ARGB
(high order bits first) format, e.g.
Color.RED.getRGB(); gives 0xffff0000
then take the raster class with say the SinglePixelPackedSampleModel
(the following line gives u a raster with a databuffer holding width x
height x 4 samples while 4 samples represent the color value for a
stored pixel -- so it's SinglePixelPacked since the 4 color bands each
have a depth of 8bit, that makes 32bit/pixel and the databuffer's
integral type (TYPE_INT) matches this lovely)
Raster ras = Raster.createPackedRaster(DataBuffer.TYPE_INT,width,height,4,8,null);
the raster methods (setPixel) basically don't care about the color
format, as long as it's some 32bit value they'll eat it, same with the
setSample methods - they just navigate you through the bitmaze, ähm
array
so it's somebody else's task to interpret the values in the raster
right, let me introduce BufferedImage which enables you to command
exactly that, here's the code
BufferedImage bImg = new
BufferedImage(ras.getWidth(),ras.getHeight(),BufferedImage.TYPE_INT_ARGB);
along TYPE_INT_ARGB there are other types, those of interest here are
just
TYPE_INT_ARGB - MISLEADING, it's really ABGR (high order first), or
RGBA (low order first), like the api help will tell you
TYPE_4BYTE_ABGR - CONSISTENT at once, this actually interprets ABGR
(low order bits first, or RGBA (high order first)
(now low order bits first
why can't i just tell a java BufferedImage (colorformats either RGBA,
or ABGR) to take an java Color (colorformat BGRA) and display it
right, this sucks
there are two ways around this, but my guts tell me one shouldn't have
to bother with this and be changed in the api design
1) take the 32 bit value from getRGB(), left shifting it by 8 and
putting the alpha value in the low order 8bits of the integer
int color = Color.RED.geRGB();
color <<= 8;
color |= (optalpha & 0xFF);
now put the value in the raster and tell your buffered image to
interpret the data as TYPE_4BYTE_ABGR - WOW you've done it, thanks
SUN, this is really easy
2) tell the raster to switch things around - u use a different
constructor for that purpose
Raster ras = Raster.createPackedRaster(DataBuffer.TYPE_INT,r.width,r.height,new
int[]{0xFF<<16,0xFF<<8,0xFF<<0,0xFF<<24},null);
this switches your BGRA color class output into RGBA style (both low
order bits first), so that one can safely use TYPE_INT_ARGB for the
BufferedImage (which actually is RGBA as discussed above)
of course if u design your own 4-band integer array, u have to
consider this and do it the way the getRGB() method spits out it's
Color value - u want to put RED at (x,y) (3,3) on the raster, use
ras.getSampleModel().setPixel(3,3,new int[]{BLUEVAL, GREENVAL, REDVAL,
ALPHAVAL}, ras.getDataBuffer());
this doesn't apply to the first solution - there it's lovely ARGB for
arrays, just like the BufferedImageType
=============================================================================
next thing: there is a setPixel method in the SampleModelMethods that
takes a float array, just gorgeous u think - it'll propaply behave
like the Color constructor that takes float arguments - and scale your
fractional values between [0.0,1.0] to range [0,255]
of course all it does is casting away the fractional part and putting
that as the value for a color-band-sample
=============================================================================
if u know better, please tell me!
is it on purpose or is it just a designflaw?
i also appreciate any better solutions
what i'm doing?
implementing stuff that's already there - like drawing antialiasing
lines for study - works wonderfully, but i realized that this get's
really sloooow (no wonder, there's no setpixel operation in
java.awt.graphics, so one had to cripple drawLine(x1,y1,x2,y2) to
drawLine(x1,y1,x1,y1))
now i'm working offscreen on this raster and then blitting it to the
screen
is there a better way to intersect the (re-)drawing process in java
for such low level algorithms, making it even faster?
i also tried getting SurfaceData surData =
((SunGraphics2D)g).getSurfaceData().getRaster()...
but this feature isn't implemented yet, SUN tells me via Exception
thx in advance