mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2026-05-01 00:00:02 -04:00
It all works
This commit is contained in:
Executable
+574
@@ -0,0 +1,574 @@
|
||||
/*
|
||||
* Copyright (c) 2008, Harald Kuhr
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name "TwelveMonkeys" nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.imageio.plugins.svg;
|
||||
|
||||
import com.twelvemonkeys.image.ImageUtil;
|
||||
import com.twelvemonkeys.imageio.ImageReaderBase;
|
||||
import com.twelvemonkeys.imageio.util.IIOUtil;
|
||||
import org.apache.batik.bridge.*;
|
||||
import org.apache.batik.dom.svg.SVGDOMImplementation;
|
||||
import org.apache.batik.dom.svg.SVGOMDocument;
|
||||
import org.apache.batik.dom.util.DOMUtilities;
|
||||
import org.apache.batik.ext.awt.image.GraphicsUtil;
|
||||
import org.apache.batik.gvt.CanvasGraphicsNode;
|
||||
import org.apache.batik.gvt.GraphicsNode;
|
||||
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.*;
|
||||
import org.apache.batik.transcoder.image.ImageTranscoder;
|
||||
import org.apache.batik.util.ParsedURL;
|
||||
import org.w3c.dom.DOMImplementation;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.svg.SVGSVGElement;
|
||||
|
||||
import javax.imageio.IIOException;
|
||||
import javax.imageio.ImageReadParam;
|
||||
import javax.imageio.ImageTypeSpecifier;
|
||||
import javax.imageio.spi.ImageReaderSpi;
|
||||
import java.awt.*;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Dimension2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Image reader for SVG document fragments.
|
||||
* <p/>
|
||||
*
|
||||
* @author Harald Kuhr
|
||||
* @author Inpspired by code from the Batik Team
|
||||
* @version $Id: $
|
||||
* @see <A href="http://www.mail-archive.com/batik-dev@xml.apache.org/msg00992.html">batik-dev</A>
|
||||
*/
|
||||
public class SVGImageReader extends ImageReaderBase {
|
||||
private Rasterizer mRasterizer = new Rasterizer();
|
||||
|
||||
/**
|
||||
* Creates an {@code SVGImageReader}.
|
||||
*
|
||||
* @param pProvider the provider
|
||||
*/
|
||||
public SVGImageReader(ImageReaderSpi pProvider) {
|
||||
super(pProvider);
|
||||
}
|
||||
|
||||
protected void resetMembers() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
super.dispose();
|
||||
mRasterizer = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInput(Object pInput, boolean pSeekForwardOnly, boolean pIgnoreMetadata) {
|
||||
super.setInput(pInput, pSeekForwardOnly, pIgnoreMetadata);
|
||||
|
||||
if (mImageInput != null) {
|
||||
TranscoderInput input = new TranscoderInput(IIOUtil.createStreamAdapter(mImageInput));
|
||||
mRasterizer.setInput(input);
|
||||
}
|
||||
}
|
||||
|
||||
public BufferedImage read(int pIndex, ImageReadParam pParam) throws IOException {
|
||||
checkBounds(pIndex);
|
||||
|
||||
String baseURI = null;
|
||||
|
||||
if (pParam instanceof SVGReadParam) {
|
||||
SVGReadParam svgParam = (SVGReadParam) pParam;
|
||||
// Set IIOParams as hints
|
||||
// Note: The cast to Map invokes a different method that preserves
|
||||
// unset defaults, DO NOT REMOVE!
|
||||
mRasterizer.setTranscodingHints((Map) paramsToHints(svgParam));
|
||||
|
||||
// Get the base URI (not a hint)
|
||||
baseURI = svgParam.getBaseURI();
|
||||
}
|
||||
|
||||
Dimension size;
|
||||
if (pParam != null && (size = pParam.getSourceRenderSize()) != null) {
|
||||
// Use size...
|
||||
}
|
||||
else {
|
||||
size = new Dimension(getWidth(pIndex), getHeight(pIndex));
|
||||
}
|
||||
|
||||
BufferedImage destination = getDestination(pParam, getImageTypes(pIndex), size.width, size.height);
|
||||
|
||||
// Read in the image, using the Batik Transcoder
|
||||
try {
|
||||
processImageStarted(pIndex);
|
||||
|
||||
mRasterizer.mTranscoderInput.setURI(baseURI);
|
||||
BufferedImage image = mRasterizer.getImage();
|
||||
|
||||
Graphics2D g = destination.createGraphics();
|
||||
try {
|
||||
g.setComposite(AlphaComposite.Src);
|
||||
g.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE);
|
||||
g.drawImage(image, 0, 0, null); // TODO: Dest offset?
|
||||
}
|
||||
finally {
|
||||
g.dispose();
|
||||
}
|
||||
|
||||
processImageComplete();
|
||||
|
||||
return destination;
|
||||
}
|
||||
catch (TranscoderException e) {
|
||||
throw new IIOException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private TranscodingHints paramsToHints(SVGReadParam pParam) throws IOException {
|
||||
TranscodingHints hints = new TranscodingHints();
|
||||
// Note: We must allow generic ImageReadParams, so converting to
|
||||
// TanscodingHints should be done outside the SVGReadParam class.
|
||||
|
||||
// Set dimensions
|
||||
Dimension size = pParam.getSourceRenderSize();
|
||||
Dimension origSize = new Dimension(getWidth(0), getHeight(0));
|
||||
if (size == null) {
|
||||
// SVG is not a pixel based format, but we'll scale it, according to
|
||||
// the subsampling for compatibility
|
||||
size = getSourceRenderSizeFromSubsamping(pParam, origSize);
|
||||
}
|
||||
|
||||
if (size != null) {
|
||||
hints.put(ImageTranscoder.KEY_WIDTH, new Float(size.getWidth()));
|
||||
hints.put(ImageTranscoder.KEY_HEIGHT, new Float(size.getHeight()));
|
||||
}
|
||||
|
||||
// Set area of interest
|
||||
Rectangle region = pParam.getSourceRegion();
|
||||
if (region != null) {
|
||||
hints.put(ImageTranscoder.KEY_AOI, region);
|
||||
|
||||
// Avoid that the batik transcoder scales the AOI up to original image size
|
||||
if (size == null) {
|
||||
hints.put(ImageTranscoder.KEY_WIDTH, new Float(region.getWidth()));
|
||||
hints.put(ImageTranscoder.KEY_HEIGHT, new Float(region.getHeight()));
|
||||
}
|
||||
else {
|
||||
// Need to resize here...
|
||||
double xScale = size.getWidth() / origSize.getWidth();
|
||||
double yScale = size.getHeight() / origSize.getHeight();
|
||||
|
||||
hints.put(ImageTranscoder.KEY_WIDTH, new Float(region.getWidth() * xScale));
|
||||
hints.put(ImageTranscoder.KEY_HEIGHT, new Float(region.getHeight() * yScale));
|
||||
}
|
||||
}
|
||||
else if (size != null) {
|
||||
// Allow non-uniform scaling
|
||||
hints.put(ImageTranscoder.KEY_AOI, new Rectangle(origSize));
|
||||
}
|
||||
|
||||
// Background color
|
||||
Paint bg = pParam.getBackgroundColor();
|
||||
if (bg != null) {
|
||||
hints.put(ImageTranscoder.KEY_BACKGROUND_COLOR, bg);
|
||||
}
|
||||
|
||||
return hints;
|
||||
}
|
||||
|
||||
private Dimension getSourceRenderSizeFromSubsamping(ImageReadParam pParam, Dimension pOrigSize) {
|
||||
if (pParam.getSourceXSubsampling() > 1 || pParam.getSourceYSubsampling() > 1) {
|
||||
return new Dimension((int) (pOrigSize.width / (float) pParam.getSourceXSubsampling()),
|
||||
(int) (pOrigSize.height / (float) pParam.getSourceYSubsampling()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ImageReadParam getDefaultReadParam() {
|
||||
return new SVGReadParam();
|
||||
}
|
||||
|
||||
public int getWidth(int pIndex) throws IOException {
|
||||
checkBounds(pIndex);
|
||||
try {
|
||||
return mRasterizer.getDefaultWidth();
|
||||
}
|
||||
catch (TranscoderException e) {
|
||||
throw new IIOException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public int getHeight(int pIndex) throws IOException {
|
||||
checkBounds(pIndex);
|
||||
try {
|
||||
return mRasterizer.getDefaultHeight();
|
||||
}
|
||||
catch (TranscoderException e) {
|
||||
throw new IIOException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<ImageTypeSpecifier> getImageTypes(int imageIndex) throws IOException {
|
||||
return Collections.singleton(ImageTypeSpecifier.createFromRenderedImage(mRasterizer.createImage(1, 1))).iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* An image transcoder that stores the resulting image.
|
||||
* <p/>
|
||||
* NOTE: This class includes a lot of copy and paste code from the Batik classes
|
||||
* and needs major refactoring!
|
||||
*/
|
||||
private class Rasterizer extends SVGAbstractTranscoder /*ImageTranscoder*/ {
|
||||
|
||||
BufferedImage mImage = null;
|
||||
private TranscoderInput mTranscoderInput;
|
||||
private float mDefaultWidth;
|
||||
private float mDefaultHeight;
|
||||
private boolean mInit = false;
|
||||
private SVGOMDocument mDocument;
|
||||
private String mURI;
|
||||
private GraphicsNode mGVTRoot;
|
||||
private TranscoderException mException;
|
||||
private BridgeContext mContext;
|
||||
|
||||
public BufferedImage createImage(int w, int h) {
|
||||
return ImageUtil.createTransparent(w, h);//, BufferedImage.TYPE_INT_ARGB);
|
||||
}
|
||||
|
||||
// This is cheating... We don't fully transcode after all
|
||||
protected void transcode(Document document, String uri, TranscoderOutput output) throws TranscoderException {
|
||||
// Sets up root, curTxf & curAoi
|
||||
// ----
|
||||
if ((document != null) &&
|
||||
!(document.getImplementation() instanceof SVGDOMImplementation)) {
|
||||
DOMImplementation impl;
|
||||
impl = (DOMImplementation) hints.get(KEY_DOM_IMPLEMENTATION);
|
||||
// impl = ExtensibleSVGDOMImplementation.getDOMImplementation();
|
||||
document = DOMUtilities.deepCloneDocument(document, impl);
|
||||
if (uri != null) {
|
||||
try {
|
||||
URL url = new URL(uri);
|
||||
((SVGOMDocument) document).setURLObject(url);
|
||||
}
|
||||
catch (MalformedURLException ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx = createBridgeContext();
|
||||
SVGOMDocument svgDoc = (SVGOMDocument) document;
|
||||
//SVGSVGElement root = svgDoc.getRootElement();
|
||||
|
||||
// build the GVT tree
|
||||
builder = new GVTBuilder();
|
||||
// flag that indicates if the document is dynamic
|
||||
boolean isDynamic =
|
||||
(hints.containsKey(KEY_EXECUTE_ONLOAD) &&
|
||||
(Boolean) hints.get(KEY_EXECUTE_ONLOAD) &&
|
||||
BaseScriptingEnvironment.isDynamicDocument(ctx, svgDoc));
|
||||
|
||||
if (isDynamic) {
|
||||
ctx.setDynamicState(BridgeContext.DYNAMIC);
|
||||
}
|
||||
|
||||
// Modified code below:
|
||||
GraphicsNode root = null;
|
||||
try {
|
||||
root = builder.build(ctx, svgDoc);
|
||||
}
|
||||
catch (BridgeException ex) {
|
||||
// Note: This might fail, but we STILL have the dimensions we need
|
||||
// However, we need to reparse later...
|
||||
//throw new TranscoderException(ex);
|
||||
mException = new TranscoderException(ex);
|
||||
}
|
||||
|
||||
// ----
|
||||
|
||||
// get the 'width' and 'height' attributes of the SVG document
|
||||
Dimension2D docSize = ctx.getDocumentSize();
|
||||
if (docSize != null) {
|
||||
mDefaultWidth = (float) docSize.getWidth();
|
||||
mDefaultHeight = (float) docSize.getHeight();
|
||||
}
|
||||
else {
|
||||
mDefaultWidth = 200;
|
||||
mDefaultHeight = 200;
|
||||
}
|
||||
|
||||
// Hack to work around exception above
|
||||
if (root != null) {
|
||||
mGVTRoot = root;
|
||||
}
|
||||
mDocument = svgDoc;
|
||||
mURI = uri;
|
||||
|
||||
//ctx.dispose();
|
||||
// Hack to avoid the transcode method wacking my context...
|
||||
mContext = ctx;
|
||||
ctx = null;
|
||||
}
|
||||
|
||||
private BufferedImage readImage() throws TranscoderException {
|
||||
init();
|
||||
|
||||
if (abortRequested()) {
|
||||
processReadAborted();
|
||||
return null;
|
||||
}
|
||||
processImageProgress(10f);
|
||||
|
||||
|
||||
// Hacky workaround below...
|
||||
if (mGVTRoot == null) {
|
||||
// Try to reparse, if we had no URI last time...
|
||||
if (mURI != mTranscoderInput.getURI()) {
|
||||
try {
|
||||
mContext.dispose();
|
||||
mDocument.setURLObject(new URL(mTranscoderInput.getURI()));
|
||||
transcode(mDocument, mTranscoderInput.getURI(), null);
|
||||
}
|
||||
catch (MalformedURLException ignore) {
|
||||
// Ignored
|
||||
}
|
||||
}
|
||||
|
||||
if (mGVTRoot == null) {
|
||||
throw mException;
|
||||
}
|
||||
}
|
||||
ctx = mContext;
|
||||
// /Hacky
|
||||
if (abortRequested()) {
|
||||
processReadAborted();
|
||||
return null;
|
||||
}
|
||||
processImageProgress(20f);
|
||||
|
||||
// -- --
|
||||
SVGSVGElement root = mDocument.getRootElement();
|
||||
// ----
|
||||
|
||||
|
||||
// ----
|
||||
setImageSize(mDefaultWidth, mDefaultHeight);
|
||||
|
||||
if (abortRequested()) {
|
||||
processReadAborted();
|
||||
return null;
|
||||
}
|
||||
processImageProgress(40f);
|
||||
|
||||
// compute the preserveAspectRatio matrix
|
||||
AffineTransform Px;
|
||||
String ref = new ParsedURL(mURI).getRef();
|
||||
|
||||
try {
|
||||
Px = ViewBox.getViewTransform(ref, root, width, height);
|
||||
|
||||
}
|
||||
catch (BridgeException ex) {
|
||||
throw new TranscoderException(ex);
|
||||
}
|
||||
|
||||
if (Px.isIdentity() && (width != mDefaultWidth || height != mDefaultHeight)) {
|
||||
// The document has no viewBox, we need to resize it by hand.
|
||||
// we want to keep the document size ratio
|
||||
float xscale, yscale;
|
||||
xscale = width / mDefaultWidth;
|
||||
yscale = height / mDefaultHeight;
|
||||
float scale = Math.min(xscale, yscale);
|
||||
Px = AffineTransform.getScaleInstance(scale, scale);
|
||||
}
|
||||
// take the AOI into account if any
|
||||
if (hints.containsKey(KEY_AOI)) {
|
||||
Rectangle2D aoi = (Rectangle2D) hints.get(KEY_AOI);
|
||||
// transform the AOI into the image's coordinate system
|
||||
aoi = Px.createTransformedShape(aoi).getBounds2D();
|
||||
AffineTransform Mx = new AffineTransform();
|
||||
double sx = width / aoi.getWidth();
|
||||
double sy = height / aoi.getHeight();
|
||||
Mx.scale(sx, sy);
|
||||
double tx = -aoi.getX();
|
||||
double ty = -aoi.getY();
|
||||
Mx.translate(tx, ty);
|
||||
// take the AOI transformation matrix into account
|
||||
// we apply first the preserveAspectRatio matrix
|
||||
Px.preConcatenate(Mx);
|
||||
curAOI = aoi;
|
||||
}
|
||||
else {
|
||||
curAOI = new Rectangle2D.Float(0, 0, width, height);
|
||||
}
|
||||
|
||||
if (abortRequested()) {
|
||||
processReadAborted();
|
||||
return null;
|
||||
}
|
||||
processImageProgress(50f);
|
||||
|
||||
CanvasGraphicsNode cgn = getCanvasGraphicsNode(mGVTRoot);
|
||||
if (cgn != null) {
|
||||
cgn.setViewingTransform(Px);
|
||||
curTxf = new AffineTransform();
|
||||
}
|
||||
else {
|
||||
curTxf = Px;
|
||||
}
|
||||
|
||||
try {
|
||||
// dispatch an 'onload' event if needed
|
||||
if (ctx.isDynamic()) {
|
||||
BaseScriptingEnvironment se;
|
||||
se = new BaseScriptingEnvironment(ctx);
|
||||
se.loadScripts();
|
||||
se.dispatchSVGLoadEvent();
|
||||
}
|
||||
}
|
||||
catch (BridgeException ex) {
|
||||
throw new TranscoderException(ex);
|
||||
}
|
||||
|
||||
this.root = mGVTRoot;
|
||||
// ----
|
||||
|
||||
// NOTE: The code below is copied and pasted from the Batik
|
||||
// ImageTranscoder class' transcode() method:
|
||||
|
||||
// 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
|
||||
ImageRendererFactory rendFactory = new ConcreteImageRendererFactory();
|
||||
// ImageRenderer renderer = rendFactory.createDynamicImageRenderer();
|
||||
ImageRenderer renderer = rendFactory.createStaticImageRenderer();
|
||||
renderer.updateOffScreen(w, h);
|
||||
renderer.setTransform(curTxf);
|
||||
renderer.setTree(this.root);
|
||||
this.root = null; // We're done with it...
|
||||
|
||||
if (abortRequested()) {
|
||||
processReadAborted();
|
||||
return null;
|
||||
}
|
||||
processImageProgress(75f);
|
||||
|
||||
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));
|
||||
// NOTE: repaint above cause nullpointer exception with fonts..???
|
||||
|
||||
|
||||
BufferedImage rend = renderer.getOffScreen();
|
||||
renderer = null; // We're done with it...
|
||||
|
||||
BufferedImage dest = createImage(w, h);
|
||||
|
||||
Graphics2D g2d = GraphicsUtil.createGraphics(dest);
|
||||
try {
|
||||
if (hints.containsKey(ImageTranscoder.KEY_BACKGROUND_COLOR)) {
|
||||
Paint bgcolor = (Paint) hints.get(ImageTranscoder.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());
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (g2d != null) {
|
||||
g2d.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
if (abortRequested()) {
|
||||
processReadAborted();
|
||||
return null;
|
||||
}
|
||||
processImageProgress(99f);
|
||||
|
||||
return dest;
|
||||
//writeImage(dest, output);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new TranscoderException(ex.getMessage(), ex);
|
||||
}
|
||||
finally {
|
||||
if (mContext != null) {
|
||||
mContext.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void init() throws TranscoderException {
|
||||
if (!mInit) {
|
||||
if (mTranscoderInput == null) {
|
||||
throw new IllegalStateException("input == null");
|
||||
}
|
||||
|
||||
mInit = true;
|
||||
|
||||
super.transcode(mTranscoderInput, null);
|
||||
}
|
||||
}
|
||||
|
||||
private BufferedImage getImage() throws TranscoderException {
|
||||
if (mImage == null) {
|
||||
mImage = readImage();
|
||||
}
|
||||
return mImage;
|
||||
}
|
||||
|
||||
protected int getDefaultWidth() throws TranscoderException {
|
||||
init();
|
||||
return (int) (mDefaultWidth + 0.5);
|
||||
}
|
||||
|
||||
protected int getDefaultHeight() throws TranscoderException {
|
||||
init();
|
||||
return (int) (mDefaultHeight + 0.5);
|
||||
}
|
||||
|
||||
public void setInput(TranscoderInput pInput) {
|
||||
mTranscoderInput = pInput;
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
+174
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* Copyright (c) 2008, Harald Kuhr
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name "TwelveMonkeys" nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.imageio.plugins.svg;
|
||||
|
||||
import com.twelvemonkeys.imageio.spi.ProviderInfo;
|
||||
import com.twelvemonkeys.lang.SystemUtil;
|
||||
import com.twelvemonkeys.imageio.util.IIOUtil;
|
||||
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.spi.ImageReaderSpi;
|
||||
import javax.imageio.spi.ServiceRegistry;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* SVGImageReaderSpi
|
||||
* <p/>
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: SVGImageReaderSpi.java,v 1.1 2003/12/02 16:45:00 haku Exp $
|
||||
*/
|
||||
public class SVGImageReaderSpi extends ImageReaderSpi {
|
||||
|
||||
private final static boolean SVG_READER_AVAILABLE = SystemUtil.isClassAvailable("com.twelvemonkeys.imageio.plugins.svg.SVGImageReader");
|
||||
|
||||
/**
|
||||
* Creates an {@code SVGImageReaderSpi}.
|
||||
*/
|
||||
public SVGImageReaderSpi() {
|
||||
this(IIOUtil.getProviderInfo(SVGImageReaderSpi.class));
|
||||
}
|
||||
|
||||
private SVGImageReaderSpi(final ProviderInfo pProviderInfo) {
|
||||
super(
|
||||
pProviderInfo.getVendorName(), // Vendor name
|
||||
pProviderInfo.getVersion(), // Version
|
||||
SVG_READER_AVAILABLE ? new String[]{"svg", "SVG"} : new String[]{""}, // Names
|
||||
SVG_READER_AVAILABLE ? new String[]{"svg"} : null, // Suffixes
|
||||
SVG_READER_AVAILABLE ? new String[]{"image/svg", "image/x-svg", "image/svg+xml", "image/svg-xml"} : null, // Mime-types
|
||||
"com.twelvemonkeys.imageio.plugins.svg.SVGImageReader", // Reader class name
|
||||
ImageReaderSpi.STANDARD_INPUT_TYPE, // Output types
|
||||
null, // Writer SPI names
|
||||
true, // Supports standard stream metadata format
|
||||
null, // Native stream metadata format name
|
||||
null, // Native stream metadata format class name
|
||||
null, // Extra stream metadata format names
|
||||
null, // Extra stream metadata format class names
|
||||
true, // Supports standard image metadata format
|
||||
null, // Native image metadata format name
|
||||
null, // Native image metadata format class name
|
||||
null, // Extra image metadata format names
|
||||
null // Extra image metadata format class names
|
||||
);
|
||||
}
|
||||
|
||||
public boolean canDecodeInput(Object pSource) throws IOException {
|
||||
return pSource instanceof ImageInputStream && SVG_READER_AVAILABLE && canDecode((ImageInputStream) pSource);
|
||||
}
|
||||
|
||||
private static boolean canDecode(ImageInputStream pInput) throws IOException {
|
||||
// NOTE: This test is quite quick as it does not involve any parsing,
|
||||
// however it requires the doctype to be "svg", which may not be correct
|
||||
// in all cases...
|
||||
try {
|
||||
pInput.mark();
|
||||
|
||||
// TODO: This is may not be ok for non-UTF/iso-latin encodings...
|
||||
// TODO: Use an XML (encoding) aware Reader instance instead
|
||||
// Need to figure out pretty fast if this is XML or not
|
||||
int b;
|
||||
while (Character.isWhitespace((char) (b = pInput.read()))) {
|
||||
// Skip over leading WS
|
||||
}
|
||||
|
||||
if (!((b == '<') && (pInput.read() == '?') && (pInput.read() == 'x') && (pInput.read() == 'm')
|
||||
&& (pInput.read() == 'l'))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Okay, we have XML. But, is it really SVG?
|
||||
boolean docTypeFound = false;
|
||||
while (!docTypeFound) {
|
||||
while (pInput.read() != '<') {
|
||||
// Skip over, until begin tag
|
||||
}
|
||||
|
||||
// If this is not a comment, or the DOCTYPE declaration, the doc
|
||||
// has no DOCTYPE and it can't be svg
|
||||
if (pInput.read() != '!') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// There might be comments before the doctype, unfortunately...
|
||||
// If next is "--", this is a comment
|
||||
if ((b = pInput.read()) == '-' && pInput.read() == '-') {
|
||||
while (!(pInput.read() == '-' && pInput.read() == '-' && pInput.read() == '>')) {
|
||||
// Skip until end of comment
|
||||
}
|
||||
}
|
||||
|
||||
// If we are lucky, this is DOCTYPE declaration
|
||||
if (b == 'D' && pInput.read() == 'O' && pInput.read() == 'C'
|
||||
&& pInput.read() == 'T' && pInput.read() == 'Y' && pInput.read() == 'P'
|
||||
&& pInput.read() == 'E') {
|
||||
docTypeFound = true;
|
||||
while (Character.isWhitespace((char) (b = pInput.read()))) {
|
||||
// Skip over WS
|
||||
}
|
||||
if (b == 's' && pInput.read() == 'v' && pInput.read() == 'g') {
|
||||
//System.out.println("It's svg!");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
finally {
|
||||
pInput.reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public ImageReader createReaderInstance(Object extension) throws IOException {
|
||||
return new SVGImageReader(this);
|
||||
}
|
||||
|
||||
public String getDescription(Locale locale) {
|
||||
return "Scaleable Vector Graphics (SVG) format image reader";
|
||||
}
|
||||
|
||||
@SuppressWarnings({"deprecation"})
|
||||
@Override
|
||||
public void onRegistration(ServiceRegistry registry, Class<?> category) {
|
||||
if (!SVG_READER_AVAILABLE) {
|
||||
try {
|
||||
// NOTE: This will break, but it gives us some useful debug info
|
||||
new SVGImageReader(this);
|
||||
}
|
||||
catch (Throwable t) {
|
||||
System.err.println("Could not instantiate SVGImageReader (missing support classes).");
|
||||
t.printStackTrace();
|
||||
}
|
||||
|
||||
IIOUtil.deregisterProvider(registry, this, category);
|
||||
}
|
||||
}}
|
||||
|
||||
Executable
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2008, Harald Kuhr
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name "TwelveMonkeys" nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.imageio.plugins.svg;
|
||||
|
||||
import javax.imageio.ImageReadParam;
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* Implementation of {@code IamgeReadParam} for SVG images.
|
||||
* SVG images allows for different source render sizes.
|
||||
*
|
||||
*/
|
||||
public class SVGReadParam extends ImageReadParam {
|
||||
private Paint mBackground;
|
||||
private String mBaseURI;
|
||||
|
||||
public Paint getBackgroundColor() {
|
||||
return mBackground;
|
||||
}
|
||||
|
||||
public void setBackgroundColor(Paint pColor) {
|
||||
mBackground = pColor;
|
||||
}
|
||||
|
||||
public String getBaseURI() {
|
||||
return mBaseURI;
|
||||
}
|
||||
|
||||
public void setBaseURI(String pBaseURI) {
|
||||
mBaseURI = pBaseURI;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canSetSourceRenderSize() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Executable
+189
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Copyright (c) 2008, Harald Kuhr
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name "TwelveMonkeys" nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.imageio.plugins.tiff;
|
||||
|
||||
import com.twelvemonkeys.image.ImageUtil;
|
||||
import com.twelvemonkeys.imageio.ImageReaderBase;
|
||||
import org.apache.batik.ext.awt.image.codec.SeekableStream;
|
||||
import org.apache.batik.ext.awt.image.codec.tiff.TIFFDecodeParam;
|
||||
import org.apache.batik.ext.awt.image.codec.tiff.TIFFImageDecoder;
|
||||
|
||||
import javax.imageio.ImageReadParam;
|
||||
import javax.imageio.ImageTypeSpecifier;
|
||||
import javax.imageio.spi.ImageReaderSpi;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.RenderedImage;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* TIFFImageReader class description.
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: TIFFImageReader.java,v 1.0 29.jul.2004 12:52:33 haku Exp $
|
||||
*/
|
||||
// TODO: Massive clean-up
|
||||
// TODO: Support raster decoding...
|
||||
public class TIFFImageReader extends ImageReaderBase {
|
||||
|
||||
private TIFFImageDecoder mDecoder = null;
|
||||
private List<RenderedImage> mImages = new ArrayList<RenderedImage>();
|
||||
|
||||
protected TIFFImageReader(final ImageReaderSpi pOriginatingProvider) {
|
||||
super(pOriginatingProvider);
|
||||
}
|
||||
|
||||
protected void resetMembers() {
|
||||
mDecoder = null;
|
||||
}
|
||||
|
||||
public BufferedImage read(int pIndex, ImageReadParam pParam) throws IOException {
|
||||
// Decode image, convert and return as BufferedImage
|
||||
RenderedImage image = readAsRenderedImage(pIndex, pParam);
|
||||
return ImageUtil.toBuffered(image);
|
||||
}
|
||||
|
||||
public RenderedImage readAsRenderedImage(int pIndex, ImageReadParam pParam) throws IOException {
|
||||
init(pIndex);
|
||||
|
||||
processImageStarted(pIndex);
|
||||
|
||||
if (pParam == null) {
|
||||
// Cache image for use by getWidth and getHeight methods
|
||||
RenderedImage image;
|
||||
if (mImages.size() > pIndex && mImages.get(pIndex) != null) {
|
||||
image = mImages.get(pIndex);
|
||||
}
|
||||
else {
|
||||
// Decode
|
||||
image = mDecoder.decodeAsRenderedImage(pIndex);
|
||||
|
||||
// Make room
|
||||
for (int i = mImages.size(); i < pIndex; i++) {
|
||||
mImages.add(pIndex, null);
|
||||
}
|
||||
mImages.add(pIndex, image);
|
||||
}
|
||||
|
||||
if (abortRequested()) {
|
||||
processReadAborted();
|
||||
return image;
|
||||
}
|
||||
|
||||
processImageComplete();
|
||||
return image;
|
||||
}
|
||||
else {
|
||||
// TODO: Parameter conversion
|
||||
mDecoder.setParam(new TIFFDecodeParam());
|
||||
|
||||
RenderedImage image = mDecoder.decodeAsRenderedImage(pIndex);
|
||||
|
||||
// Subsample and apply AOI
|
||||
if (pParam.getSourceRegion() != null) {
|
||||
image = fakeAOI(ImageUtil.toBuffered(image), pParam);
|
||||
}
|
||||
if (pParam.getSourceXSubsampling() > 1 || pParam.getSourceYSubsampling() > 1) {
|
||||
image = ImageUtil.toBuffered(fakeSubsampling(ImageUtil.toBuffered(image), pParam));
|
||||
}
|
||||
|
||||
processImageComplete();
|
||||
return image;
|
||||
}
|
||||
}
|
||||
|
||||
private void init(int pIndex) throws IOException {
|
||||
init();
|
||||
checkBounds(pIndex);
|
||||
}
|
||||
|
||||
protected void checkBounds(int pIndex) throws IOException {
|
||||
if (pIndex < getMinIndex()){
|
||||
throw new IndexOutOfBoundsException("index < minIndex");
|
||||
}
|
||||
else if (pIndex >= getNumImages(true)) {
|
||||
throw new IndexOutOfBoundsException("index > numImages");
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void init() {
|
||||
if (mDecoder == null) {
|
||||
if (mImageInput == null) {
|
||||
throw new IllegalStateException("input == null");
|
||||
}
|
||||
|
||||
mDecoder = new TIFFImageDecoder(new SeekableStream() {
|
||||
public int read() throws IOException {
|
||||
return mImageInput.read();
|
||||
}
|
||||
|
||||
public int read(final byte[] pBytes, final int pStart, final int pLength) throws IOException {
|
||||
return mImageInput.read(pBytes, pStart, pLength);
|
||||
}
|
||||
|
||||
public long getFilePointer() throws IOException {
|
||||
return mImageInput.getStreamPosition();
|
||||
}
|
||||
|
||||
public void seek(final long pPos) throws IOException {
|
||||
mImageInput.seek(pPos);
|
||||
}
|
||||
}, null);
|
||||
}
|
||||
}
|
||||
|
||||
public int getWidth(int pIndex) throws IOException {
|
||||
init(pIndex);
|
||||
|
||||
// TODO: Use cache...
|
||||
return mDecoder.decodeAsRenderedImage(pIndex).getWidth();
|
||||
}
|
||||
|
||||
public int getHeight(int pIndex) throws IOException {
|
||||
init(pIndex);
|
||||
|
||||
// TODO: Use cache...
|
||||
return mDecoder.decodeAsRenderedImage(pIndex).getHeight();
|
||||
}
|
||||
|
||||
public Iterator<ImageTypeSpecifier> getImageTypes(final int imageIndex) throws IOException {
|
||||
throw new UnsupportedOperationException("Method getImageTypes not implemented");// TODO: Implement
|
||||
}
|
||||
|
||||
public int getNumImages(boolean pAllowSearch) throws IOException {
|
||||
init();
|
||||
if (pAllowSearch) {
|
||||
return mDecoder.getNumPages();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
Executable
+125
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (c) 2008, Harald Kuhr
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name "TwelveMonkeys" nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.imageio.plugins.tiff;
|
||||
|
||||
import com.twelvemonkeys.imageio.spi.ProviderInfo;
|
||||
import com.twelvemonkeys.lang.SystemUtil;
|
||||
import com.twelvemonkeys.imageio.util.IIOUtil;
|
||||
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.spi.ImageReaderSpi;
|
||||
import javax.imageio.spi.ServiceRegistry;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* TIFFImageReaderSpi
|
||||
* <p/>
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: TIFFImageReaderSpi.java,v 1.1 2003/12/02 16:45:00 wmhakur Exp $
|
||||
*/
|
||||
public class TIFFImageReaderSpi extends ImageReaderSpi {
|
||||
|
||||
final static boolean TIFF_CLASSES_AVAILABLE = SystemUtil.isClassAvailable("com.twelvemonkeys.imageio.plugins.tiff.TIFFImageReader");
|
||||
|
||||
/**
|
||||
* Creates a {@code TIFFImageReaderSpi}.
|
||||
*/
|
||||
public TIFFImageReaderSpi() {
|
||||
this(IIOUtil.getProviderInfo(TIFFImageReaderSpi.class));
|
||||
}
|
||||
|
||||
private TIFFImageReaderSpi(final ProviderInfo pProviderInfo) {
|
||||
super(
|
||||
pProviderInfo.getVendorName(), // Vendor name
|
||||
pProviderInfo.getVersion(), // Version
|
||||
TIFF_CLASSES_AVAILABLE ? new String[]{"tiff", "TIFF"} : new String[] {""}, // Names
|
||||
TIFF_CLASSES_AVAILABLE ? new String[]{"tiff", "tif"} : null, // Suffixes
|
||||
TIFF_CLASSES_AVAILABLE ? new String[]{"image/tiff", "image/x-tiff"} : null, // Mime-types
|
||||
"com.twelvemonkeys.imageio.plugins.tiff.TIFFImageReader", // Writer class name..?
|
||||
ImageReaderSpi.STANDARD_INPUT_TYPE, // Output types
|
||||
new String[]{"com.twelvemonkeys.imageio.plugins.tiff.TIFFImageWriterSpi"}, // Writer SPI names
|
||||
true, // Supports standard stream metadata format
|
||||
null, // Native stream metadata format name
|
||||
null, // Native stream metadata format class name
|
||||
null, // Extra stream metadata format names
|
||||
null, // Extra stream metadata format class names
|
||||
true, // Supports standard image metadata format
|
||||
null, // Native image metadata format name
|
||||
null, // Native image metadata format class name
|
||||
null, // Extra image metadata format names
|
||||
null // Extra image metadata format class names
|
||||
);
|
||||
}
|
||||
|
||||
public boolean canDecodeInput(Object source) throws IOException {
|
||||
return source instanceof ImageInputStream && TIFF_CLASSES_AVAILABLE && canDecode((ImageInputStream) source);
|
||||
}
|
||||
|
||||
|
||||
static boolean canDecode(ImageInputStream pInput) throws IOException {
|
||||
try {
|
||||
pInput.mark();
|
||||
int byte0 = pInput.read(); // Byte order 1 (M or I)
|
||||
int byte1 = pInput.read(); // Byte order 2 (always same as 1)
|
||||
int byte2 = pInput.read(); // Version number 1 (M: 0, I: 42)
|
||||
int byte3 = pInput.read(); // Version number 2 (M: 42, I: 0)
|
||||
|
||||
// Test for Motorola or Intel byte order, and version number == 42
|
||||
if ((byte0 == 'M' && byte1 == 'M' && byte2 == 0 && byte3 == 42)
|
||||
|| (byte0 == 'I' && byte1 == 'I' && byte2 == 42 && byte3 == 0)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
finally {
|
||||
pInput.reset();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public ImageReader createReaderInstance(Object extension) throws IOException {
|
||||
return new TIFFImageReader(this);
|
||||
}
|
||||
|
||||
public String getDescription(Locale locale) {
|
||||
return "Tagged Image File Format (TIFF) image reader";
|
||||
}
|
||||
|
||||
@SuppressWarnings({"deprecation"})
|
||||
@Override
|
||||
public void onRegistration(ServiceRegistry registry, Class<?> category) {
|
||||
if (!TIFF_CLASSES_AVAILABLE) {
|
||||
IIOUtil.deregisterProvider(registry, this, category);
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
+145
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright (c) 2008, Harald Kuhr
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name "TwelveMonkeys" nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.imageio.plugins.tiff;
|
||||
|
||||
import com.twelvemonkeys.image.ImageUtil;
|
||||
import com.twelvemonkeys.imageio.ImageWriterBase;
|
||||
import com.twelvemonkeys.imageio.util.IIOUtil;
|
||||
import org.apache.batik.ext.awt.image.codec.ImageEncodeParam;
|
||||
import org.apache.batik.ext.awt.image.codec.tiff.TIFFEncodeParam;
|
||||
import org.apache.batik.ext.awt.image.codec.tiff.TIFFImageEncoder;
|
||||
|
||||
import javax.imageio.IIOImage;
|
||||
import javax.imageio.ImageTypeSpecifier;
|
||||
import javax.imageio.ImageWriteParam;
|
||||
import javax.imageio.metadata.IIOMetadata;
|
||||
import javax.imageio.spi.ImageWriterSpi;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.RenderedImage;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* TIFFImageWriter class description.
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: TIFFImageWriter.java,v 1.0 29.jul.2004 12:52:54 haku Exp $
|
||||
*/
|
||||
public class TIFFImageWriter extends ImageWriterBase {
|
||||
|
||||
private TIFFImageEncoder mEncoder = null;
|
||||
|
||||
protected TIFFImageWriter(final ImageWriterSpi pProvider) {
|
||||
super(pProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOutput(final Object pOutput) {
|
||||
mEncoder = null;
|
||||
super.setOutput(pOutput);
|
||||
}
|
||||
|
||||
public IIOMetadata getDefaultImageMetadata(final ImageTypeSpecifier imageType, final ImageWriteParam param) {
|
||||
throw new UnsupportedOperationException("Method getDefaultImageMetadata not implemented");// TODO: Implement
|
||||
}
|
||||
|
||||
public IIOMetadata convertImageMetadata(final IIOMetadata inData, final ImageTypeSpecifier imageType, final ImageWriteParam param) {
|
||||
throw new UnsupportedOperationException("Method convertImageMetadata not implemented");// TODO: Implement
|
||||
}
|
||||
|
||||
public void write(final IIOMetadata pStreamMetadata, final IIOImage pImage, final ImageWriteParam pParam) throws IOException {
|
||||
RenderedImage renderedImage = pImage.getRenderedImage();
|
||||
init();
|
||||
|
||||
ImageEncodeParam param;
|
||||
if (pParam != null) {
|
||||
param = new TIFFEncodeParam();
|
||||
// TODO: Convert params
|
||||
|
||||
mEncoder.setParam(param);
|
||||
}
|
||||
|
||||
BufferedImage image;
|
||||
|
||||
// FIX: TIFFEnocder chokes on a any of the TYPE_INT_* types...
|
||||
// (The TIFFEncoder expects int types to have 1 sample of size 32
|
||||
// while there actually is 4 samples of size 8, according to the
|
||||
// SampleModel...)
|
||||
if (renderedImage instanceof BufferedImage && (
|
||||
((BufferedImage) renderedImage).getType() == BufferedImage.TYPE_INT_ARGB
|
||||
|| ((BufferedImage) renderedImage).getType() == BufferedImage.TYPE_INT_ARGB_PRE)) {
|
||||
image = ImageUtil.toBuffered(renderedImage, BufferedImage.TYPE_4BYTE_ABGR);
|
||||
}
|
||||
else if (renderedImage instanceof BufferedImage && (
|
||||
((BufferedImage) renderedImage).getType() == BufferedImage.TYPE_INT_BGR
|
||||
|| ((BufferedImage) renderedImage).getType() == BufferedImage.TYPE_INT_RGB)) {
|
||||
image = ImageUtil.toBuffered(renderedImage, BufferedImage.TYPE_3BYTE_BGR);
|
||||
}
|
||||
else {
|
||||
image = ImageUtil.toBuffered(renderedImage);
|
||||
}
|
||||
|
||||
image = fakeAOI(image, pParam);
|
||||
image = ImageUtil.toBuffered(fakeSubsampling(image, pParam));
|
||||
|
||||
/*
|
||||
System.out.println("Image: " + pImage);
|
||||
SampleModel sampleModel = pImage.getSampleModel();
|
||||
System.out.println("SampleModel: " + sampleModel);
|
||||
int sampleSize[] = sampleModel.getSampleSize();
|
||||
System.out.println("Samples: " + sampleSize.length);
|
||||
for (int i = 0; i < sampleSize.length; i++) {
|
||||
System.out.println("SampleSize[" + i + "]: " + sampleSize[i]);
|
||||
}
|
||||
int dataType = sampleModel.getDataType();
|
||||
System.out.println("DataType: " + dataType);
|
||||
*/
|
||||
|
||||
processImageStarted(0);
|
||||
|
||||
mEncoder.encode(image);
|
||||
mImageOutput.flush();
|
||||
|
||||
processImageComplete();
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
super.dispose();
|
||||
mEncoder = null;
|
||||
}
|
||||
|
||||
private synchronized void init() {
|
||||
if (mEncoder == null) {
|
||||
if (mImageOutput == null) {
|
||||
throw new IllegalStateException("output == null");
|
||||
}
|
||||
mEncoder = new TIFFImageEncoder(IIOUtil.createStreamAdapter(mImageOutput), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
+107
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) 2008, Harald Kuhr
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name "TwelveMonkeys" nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.imageio.plugins.tiff;
|
||||
|
||||
import com.twelvemonkeys.imageio.spi.ProviderInfo;
|
||||
import com.twelvemonkeys.imageio.util.IIOUtil;
|
||||
|
||||
import javax.imageio.ImageTypeSpecifier;
|
||||
import javax.imageio.ImageWriter;
|
||||
import javax.imageio.spi.ImageWriterSpi;
|
||||
import javax.imageio.spi.ServiceRegistry;
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* TIFFmageWriterSpi
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: TIFFImageWriterSpi.java,v 1.2 2004/01/14 15:21:44 wmhakur Exp $
|
||||
*/
|
||||
public class TIFFImageWriterSpi extends ImageWriterSpi {
|
||||
|
||||
/**
|
||||
* Creates a {@code TIFFImageWriterSpi}.
|
||||
*/
|
||||
public TIFFImageWriterSpi() {
|
||||
this(IIOUtil.getProviderInfo(TIFFImageWriterSpi.class));
|
||||
}
|
||||
|
||||
private TIFFImageWriterSpi(final ProviderInfo pProviderInfo) {
|
||||
super(
|
||||
pProviderInfo.getVendorName(), // Vendor name
|
||||
pProviderInfo.getVersion(), // Version
|
||||
new String[]{"tiff", "TIFF"}, // Names
|
||||
new String[]{"tif", "tiff"}, // Suffixes
|
||||
new String[]{"image/tiff", "image/x-tiff"}, // Mime-types
|
||||
"com.twelvemonkeys.imageio.plugins.tiff.TIFFImageWriter", // Writer class name..?
|
||||
STANDARD_OUTPUT_TYPE, // Output types
|
||||
new String[]{"com.twelvemonkeys.imageio.plugins.tiff.TIFFImageReaderSpi"}, // Reader SPI names
|
||||
true, // Supports standard stream metadata format
|
||||
null, // Native stream metadata format name
|
||||
null, // Native stream metadata format class name
|
||||
null, // Extra stream metadata format names
|
||||
null, // Extra stream metadata format class names
|
||||
true, // Supports standard image metadata format
|
||||
null, // Native image metadata format name
|
||||
null, // Native image metadata format class name
|
||||
null, // Extra image metadata format names
|
||||
null // Extra image metadata format class names
|
||||
);
|
||||
}
|
||||
|
||||
public boolean canEncodeImage(ImageTypeSpecifier type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public ImageWriter createWriterInstance(Object extension) throws IOException {
|
||||
try {
|
||||
return new TIFFImageWriter(this);
|
||||
}
|
||||
catch (Throwable t) {
|
||||
// Wrap in IOException if the writer can't be instantiated.
|
||||
// This makes the IIORegistry deregister this service provider
|
||||
IOException exception = new IOException(t.getMessage());
|
||||
exception.initCause(t);
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
|
||||
public String getDescription(Locale locale) {
|
||||
return "Tagged Image File Format (TIFF) image writer";
|
||||
}
|
||||
|
||||
@SuppressWarnings({"deprecation"})
|
||||
@Override
|
||||
public void onRegistration(ServiceRegistry registry, Class<?> category) {
|
||||
if (!TIFFImageReaderSpi.TIFF_CLASSES_AVAILABLE) {
|
||||
IIOUtil.deregisterProvider(registry, this, category);
|
||||
}
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2008, Harald Kuhr
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name "TwelveMonkeys" nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.imageio.plugins.wmf;
|
||||
|
||||
/**
|
||||
* WMF
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: WMF.java,v 1.0 Feb 17, 2008 5:46:59 PM haraldk Exp$
|
||||
*/
|
||||
interface WMF {
|
||||
static byte[] HEADER = new byte[] {
|
||||
(byte) 0xd7, (byte) 0xcd, (byte) 0xc6, (byte) 0x9a, (byte) 0x00,
|
||||
(byte) 0x00, //(byte) 0x7a, (byte) 0xf3, (byte) 0xa6, (byte) 0xfe,
|
||||
//(byte) 0xf5, (byte) 0x06, (byte) 0x1c, (byte) 0x01, (byte) 0xe8,
|
||||
//(byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||
//(byte) 0xcc,
|
||||
};
|
||||
}
|
||||
Executable
+137
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (c) 2008, Harald Kuhr
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name "TwelveMonkeys" nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.imageio.plugins.wmf;
|
||||
|
||||
import com.twelvemonkeys.imageio.ImageReaderBase;
|
||||
import com.twelvemonkeys.imageio.plugins.svg.SVGImageReader;
|
||||
import com.twelvemonkeys.imageio.plugins.svg.SVGReadParam;
|
||||
import com.twelvemonkeys.imageio.util.IIOUtil;
|
||||
import org.apache.batik.transcoder.TranscoderException;
|
||||
import org.apache.batik.transcoder.TranscoderInput;
|
||||
import org.apache.batik.transcoder.TranscoderOutput;
|
||||
import org.apache.batik.transcoder.wmf.tosvg.WMFTranscoder;
|
||||
|
||||
import javax.imageio.IIOException;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.ImageReadParam;
|
||||
import javax.imageio.ImageTypeSpecifier;
|
||||
import javax.imageio.spi.ImageReaderSpi;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.*;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* WMFImageReader class description.
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: WMFImageReader.java,v 1.0 29.jul.2004 13:00:59 haku Exp $
|
||||
*/
|
||||
// TODO: Probably possible to do less wrapping/unwrapping of data...
|
||||
// TODO: Consider using temp file instead of in-memory stream
|
||||
public class WMFImageReader extends ImageReaderBase {
|
||||
|
||||
private SVGImageReader mReader = null;
|
||||
|
||||
public WMFImageReader(final ImageReaderSpi pProvider) {
|
||||
super(pProvider);
|
||||
}
|
||||
|
||||
protected void resetMembers() {
|
||||
if (mReader != null) {
|
||||
mReader.dispose();
|
||||
}
|
||||
mReader = null;
|
||||
}
|
||||
|
||||
public BufferedImage read(int pIndex, ImageReadParam pParam) throws IOException {
|
||||
init();
|
||||
|
||||
processImageStarted(pIndex);
|
||||
|
||||
BufferedImage image = mReader.read(pIndex, pParam);
|
||||
if (abortRequested()) {
|
||||
processReadAborted();
|
||||
return image;
|
||||
}
|
||||
|
||||
processImageComplete();
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
private synchronized void init() throws IOException {
|
||||
// Need the extra test, to avoid throwing an IOException from the Transcoder
|
||||
if (mImageInput == null) {
|
||||
throw new IllegalStateException("input == null");
|
||||
}
|
||||
|
||||
if (mReader == null) {
|
||||
WMFTranscoder transcoder = new WMFTranscoder();
|
||||
|
||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||
Writer writer = new OutputStreamWriter(output, "UTF8");
|
||||
try {
|
||||
TranscoderInput in = new TranscoderInput(IIOUtil.createStreamAdapter(mImageInput));
|
||||
TranscoderOutput out = new TranscoderOutput(writer);
|
||||
|
||||
// TODO: Transcodinghints?
|
||||
|
||||
transcoder.transcode(in, out);
|
||||
}
|
||||
catch (TranscoderException e) {
|
||||
throw new IIOException(e.getMessage(), e);
|
||||
}
|
||||
|
||||
mReader = new SVGImageReader(getOriginatingProvider());
|
||||
mReader.setInput(ImageIO.createImageInputStream(new ByteArrayInputStream(output.toByteArray())));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageReadParam getDefaultReadParam() {
|
||||
return new SVGReadParam();
|
||||
}
|
||||
|
||||
public int getWidth(int pIndex) throws IOException {
|
||||
init();
|
||||
return mReader.getWidth(pIndex);
|
||||
}
|
||||
|
||||
public int getHeight(int pIndex) throws IOException {
|
||||
init();
|
||||
return mReader.getHeight(pIndex);
|
||||
}
|
||||
|
||||
public Iterator<ImageTypeSpecifier> getImageTypes(final int pImageIndex) throws IOException {
|
||||
init();
|
||||
return mReader.getImageTypes(pImageIndex);
|
||||
}
|
||||
|
||||
}
|
||||
Executable
+128
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (c) 2008, Harald Kuhr
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name "TwelveMonkeys" nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.imageio.plugins.wmf;
|
||||
|
||||
import com.twelvemonkeys.imageio.spi.ProviderInfo;
|
||||
import com.twelvemonkeys.lang.SystemUtil;
|
||||
import com.twelvemonkeys.imageio.util.IIOUtil;
|
||||
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.spi.ImageReaderSpi;
|
||||
import javax.imageio.spi.ServiceRegistry;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* WMFImageReaderSpi
|
||||
* <p/>
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: WMFImageReaderSpi.java,v 1.1 2003/12/02 16:45:00 wmhakur Exp $
|
||||
*/
|
||||
public class WMFImageReaderSpi extends ImageReaderSpi {
|
||||
|
||||
// This is correct, as we rely on the SVG reader
|
||||
private final static boolean WMF_READER_AVAILABLE = SystemUtil.isClassAvailable("com.twelvemonkeys.imageio.plugins.svg.SVGImageReader");
|
||||
|
||||
/**
|
||||
* Creates a {@code WMFImageReaderSpi}.
|
||||
*/
|
||||
public WMFImageReaderSpi() {
|
||||
this(IIOUtil.getProviderInfo(WMFImageReaderSpi.class));
|
||||
}
|
||||
|
||||
private WMFImageReaderSpi(final ProviderInfo pProviderInfo) {
|
||||
super(
|
||||
pProviderInfo.getVendorName(), // Vendor name
|
||||
pProviderInfo.getVersion(), // Version
|
||||
WMF_READER_AVAILABLE ? new String[]{"wmf", "WMF"} : new String[]{""}, // Names
|
||||
WMF_READER_AVAILABLE ? new String[]{"wmf", "emf"} : null, // Suffixes
|
||||
WMF_READER_AVAILABLE ? new String[]{"application/x-msmetafile", "image/x-wmf"} : null, // Mime-types
|
||||
WMFImageReader.class.getName(), // Reader class name..?
|
||||
ImageReaderSpi.STANDARD_INPUT_TYPE, // Output types
|
||||
null, // Writer SPI names
|
||||
true, // Supports standard stream metadata format
|
||||
null, // Native stream metadata format name
|
||||
null, // Native stream metadata format class name
|
||||
null, // Extra stream metadata format names
|
||||
null, // Extra stream metadata format class names
|
||||
true, // Supports standard image metadata format
|
||||
null, // Native image metadata format name
|
||||
null, // Native image metadata format class name
|
||||
null, // Extra image metadata format names
|
||||
null // Extra image metadata format class names
|
||||
);
|
||||
}
|
||||
|
||||
public boolean canDecodeInput(Object source) throws IOException {
|
||||
return source instanceof ImageInputStream && WMF_READER_AVAILABLE && canDecode((ImageInputStream) source);
|
||||
}
|
||||
|
||||
public static boolean canDecode(ImageInputStream pInput) throws IOException {
|
||||
if (pInput == null) {
|
||||
throw new IllegalArgumentException("input == null");
|
||||
}
|
||||
|
||||
try {
|
||||
pInput.mark();
|
||||
|
||||
for (byte header : WMF.HEADER) {
|
||||
int read = (byte) pInput.read();
|
||||
if (header != read) {
|
||||
// System.out.println("--> " + i + ": " + read + " (expected " + header + ")");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
finally {
|
||||
pInput.reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public ImageReader createReaderInstance(Object extension) throws IOException {
|
||||
return new WMFImageReader(this);
|
||||
}
|
||||
|
||||
public String getDescription(Locale locale) {
|
||||
return "Windows Meta File (WMF) image reader";
|
||||
}
|
||||
|
||||
@SuppressWarnings({"deprecation"})
|
||||
@Override
|
||||
public void onRegistration(ServiceRegistry registry, Class<?> category) {
|
||||
if (!WMF_READER_AVAILABLE) {
|
||||
IIOUtil.deregisterProvider(registry, this, category);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Executable
+3
@@ -0,0 +1,3 @@
|
||||
com.twelvemonkeys.imageio.plugins.svg.SVGImageReaderSpi
|
||||
com.twelvemonkeys.imageio.plugins.wmf.WMFImageReaderSpi
|
||||
#com.twelvemonkeys.imageio.plugins.tiff.TIFFImageReaderSpi
|
||||
Executable
+1
@@ -0,0 +1 @@
|
||||
#com.twelvemonkeys.imageio.plugins.tiff.TIFFImageWriterSpi
|
||||
Reference in New Issue
Block a user