deweese 2002/06/22 04:52:56 Modified: resources/org/apache/batik/apps/rasterizer/resources Messages.properties sources/org/apache/batik/apps/rasterizer Main.java SVGConverter.java sources/org/apache/batik/transcoder/image PNGTranscoder.java Added: sources/org/apache/batik/ext/awt/image/rendered IndexImage.java Log: 1) Rasterizer now supports '-indexed' property when writting PNG images. This will generate a 256 color indexed PNG image. Revision Changes Path 1.8 +9 -3 xml-batik/resources/org/apache/batik/apps/rasterizer/resources/Messages.properties Index: Messages.properties =================================================================== RCS file: /home/cvs/xml-batik/resources/org/apache/batik/apps/rasterizer/resources/Messages.properties,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- Messages.properties 3 May 2002 07:41:46 -0000 1.7 +++ Messages.properties 22 Jun 2002 11:52:55 -0000 1.8 @@ -90,7 +90,10 @@ \tUser language to use when converting SVG documents.\n \ -q <quality> \n \ \tQuality for the output image. This is only relevant for the \n \ -image/jpeg mime type. \n \ +\timage/jpeg mime type. \n \ + -indexed \n \ +\tReduces the image to 256 colors, resulting in an Indexed image.\n \ +\tThis is only used for PNG conversion.\n \ -dpi <resolution> \n \ \tResolution for the ouptut image. \n \ -validate \n \ @@ -167,11 +170,14 @@ Example: -cssUser myStylesheet.css Default: none -Main.cl.option.q.description = \ +Main.cl.option.quality.description = \ -q <quality> Quality for the generated output image. This is only used for JPEG conversion. \n \ -The value should be in the [0,1[ range. \n \ +The value should be in the [0,1] range. \n \ Example: -q 0.5 Default: 0.99 + +Main.cl.option.indexed.description = \ +-indexed indicates that the image should be reduced to 256 colors, resulting in an Indexed image. This is only used for PNG conversion. Main.cl.option.dpi.description = \ -dpi <resolution> Resolution for the output image. This is used to compute the \n \ 1.22 +20 -1 xml-batik/sources/org/apache/batik/apps/rasterizer/Main.java Index: Main.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/apps/rasterizer/Main.java,v retrieving revision 1.21 retrieving revision 1.22 diff -u -r1.21 -r1.22 --- Main.java 21 Jun 2002 16:35:13 -0000 1.21 +++ Main.java 22 Jun 2002 11:52:56 -0000 1.22 @@ -420,6 +420,15 @@ = Messages.get("Main.cl.option.quality.description", "No description"); /** + * Option to specify if the PNG should be indexed. + */ + public static String CL_OPTION_INDEXED + = Messages.get("Main.cl.option.indexed", "-indexed"); + + public static String CL_OPTION_INDEXED_DESCRIPTION + = Messages.get("Main.cl.option.indexed.description", "No description"); + + /** * Option to specify the set of allowed scripts */ public static String CL_OPTION_ALLOWED_SCRIPTS @@ -639,6 +648,16 @@ } }); + optionMap.put(CL_OPTION_INDEXED, + new NoValueOptionHandler(){ + public void handleOption(SVGConverter c){ + c.setIndexed(true); + } + + public String getOptionDescription(){ + return CL_OPTION_INDEXED_DESCRIPTION; + } + }); optionMap.put(CL_OPTION_VALIDATE, new NoValueOptionHandler(){ public void handleOption(SVGConverter c){ 1.15 +38 -11 xml-batik/sources/org/apache/batik/apps/rasterizer/SVGConverter.java Index: SVGConverter.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/apps/rasterizer/SVGConverter.java,v retrieving revision 1.14 retrieving revision 1.15 diff -u -r1.14 -r1.15 --- SVGConverter.java 17 Jun 2002 12:40:27 -0000 1.14 +++ SVGConverter.java 22 Jun 2002 11:52:56 -0000 1.15 @@ -14,6 +14,7 @@ import org.apache.batik.transcoder.TranscoderOutput; import org.apache.batik.transcoder.image.ImageTranscoder; import org.apache.batik.transcoder.image.JPEGTranscoder; +import org.apache.batik.transcoder.image.PNGTranscoder; import java.io.File; import java.io.FileFilter; @@ -62,19 +63,25 @@ * see the {@link DestinationType} documentation.</li> * <li>width/height: they control the desired width and height, in user space, * for the output image.</li> - * <li>area: controls the specific sub-area of the image which should be rendered.</li> - * <li>backgroundColor: controls the color which is used to fill the background - * before rendering the image</li> + * <li>area: controls the specific sub-area of the image which should be + * rendered.</li> + * <li>backgroundColor: controls the color which is used to fill the + * background before rendering the image</li> * <li>quality: relevant only for JPEG destinations, this controls the - * encoding quality.</li> + * encoding quality.</li> + * <li>indexed: relevant only for PNG, controls the writting of + * indexed files.</li> * <li>mediaType: controls the CSS media, or list of media, for which the - * image should be rendered.</li> - * <li>alternate: controls the alternate CSS stylesheet to activate, if any.</li> - * <li>language: controls the user language with which the SVG document should - * be converted.</li> + * image should be rendered.</li> + * <li>alternate: controls the alternate CSS stylesheet to activate, + * if any.</li> + * <li>language: controls the user language with which the SVG document + * should be converted.</li> * <li>userStylesheet: defines the user stylesheet to apply to SVG documents - * in addition to other stylesheets referenced by or embedded in the SVG documents.</li> - * <li>pixelUnitToMillimeter: defines the size of a pixel in millimeters to use when processing the SVG documents.</li> + * in addition to other stylesheets referenced by or embedded in the + * SVG documents.</li> + * <li>pixelUnitToMillimeter: defines the size of a pixel in millimeters + * to use when processing the SVG documents.</li> * </ul> * * @version $Id$ @@ -201,6 +208,9 @@ /** Output image quality. */ protected float quality = DEFAULT_QUALITY; + /** Should output Image be indexed . */ + protected boolean indexed = false; + /** Output AOI area. */ protected Rectangle2D area = null; @@ -338,6 +348,18 @@ } /** + * Tells the PNG encoder to reduce the image to 256 colors, so the + * PNG file is indexed. + */ + public void setIndexed(boolean indexed) throws IllegalArgumentException { + this.indexed = indexed; + } + + public boolean getIndexed(){ + return indexed; + } + + /** * Sets the user language. If the value is null, then the default (see * {@link org.apache.batik.bridge.UserAgent#getLanguages}) * is used. @@ -737,6 +759,11 @@ // Set image quality. ------------------------------------------------ if (quality > 0) { map.put(JPEGTranscoder.KEY_QUALITY, new Float(this.quality)); + } + + // Set image indexed. ------------------------------------------------ + if (indexed) { + map.put(PNGTranscoder.KEY_INDEXED, new Boolean(indexed)); } // Set image background color ----------------------------------------- 1.1 xml-batik/sources/org/apache/batik/ext/awt/image/rendered/IndexImage.java Index: IndexImage.java =================================================================== /***************************************************************************** * Copyright (C) The Apache Software Foundation. All rights reserved. * * ------------------------------------------------------------------------- * * This software is published under the terms of the Apache Software License * * version 1.1, a copy of which has been included with this distribution in * * the LICENSE file. * *****************************************************************************/ package org.apache.batik.ext.awt.image.rendered; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.image.BufferedImage; import java.awt.image.IndexColorModel; import java.util.Comparator; import java.util.Vector; import java.util.Iterator; /** * This implements an adaptive pallete generator to reduce images * to 256 colors. * * This should probably be generalized to create a pallete with any number of * colors in it (rather than always 256). This should be easy to do. * * Ideally this would also support a better dither option than just * the JDK's pattern dither. * * @author <a href="mailto:[EMAIL PROTECTED]">Thomas DeWeese</a> * @author <a href="mailto:[EMAIL PROTECTED]">Jun Inamori</a> * @version $Id: IndexImage.java,v 1.1 2002/06/22 11:52:56 deweese Exp $ */ public class IndexImage{ /** * Used to track a color and the number of pixels of that colors */ 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; } } /** * Used to define a cube of the colorspace. The cube can be split * approximagely in half to generate two cubes. */ private static class Cube { int []min={0, 0, 0}, max={255,255,255}; boolean done = false; Vector []colors = null; int count=0; static final int RED = 0; static final int GRN = 1; static final int BLU = 2; /** * Define a new cube. * @param colors contains the 3D color histogram to be subdivided * @param count the total number of pixels in the 3D histogram. */ public Cube(Vector []colors, int count) { this.colors = colors; this.count = count; } /** * If this returns true then the cube can not be subdivided any * further */ public boolean isDone() { return done; } /** * Splits the cube into two parts. This cube is * changed to be one half and the returned cube is the other half. * This tries to pick the right channel to split on. */ public Cube split() { int dr = max[0]-min[0]+1; int dg = max[1]-min[1]+1; int db = max[2]-min[2]+1; int c0, c1, splitChannel; // Figure out which axis is the longest and split along // that axis (this tries to keep cubes square-ish). if (dr >= dg) { c0 = GRN; if (dr >= db) { splitChannel = RED; c1=BLU; } else { splitChannel = BLU; c1=RED; } } else if (dg >= db) { splitChannel = GRN; c0=RED; c1=BLU; } else { splitChannel = BLU; c0=RED; c1=GRN; } Cube ret; ret = splitChannel(splitChannel, c0, c1); if (ret != null ) return ret; ret = splitChannel(c0, splitChannel, c1); if (ret != null ) return ret; ret = splitChannel(c1, splitChannel, c0); if (ret != null) return ret; done = true; return null; } /** * Splits the image according to the parameters. It tries * to find a location where half the pixels are on one side * and half the pixels are on the other. */ public Cube splitChannel(int splitChannel, int c0, int c1) { if (min[splitChannel] == max[splitChannel]) return null; int splitSh4 = (2-splitChannel)*4; int c0Sh4 = (2-c0)*4; int c1Sh4 = (2-c1)*4; int splitSh8 = (2-splitChannel)*8; int c0Sh8 = (2-c0)*8; int c1Sh8 = (2-c1)*8; int half = count/2; // Each entry is the number of pixels that have that value // in the split channel within the cube (so pixels // that have that value in the split channel aren't counted // if they are outside the cube in the other color channels. int counts [] = new int[256]; int tcount = 0; // System.out.println("Cube: [" + // min[0] + "-" + max[0] + "] [" + // min[1] + "-" + max[1] + "] [" + // min[2] + "-" + max[2] + "]"); int [] minIdx = {min[0]>>4, min[1]>>4, min[2]>>4}; int [] maxIdx = {max[0]>>4, max[1]>>4, max[2]>>4}; int minR=min[0], minG=min[1], minB=min[2]; int maxR=max[0], maxG=max[1], maxB=max[2]; int val = 0; int [] vals = {0, 0, 0}; for (int i=minIdx[splitChannel]; i<=maxIdx[splitChannel]; i++) { int idx1 = i<<splitSh4; for (int j=minIdx[c0]; j<=maxIdx[c0]; j++) { int idx2 = idx1 | (j<<c0Sh4); for (int k=minIdx[c1]; k<=maxIdx[c1]; k++) { int idx = idx2 | (k<<c1Sh4); Vector v = colors[idx]; if (v==null) continue; Iterator itr = v.iterator(); Counter c; while (itr.hasNext()) { c = (Counter)itr.next(); val = c.val; vals[0] = (val&0xFF0000)>>16; vals[1] = (val&0xFF00)>>8; vals[2] = (val&0xFF); if (((vals[0] >= minR) && (vals[0] <= maxR))&& ((vals[1] >= minG) && (vals[1] <= maxG))&& ((vals[2] >= minB) && (vals[2] <= maxB))) { // The val lies within this cube so count it. counts[vals[splitChannel]] += c.count; tcount += c.count; } } } } // We've found the half way point. Note that the // rest of counts is not filled out. if (tcount >= half) break; } tcount=0; int lastAdd=-1; // These indicate what the top value for the low cube and // the low value of the high cube should be in the split channel // (they may not be one off if there are 'dead' spots in the // counts array. int splitLo=min[splitChannel], splitHi=max[splitChannel]; for (int i=min[splitChannel]; i<=max[splitChannel]; i++) { int c = counts[i]; if (c == 0) { // No counts below this so move up bottom of cube. if ((tcount == 0) && (i < max[splitChannel])) this.min[splitChannel] = i+1; continue; } if (tcount+c < half) { lastAdd = i; tcount+=c; continue; } if ((half-tcount) <= ((tcount+c)-half)) { // Then lastAdd is a better top idx for this then i. if (lastAdd == -1) { // No lower place to break. if (c == this.count) { // All pixels are at this value so make min/max // reflect that. this.max[splitChannel] = i; return null; // no split to make. } else { // There are values about this one so // split above. splitLo = i; splitHi = i+1; break; } } splitLo = lastAdd; splitHi = i; } else { if (i == this.max[splitChannel]) { if ( c == this.count) { // would move min up but that should // have happened already. return null; // no split to make. } else { // Would like to break between i and i+1 // but no i+1 so use lastAdd and i; splitLo = lastAdd; splitHi = i; break; } } // Include c in counts tcount += c; splitLo = i; splitHi = i+1; } break; } // System.out.println("Split: " + splitChannel + "@" // + splitLo + "-"+splitHi + // " Count: " + tcount + " of " + count + // " LA: " + lastAdd); // Create the new cube and update everone's bounds & counts. Cube ret = new Cube(colors, tcount); this.count = this.count-tcount; ret.min[splitChannel] = this.min[splitChannel]; ret.max[splitChannel] = splitLo; this.min[splitChannel] = splitHi; ret.min[c0] = this.min[c0]; ret.max[c0] = this.max[c0]; ret.min[c1] = this.min[c1]; ret.max[c1] = this.max[c1]; return ret; } /** * Returns the average color for this cube */ public int averageColor() { if (this.count == 0) return 0; float red=0, grn=0, blu=0; int minR=min[0], minG=min[1], minB=min[2]; int maxR=max[0], maxG=max[1], maxB=max[2]; int [] minIdx = {minR>>4, minG>>4, minB>>4}; int [] maxIdx = {maxR>>4, maxG>>4, maxB>>4}; int val, ired, igrn, iblu; float weight; for (int i=minIdx[0]; i<=maxIdx[0]; i++) { int idx1 = i<<8; for (int j=minIdx[1]; j<=maxIdx[1]; j++) { int idx2 = idx1 | (j<<4); for (int k=minIdx[2]; k<=maxIdx[2]; k++) { int idx = idx2 | k; Vector v = colors[idx]; if (v==null) continue; Iterator itr = v.iterator(); Counter c; while (itr.hasNext()) { c = (Counter)itr.next(); val = c.val; ired = (val&0xFF0000)>>16; igrn = (val&0x00FF00)>>8; iblu = (val&0x0000FF); if (((ired >= minR) && (ired <= maxR))&& ((igrn >= minG) && (igrn <= maxG))&& ((iblu >= minB) && (iblu <= maxB))) { weight = (c.count/(float)this.count); red += ((float)ired)*weight; grn += ((float)igrn)*weight; blu += ((float)iblu)*weight; } } } } } // System.out.println("RGB: [" + red + ", " + // grn + ", " + blu + "]"); return (((int)(red+0.5))<<16 | ((int)(grn+0.5))<<8 | ((int)(blu+0.5))); } } /** * Converts the input image (must be TYPE_INT_RGB or * TYPE_INT_ARGB) to an indexed image. Generating an adaptive * pallete. */ static public BufferedImage getIndexedImage(BufferedImage bi){ int w=bi.getWidth(); int h=bi.getHeight(); // 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) & 0xFFFFFF); // 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 (true) { if (i.hasNext()) { // try adding our color to each counter... if (((Counter)i.next()).add(rgb)) break; } else { v.add(new Counter(rgb)); break; } } } } } int nCubes=1; int fCube=0; Cube [] cubes = new Cube[256]; cubes[0] = new Cube(colors, w*h); while (nCubes < 256) { while (cubes[fCube].isDone()) { fCube++; if (fCube == nCubes) break; } if (fCube == nCubes) break; Cube c = cubes[fCube]; Cube nc = c.split(); if (nc != null) { if (nc.count > c.count) { Cube tmp = c; c= nc; nc = tmp; } int j = fCube; int cnt = c.count; for (int i=fCube+1; i<nCubes; i++) { if (cubes[i].count < cnt) break; cubes[j++] = cubes[i]; } cubes[j++] = c; cnt = nc.count; while (j<nCubes) { if (cubes[j].count < cnt) break; j++; } for (int i=nCubes; i>j; i--) cubes[i] = cubes[i-1]; cubes[j++] = nc; nCubes++; } } byte [] r = new byte[nCubes]; byte [] g = new byte[nCubes]; byte [] b = new byte[nCubes]; for (int i=0; i<nCubes; i++) { int val = cubes[i].averageColor(); r[i] = (byte)((val>>16)&0xFF); g[i] = (byte)((val>> 8)&0xFF); b[i] = (byte)((val )&0xFF); } IndexColorModel model=new IndexColorModel(4,256,r,g,b); BufferedImage indexed=new BufferedImage (w, h, BufferedImage.TYPE_BYTE_INDEXED,model); Graphics2D g2d=indexed.createGraphics(); g2d.setRenderingHint (RenderingHints.KEY_DITHERING,RenderingHints.VALUE_DITHER_ENABLE); g2d.drawImage(bi, 0, 0, null); g2d.dispose(); return indexed; } } 1.15 +44 -40 xml-batik/sources/org/apache/batik/transcoder/image/PNGTranscoder.java Index: PNGTranscoder.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/transcoder/image/PNGTranscoder.java,v retrieving revision 1.14 retrieving revision 1.15 diff -u -r1.14 -r1.15 --- PNGTranscoder.java 5 Jun 2002 21:14:48 -0000 1.14 +++ PNGTranscoder.java 22 Jun 2002 11:52:56 -0000 1.15 @@ -21,6 +21,7 @@ import org.apache.batik.transcoder.image.resources.Messages; import org.apache.batik.ext.awt.image.codec.PNGEncodeParam; import org.apache.batik.ext.awt.image.codec.PNGImageEncoder; +import org.apache.batik.ext.awt.image.rendered.IndexImage; /** * This class is an <tt>ImageTranscoder</tt> that produces a PNG image. @@ -60,24 +61,6 @@ throw new TranscoderException( Messages.formatMessage("png.badoutput", null)); } - PNGEncodeParam.RGB params = - (PNGEncodeParam.RGB)PNGEncodeParam.getDefaultEncodeParam(img); - params.setBackgroundRGB(new int [] { 255, 255, 255 }); - - // If they specify GAMMA key then use it otherwise don't - // write a gAMA chunk, (default Gamma=2.2). - if (hints.containsKey(KEY_GAMMA)) { - params.setGamma(((Float)hints.get(KEY_GAMMA)).floatValue()); - } - - // We always want an sRGB chunk and Our encoding intent is - // perceptual - params.setSRGBIntent(PNGEncodeParam.INTENT_PERCEPTUAL); - - float PixSzMM = userAgent.getPixelUnitToMillimeter(); - // num Pixs in 1 Meter - int numPix = (int)((1000/PixSzMM)+0.5); - params.setPhysicalDimension(numPix, numPix, 1); // 1 means 'pix/meter' // // This is a trick so that viewers which do not support the alpha @@ -121,6 +104,32 @@ } } + if (hints.containsKey(KEY_INDEXED)) { + if (((Boolean)hints.get(KEY_INDEXED)).booleanValue()) + img = IndexImage.getIndexedImage(img); + } + + PNGEncodeParam params = PNGEncodeParam.getDefaultEncodeParam(img); + if (params instanceof PNGEncodeParam.RGB) { + ((PNGEncodeParam.RGB)params).setBackgroundRGB + (new int [] { 255, 255, 255 }); + } + + // If they specify GAMMA key then use it otherwise don't + // write a gAMA chunk, (default Gamma=2.2). + if (hints.containsKey(KEY_GAMMA)) { + params.setGamma(((Float)hints.get(KEY_GAMMA)).floatValue()); + } + + // We always want an sRGB chunk and Our encoding intent is + // perceptual + params.setSRGBIntent(PNGEncodeParam.INTENT_PERCEPTUAL); + + float PixSzMM = userAgent.getPixelUnitToMillimeter(); + // num Pixs in 1 Meter + int numPix = (int)((1000/PixSzMM)+0.5); + params.setPhysicalDimension(numPix, numPix, 1); // 1 means 'pix/meter' + try { PNGImageEncoder pngEncoder = new PNGImageEncoder(ostream, params); pngEncoder.encode(img); @@ -135,59 +144,54 @@ // -------------------------------------------------------------------- /** - * The forceTransparentWhite key. + * The gamma correction key. * * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1"> * <TR> * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH> - * <TD VALIGN="TOP">KEY_FORCE_TRANSPARENT_WHITE</TD></TR> + * <TD VALIGN="TOP">KEY_GAMMA</TD></TR> * <TR> * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH> - * <TD VALIGN="TOP">Boolean</TD></TR> + * <TD VALIGN="TOP">Float</TD></TR> * <TR> * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH> - * <TD VALIGN="TOP">false</TD></TR> + * <TD VALIGN="TOP">PNGEncodeParam.INTENT_PERCEPTUAL</TD></TR> * <TR> * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH> * <TD VALIGN="TOP">No</TD></TR> * <TR> * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH> - * <TD VALIGN="TOP">It controls whether the encoder should - * force the image's fully transparent pixels to be fully transparent - * white instead of fully transparent black. This is usefull when the - * encoded PNG is displayed in a browser which does not support PNG - * transparency and lets the image display with a white background instead - * of a black background. <br /> However, note that the modified image - * will display differently over a white background in a viewer that - * supports transparency.</TD></TR> + * <TD VALIGN="TOP">Controls the gamma correction of the png image.</TD> + * </TR> * </TABLE> */ - public static final TranscodingHints.Key KEY_FORCE_TRANSPARENT_WHITE - = ImageTranscoder.KEY_FORCE_TRANSPARENT_WHITE; + public static final TranscodingHints.Key KEY_GAMMA + = new FloatKey(); /** - * The gamma correction key. + * The write a 256 color indexed image key. * * <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="1"> * <TR> * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Key: </TH> - * <TD VALIGN="TOP">KEY_GAMMA</TD></TR> + * <TD VALIGN="TOP">KEY_INDEXED</TD></TR> * <TR> * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Value: </TH> - * <TD VALIGN="TOP">Float</TD></TR> + * <TD VALIGN="TOP">Boolean</TD></TR> * <TR> * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Default: </TH> - * <TD VALIGN="TOP">PNGEncodeParam.INTENT_PERCEPTUAL</TD></TR> + * <TD VALIGN="TOP">False</TD></TR> * <TR> * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Required: </TH> * <TD VALIGN="TOP">No</TD></TR> * <TR> * <TH VALIGN="TOP" ALIGN="RIGHT"><P ALIGN="RIGHT">Description: </TH> - * <TD VALIGN="TOP">Controls the gamma correction of the png image.</TD> + * <TD VALIGN="TOP">Turns on the reduction of the image to 256 colors. + * The resultant PNG will be an indexed PNG with 256 colors.</TD> * </TR> * </TABLE> */ - public static final TranscodingHints.Key KEY_GAMMA - = new FloatKey(); + public static final TranscodingHints.Key KEY_INDEXED + = new BooleanKey(); }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]