Hi,

First of all, thank you for your enthusiastic effort for Batik.
For these few days, I've been played with Batik.
And now, I have a confidence that it will be de-facto standard API for SVG.

By the way, I have a proposal for the new implementation of ImageTranscoder interface.
PNGTranscoder works well on most cases.
But, in rare case, the "indexed" PNG will be required.
For example, only the "indexed" PNG can be used as the wall paper image for the WAP 
phone in Japan.
While I'm not familiar with image manipulation at all, I dived into the source of 
PNGTranscoder.
By the slight modification of it, I implemented IndexedPNGTranscoder, which generates 
the "index" PNG file.

I attached its source to this e-mail.
What do you think of it?
Does it have any substantial problems?
I'd like to hear your opinions.

-- 

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;

/**
 * This class is an <tt>ImageTranscoder</tt> that produces a PNG image.
 *
 * @author <a href="mailto:[EMAIL PROTECTED]";>Jun Inamori</a>
 *
 */
public class IndexedPNGTranscoder extends ImageTranscoder {
    /**
     * Constructs a new transcoder that produces png images.
     */
    public IndexedPNGTranscoder() { 
        hints.put(KEY_FORCE_TRANSPARENT_WHITE, new Boolean(false));
    }

    /**
     * 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_BYTE_INDEXED);
    }

    /**
     * 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
        PNGEncodeParam.Palette params =
            (PNGEncodeParam.Palette)PNGEncodeParam.getDefaultEncodeParam(img);

        int[] rgb=new int[15];
        byte[] alpha=new byte[15];
        for(int i=0; i<15; i++){
            rgb[i]=i*17;
            alpha[i]=(byte)255;
        }

        params.setBitDepth(8);
        params.setPalette(rgb);
        params.setBackgroundPaletteIndex(255);
        params.setPaletteTransparency(alpha);
        params.setSRGBIntent(PNGEncodeParam.INTENT_PERCEPTUAL);
        // END: By Jun Inamori

        //
        // 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.getWidth(), h = img.getHeight();
            DataBufferInt biDB = (DataBufferInt)img.getRaster().getDataBuffer();
            int scanStride = ((SinglePixelPackedSampleModel)
                              img.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);
            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();
}

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to