package org.apache.fop.datatypes;
public class ColorSpace {
+ private boolean hasICCProfile;
+ private byte[] iccProfile;
+ private int numComponents;
+
// Ok... so I had some grand purpose for this, but I can't recall.
// I'm just writing it
-
+
public static int DEVICE_UNKNOWN = -1;
public static int DEVICE_GRAY = 1;
// what's the *official* spelling?
// public static int DEVICE_GREY = 1;
public static int DEVICE_RGB = 2;
public static int DEVICE_CMYK = 3;
-
+
+
// Are there any others?
protected int currentColorSpace = -1;
public ColorSpace(int theColorSpace) {
this.currentColorSpace = theColorSpace;
-
+ hasICCProfile = false;
+ numComponents = calculateNumComponents();
}
-
- public int getColorSpace() {
- return (this.currentColorSpace);
+
+ private int calculateNumComponents() {
+ if (currentColorSpace == DEVICE_GRAY)
+ return 1;
+ else if (currentColorSpace == DEVICE_RGB)
+ return 3;
+ else if (currentColorSpace == DEVICE_CMYK)
+ return 4;
+ else
+ return 0;
}
public void setColorSpace(int theColorSpace) {
this.currentColorSpace = theColorSpace;
+ numComponents = calculateNumComponents();
}
-
+
+ public boolean hasICCProfile() {
+ return hasICCProfile;
+ }
+
+ public byte[] getICCProfile() {
+ if (hasICCProfile)
+ return iccProfile;
+ else
+ return new byte[0];
+ }
+
+ public void setICCProfile(byte[] iccProfile) {
+ this.iccProfile = iccProfile;
+ hasICCProfile = true;
+ }
+
+ public int getColorSpace() {
+ return (this.currentColorSpace);
+ }
+
+ public int getNumComponents() {
+ return numComponents;
+ }
+
public String getColorSpacePDFString() { // this is for PDF Output. Does anyone else need a string representation?
-
-
+
+
// shouldn't this be a select-case? I can never remember
// the syntax for that.
if (this.currentColorSpace == this.DEVICE_RGB) {
return ("DeviceRGB");
}
}
-
+
}
--- /dev/null
+/*
+ * $Id$
+ * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
+ * For details on use and redistribution please refer to the
+ * LICENSE file included with these sources.
+ */
+
+package org.apache.fop.image;
+
+// Java
+import java.net.URL;
+import java.net.URLConnection;
+import java.io.InputStream;
+import java.io.IOException;
+
+// FOP
+import org.apache.fop.apps.Driver;
+import org.apache.fop.messaging.*;
+import org.apache.fop.datatypes.ColorSpace;
+import org.apache.fop.pdf.PDFColor;
+import org.apache.fop.image.analyser.ImageReader;
+import org.apache.fop.image.analyser.EPSReader;
+
+import org.xml.sax.InputSource;
+import org.xml.sax.XMLReader;
+
+
+/**
+ * @see AbstractFopImage
+ * @see FopImage
+ */
+public class EPSImage extends AbstractFopImage {
+ private String docName;
+ private int[] bbox;
+
+ private byte[] epsImage = null;
+ private EPSReader epsReader = null;
+
+ /**
+ * Initialize docName and bounding box
+ */
+ private void init(URL href) {
+ bbox = new int[4];
+ bbox[0] = 0;
+ bbox[1] = 0;
+ bbox[2] = 0;
+ bbox[3] = 0;
+
+ docName = href.toString();
+ }
+
+ /**
+ * Return the name of the eps
+ */
+ public String getDocName() {
+ return docName;
+ }
+
+ /**
+ * Return the bounding box
+ */
+ public int[] getBBox() {
+ return bbox;
+ }
+
+ public EPSImage(URL href) throws FopImageException {
+ super(href);
+ init(href);
+ }
+
+ public EPSImage(URL href,
+ ImageReader imgReader) throws FopImageException {
+ super(href, imgReader);
+ init(href);
+ if (imgReader instanceof EPSReader) {
+ EPSReader eimgReader = (EPSReader)imgReader;
+ epsReader = eimgReader;
+ epsImage = eimgReader.getEpsFile();
+ m_bitmaps = epsImage;
+ bbox = eimgReader.getBBox();
+ }
+ }
+
+ protected void loadImage() throws FopImageException {
+ // Image is loaded in reader
+ }
+
+ public byte[] getEPSImage() throws FopImageException {
+ if (epsImage == null)
+ MessageHandler.errorln("ERROR LOADING EXTERNAL EPS");
+ return epsImage;
+ }
+
+}
} else if ("image/bmp".equals(imgMimeType)) {
imgClassName = "org.apache.fop.image.BmpImage";
// imgClassName = "org.apache.fop.image.JAIImage";
+ } else if ("image/eps".equals(imgMimeType)) {
+ imgClassName = "org.apache.fop.image.EPSImage";
} else if ("image/png".equals(imgMimeType)) {
imgClassName = "org.apache.fop.image.JimiImage";
// imgClassName = "org.apache.fop.image.JAIImage";
* @see FopImage
*/
public class JpegImage extends AbstractFopImage {
+ boolean found_icc_profile = false;
+ boolean found_dimensions = false;
+
public JpegImage(URL href) throws FopImageException {
super(href);
}
-
+
public JpegImage(URL href,
ImageReader imgReader) throws FopImageException {
super(href, imgReader);
}
-
+
protected void loadImage() throws FopImageException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ByteArrayOutputStream iccStream = new ByteArrayOutputStream();
InputStream inStream;
-
+ this.m_colorSpace = new ColorSpace(ColorSpace.DEVICE_UNKNOWN);
byte[] readBuf = new byte[4096];
int bytes_read;
int index = 0;
boolean cont = true;
-
+
this.m_compressionType = new DCTFilter();
this.m_compressionType.setApplied(true);
-
+
try {
inStream = this.m_href.openStream();
-
+
while ((bytes_read = inStream.read(readBuf)) != -1) {
baos.write(readBuf, 0, bytes_read);
}
this.m_href.toString() + " : " + ex.getClass() +
" - " + ex.getMessage());
}
-
+
this.m_bitmaps = baos.toByteArray();
this.m_bitsPerPixel = 8;
this.m_isTransparent = false;
-
+
if (this.m_bitmaps.length > (index + 2) &&
- uByte(this.m_bitmaps[index]) == 255 &&
- uByte(this.m_bitmaps[index + 1]) == 216) {
+ uByte(this.m_bitmaps[index]) == 255 &&
+ uByte(this.m_bitmaps[index + 1]) == 216) {
index += 2;
-
+
while (index < this.m_bitmaps.length && cont) {
- //check to be sure this is the begining of a header
+ //check to be sure this is the begining of a header
if (this.m_bitmaps.length > (index + 2) &&
- uByte(this.m_bitmaps[index]) == 255) {
-
- //192 or 194 are the header bytes that contain the jpeg width height and color depth.
+ uByte(this.m_bitmaps[index]) == 255) {
+
+ //192 or 194 are the header bytes that contain the jpeg width height and color depth.
if (uByte(this.m_bitmaps[index + 1]) == 192 ||
- uByte(this.m_bitmaps[index + 1]) == 194) {
-
+ uByte(this.m_bitmaps[index + 1]) == 194) {
+
this.m_height = calcBytes(this.m_bitmaps[index + 5],
this.m_bitmaps[index + 6]);
this.m_width = calcBytes(this.m_bitmaps[index + 7],
this.m_bitmaps[index + 8]);
-
+
if (this.m_bitmaps[index + 9] == 1) {
- this.m_colorSpace = new ColorSpace(
- ColorSpace.DEVICE_GRAY);
+ this.m_colorSpace.setColorSpace(ColorSpace.DEVICE_GRAY);
} else if (this.m_bitmaps[index + 9] == 3) {
- this.m_colorSpace =
- new ColorSpace(ColorSpace.DEVICE_RGB);
- } else {
+ this.m_colorSpace.setColorSpace(ColorSpace.DEVICE_RGB);
+ } else if (this.m_bitmaps[index + 9] == 4) {
+ this.m_colorSpace.setColorSpace(ColorSpace.DEVICE_CMYK);
+ }
+
+ found_dimensions = true;
+ if (found_icc_profile) {
cont = false;
- throw new FopImageException(
- "\n2 Error while loading image " +
- this.m_href.toString() +
- " : JpegImage - Invalid JPEG Header (bad color space " +
- this.m_bitmaps[index + 9] + ").");
+ break;
}
-
- cont = false;
- break;
-
- } else { // if (uByte(this.m_bitmaps[index + 1]) == headers[headerIndex]) {
+ index += calcBytes(this.m_bitmaps[index + 2],
+ this.m_bitmaps[index + 3]) + 2;
+
+ } else if (uByte(this.m_bitmaps[index+1]) == 226 &&
+ this.m_bitmaps.length > (index+60)) {
+ // Check if ICC profile
+ byte[] icc_string = new byte[11];
+ System.arraycopy(this.m_bitmaps, index+4, icc_string, 0, 11);
+
+ if ("ICC_PROFILE".equals(new String(icc_string))){
+ int chunkSize = calcBytes(this.m_bitmaps[index + 2],
+ this.m_bitmaps[index + 3]) + 2;
+
+ if (iccStream.size() == 0)
+ iccStream.write(this.m_bitmaps, index+18,
+ chunkSize - 20);
+ else
+ iccStream.write(this.m_bitmaps, index+16,
+ chunkSize - 18);
+
+ }
+
+ index += calcBytes(this.m_bitmaps[index + 2],
+ this.m_bitmaps[index + 3]) + 2;
+ } else {
index += calcBytes(this.m_bitmaps[index + 2],
this.m_bitmaps[index + 3]) + 2;
}
-
+
} else {
cont = false;
- throw new FopImageException(
- "\n2 Error while loading image " +
- this.m_href.toString() + " : JpegImage - Invalid JPEG Header (bad header byte).");
}
}
} else {
throw new FopImageException( "\n1 Error while loading image " +
- this.m_href.toString() + " : JpegImage - Invalid JPEG Header.");
+ this.m_href.toString() +
+ " : JpegImage - Invalid JPEG Header.");
+ }
+ if (iccStream.size() > 0) {
+ byte[] align = new byte[((iccStream.size()) % 8) + 8];
+ try {iccStream.write(align);} catch (Exception e) {
+ throw new FopImageException( "\n1 Error while loading image " +
+ this.m_href.toString() + " : " +
+ e.getMessage());
+ }
+ this.m_colorSpace.setICCProfile(iccStream.toByteArray());
}
}
-
+
private int calcBytes(byte bOne, byte bTwo) {
return (uByte(bOne) * 256) + uByte(bTwo);
}
-
+
private int uByte(byte bIn) {
if (bIn < 0) {
return 256 + bIn;
}
}
-
--- /dev/null
+/*
+ * $Id$
+ * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
+ * For details on use and redistribution please refer to the
+ * LICENSE file included with these sources.
+ */
+
+package org.apache.fop.image.analyser;
+
+// Java
+import java.io.BufferedInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+
+// FOP
+import org.apache.fop.messaging.*;
+import org.apache.fop.image.SVGImage;
+
+import org.xml.sax.InputSource;
+import org.xml.sax.XMLReader;
+
+
+/**
+ * ImageReader object for SVG document image type.
+ */
+public class EPSReader extends AbstractImageReader {
+ private long[] bbox;
+ private boolean isAscii; // True if plain ascii eps file
+
+ // offsets if not ascii
+ long psStart = 0;
+ long psLength = 0;
+ long wmfStart = 0;
+ long wmfLength = 0;
+ long tiffStart = 0;
+ long tiffLength = 0;
+
+ /** raw eps file */
+ private byte[] rawEps;
+ /** eps part */
+ private byte[] epsFile;
+ private byte[] preview = null;
+
+ private long getLong(byte[] buf, int idx) {
+ int b1 = buf[idx] & 0xff;
+ int b2 = buf[idx+1] & 0xff;
+ int b3 = buf[idx+2] & 0xff;
+ int b4 = buf[idx+3] & 0xff;
+
+ return (long)((b4 << 24) | (b3 << 16) | (b2 << 8) | b1);
+ }
+
+ public boolean verifySignature(String uri, BufferedInputStream fis)
+ throws IOException {
+ boolean isEPS = false;
+ this.imageStream = fis;
+ fis.mark(32);
+ byte[] header = new byte[30];
+ fis.read(header, 0, 30);
+ fis.reset();
+
+ // Check if binary header
+ if (getLong(header, 0) == 0xC6D3D0C5) {
+ isAscii = false;
+ isEPS = true;
+
+ psStart = getLong(header, 4);
+ psLength = getLong(header, 8);
+ wmfStart = getLong(header, 12);
+ wmfLength = getLong(header, 16);
+ tiffStart = getLong(header, 20);
+ tiffLength = getLong(header, 24);
+
+ } else {
+ // Check if plain ascii
+ byte[] epsh = "%!PS".getBytes();
+ if (epsh[0] == header[0] &&
+ epsh[1] == header[1] &&
+ epsh[2] == header[2] &&
+ epsh[3] == header[3]) {
+ isAscii = true;
+ isEPS = true;
+ }
+ }
+
+ if (isEPS) {
+ readEPSImage(fis);
+ bbox = readBBox();
+
+ if (bbox != null) {
+ width = (int)(bbox[2]-bbox[0]);
+ height = (int)(bbox[3]-bbox[1]);
+ } else {
+ // Ain't eps if no BoundingBox
+ isEPS = false;
+ }
+ }
+
+ return isEPS;
+ }
+
+ /** read the eps file and extract eps part */
+ private void readEPSImage(BufferedInputStream fis) throws IOException {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ byte[] file;
+ byte[] readBuf = new byte[20480];
+ int bytes_read;
+ int index = 0;
+ boolean cont = true;
+
+
+ try {
+ while ((bytes_read = fis.read(readBuf)) != -1) {
+ baos.write(readBuf, 0, bytes_read);
+ }
+ } catch (java.io.IOException ex) {
+ throw new IOException("Error while loading EPS image " + ex.getMessage());
+ }
+
+ file = baos.toByteArray();
+
+ if (isAscii) {
+ rawEps = null;
+ epsFile = new byte[file.length];
+ System.arraycopy(file, 0, epsFile, 0, epsFile.length);
+ } else {
+ rawEps = new byte[file.length];
+ epsFile = new byte[(int)psLength];
+ System.arraycopy(file, 0, rawEps, 0, rawEps.length);
+ System.arraycopy(rawEps, (int)psStart, epsFile, 0, (int)psLength);
+ }
+ }
+
+ public byte[] getEpsFile() {
+ return epsFile;
+ }
+
+ /* Get embedded preview or null */
+ public byte[] getPreview() {
+ InputStream is = null;
+ if (preview == null) {
+ if (tiffLength > 0) {
+ preview = new byte[(int)tiffLength];
+ System.arraycopy(rawEps, (int)tiffStart, preview, 0, (int)tiffLength);
+ }
+ }
+ return preview;
+ }
+
+ /** Extract bounding box from eps part
+ */
+ private long[] readBBox() {
+ long[] mbbox = null;
+ int idx = 0;
+ byte[] bbxName = "%%BoundingBox: ".getBytes();
+ boolean found = false;
+
+ while (!found && (epsFile.length > (idx + bbxName.length))) {
+ boolean sfound = true;
+ int i = idx;
+ for (i = idx; sfound && (i-idx) < bbxName.length; i++) {
+ if (bbxName[i - idx] != epsFile[i])
+ sfound = false;
+ }
+ if (sfound) {
+ found = true;
+ idx = i;
+ } else {
+ idx++;
+ }
+ }
+
+ if (!found)
+ return mbbox;
+
+
+ mbbox = new long[4];
+ idx += readLongString(mbbox, 0, idx);
+ idx += readLongString(mbbox, 1, idx);
+ idx += readLongString(mbbox, 2, idx);
+ idx += readLongString(mbbox, 3, idx);
+
+ return mbbox;
+ }
+
+ private int readLongString(long[] mbbox, int i, int idx) {
+ while (idx < epsFile.length &&
+ (epsFile[idx] == 32))
+ idx++;
+
+ int nidx = idx;
+
+ while (nidx < epsFile.length &&
+ (epsFile[nidx] >= 48 && epsFile[nidx] <= 57))
+ nidx++;
+
+ byte[] num = new byte[nidx - idx];
+ System.arraycopy(epsFile, idx, num, 0, nidx-idx);
+ String ns = new String(num);
+ mbbox[i] = Long.parseLong(ns);
+
+ return (1+nidx - idx);
+ }
+
+ public String getMimeType() {
+ return "image/eps";
+ }
+
+ /**
+ * Return the BoundingBox
+ */
+ public int[] getBBox() {
+ int[] bbox = new int[4];
+ bbox[0] = (int)this.bbox[0];
+ bbox[1] = (int)this.bbox[1];
+ bbox[2] = (int)this.bbox[2];
+ bbox[3] = (int)this.bbox[3];
+ return bbox;
+ }
+}
+
formats.addElement(new GIFReader());
formats.addElement(new PNGReader());
formats.addElement(new TIFFReader());
+ formats.addElement(new EPSReader());
formats.addElement(new SVGReader());
//
return encoding;
}
-
+ /**
+ * Create a PDFICCStream
+ @see PDFXObject
+ @see org.apache.fop.image.JpegImage
+ @see org.apache.fop.datatypes.ColorSpace
+ */
+ public PDFICCStream makePDFICCStream() {
+ PDFICCStream iccStream = new PDFICCStream(++this.objectcount);
+ this.objects.addElement(iccStream);
+ return iccStream;
+ }
+
+
/**
* make a Type1 /Font object
*
return xObject.getXNumber();
// else, create a new one
xObject = new PDFXObject(++this.objectcount, ++this.xObjectCount,
- img);
+ img, this);
this.objects.add(xObject);
this.xObjects.add(xObject);
this.xObjectsMap.put(url, xObject);
--- /dev/null
+/*
+ * $Id$
+ * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
+ * For details on use and redistribution please refer to the
+ * LICENSE file included with these sources.
+ */
+
+package org.apache.fop.pdf;
+import org.apache.fop.datatypes.ColorSpace;
+
+public class PDFICCStream extends PDFStream {
+ private int origLength;
+ private int len1, len3;
+ private byte[] originalData = null;
+
+ private ColorSpace cs;
+
+ public void setColorSpace(ColorSpace cs) throws java.io.IOException {
+ this.cs = cs;
+ setData(cs.getICCProfile());
+ }
+
+ public PDFICCStream(int num) {
+ super(num);
+ cs = null;
+ }
+
+ public PDFICCStream(int num, ColorSpace cs) throws java.io.IOException {
+ super(num);
+ setColorSpace(cs);
+ }
+
+ // overload the base object method so we don't have to copy
+ // byte arrays around so much
+ protected int output(java.io.OutputStream stream)
+ throws java.io.IOException {
+ int length = 0;
+ String filterEntry = applyFilters();
+ StringBuffer pb = new StringBuffer();
+ pb.append(this.number).append(" ").append(this.generation).append(" obj\n<< ");
+ pb.append("/N ").append(cs.getNumComponents()).append(" ");
+
+ if (cs.getColorSpace() > 0)
+ pb.append("/Alternate /").append(cs.getColorSpacePDFString()).append(" ");
+
+ pb.append("/Length ").append((_data.size() + 1)).append(" ").append(filterEntry);
+ pb.append(" >>\n");
+ byte[] p = pb.toString().getBytes();
+ stream.write(p);
+ length += p.length;
+ length += outputStreamData(stream);
+ p = "endobj\n".getBytes();
+ stream.write(p);
+ length += p.length;
+ return length;
+ }
+}
// FOP
import org.apache.fop.datatypes.ColorSpace;
+import org.apache.fop.pdf.PDFDocument;
+import org.apache.fop.pdf.PDFICCStream;
import org.apache.fop.image.FopImage;
+import org.apache.fop.image.EPSImage;
+import org.apache.fop.image.JpegImage;
import org.apache.fop.image.FopImageException;
/**
* the dictionary just provides information like the stream length
*/
public class PDFXObject extends PDFObject {
-
+ private boolean isPS;
+ private PDFDocument pdfDoc;
+ private PDFICCStream pdfICCStream;
+
FopImage fopimage;
int Xnum;
-
/**
* create an Xobject with the given number and name and load the
* image in the object
*/
public PDFXObject(int number, int Xnumber, FopImage img) {
+ this(number, Xnumber, img, null);
+ }
+
+ public PDFXObject(int number, int Xnumber, FopImage img, PDFDocument pdfdoc) {
super(number);
+ isPS = false;
this.Xnum = Xnumber;
if (img == null)
MessageHandler.errorln("FISH");
fopimage = img;
+ this.pdfDoc = pdfdoc;
+ pdfICCStream = null;
+ try {
+ if (fopimage instanceof JpegImage) {
+ /* hasICCProfile is not initialized before
+ the bitmaps is read - should maybe fix this in
+ the JpegImage instead...
+ */
+ fopimage.getBitmaps();
+ JpegImage jpegimage = (JpegImage)fopimage;
+ if (jpegimage.getColorSpace().hasICCProfile()) {
+ pdfICCStream = pdfDoc.makePDFICCStream();
+ pdfICCStream.setColorSpace(jpegimage.getColorSpace());
+ pdfICCStream.addDefaultFilters();
+ }
+ }
+ } catch (Exception e) {
+ MessageHandler.errorln("Error while reading image " +
+ fopimage.getURL() +
+ ": " + e.getMessage());
+ }
}
-
+
/**
* @return the PDF XObject number
*/
protected int output(OutputStream stream) throws IOException {
int length = 0;
int i = 0;
- int x, y;
-
+
try {
- // delegate the stream work to PDFStream
- PDFStream imgStream = new PDFStream(0);
-
- imgStream.setData(fopimage.getBitmaps());
-
- /*
- * Added by Eric Dalquist
- * If the DCT filter hasn't been added to the object we add it here
- */
- if (fopimage.getPDFFilter() != null) {
- imgStream.addFilter(fopimage.getPDFFilter());
- }
-
- imgStream.addDefaultFilters();
-
- String dictEntries = imgStream.applyFilters();
-
- String p = this.number + " " + this.generation + " obj\n";
- p = p + "<</Type /XObject\n";
- p = p + "/Subtype /Image\n";
- p = p + "/Name /Im" + Xnum + "\n";
- p = p + "/Length " + imgStream.getDataLength() + "\n";
- p = p + "/Width " + fopimage.getWidth() + "\n";
- p = p + "/Height " + fopimage.getHeight() + "\n";
- p = p + "/BitsPerComponent " + fopimage.getBitsPerPixel() + "\n";
- ColorSpace cs = fopimage.getColorSpace();
- p = p + "/ColorSpace /" + cs.getColorSpacePDFString() + "\n";
- if (fopimage.isTransparent()) {
- PDFColor transp = fopimage.getTransparentColor();
- p = p + "/Mask [" + transp.red255() + " " + transp.red255()
- + " " + transp.green255() + " " + transp.green255() + " "
- + transp.blue255() + " " + transp.blue255() + "]\n";
+ if (fopimage instanceof EPSImage) {
+ isPS = true;
+ EPSImage epsImage = (EPSImage)fopimage;
+ int[] bbox = epsImage.getBBox();
+ int bboxw = bbox[2] - bbox[0];
+ int bboxh = bbox[3] - bbox[1];
+
+ // delegate the stream work to PDFStream
+ PDFStream imgStream = new PDFStream(0);
+
+ StringBuffer preamble = new StringBuffer();
+ preamble.append("%%BeginDocument: " + epsImage.getDocName() + "\n");
+
+ preamble.append("userdict begin % Push userdict on dict stack\n");
+ preamble.append("/PreEPS_state save def\n");
+ preamble.append("/dict_stack countdictstack def\n");
+ preamble.append("/ops_count count 1 sub def\n");
+ preamble.append("/showpage {} def\n");
+
+
+ preamble.append((double)(1f/(double)bboxw) + " " + (double)(1f/(double)bboxh) + " scale\n");
+ preamble.append(-bbox[0] + " " + (-bbox[1]) + " translate\n");
+ preamble.append(bbox[0] + " " + bbox[1] + " " + bboxw + " " + bboxh + " rectclip\n");
+ preamble.append("newpath\n");
+
+ StringBuffer post = new StringBuffer();
+ post.append("%%EndDocument\n");
+ post.append("count ops_count sub {pop} repeat\n");
+ post.append("countdictstack dict_stack sub {end} repeat\n");
+ post.append("PreEPS_state restore\n");
+ post.append("end % userdict\n");
+
+ byte[] preBytes = preamble.toString().getBytes();
+ byte[] postBytes = post.toString().getBytes();
+ byte[] imgData = new byte[preBytes.length + postBytes.length + fopimage.getBitmaps().length];
+
+ System.arraycopy (preBytes, 0, imgData, 0, preBytes.length);
+ System.arraycopy (fopimage.getBitmaps(), 0, imgData, preBytes.length, fopimage.getBitmaps().length);
+ System.arraycopy (postBytes, 0, imgData, preBytes.length + fopimage.getBitmaps().length, postBytes.length);
+
+
+ imgStream.setData(imgData);
+ imgStream.addDefaultFilters();
+
+ String dictEntries = imgStream.applyFilters();
+
+ String p = this.number + " " + this.generation + " obj\n";
+ p = p + "<</Type /XObject\n";
+ p = p + "/Subtype /PS\n";
+ p = p + "/Length " + imgStream.getDataLength();
+
+ // don't know if it's the good place (other objects can have references to it)
+ fopimage.close();
+ p = p + dictEntries;
+ p = p + ">>\n";
+
+ // push the pdf dictionary on the writer
+ byte[] pdfBytes = p.getBytes();
+ stream.write(pdfBytes);
+ length += pdfBytes.length;
+ // push all the image data on the writer and takes care of length for trailer
+ length += imgStream.outputStreamData(stream);
+
+ pdfBytes = ("endobj\n").getBytes();
+ stream.write(pdfBytes);
+ length += pdfBytes.length;
+
+ } else {
+
+ // delegate the stream work to PDFStream
+ PDFStream imgStream = new PDFStream(0);
+
+ imgStream.setData(fopimage.getBitmaps());
+
+ /*
+ * Added by Eric Dalquist
+ * If the DCT filter hasn't been added to the object we add it here
+ */
+ if (fopimage.getPDFFilter() != null) {
+ imgStream.addFilter(fopimage.getPDFFilter());
+ }
+
+ imgStream.addDefaultFilters();
+
+ String dictEntries = imgStream.applyFilters();
+
+ String p = this.number + " " + this.generation + " obj\n";
+ p = p + "<</Type /XObject\n";
+ p = p + "/Subtype /Image\n";
+ p = p + "/Name /Im" + Xnum + "\n";
+ p = p + "/Length " + imgStream.getDataLength() + "\n";
+ p = p + "/Width " + fopimage.getWidth() + "\n";
+ p = p + "/Height " + fopimage.getHeight() + "\n";
+ p = p + "/BitsPerComponent " + fopimage.getBitsPerPixel() + "\n";
+
+ if (pdfICCStream != null ) {
+ p = p + "/ColorSpace [/ICCBased " + pdfICCStream.referencePDF() + "]\n";
+ } else {
+ ColorSpace cs = fopimage.getColorSpace();
+ p = p + "/ColorSpace /" + cs.getColorSpacePDFString() + "\n";
+ }
+
+ /* PhotoShop generates CMYK values that's inverse,
+ this will invert the values - too bad if it's not a PhotoShop image...*/
+ if (fopimage.getColorSpace().getColorSpace() == ColorSpace.DEVICE_CMYK) {
+ p = p + "/Decode [ 1.0 0.0 1.0 0.0 1.0 0.0 1.1 0.0 ]\n";
+ }
+
+ if (fopimage.isTransparent()) {
+ PDFColor transp = fopimage.getTransparentColor();
+ p = p + "/Mask [" + transp.red255() + " " + transp.red255()
+ + " " + transp.green255() + " " + transp.green255() + " "
+ + transp.blue255() + " " + transp.blue255() + "]\n";
+ }
+ p = p + dictEntries;
+ p = p + ">>\n";
+
+ // don't know if it's the good place (other objects can have references to it)
+ fopimage.close();
+
+ // push the pdf dictionary on the writer
+ byte[] pdfBytes = p.getBytes();
+ stream.write(pdfBytes);
+ length += pdfBytes.length;
+ // push all the image data on the writer and takes care of length for trailer
+ length += imgStream.outputStreamData(stream);
+
+ pdfBytes = ("endobj\n").getBytes();
+ stream.write(pdfBytes);
+ length += pdfBytes.length;
}
- p = p + dictEntries;
- p = p + ">>\n";
-
- // don't know if it's the good place (other objects can have references to it)
- fopimage.close();
-
- // push the pdf dictionary on the writer
- byte[] pdfBytes = p.getBytes();
- stream.write(pdfBytes);
- length += pdfBytes.length;
- // push all the image data on the writer and takes care of length for trailer
- length += imgStream.outputStreamData(stream);
-
- pdfBytes = ("endobj\n").getBytes();
- stream.write(pdfBytes);
- length += pdfBytes.length;
} catch (FopImageException imgex) {
MessageHandler.errorln("Error in XObject : "
+ imgex.getMessage());
}
-
+
return length;
}
-
+
byte[] toPDF() {
return null;
}
write("%%EndProlog");
write("%%BeginSetup");
writeFontDict(fontInfo);
+
+ /* Write proc for including EPS */
+ write("%%BeginResource: procset EPSprocs");
+ write("%%Title: EPS encapsulation procs");
+
+ write("/BeginEPSF { %def");
+ write("/b4_Inc_state save def % Save state for cleanup");
+ write("/dict_count countdictstack def % Count objects on dict stack");
+ write("/op_count count 1 sub def % Count objects on operand stack");
+ write("userdict begin % Push userdict on dict stack");
+ write("/showpage { } def % Redefine showpage, { } = null proc");
+ write("0 setgray 0 setlinecap % Prepare graphics state");
+ write("1 setlinewidth 0 setlinejoin");
+ write("10 setmiterlimit [ ] 0 setdash newpath");
+ write("/languagelevel where % If level not equal to 1 then");
+ write("{pop languagelevel % set strokeadjust and");
+ write("1 ne % overprint to their defaults.");
+ write("{false setstrokeadjust false setoverprint");
+ write("} if");
+ write("} if");
+ write("} bind def");
+
+ write("/EndEPSF { %def");
+ write("count op_count sub {pop} repeat % Clean up stacks");
+ write("countdictstack dict_count sub {end} repeat");
+ write("b4_Inc_state restore");
+ write("} bind def");
+ write("%%EndResource");
+
write("%%EndSetup");
write("FOPFonts begin");
}
public PSStream(OutputStream out) {
super(out);
}
-
+
public void write(String cmd) throws IOException {
if (cmd.length() > 255)
throw new RuntimeException("PostScript command exceeded limit of 255 characters");
write(cmd.getBytes("US-ASCII"));
write('\n');
}
-
+
+ public void writeByteArr(byte[] cmd) throws IOException {
+ write(cmd);
+ write('\n');
+ }
}