| /* |
| * 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$ */ |
| |
| package org.apache.fop.pdf; |
| |
| // Java |
| import java.io.IOException; |
| import java.io.OutputStream; |
| |
| /* modified by JKT to integrate with 0.12.0 */ |
| /* modified by Eric SCHAEFFER to integrate with 0.13.0 */ |
| |
| /** |
| * PDF XObject |
| * |
| * A derivative of the PDF Object, is a PDF Stream that has not only a |
| * dictionary but a stream of image data. |
| * The dictionary just provides information like the stream length. |
| * This outputs the image dictionary and the image data. |
| * This is used as a reference for inserting the same image in the |
| * document in another place. |
| */ |
| public class PDFImageXObject extends PDFXObject { |
| |
| private PDFImage pdfimage; |
| |
| /** |
| * create an XObject with the given number and name and load the |
| * image in the object |
| * |
| * @param xnumber the pdf object X number |
| * @param img the pdf image that contains the image data |
| */ |
| public PDFImageXObject(int xnumber, PDFImage img) { |
| super(); |
| put("Name", new PDFName("Im" + xnumber)); |
| pdfimage = img; |
| } |
| |
| /** |
| * Output the image as PDF. |
| * This sets up the image dictionary and adds the image data stream. |
| * |
| * @param stream the output stream to write the data |
| * @throws IOException if there is an error writing the data |
| * @return the length of the data written |
| */ |
| public int output(OutputStream stream) throws IOException { |
| int length = super.output(stream); |
| |
| // let it gc |
| // this object is retained as a reference to inserting |
| // the same image but the image data is no longer needed |
| pdfimage = null; |
| return length; |
| } |
| |
| /** {@inheritDoc} */ |
| protected void populateStreamDict(Object lengthEntry) { |
| super.populateStreamDict(lengthEntry); |
| if (pdfimage.isPS()) { |
| populateDictionaryFromPS(); |
| } else { |
| populateDictionaryFromImage(); |
| } |
| } |
| |
| private void populateDictionaryFromPS() { |
| getDocumentSafely().getProfile().verifyPSXObjectsAllowed(); |
| put("Subtype", new PDFName("PS")); |
| } |
| |
| private void populateDictionaryFromImage() { |
| put("Subtype", new PDFName("Image")); |
| put("Width", new Integer(pdfimage.getWidth())); |
| put("Height", new Integer(pdfimage.getHeight())); |
| put("BitsPerComponent", new Integer(pdfimage.getBitsPerComponent())); |
| |
| PDFICCStream pdfICCStream = pdfimage.getICCStream(); |
| if (pdfICCStream != null) { |
| put("ColorSpace", new PDFArray(this, |
| new Object[] {new PDFName("ICCBased"), pdfICCStream})); |
| } else { |
| PDFDeviceColorSpace cs = pdfimage.getColorSpace(); |
| put("ColorSpace", new PDFName(cs.getName())); |
| } |
| |
| if (pdfimage.isInverted()) { |
| /* PhotoShop generates CMYK values that's inverse, |
| * this will invert the values - too bad if it's not |
| * a PhotoShop image... |
| */ |
| final Float zero = new Float(0.0f); |
| final Float one = new Float(1.0f); |
| PDFArray decode = new PDFArray(this); |
| for (int i = 0, c = pdfimage.getColorSpace().getNumComponents(); i < c; i++) { |
| decode.add(one); |
| decode.add(zero); |
| } |
| put("Decode", decode); |
| } |
| |
| if (pdfimage.isTransparent()) { |
| PDFColor transp = pdfimage.getTransparentColor(); |
| PDFArray mask = new PDFArray(this); |
| if (pdfimage.getColorSpace().isGrayColorSpace()) { |
| mask.add(new Integer(transp.red255())); |
| mask.add(new Integer(transp.red255())); |
| } else { |
| mask.add(new Integer(transp.red255())); |
| mask.add(new Integer(transp.red255())); |
| mask.add(new Integer(transp.green255())); |
| mask.add(new Integer(transp.green255())); |
| mask.add(new Integer(transp.blue255())); |
| mask.add(new Integer(transp.blue255())); |
| } |
| put("Mask", mask); |
| } |
| PDFReference ref = pdfimage.getSoftMaskReference(); |
| if (ref != null) { |
| put("SMask", ref); |
| } |
| //Important: do this at the end so previous values can be overwritten. |
| pdfimage.populateXObjectDictionary(getDictionary()); |
| } |
| |
| /** {@inheritDoc} */ |
| protected void outputRawStreamData(OutputStream out) throws IOException { |
| pdfimage.outputContents(out); |
| } |
| |
| /** {@inheritDoc} */ |
| protected int getSizeHint() throws IOException { |
| return 0; |
| } |
| |
| /** {@inheritDoc} */ |
| protected void prepareImplicitFilters() { |
| PDFFilter pdfFilter = pdfimage.getPDFFilter(); |
| if (pdfFilter != null) { |
| getFilterList().ensureFilterInPlace(pdfFilter); |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| * This class uses the PDFImage instance to determine the default filter. |
| */ |
| protected String getDefaultFilterName() { |
| return pdfimage.getFilterHint(); |
| } |
| |
| /** {@inheritDoc} */ |
| protected boolean multipleFiltersAllowed() { |
| return pdfimage.multipleFiltersAllowed(); |
| } |
| |
| } |