org.apache.xmlgraphics.image.loader.impl.PreloaderEPS Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.apache.fop Show documentation
Show all versions of org.apache.fop Show documentation
The core maven build properties
The newest version!
/*
* 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.
*/
/* $Id: PreloaderEPS.java 1610846 2014-07-15 20:44:18Z vhennebert $ */
package org.apache.xmlgraphics.image.loader.impl;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.nio.ByteOrder;
import javax.imageio.stream.ImageInputStream;
import javax.xml.transform.Source;
import org.apache.xmlgraphics.image.loader.ImageContext;
import org.apache.xmlgraphics.image.loader.ImageInfo;
import org.apache.xmlgraphics.image.loader.ImageSize;
import org.apache.xmlgraphics.image.loader.util.ImageInputStreamAdapter;
import org.apache.xmlgraphics.image.loader.util.ImageUtil;
import org.apache.xmlgraphics.ps.DSCConstants;
import org.apache.xmlgraphics.ps.dsc.DSCException;
import org.apache.xmlgraphics.ps.dsc.DSCParser;
import org.apache.xmlgraphics.ps.dsc.DSCParserConstants;
import org.apache.xmlgraphics.ps.dsc.events.DSCComment;
import org.apache.xmlgraphics.ps.dsc.events.DSCCommentBoundingBox;
import org.apache.xmlgraphics.ps.dsc.events.DSCEvent;
import org.apache.xmlgraphics.util.MimeConstants;
/**
* Image preloader for EPS images (Encapsulated PostScript).
*/
public class PreloaderEPS extends AbstractImagePreloader {
/** Key for binary header object used in custom objects of the ImageInfo class. */
public static final Object EPS_BINARY_HEADER = EPSBinaryFileHeader.class;
/** Key for bounding box used in custom objects of the ImageInfo class. */
public static final Object EPS_BOUNDING_BOX = Rectangle2D.class;
/** {@inheritDoc} */
public ImageInfo preloadImage(String uri, Source src, ImageContext context)
throws IOException {
if (!ImageUtil.hasImageInputStream(src)) {
return null;
}
ImageInputStream in = ImageUtil.needImageInputStream(src);
in.mark();
ByteOrder originalByteOrder = in.getByteOrder();
in.setByteOrder(ByteOrder.LITTLE_ENDIAN);
EPSBinaryFileHeader binaryHeader = null;
try {
long magic = in.readUnsignedInt();
magic &= 0xFFFFFFFFL; //Work-around for bug in Java 1.4.2
// Check if binary header
boolean supported = false;
if (magic == 0xC6D3D0C5L) {
supported = true; //binary EPS
binaryHeader = readBinaryFileHeader(in);
in.reset();
in.mark(); //Mark start of file again
in.seek(binaryHeader.psStart);
} else if (magic == 0x53502125L) { //"%!PS" in little endian
supported = true; //ascii EPS
in.reset();
in.mark(); //Mark start of file again
} else {
in.reset();
}
if (supported) {
ImageInfo info = new ImageInfo(uri, MimeConstants.MIME_EPS);
boolean success = determineSize(in, context, info);
in.reset(); //Need to go back to start of file
if (!success) {
//No BoundingBox found, so probably no EPS
return null;
}
if (in.getStreamPosition() != 0) {
throw new IllegalStateException("Need to be at the start of the file here");
}
if (binaryHeader != null) {
info.getCustomObjects().put(EPS_BINARY_HEADER, binaryHeader);
}
return info;
} else {
return null;
}
} finally {
in.setByteOrder(originalByteOrder);
}
}
private EPSBinaryFileHeader readBinaryFileHeader(ImageInputStream in) throws IOException {
EPSBinaryFileHeader offsets = new EPSBinaryFileHeader();
offsets.psStart = in.readUnsignedInt();
offsets.psLength = in.readUnsignedInt();
offsets.wmfStart = in.readUnsignedInt();
offsets.wmfLength = in.readUnsignedInt();
offsets.tiffStart = in.readUnsignedInt();
offsets.tiffLength = in.readUnsignedInt();
return offsets;
}
private boolean determineSize(ImageInputStream in, ImageContext context, ImageInfo info)
throws IOException {
in.mark();
try {
Rectangle2D bbox = null;
DSCParser parser;
try {
parser = new DSCParser(new ImageInputStreamAdapter(in));
outerLoop:
while (parser.hasNext()) {
DSCEvent event = parser.nextEvent();
switch (event.getEventType()) {
case DSCParserConstants.HEADER_COMMENT:
case DSCParserConstants.COMMENT:
//ignore
break;
case DSCParserConstants.DSC_COMMENT:
DSCComment comment = event.asDSCComment();
if (comment instanceof DSCCommentBoundingBox) {
DSCCommentBoundingBox bboxComment = (DSCCommentBoundingBox)comment;
if (DSCConstants.BBOX.equals(bboxComment.getName()) && bbox == null) {
bbox = (Rectangle2D)bboxComment.getBoundingBox().clone();
//BoundingBox is good but HiRes is better so continue
} else if (DSCConstants.HIRES_BBOX.equals(bboxComment.getName())) {
bbox = (Rectangle2D)bboxComment.getBoundingBox().clone();
//HiRefBBox is great so stop
break outerLoop;
}
}
break;
default:
//No more header so stop
break outerLoop;
}
}
if (bbox == null) {
return false;
}
} catch (DSCException e) {
throw new IOException("Error while parsing EPS file: " + e.getMessage());
}
ImageSize size = new ImageSize();
size.setSizeInMillipoints(
(int)Math.round(bbox.getWidth() * 1000),
(int)Math.round(bbox.getHeight() * 1000));
size.setResolution(context.getSourceResolution());
size.calcPixelsFromSize();
info.setSize(size);
info.getCustomObjects().put(EPS_BOUNDING_BOX, bbox);
return true;
} finally {
in.reset();
}
}
/**
* Holder class for various pointers to the contents of the EPS file.
*/
public static class EPSBinaryFileHeader {
private long psStart;
private long psLength;
private long wmfStart;
private long wmfLength;
private long tiffStart;
private long tiffLength;
/**
* Returns the start offset of the PostScript section.
* @return the start offset
*/
public long getPSStart() {
return psStart;
}
/**
* Returns the length of the PostScript section.
* @return the length of the PostScript section (in bytes)
*/
public long getPSLength() {
return psLength;
}
/**
* Indicates whether the EPS has a WMF preview.
* @return true if there is a WMF preview
*/
public boolean hasWMFPreview() {
return (wmfStart != 0);
}
/**
* Returns the start offset of the WMF preview.
* @return the start offset (or 0 if there's no WMF preview)
*/
public long getWMFStart() {
return wmfStart;
}
/**
* Returns the length of the WMF preview.
* @return the length of the WMF preview (in bytes)
*/
public long getWMFLength() {
return wmfLength;
}
/**
* Indicates whether the EPS has a TIFF preview.
* @return true if there is a TIFF preview
*/
public boolean hasTIFFPreview() {
return (tiffStart != 0);
}
/**
* Returns the start offset of the TIFF preview.
* @return the start offset (or 0 if there's no TIFF preview)
*/
public long getTIFFStart() {
return tiffStart;
}
/**
* Returns the length of the TIFF preview.
* @return the length of the TIFF preview (in bytes)
*/
public long getTIFFLength() {
return tiffLength;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy