Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / March 2007

Tip: Looking for answers? Try searching our database.

confused about image colorspaces

Thread view: 
LC's NoSpam Newsreading account - 05 Mar 2007 16:46 GMT
I'd like to write a small applet to display astronomical images. As
customary in astronomy, for us an image is an array img(x,y) of real
values in physical units, and colour is a mere way of representing them.
We usually scale the values img(x,y) according to user choice (linear
scale, log scale, histogram equalization) to normalized values i(x,y)
e.g. in the range [0,255] or [0.0,1.0] and use the latter as index into
a lookup table (LUT) of R G B values (the LUT is also chosen by the
user).

I have code which does that in Xlib, in Postscript (using [/Indexed
/DeviceRGB 255 {LUT} ] setcolorspace) and in RSI IDL (using
device,decomposed=0, and then setting tvlct,r,g,b where r,g,b are arrays
of R G B levels). I'd like to do it in java as well in the same way. I
am confused by the API documentation about images and color spaces which
seems overshooting for my needs.

I tried therefore to define a small LUT of 10 colours (as a test) with
one-byte depth and then to use this code to fill the image

IndexColorModel cm = new IndexColorModel(8,10, red,gre,blu) ;
BufferedImage img = new
BufferedImage(30,10,BufferedImage.TYPE_BYTE_INDEXED,cm)
for (int jx=0; jx<30 ; jx++) {
 for (int  jy=0; jy<10 ; jy++) {
   img.setRGB(jx,jy,jy) ;
 }
}
g2.drawImage(img,myx,myy,null) ;      

With the assignment I do in setRGB I'd expect to get a 30x10 image with
10 horizontal stripes each one of a different colour as defined in my
table. But what I get is always a gray rectangle, and the same occurs if
I do img.setRGB(jx,jy,CONSTANT) ;

What am I doing wrong ?

As example this is the equivalent IDL codes (the Java R G B values will
be scaled in the range -128 to 127 instead of 0-255)

IDL> red=[0,255,255,  0,  0,255,255,  0,128,  0]
IDL> gre=[0,255,  0,255,  0,255,  0,255,128,128]
IDL> blu=[0,255,  0,  0,255,  0,255,255,128,  0]
IDL> tvlct,red,gre,blu
IDL> img=fltarr(30,10)
IDL> for i=0,29 do begin &
      for j=0,9 do begin &
       img(i,j)=j &
      endfor &
    endfor
IDL> tv,img

Signature

----------------------------------------------------------------------
nospam@mi.iasf.cnr.it is a newsreading account used by more persons to
avoid unwanted spam. Any mail returning to this address will be rejected.
Users can disclose their e-mail address in the article if they wish so.

Mark Space - 05 Mar 2007 20:06 GMT
> IndexColorModel cm = new IndexColorModel(8,10, red,gre,blu) ;
> BufferedImage img = new
[quoted text clipped - 10 lines]
> table. But what I get is always a gray rectangle, and the same occurs if
> I do img.setRGB(jx,jy,CONSTANT) ;

I'm not an expert on this, but i don't see where you set up the index or
the color LUT.  Is it just in a different portion of the code?

Java images mostly mimic the historical graphics modes of PCs.  Trying
to set a byte depth with only ten colors when the system is expecting
256 may be an issue.  I'd try setting all of them (256 colors) and see
if that helps.
a24900@googlemail.com - 05 Mar 2007 22:29 GMT
On Mar 5, 5:46 pm, LC's NoSpam Newsreading account
<nos...@mi.iasf.cnr.it> wrote:
> IndexColorModel cm = new IndexColorModel(8,10, red,gre,blu) ;
> BufferedImage img = new
[quoted text clipped - 3 lines]
>     img.setRGB(jx,jy,jy) ;
>   }}

> What am I doing wrong ?

Each component in setRGB() has a value range from 0...255. You
generate colors from (0,0,0) to (29,9,9) in the loop. The values are
mapped to the nearest color in the LUT. Unfortunately, you neglected
to show us the LUT. If you use the same LUT as in your IDL example,
then the nearest color in the LUT is likely (0,0,0), even for your
largest value (29,9,9). You asked for black, you got black.
LC's NoSpam Newsreading account - 06 Mar 2007 09:21 GMT
> > IndexColorModel cm = new IndexColorModel(8,10, red,gre,blu) ;
> >  BufferedImage(30,10,BufferedImage.TYPE_BYTE_INDEXED,cm)

