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]