You are viewing a plain text version of this content. The canonical link for it is here.
Posted to batik-dev@xmlgraphics.apache.org by Jun Inamori <ju...@oop-reserch.com> on 2002/06/20 22:42:51 UTC

Re: ImageTranscoder

Hi Thomas,

On May16, 2002 08:40 -0400, Thomas E Deweese wrote:
> >>>>> "JI" == Jun Inamori <ju...@oop-reserch.com> writes:
> 
> JI> Hi Thomas,
> >> Correct GIMP creates palette that adapts to the contents of the
> >> image.  There are many ways of doing this, I don't know what method
> >> GIMP uses but it is probably a pretty good one, the one I
> >> referenced earlier is also pretty good and very standard.
> 
> JI> While I don't understand what GIMP is doing, the resulting PNG
> JI> will be the good starting point for me.  Because I'm not familiar
> JI> with the image manipulation at all, my first step is to know "What
> JI> is the desirable Color Palette?" :-) I played with the indexed PNG
> JI> from GIMP.  The next code fragment prints the RGB values in the
> JI> indexed Color Palette:
> 
>     This looks ok.  One point you seem to be missing is that the red,
> greens & blues aren't independent things.  They are tied togeather as
> a 24bit quanitity.  So it is much more correct to print the triplet
> rather than each color seperately.
> 
> int mask = 0x00FF;  // Short hand for Integer.parseInt("00ff",16);
> for (int i=0; i<mapSize; i++)
>    System.out.println("Color: [" + 
>                       ((int)red  [i])&mask + ", "
>                       ((int)green[i])&mask + ", "
>                       ((int)blue [i])&mask + "]");
>    
> JI> From RGB-PNG, I should calculate the values for:
> 
> JI> 	    byte[] red=new byte[x]; byte[] green=new byte[x]; byte[]
> JI> blue=new byte[x];
> 
> JI> Then, I can use:
> 
> JI> IndexColorModel model=new IndexColorModel(8,x,red,green,blue); new
> JI> BufferedImage(w, h, BufferedImage.TYPE_BYTE_INDEXED, model);
> 
> JI> Is this the way to go?
> 
>     correct this is how you would construct the buffered image to
> draw the RGB image into.
> 
> JI> Anyway, I tried to pick up all the available colors in RGB-PNG.
> JI> Only way I found is....
> 
>     Once again you are treating the RGB's as independent you can't do
> this.  Usually what is done is that you make an array indexed by the
> first 3-4 bits of each color:
> 
> private static class Counter {
>         public int val;
>         public int count=1;
>         public Counter(int val) {  this.val = val; }
>         public boolean add(int val) {
>         // See if the value matches us...
>         if (this.val != val)
>           return false;
>         count++;
>         return true;
>         }
> }
> 
> // Using 4 bits from RG & B.
> Vector [] colors = new Vector[1<12]; 
> 
>     int rgb=0;
>     for(int i_w=0; i_w<w; i_w++){
> 	for(int i_h=0; i_h<h; i_h++){
> 	    rgb=bi.getRGB(i_w,i_h);
> 
>             // Get index from high four bits of each component.
>             int idx = (((rgb&0xF00000)>>> 12) |
>                        ((rgb&0x00F000)>>>  8) |
>                        ((rgb&0x0000F0)>>>  4))
> 
>             // Get the 'hash vector' for that key.
>             Vector v = colors[idx];
>             if (v == null) {
>                // No colors in this bin yet so create vector and add color.
>                v = new Vector();
>                v.add(new Counter(rgb));
>                colors[idx] = v;
>             } else {
>                // find our color in the bin or create a counter for it.
>                Iterator i = v.iterator();
>                while (i.hasNext())
>                  // try adding our color to each counter...
>                  if (((Counter)i.next()).add(rgb)) break;
>                if(!i.hasNext())
>                   v.add(new Counter(rgb));
>             }
>         }
> 
>     Now you have every unique color in the image stored in the various
> bins of colors, and you have a count for each color.  So if there are
> more than 256 colors (which there often will be) you can select which
> colors to use based on frequency...
> 
> JI> I think I made a little progress, but I'm not sure if this is the
> JI> right way or not.
> 
>     The above should help get you back on track...
> 

I apologize my delayed response.
I'm still interested in the conversion to the indexed PNG.
In my previous proposal, the poor default ColorPalette results in somewhat ugly image.

Based on the suggestions from Thomas, I tried to find the way to create the ColorPalette from the original BufferedImage.
To make the things clearer, I implemented the simple conversion class.
It has only one static method, which converts the RGB BufferedImage to the indexed BufferedImage.
If it works well, it can be used by:
 org/apache/batik/transcoder/image/PNGTranscoder.java
and Batik can produce the indexed image from SVG.

The resulting image looks better than before, but it still looks different than the one indexed by Gimp.
(Gimp is the image manipulation tool.)
What is wrong with my class?

Happy Java programming!
-------------------------------------
Jun Inamori
OOP-Reserch
E-mail: jun@oop-reserch.com
URL:    http://www.oop-reserch.com/