> >     img.setRGB(jx,jy,jy) ;

> Each component in setRGB() has a value range from 0...255. You
> generate colors from (0,0,0) to (29,9,9) in the loop. The values are
> mapped to the nearest color in the LUT. Unfortunately, you neglected
> to show us the LUT. If you use the same LUT as in your IDL example,
> then the nearest color in the LUT is likely (0,0,0), even for your
> largest value (29,9,9). You asked for black, you got black.

Hmm ... there should be a basic misunderstanding here ... the API doc
says "setRGB(int x, int y, int rgb) Sets a pixel in this BufferedImage
to the specified RGB value".  So I assumed that the first two values
were SPATIAL coordinates not R and G values ... the API doc does not say
how to code an "int rgb", so I assumed that was just an INDEX in the LUT
i.e. a number from 0 to n-1

What I wanted to achieve was an image with 10 rows of 30 pixels

a row of 30 0's
a row of 30 1's
...
a row of 30 9's

You and also Mark Space say "I don't see where you set up the index or
the color LUT, is it just in a different portion of the code?"

Well, to me the equivalent of the IDL tvlct,red,gre,blu was

> > IndexColorModel cm = new IndexColorModel(8,10, red,gre,blu) ;

I assumed "10" meant the LUT in this test has only 10 colours (which
should be possible, why not ?) and "8" meant red, gre and blu were
ranging -128,127.

Did I not understand how java LUTs work ?

I did not show the actual LUT (or what I intended to be it) because the
actual numbers were not interesting, and the code was slightly long
(or clumsy ?). Essentially I start with three integer arrays (IDL-style)
in range 0-255

 int[] red1={0,255,255,  0,  0,255,255,  0,128,  0} ;
 int[] gre1={0,255,  0,255,  0,255,  0,255,128,128} ;
 int[] blu1={0,255,  0,  0,255,  0,255,255,128,  0} ;

then cast them into byte arrays red,gre,blu which I use in the call to
IndexColorModel. I'm slightly upset by the fact that java byte values
are signed in the range -128,127 ... my clumsy conversion code is in a
loop and similar to this

int ti=red1[i]-128  ;
Integer t=new Integer(ti) ;
red[i]=t.byteValue() ;

Anyhow I've found a different way of doing it in an example :
This uses my integer LUT above, and generates the horizontal stripe test
image I want.

for (int jy=0; jy<10 ; jy++) {
for (int jx=0; jx<30 ; jx++) {      
 pix[index++] = (255<<24) | (red1[jy]<<16) | (gre1[jy]<<8) | blu1[jy]
}
}
Image ima = createImage(new MemoryImageSource(30,10,pix,0,30));    
g2.drawImage(ima,myx,myy,null) ;  

Replacing red1[jy] gre1[jy] blu1[jy] with red1(scaleddata[jx,jy]) and
alike where my original data are scaled via an ITT to values 0 to n-1
where n is the size of the red1,gre1,blu1 arrays will implement the LUT.  

But I hoped to find a ready-made solution for that (a bit like my
Postscript level 2 solution does it in the Postscript language and sends
an array of scaled data, while my Postscript level 1 solution does it in
my code and sends three arrays of R G B.

On Mon, 5 Mar 2007, Mark Space wrote:
> Java images mostly mimic the historical graphics modes of PCs.  
> Trying to set a byte depth with only ten colors when the system is
> expecting 256 may be an issue.  I'd try setting all of them (256
> colors) and see if that helps.

More familiar with oldtimer things like Ramtek, Sigma ARGS, DeAnza :-)
Or Xlib and IDL. I've always used LUTs of less than 256 colours when I
needed only few (mainly for vector graphics than image display), taking
care I did not address colours beyond the LUT size.

Signature

----------------------------------------------------------------------
nospam@mi.iasf.cnr.it is a newsreading account used by more persons to
avoid unwanted spam. Any mail returning to this address will be rejected.
Users can disclose their e-mail address in the article if they wish so.

