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]

Reply via email to