org.apache.batik.transcoder.image.ImageTranscoder Maven / Gradle / Ivy
/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package org.apache.batik.transcoder.image;
import java.awt.AlphaComposite;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.awt.image.SinglePixelPackedSampleModel;
import org.apache.batik.ext.awt.image.GraphicsUtil;
import org.apache.batik.gvt.renderer.ConcreteImageRendererFactory;
import org.apache.batik.gvt.renderer.ImageRenderer;
import org.apache.batik.gvt.renderer.ImageRendererFactory;
import org.apache.batik.transcoder.SVGAbstractTranscoder;
import org.apache.batik.transcoder.TranscoderException;
import org.apache.batik.transcoder.TranscoderOutput;
import org.apache.batik.transcoder.TranscodingHints;
import org.apache.batik.transcoder.keys.BooleanKey;
import org.apache.batik.transcoder.keys.PaintKey;
import org.w3c.dom.Document;
/**
* This class enables to transcode an input to an image of any format.
*
* Two transcoding hints (KEY_WIDTH
and
* KEY_HEIGHT
) can be used to respectively specify the image
* width and the image height. If only one of these keys is specified,
* the transcoder preserves the aspect ratio of the original image.
*
*
The KEY_BACKGROUND_COLOR
defines the background color
* to use for opaque image formats, or the background color that may
* be used for image formats that support alpha channel.
*
*
The KEY_AOI
represents the area of interest to paint
* in device space.
*
*
Three additional transcoding hints that act on the SVG
* processor can be specified:
*
*
KEY_LANGUAGE
to set the default language to use (may be
* used by a <switch> SVG element for example),
* KEY_USER_STYLESHEET_URI
to fix the URI of a user
* stylesheet, and KEY_MM_PER_PIXEL
to specify the number of
* millimeters in each pixel .
*
* @author Thierry Kormann
* @version $Id: ImageTranscoder.java 1805419 2017-08-18 13:04:30Z ssteiner $
*/
public abstract class ImageTranscoder extends SVGAbstractTranscoder {
/**
* Constructs a new ImageTranscoder
.
*/
protected ImageTranscoder() {
}
/**
* Transcodes the specified Document as an image in the specified output.
*
* @param document the document to transcode
* @param uri the uri of the document or null if any
* @param output the ouput where to transcode
* @exception TranscoderException if an error occured while transcoding
*/
protected void transcode(Document document,
String uri,
TranscoderOutput output)
throws TranscoderException {
// Sets up root, curTxf & curAoi
super.transcode(document, uri, output);
// prepare the image to be painted
int w = (int)(width+0.5);
int h = (int)(height+0.5);
// paint the SVG document using the bridge package
// create the appropriate renderer
ImageRenderer renderer = createRenderer();
renderer.updateOffScreen(w, h);
// curTxf.translate(0.5, 0.5);
renderer.setTransform(curTxf);
renderer.setTree(this.root);
this.root = null; // We're done with it...
try {
// now we are sure that the aoi is the image size
Shape raoi = new Rectangle2D.Float(0, 0, width, height);
// Warning: the renderer's AOI must be in user space
renderer.repaint(curTxf.createInverse().
createTransformedShape(raoi));
BufferedImage rend = renderer.getOffScreen();
renderer = null; // We're done with it...
BufferedImage dest = createImage(w, h);
Graphics2D g2d = GraphicsUtil.createGraphics(dest);
if (hints.containsKey(KEY_BACKGROUND_COLOR)) {
Paint bgcolor = (Paint)hints.get(KEY_BACKGROUND_COLOR);
g2d.setComposite(AlphaComposite.SrcOver);
g2d.setPaint(bgcolor);
g2d.fillRect(0, 0, w, h);
}
if (rend != null) { // might be null if the svg document is empty
g2d.drawRenderedImage(rend, new AffineTransform());
}
g2d.dispose();
rend = null; // We're done with it...
writeImage(dest, output);
} catch (Exception ex) {
throw new TranscoderException(ex);
}
}
/**
* Method so subclasses can modify the Renderer used to render document.
*/
protected ImageRenderer createRenderer() {
ImageRendererFactory rendFactory = new ConcreteImageRendererFactory();
// ImageRenderer renderer = rendFactory.createDynamicImageRenderer();
return rendFactory.createStaticImageRenderer();
}
/**
* Converts an image so that viewers which do not support the
* alpha channel will see a white background (and not a black
* one).
* @param img the image to convert
* @param sppsm
*/
protected void forceTransparentWhite(BufferedImage img, SinglePixelPackedSampleModel sppsm) {
//
// This is a trick so that viewers which do not support
// the alpha channel will see a white background (and not
// a black one).
//
int w = img.getWidth();
int h = img.getHeight();
DataBufferInt biDB=(DataBufferInt)img.getRaster().getDataBuffer();
int scanStride = sppsm.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> 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;
}
}
/**
* Creates a new image with the specified dimension.
* @param width the image width in pixels
* @param height the image height in pixels
*/
public abstract BufferedImage createImage(int width, int height);
/**
* Writes the specified image to the specified output.
* @param img the image to write
* @param output the output where to store the image
* @throws TranscoderException if an error occured while storing the image
*/
public abstract void writeImage(BufferedImage img, TranscoderOutput output)
throws TranscoderException;
// --------------------------------------------------------------------
// Keys definition
// --------------------------------------------------------------------
/**
* The image background paint key.
*
*
* Key:
* KEY_BACKGROUND_COLOR
*
*
* Value:
* Paint
*
*
* Default:
* null
*
*
* Required:
* No
*
*
* Description:
* Specify the background color to use.
* The color is required by opaque image formats and is used by
* image formats that support alpha channel.
*
*
*/
public static final TranscodingHints.Key KEY_BACKGROUND_COLOR
= new PaintKey();
/**
* The forceTransparentWhite key.
*
*
*
* Key:
* KEY_FORCE_TRANSPARENT_WHITE
*
*
* Value:
* Boolean
*
*
* Default:
* false
*
*
* Required:
* No
*
*
* Description:
* 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 useful when
* the encoded file is displayed in a browser which does not
* support transparency correctly and lets the image display with
* a white background instead of a black background.
*
* However, note that the modified image will display differently
* over a white background in a viewer that supports
* transparency.
*
* Not all Transcoders use this key (in particular some formats
* can't preserve the alpha channel at all in which case this
* is not used).
*
*
*/
public static final TranscodingHints.Key KEY_FORCE_TRANSPARENT_WHITE
= new BooleanKey();
}