Chris Uppal - 06 Mar 2007 17:59 GMT
>  the API doc
> says "setRGB(int x, int y, int rgb) Sets a pixel in this BufferedImage
> to the specified RGB value".  So I assumed that the first two values
> were SPATIAL coordinates not R and G values ... the API doc does not say
> how to code an "int rgb", so I assumed that was just an INDEX in the LUT
> i.e. a number from 0 to n-1

The doc says:

   Sets a pixel in this BufferedImage to the specified RGB value.
   The pixel is assumed to be in the default RGB color model,
   TYPE_INT_ARGB, and default sRGB color space. For images
   with an IndexColorModel, the index with the nearest color is chosen.

I'm no expert on the Image stuff, but as far as I can tell, you have two
options (given that you are starting with input data which is already organised
assuming a lookup table).

One is to use an "ordinary" BufferedImage -- not trying to specify a LUT colour
model -- and then write RBG values into it, using your own colour-mapping logic
to convert raw data into whatever RBG values.   Thus the colour-mapping happens
as the BufferedImage is written to.

The other is to start with your "raw" image data and  lookup table, and then
wrap suitable instances of ColorModel and Raster around them (using custom
ColorModel and Raster subclasses if necessary), and then use them to create a
BufferedImage.   Thus the colour mapping happens when the BufferedImage is read
from.

You seem to be trying to do both at once, and I can't see what the point is.

FWIW, the first option seems a lot simpler to me, but that's not to say that
the second option may not have significant advantages which I don't know about.

   -- chris
a24900@googlemail.com - 06 Mar 2007 20:27 GMT
On Mar 6, 10:21 am, LC's NoSpam Newsreading account
<nos...@mi.iasf.cnr.it> wrote:
> Hmm ... there should be a basic misunderstanding here ... the API doc
> says "setRGB(int x, int y, int rgb) Sets a pixel in this BufferedImage
> to the specified RGB value".  So I assumed that the first two values
> were SPATIAL coordinates not R and G values ...

Yes that's right. But it doesn't change the principle issue.

> the API doc does not say
> how to code an "int rgb", so I assumed that was just an INDEX in the LUT
> i.e. a number from 0 to n-1

The documentation gives a hint: TYPE_INT_ARGB. That is 8 bit/
component, packed in the order alpha, red, green, blue packed into an
int.

You actually asked for the nearest color in the LUT to alpha = 0, red
= 0, green = 0, blue = 0 ... 9 That is even more close to black than
my misinterpreted (29,9,9).

> You and also Mark Space say "I don't see where you set up the index or
> the color LUT, is it just in a different portion of the code?"
>
> Well, to me the equivalent of the IDL tvlct,red,gre,blu was
>
> > > IndexColorModel cm = new IndexColorModel(8,10, red,gre,blu) ;

What we both wanted to know is the contents of the red, gre, and blu
arrays. The contents, byte for byte. Each one should be a byte[], with
at least 10 elements.

> I assumed "10" meant the LUT in this test has only 10 colours (which
> should be possible, why not ?)

Yes, but we wanted to know how your particular LUT looks like. If you
put in ten times black it is a LUT with ten entries, but don't expect
to see very much.

> ranging -128,127.

You seem to be obsessed with this range, which is entirely wrong. The
8 bit color component range is 0 ... 255. When encoded into a signed
byte the range becomes 0 ... 127, -128 ... -1 In that particular
order, not -128 ... 127!

> I did not show the actual LUT (or what I intended to be it) because the
> actual numbers were not interesting,

They are. If you happen to put ten times black into the LUT ...

>   int[] red1={0,255,255,  0,  0,255,255,  0,128,  0} ;
>   int[] gre1={0,255,  0,255,  0,255,  0,255,128,128} ;
>   int[] blu1={0,255,  0,  0,255,  0,255,255,128,  0} ;
>
> then cast them into byte arrays

You can't cast arrays.

> red,gre,blu which I use in the call to
> IndexColorModel. I'm slightly upset by the fact that java byte values
[quoted text clipped - 4 lines]
>  Integer t=new Integer(ti) ;
>  red[i]=t.byteValue() ;

That is not casting. This is casting:

red[i] = (byte)red1[i];

And that casting would have work for the intended purpose. See why we
want to see how you build the LUT arrays? It would anyhow be simpler
to just define the byte arrays:

int[] red = { 0, (byte)255, (byte)255,  0,  0, (byte)255, (byte)255,
0, (byte)128,  0} ;

Sometimes the casting goes on people's nerves, so people also do
things like

