List of usage examples for org.apache.pdfbox.cos COSArray toList
public List<? extends COSBase> toList()
From source file:com.esri.geoportal.commons.pdf.PdfUtils.java
License:Apache License
/** * Extracts the geospatial metadata from a GeoPDF * //from w ww. j a v a2s . c o m * @param page the PDF page to read geospatial metadata from * @param geometryServiceUrl url of a <a href="https://developers.arcgis.com/rest/services-reference/geometry-service.htm">geometry service</a> for reprojecting coordinates. * * @see <a href="https://www.loc.gov/preservation/digital/formats/fdd/fdd000312.shtml">Library of Congress information on GeoPDF</a> * @see <a href="https://www.adobe.com/content/dam/acom/en/devnet/pdf/pdfs/PDF32000_2008.pdf">The PDF specification</a>, section 8, for instructions for translating coordinates. * * @returns the bounding box of the GeoPDF as "yMin xMin, yMax xMax" */ private static String extractGeoPDFProps(PDPage page, String geometryServiceUrl) { // The LGI dictionary is an array, we'll loop through all entries and pull the first one for a bounding box COSArray lgi = (COSArray) page.getCOSObject().getDictionaryObject("LGIDict"); List<String> bBoxes = new ArrayList<>(); lgi.iterator().forEachRemaining(item -> { String currentBbox = null; // Set up the Coordinate Transformation Matrix (used to translate PDF coords to geo coords) Double[][] ctmValues = null; COSDictionary dictionary = (COSDictionary) item; if (dictionary.containsKey("CTM")) { ctmValues = new Double[3][3]; // The last column in the matrix is always constant ctmValues[0][2] = 0.0; ctmValues[1][2] = 0.0; ctmValues[2][2] = 1.0; COSArray ctm = (COSArray) dictionary.getDictionaryObject("CTM"); for (int i = 0; i < ctm.toList().size(); i += 2) { int ctmRow = i / 2; ctmValues[ctmRow][0] = Double.parseDouble(((COSString) ctm.get(i)).getString()); ctmValues[ctmRow][1] = Double.parseDouble(((COSString) ctm.get(i + 1)).getString()); } } // Get the neatline (i.e. the bounding box in *PDF* coordinates) Double[][] neatLineValues = null; int neatLineLength = 0; if (dictionary.containsKey("Neatline")) { COSArray neatline = (COSArray) dictionary.getDictionaryObject("Neatline"); neatLineLength = neatline.toList().size(); neatLineValues = new Double[neatLineLength / 2][3]; for (int i = 0; i < neatline.toList().size(); i += 2) { int neatLineRow = i / 2; neatLineValues[neatLineRow][0] = Double.parseDouble(((COSString) neatline.get(i)).getString()); neatLineValues[neatLineRow][1] = Double .parseDouble(((COSString) neatline.get(i + 1)).getString()); neatLineValues[neatLineRow][2] = 1.0; } } // Translate the PDF coordinates to Geospatial coordintates by multiplying the two matricies MultiPoint mp = new MultiPoint(); if (ctmValues != null && neatLineValues != null) { Double[][] resultCoords = new Double[neatLineLength / 2][3]; for (int z = 0; z < neatLineLength / 2; z++) { for (int i = 0; i < 3; i++) { resultCoords[z][i] = neatLineValues[z][0] * ctmValues[0][i] + neatLineValues[z][1] * ctmValues[1][i] + neatLineValues[z][2] * ctmValues[2][i]; } mp.add(resultCoords[z][0], resultCoords[z][1]); } } // Project the geospatial coordinates to WGS84 for the Dublin-Core metadata if (dictionary.containsKey("Projection")) { COSDictionary projectionDictionary = (COSDictionary) dictionary.getDictionaryObject("Projection"); String projectionType = projectionDictionary.getString("ProjectionType"); try (GeometryService svc = new GeometryService(HttpClients.custom().useSystemProperties().build(), new URL(geometryServiceUrl));) { // UTM projections require slightly different processing if ("UT".equals(projectionType)) { String zone = Integer.toString(projectionDictionary.getInt("Zone")); String hemisphere = projectionDictionary.getString("Hemisphere"); // Get the wkt for the geospatial coordinate system String wkt = datumTranslation(projectionDictionary.getItem("Datum")); if (zone != null && hemisphere != null && wkt != null) { // Generate a list of UTM strings List<String> utmCoords = new ArrayList<>(); for (Point2D pt : mp.getCoordinates2D()) { String coord = String.format("%s%s %s %s", zone, hemisphere, Math.round(pt.x), Math.round(pt.y)); utmCoords.add(coord); } MultiPoint reproj = svc.fromGeoCoordinateString(utmCoords, WGS84_WKID); currentBbox = generateBbox(reproj); } else { LOG.warn("Missing UTM argument: zone: {}, hemisphere: {}, datum: {}", zone, hemisphere, wkt); LOG.debug("Projection dictionary {}", projectionDictionary); } } else { // Generate Well Known Text for projection and re-projects the points to WGS 84 String wkt = getProjectionWKT(projectionDictionary, projectionType); if (wkt != null) { MultiPoint reproj = svc.project(mp, wkt, WGS84_WKID); currentBbox = generateBbox(reproj); } else if (LOG.isDebugEnabled()) { // Print out translated coordinates for debugging purposes LOG.debug("Translated Coordinates"); for (Point2D pt : mp.getCoordinates2D()) { LOG.debug(String.format("\t%s, %s", pt.x, pt.y)); } } } } catch (Exception e) { // If something goes wrong, just try the next set of coordinates LOG.error("Exception reprojecting geometry, skipping this geopdf dictionary instance...", e); } } if (currentBbox != null) { bBoxes.add(currentBbox); } }); return bBoxes.get(0); }
From source file:net.padaf.preflight.font.SimpleFontValidator.java
License:Apache License
/** * Check if the widths array contains integer and if its length is valid. If * the validation fails, the FontContainer is updated. * /* w ww . j a va2 s . co m*/ * @param cDoc */ protected boolean checkWidthsArray(COSDocument cDoc) { // ---- the Widths value can be a reference to an object // ---- Access the object using the COSkey COSArray wArr = COSUtils.getAsArray(this.widths, cDoc); if (wArr == null) { this.fontContainer.addError( new ValidationError(ERROR_FONTS_DICTIONARY_INVALID, "The Witdhs array is unreachable")); return false; } // ---- firstChar and lastChar must be integer. int fc = ((COSInteger) this.firstChar).intValue(); int lc = ((COSInteger) this.lastChar).intValue(); // ---- wArr length = (lc - fc) +1 and it is an array of int. // ---- If FirstChar is greater than LastChar, the validation will fail // because of // ---- the array will have an expected size <= 0. int expectedLength = (lc - fc) + 1; if (wArr.size() != expectedLength) { this.fontContainer.addError(new ValidationError(ERROR_FONTS_DICTIONARY_INVALID, "The length of Witdhs array is invalid. Expected : \"" + expectedLength + "\" Current : \"" + wArr.size() + "\"")); return false; } for (Object arrContent : wArr.toList()) { boolean isInt = false; if (arrContent instanceof COSBase) { isInt = COSUtils.isInteger((COSBase) arrContent, cDoc); } if (!isInt) { this.fontContainer.addError(new ValidationError(ERROR_FONTS_DICTIONARY_INVALID, "The Witdhs array is invalid. (some element aren't integer)")); return false; } } return true; }
From source file:net.padaf.preflight.font.TrueTypeFontValidator.java
License:Apache License
/** * This method checks the metric consistency. If the validation fails, the * FontContainer is updated. If the validation is a success, the * FontContainer.cidKnownByFont map is updated. * /*from w ww.j av a 2 s. com*/ * @param ttf * @return * @throws IOException */ protected boolean checkFontMetrics(TrueTypeFont ttf) throws IOException, ValidationException { int firstChar = pFont.getFirstChar(); float defaultGlyphWidth = this.pFontDesc.getMissingWidth(); List<?> pdfWidths = this.pFont.getWidths(); COSArray widths = null; if (pdfWidths instanceof COSArrayList) { widths = ((COSArrayList) pdfWidths).toList(); } else { widths = ((COSArray) pdfWidths); } ((TrueTypeFontContainer) this.fontContainer).setWidthsArray(widths.toList()); ((TrueTypeFontContainer) this.fontContainer).setFirstCharInWidthsArray(firstChar); ((TrueTypeFontContainer) this.fontContainer).setDefaultGlyphWidth(defaultGlyphWidth); ((TrueTypeFontContainer) this.fontContainer).setFontObjectAndInitializeInnerFields(ttf); ((TrueTypeFontContainer) this.fontContainer).setCMap(getCMapOfFontProgram(ttf)); return true; }
From source file:net.padaf.preflight.font.Type1FontValidator.java
License:Apache License
/** * Type1C is a CFF font format, extract all CFFFont object from the stream * /* ww w.j av a2s .com*/ * @param fontStream * @return * @throws ValidationException */ protected boolean checkCIDFontWidths(PDStream fontStream) throws ValidationException { try { CFFParser cffParser = new CFFParser(); List<CFFFont> lCFonts = cffParser.parse(fontStream.getByteArray()); if (lCFonts == null || lCFonts.isEmpty()) { this.fontContainer.addError(new ValidationResult.ValidationError(ERROR_FONTS_CID_DAMAGED, "The FontFile can't be read")); return false; } ((Type1FontContainer) this.fontContainer).setCFFFontObjects(lCFonts); List<?> pdfWidths = this.pFont.getWidths(); int firstChar = pFont.getFirstChar(); float defaultGlyphWidth = pFontDesc.getMissingWidth(); COSArray widths = null; if (pdfWidths instanceof COSArrayList) { widths = ((COSArrayList) pdfWidths).toList(); } else { widths = ((COSArray) pdfWidths); } ((Type1FontContainer) this.fontContainer).setWidthsArray(widths.toList()); ((Type1FontContainer) this.fontContainer).setFirstCharInWidthsArray(firstChar); ((Type1FontContainer) this.fontContainer).setDefaultGlyphWidth(defaultGlyphWidth); return true; } catch (IOException e) { this.fontContainer.addError( new ValidationResult.ValidationError(ERROR_FONTS_CID_DAMAGED, "The FontFile can't be read")); return false; } }
From source file:net.padaf.preflight.font.Type1FontValidator.java
License:Apache License
/** * This method checks the metric consistency and adds the FontContainer in the * DocumentHandler./*ww w . j a v a 2s . co m*/ * * @param fontStream * @return * @throws ValidationException */ protected boolean checkFontMetricsDataAndFeedFontContainer(PDStream fontStream) throws ValidationException { try { // ---- Parse the Type1 Font program ByteArrayInputStream bis = new ByteArrayInputStream(fontStream.getByteArray()); COSStream streamObj = fontStream.getStream(); int length1 = streamObj.getInt(COSName.getPDFName(FONT_DICTIONARY_KEY_LENGTH1)); int length2 = streamObj.getInt(COSName.getPDFName(FONT_DICTIONARY_KEY_LENGTH2)); Type1Parser parserForMetrics = Type1Parser.createParserWithEncodingObject(bis, length1, length2, pFont.getFontEncoding()); Type1 parsedData = parserForMetrics.parse(); ((Type1FontContainer) this.fontContainer).setFontObject(parsedData); List<?> pdfWidths = this.pFont.getWidths(); int firstChar = pFont.getFirstChar(); float defaultGlyphWidth = pFontDesc.getMissingWidth(); COSArray widths = null; if (pdfWidths instanceof COSArrayList) { widths = ((COSArrayList) pdfWidths).toList(); } else { widths = ((COSArray) pdfWidths); } ((Type1FontContainer) this.fontContainer).setWidthsArray(widths.toList()); ((Type1FontContainer) this.fontContainer).setFirstCharInWidthsArray(firstChar); ((Type1FontContainer) this.fontContainer).setDefaultGlyphWidth(defaultGlyphWidth); return true; } catch (IOException e) { throw new ValidationException("Unable to check Type1 metrics due to : " + e.getMessage(), e); } }
From source file:net.padaf.preflight.helpers.TrailerValidationHelper.java
License:Apache License
/** * Return true if the ID of the first dictionary is the same as the id of the * last dictionary Return false otherwise. * /*from w w w .j av a 2 s . c o m*/ * @param first * @param last * @return */ protected boolean compareIds(COSDictionary first, COSDictionary last, COSDocument doc) { COSBase idFirst = first.getItem(COSName.getPDFName(TRAILER_DICTIONARY_KEY_ID)); COSBase idLast = last.getItem(COSName.getPDFName(TRAILER_DICTIONARY_KEY_ID)); if (idFirst == null || idLast == null) { return false; } // ---- cast two COSBase to COSArray. COSArray af = COSUtils.getAsArray(idFirst, doc); COSArray al = COSUtils.getAsArray(idLast, doc); // ---- if one COSArray is null, the PDF/A isn't valid if ((af == null) || (al == null)) { return false; } // ---- compare both arrays boolean isEqual = true; for (Object of : af.toList()) { boolean oneIsEquals = false; for (Object ol : al.toList()) { // ---- according to PDF Reference 1-4, ID is an array containing two // strings if (!oneIsEquals) oneIsEquals = ((COSString) ol).getString().equals(((COSString) of).getString()); } isEqual = isEqual && oneIsEquals; } return isEqual; }