Hi again Thomas, Based on my understanding, I re-write my source again. And I attached it to this e-mail. My understanding to your suggestions are...
> 1) The image should still be generated in a ARGB > Buffered Image. > Generating directly to a palletized BufferedImage > will generally give poor results > (slower and will look worse). The original BufferedImage should always ARGB-based, regardless of the intended output. So, we should leave: public BufferedImage createImage(int... un-changed. Rather, the "palletized BufferedImage" can be created within: public void writeImage(BufferedImage.... only when we need the indexed PNG. Within this method, the better IndexColorModel can be created, because ARGB-based BufferedImage is available. Based on this IndexColorModel, we can create the "palletized BufferedImage" to which the data from ARGB-based BufferedImage will be rendered. (But I don't know how to create the IndexColorModel. Please look into my source code.) Is this right? > 2) From what I could see your code used a 5 entry, > what I will simply refer to as "weird" palette. > It looks like you didn't quite understand how the > palette was specified to the PNG encoder. > In any case the palette should come from the > indexed buffered image (by getting it's ColorModel > casting it down to an IndexColorModel and getting > the palette out of that). We need not to explicitly set the RGB palette on PNGEncodeParam.Palette. If they are not set yet, org.apache.batik.ext.awt.image.codec.PNGImageEncoder is wise enough to set them by the way you describe. Is this right? As for the rest of your suggestions, I don't understand them at all :-( Happy Java programming! ------------------------- Jun Inamori OOP-Reserch E-mail: [EMAIL PROTECTED] URL: http://www.oop-reserch.com/
/***************************************************************************** * 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.transcoder.image; import java.awt.image.BufferedImage; import java.awt.image.DataBufferInt; import java.awt.image.SinglePixelPackedSampleModel; import java.io.IOException; import java.io.OutputStream; import org.apache.batik.transcoder.keys.BooleanKey; import org.apache.batik.transcoder.TranscoderException; import org.apache.batik.transcoder.TranscoderOutput; import org.apache.batik.transcoder.TranscodingHints; 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; // By Jun Inamori ([EMAIL PROTECTED]) import java.awt.*; import java.awt.geom.*; import java.awt.image.*; /** * This class is an <tt>ImageTranscoder</tt> that produces a PNG image. * * @author <a href="mailto:[EMAIL PROTECTED]">Thierry Kormann</a> * @version $Id: PNGTranscoder.java,v 1.9 2001/10/29 17:38:27 tkormann Exp $ */ public class PNGTranscoder extends ImageTranscoder { /** * Constructs a new transcoder that produces png images. */ public PNGTranscoder() { hints.put(KEY_FORCE_TRANSPARENT_WHITE, new Boolean(false)); // Start: By Jun Inamori ([EMAIL PROTECTED]) hints.put(KEY_INDEXED_PNG, new Boolean(false)); hints.put(KEY_INTERLACING, new Boolean(false)); // End: By Jun Inamori ([EMAIL PROTECTED]) } /** * Creates a new ARGB image with the specified dimension. * @param width the image width in pixels * @param height the image height in pixels */ public BufferedImage createImage(int width, int height) { return new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); } /** * Writes the specified image to the specified output. * @param img the image to write * @param output the output where to store the image * @param TranscoderException if an error occured while storing the image */ public void writeImage(BufferedImage img, TranscoderOutput output) throws TranscoderException { OutputStream ostream = output.getOutputStream(); if (ostream == null) { throw new TranscoderException( Messages.formatMessage("png.badoutput", null)); } // Start: By Jun Inamori ([EMAIL PROTECTED]) BufferedImage img_src=null; PNGEncodeParam params=null; boolean isIndexed = false; if (hints.containsKey(KEY_INDEXED_PNG)) { isIndexed= ((Boolean)hints.get (KEY_INDEXED_PNG)).booleanValue(); } if(isIndexed){ // XXXX: Fix me! // Based on the given BufferedImage, // I should create IndexColorModel. // Then, I can create better BufferedImage // and can get the better result. // But I don't know how... img_src=new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_BYTE_INDEXED); Graphics2D g2d=img_src.createGraphics(); g2d.setRenderingHint(RenderingHints.KEY_DITHERING,RenderingHints.VALUE_DITHER_ENABLE); g2d.drawRenderedImage(img,(new AffineTransform())); params=PNGEncodeParam.getDefaultEncodeParam(img_src); ((PNGEncodeParam.Palette)params).setBackgroundPaletteIndex(255); } else{ img_src=img; params=PNGEncodeParam.getDefaultEncodeParam(img); ((PNGEncodeParam.RGB)params).setBackgroundRGB(new int [] { 255, 255, 255 }); } // We are using sRGB (gamma 2.2). params.setSRGBIntent(PNGEncodeParam.INTENT_PERCEPTUAL); boolean interlacing = false; if (hints.containsKey(KEY_INTERLACING)) { interlacing= ((Boolean)hints.get (KEY_INTERLACING)).booleanValue(); } params.setInterlacing(interlacing); // END: By Jun Inamori ([EMAIL PROTECTED]) // // This is a trick so that viewers which do not support the alpha // channel will see a white background (and not a black one). // boolean forceTransparentWhite = false; if (hints.containsKey(KEY_FORCE_TRANSPARENT_WHITE)) { forceTransparentWhite = ((Boolean)hints.get (KEY_FORCE_TRANSPARENT_WHITE)).booleanValue(); } if (forceTransparentWhite) { int w = img_src.getWidth(), h = img_src.getHeight(); DataBufferInt biDB = (DataBufferInt)img_src.getRaster().getDataBuffer(); int scanStride = ((SinglePixelPackedSampleModel) img_src.getSampleModel()).getScanlineStride(); int dbOffset = biDB.getOffset(); int pixels[] = biDB.getBankData()[0]; int p = dbOffset; int adjust = scanStride - w; int a=0, r=0, g=0, b=0, pel=0; for(int i=0; i<h; i++){ for(int j=0; j<w; j++){ pel = pixels[p]; a = (pel >> 24) & 0xff; r = (pel >> 16) & 0xff; g = (pel >> 8 ) & 0xff; b = pel & 0xff; r = (255*(255 -a) + a*r)/255; g = (255*(255 -a) + a*g)/255; b = (255*(255 -a) + a*b)/255; pixels[p++] = (a<<24 & 0xff000000) | (r<<16 & 0xff0000) | (g<<8 & 0xff00) | (b & 0xff); } p += adjust; } } try { PNGImageEncoder pngEncoder = new PNGImageEncoder(ostream, params); pngEncoder.encode(img_src); ostream.close(); } catch (IOException ex) { throw new TranscoderException(ex); } } // -------------------------------------------------------------------- // Keys definition // -------------------------------------------------------------------- /** * The 'forceTransparentWhite' key. 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. */ public static final TranscodingHints.Key KEY_FORCE_TRANSPARENT_WHITE = new BooleanKey(); // Start: By Jun Inamori ([EMAIL PROTECTED]) public static final TranscodingHints.Key KEY_INDEXED_PNG = new BooleanKey(); public static final TranscodingHints.Key KEY_INTERLACING = new BooleanKey(); // End: By Jun Inamori ([EMAIL PROTECTED]) }
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]