static final byte eo = (byte)128;
static final byte ff = (byte)255;
int[] red = { 0, ff, ff, 0, 0, ff, ff, 0, eo,  0} ;
LC's NoSpam Newsreading account - 07 Mar 2007 11:30 GMT
> > the API doc does not say
> > how to code an "int rgb", so I assumed that was just an INDEX in the LUT
[quoted text clipped - 3 lines]
> component, packed in the order alpha, red, green, blue packed into an
> int.

So that will be analogous to my second (working) example using
MemoryImageSource(30,10,pix,0,30) with pix built e.g. as

pix[index++] = (255<<24) | (red1[jy]<<16) | (gre1[jy]<<8) | blu1[jy]

I thought the rgb value in setRGB was the index in the LUT. This looks
not to be the case.


> > ranging -128,127.
>
> You seem to be obsessed with this range, which is entirely wrong. The
> 8 bit color component range is 0 ... 255. When encoded into a signed
> byte the range becomes 0 ... 127, -128 ... -1 In that particular
> order, not -128 ... 127!

http://java.sun.com/docs/books/tutorial/java/nutsandbolts/datatypes.html
says "byte: The byte data type [...]. It has a minimum value of -128 and
a maximum value of 127 (inclusive)." This misled me. The above
masking-with-shifting into pix[] works with actual 0-255 values.

> >   int[] red1={0,255,255,  0,  0,255,255,  0,128,  0} ;
> >   int[] gre1={0,255,  0,255,  0,255,  0,255,128,128} ;
> >   int[] blu1={0,255,  0,  0,255,  0,255,255,128,  0} ;
> >
> > then cast them into byte arrays
> You can't cast arrays.

I may have used the wrong expression ("effective content casting" ?
"casting of array elements" ?) but I suppose it was clear what I wanted
to achieve (despite I might have coded it wrongly). Three arrays
defining : black, white, red, green, blue, yellow, magenta. cyan, gray
and dark green.


> >  int ti=red1[i]-128  ;
> >  Integer t=new Integer(ti) ;
[quoted text clipped - 3 lines]
>
> red[i] = (byte)red1[i];

This is what I tried originally, but I got compilation errors about
"possible loss of precision", which I attributed to the issue of 0-255
vs -128-127, and that's why I used the clumsier code. Sorry but I'm used
to languages like Fortran and IDL with implicit type conversion.

> int[] red = { 0, (byte)255, (byte)255,  0,  0, (byte)255, (byte)255,
> 0, (byte)128,  0} ;
>
> Sometimes the casting goes on people's nerves

Yes that form seemed excessively verbose to me ...
especially since I wanted to create a byte array and

byte[] test={0,255,255,  0,  0,255,255,  0,128,  0}

gave me the "possible loss of precision" error.

In IDL I'd use either one of "lighter" form.

b=byte([0,255,255,  0,  0,255,255,  0,128,  0])
b=[0B,255B,255B,  0B,  0B,255B,255B,  0B,128B,  0B]

Let's now assume that I'd got the correct byte arrays red,gre,blu
Then I'd do

IndexColorModel cm = new IndexColorModel(8,10, red,gre,blu) ;  
BufferedImage img = new
BufferedImage(30,10,BufferedImage.TYPE_BYTE_INDEXED,cm) ;

How do I then fill the content of img (or a random pixel region of it)
with values which are indexes in my LUT (numbers 0-9 in the example) if
setRGB assumes TYPE_INT_ARGB and default sRGB color space i.e. is
inconsistent with the definition of img ?

Signature

----------------------------------------------------------------------
nospam@mi.iasf.cnr.it is a newsreading account used by more persons to
avoid unwanted spam. Any mail returning to this address will be rejected.
Users can disclose their e-mail address in the article if they wish so.

a24900@googlemail.com - 07 Mar 2007 18:35 GMT
On Mar 7, 12:30 pm, LC's NoSpam Newsreading account
<nos...@mi.iasf.cnr.it> wrote:
> How do I then fill the content of img (or a random pixel region of it)
> with values which are indexes in my LUT (numbers 0-9 in the example) if
> setRGB assumes TYPE_INT_ARGB and default sRGB color space i.e. is
> inconsistent with the definition of img ?

getRaster().setSample(x, y, 0, value)


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.