public Map<String, Image> getImages() { Map<String, Image> images = new HashMap<String, Image>(); COSDictionary xobjectsDictionary = (COSDictionary) getDictionary().getDictionaryObject(COSName.XOBJECT); if (xobjectsDictionary == null) { return images; } for (COSName objName : xobjectsDictionary.keySet()) { try { COSBase xobject = xobjectsDictionary.getDictionaryObject(objName); if (xobject instanceof COSStream) { COSStream xstream = (COSStream) xobject; String subtype = xstream.getNameAsString(COSName.SUBTYPE); if (!subtype.equals("Image")) { continue; } PDFunction tintTransformer = getTintTransformer(xstream); PDStream pdstream = new PDStream(xstream); byte[] data = getStreamData(pdstream); Image image = processStream(data, tintTransformer); if (image != null) { images.put(objName.getName(), image); } } } catch (Exception e) { LOG.error("error while creating a image", e); } } return images; }
/** * Decode JBIG2 data using Java ImageIO library. * * <p>{@inheritDoc} */ public void decode( InputStream compressedData, OutputStream result, COSDictionary options, int filterIndex) throws IOException { /** * A working JBIG2 ImageIO plugin is needed to decode JBIG2 encoded streams. The following is * known to be working. It can't be bundled with PDFBox because of an incompatible license. * http://code.google.com/p/jbig2-imageio/ */ Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("JBIG2"); if (!readers.hasNext()) { LOG.error("Can't find an ImageIO plugin to decode the JBIG2 encoded datastream."); return; } ImageReader reader = readers.next(); COSDictionary decodeP = (COSDictionary) options.getDictionaryObject(COSName.DECODE_PARMS); COSInteger bits = (COSInteger) options.getDictionaryObject(COSName.BITS_PER_COMPONENT); COSStream st = null; if (decodeP != null) { st = (COSStream) decodeP.getDictionaryObject(COSName.JBIG2_GLOBALS); } if (st != null) { reader.setInput( ImageIO.createImageInputStream( new SequenceInputStream(st.getFilteredStream(), compressedData))); } else { reader.setInput(ImageIO.createImageInputStream(compressedData)); } BufferedImage bi = reader.read(0); reader.dispose(); if (bi != null) { // I am assuming since JBIG2 is always black and white // depending on your renderer this might or might be needed if (bi.getColorModel().getPixelSize() != bits.intValue()) { if (bits.intValue() != 1) { LOG.error("Do not know how to deal with JBIG2 with more than 1 bit"); return; } BufferedImage packedImage = new BufferedImage(bi.getWidth(), bi.getHeight(), BufferedImage.TYPE_BYTE_BINARY); Graphics graphics = packedImage.getGraphics(); graphics.drawImage(bi, 0, 0, null); graphics.dispose(); bi = packedImage; } DataBuffer dBuf = bi.getData().getDataBuffer(); if (dBuf.getDataType() == DataBuffer.TYPE_BYTE) { result.write(((DataBufferByte) dBuf).getData()); } else { LOG.error("Image data buffer not of type byte but type " + dBuf.getDataType()); } } else { LOG.error("Something went wrong when decoding the JBIG2 encoded datastream."); } }
/** {@inheritDoc} */ protected void determineEncoding() { String cmapName = null; COSName encodingName = null; COSBase encoding = getEncoding(); Encoding fontEncoding = null; if (encoding != null) { if (encoding instanceof COSName) { if (cmap == null) { encodingName = (COSName) encoding; cmap = cmapObjects.get(encodingName.getName()); if (cmap == null) { cmapName = encodingName.getName(); } } if (cmap == null && cmapName != null) { try { fontEncoding = EncodingManager.INSTANCE.getEncoding(encodingName); } catch (IOException exception) { LOG.debug("Debug: Could not find encoding for " + encodingName); } } } else if (encoding instanceof COSStream) { if (cmap == null) { COSStream encodingStream = (COSStream) encoding; try { cmap = parseCmap(null, encodingStream.getUnfilteredStream()); } catch (IOException exception) { LOG.error("Error: Could not parse the embedded CMAP"); } } } else if (encoding instanceof COSDictionary) { try { fontEncoding = new DictionaryEncoding((COSDictionary) encoding); } catch (IOException exception) { LOG.error("Error: Could not create the DictionaryEncoding"); } } } setFontEncoding(fontEncoding); extractToUnicodeEncoding(); if (cmap == null && cmapName != null) { String resourceName = resourceRootCMAP + cmapName; try { cmap = parseCmap(resourceRootCMAP, ResourceLoader.loadResource(resourceName)); if (cmap == null && encodingName == null) { LOG.error("Error: Could not parse predefined CMAP file for '" + cmapName + "'"); } } catch (IOException exception) { LOG.error("Error: Could not find predefined CMAP file for '" + cmapName + "'"); } } }
/** * This method checks if required fields are present. * * @param result the list of error to update if the validation fails. * @return true if all fields are present, false otherwise. */ protected boolean checkMandatoryFields(List<ValidationError> errors) { boolean res = pattern.getItem(COSName.getPDFName(DICTIONARY_KEY_RESOURCES)) != null; res = res && pattern.getItem(COSName.getPDFName(PATTERN_KEY_BBOX)) != null; res = res && pattern.getItem(COSName.getPDFName(PATTERN_KEY_PAINT_TYPE)) != null; res = res && pattern.getItem(COSName.getPDFName(PATTERN_KEY_TILING_TYPE)) != null; res = res && pattern.getItem(COSName.getPDFName(PATTERN_KEY_XSTEP)) != null; res = res && pattern.getItem(COSName.getPDFName(PATTERN_KEY_YSTEP)) != null; if (!res) { errors.add(new ValidationError(ERROR_GRAPHIC_INVALID_PATTERN_DEFINITION)); } return res; }
private COSStream getStream(Map<String, COSStream> streams, Token token) throws IOException { COSStream stream = streams.get(token.getDSSIdAsString()); if (stream == null) { RandomAccessBuffer storage = new RandomAccessBuffer(); stream = new COSStream(storage); OutputStream unfilteredStream = stream.createUnfilteredStream(); unfilteredStream.write(token.getEncoded()); unfilteredStream.flush(); streams.put(token.getDSSIdAsString(), stream); } return stream; }
@SuppressWarnings("unchecked") public static void main_3(String[] args) throws IOException { PDDocument doc = PDDocument.load(iconFile); List<PDPage> pages = doc.getDocumentCatalog().getAllPages(); List<COSObject> objects = doc.getDocument().getObjects(); for (COSObject cosObject : objects) { COSBase cosbase = cosObject.getObject(); if (cosObject.getObject() instanceof COSStream) { COSStream cosstream = (COSStream) cosbase; COSBase filter = cosstream.getDictionaryObject(COSName.FILTER); COSBase subtype = cosstream.getDictionaryObject(COSName.SUBTYPE); if (subtype != null && subtype.equals(COSName.IMAGE)) { System.out.println(filter); InputStream filtered = cosstream.getFilteredStream(); // PDStream stream = new PDStream(costream); System.out.println(Hex.encodeHex(IOUtils.toByteArray(filtered))); } } } for (PDPage pdPage : pages) { PDResources resources = pdPage.getResources(); Map<String, PDXObject> images = resources.getXObjects(); Set<String> keys = images.keySet(); for (String key : keys) { PDXObject image = images.get(key); byte[] imgData = image.getPDStream().getByteArray(); System.out.println(Hex.encodeHex(imgData)); } } }
/** * This will get the logical content stream with none of the filters. * * @return the bytes of the logical (decoded) stream * @throws IOException when encoding/decoding causes an exception */ public InputStream getUnfilteredStream() throws IOException { Vector<InputStream> inputStreams = new Vector<InputStream>(); byte[] inbetweenStreamBytes = "\n".getBytes("ISO-8859-1"); for (int i = 0; i < streams.size(); i++) { COSStream stream = (COSStream) streams.getObject(i); inputStreams.add(stream.getUnfilteredStream()); // handle the case where there is no whitespace in the // between streams in the contents array, without this // it is possible that two operators will get concatenated // together inputStreams.add(new ByteArrayInputStream(inbetweenStreamBytes)); } return new SequenceInputStream(inputStreams.elements()); }
protected PDFunction getTintTransformer(COSStream xstream) throws IOException { COSBase cs = xstream.getDictionaryObject(COSName.COLORSPACE, COSName.CS); if (cs == null) { return null; } COSArray array = getCOSArray(cs); if (array == null) { return null; } String name = ((COSName) array.getObject(0)).getName(); if (name.equals("DeviceN")) { PDFunction function = PDFunction.create(array.getObject(3)); return function; } return null; }
/** * This will get an object from this streams dictionary. * * @param key The key to the object. * @return The dictionary object with the key or null if one does not exist. */ public COSBase getItem(COSName key) { return firstStream.getItem(key); }
/** * This will get the scratch file associated with this stream. * * @return The scratch file where this stream is being stored. */ public RandomAccess getScratchFile() { return firstStream.getScratchFile(); }
/** * This will create an output stream that can be written to. * * @return An output stream which raw data bytes should be written to. * @throws IOException If there is an error creating the stream. */ public OutputStream createUnfilteredStream() throws IOException { return firstStream.createUnfilteredStream(); }
/** * set the filters to be applied to the stream. * * @param filters The filters to set on this stream. * @throws IOException If there is an error clearing the old filters. */ public void setFilters(COSBase filters) throws IOException { // should this be allowed? Should this // propagate to all streams in the array? firstStream.setFilters(filters); }
/** * This will create a new stream for which filtered byte should be written to. You probably don't * want this but want to use the createUnfilteredStream, which is used to write raw bytes to. * * @param expectedLength An entry where a length is expected. * @return A stream that can be written to. * @throws IOException If there is an error creating the stream. */ public OutputStream createFilteredStream(COSBase expectedLength) throws IOException { return firstStream.createFilteredStream(expectedLength); }
/** * This will return the filters to apply to the byte stream the method will return. - null if no * filters are to be applied - a COSName if one filter is to be applied - a COSArray containing * COSNames if multiple filters are to be applied * * @return the COSBase object representing the filters */ public COSBase getFilters() { return firstStream.getFilters(); }
/** * This will get an object from this streams dictionary and dereference it if necessary. * * @param key The key to the object. * @return The dictionary object with the key or null if one does not exist. */ public COSBase getDictionaryObject(COSName key) { return firstStream.getDictionaryObject(key); }