Como posso extrair imagens e seus metadados de PDFs?

É possível usar o Java para extrair imagens de um arquivo PDF e exportá-las para uma pasta específica sem perder suas datas originais de criação e modificação? Eu tentei atingir esse objective usando IText e PDFBox, mas não tive sucesso. Quaisquer idéias ou exemplos são bem-vindos.

As imagens não contêm metadados e são armazenadas como dados brutos, que precisam ser reunidos em imagens. Eu escrevi 2 posts no blog explicando como os dados de imagem são armazenados em um arquivo PDF em http://www.jpedal.org/PDFblog/2010/04/understanding-the-pdf-file-format-how-are-images-stored/ e http://www.jpedal.org/PDFblog/2010/09/understanding-the-pdf-file-format-images/

Eu não concordo com os outros e tenho um POC para sua pergunta: Você pode extrair os metadados XMP de imagens usando o pdfbox da seguinte maneira:

public void getXMPInformation() { // Open PDF document PDDocument document = null; try { document = PDDocument.load(PATH_TO_YOUR_DOCUMENT); } catch (IOException e) { e.printStackTrace(); } // Get all pages and loop through them List pages = document.getDocumentCatalog().getAllPages(); Iterator iter = pages.iterator(); while( iter.hasNext() ) { PDPage page = (PDPage)iter.next(); PDResources resources = page.getResources(); Map images = null; // Get all Images on page try { images = resources.getImages(); } catch (IOException e) { e.printStackTrace(); } if( images != null ) { // Check all images for metadata Iterator imageIter = images.keySet().iterator(); while( imageIter.hasNext() ) { String key = (String)imageIter.next(); PDXObjectImage image = (PDXObjectImage)images.get( key ); PDMetadata metadata = image.getMetadata(); System.out.println("Found a image: Analyzing for Metadata"); if (metadata == null) { System.out.println("No Metadata found for this image."); } else { InputStream xmlInputStream = null; try { xmlInputStream = metadata.createInputStream(); } catch (IOException e) { e.printStackTrace(); } try { System.out.println("--------------------------------------------------------------------------------"); String mystring = convertStreamToString(xmlInputStream); System.out.println(mystring); } catch (IOException e) { e.printStackTrace(); } } // Export the images String name = getUniqueFileName( key, image.getSuffix() ); System.out.println( "Writing image:" + name ); try { image.write2file( name ); } catch (IOException e) { // TODO Auto-generated catch block //e.printStackTrace(); } System.out.println("--------------------------------------------------------------------------------"); } } } } 

E os “methods auxiliares”:

 public String convertStreamToString(InputStream is) throws IOException { /* * To convert the InputStream to String we use the BufferedReader.readLine() * method. We iterate until the BufferedReader return null which means * there's no more data to read. Each line will appended to a StringBuilder * and returned as String. */ if (is != null) { StringBuilder sb = new StringBuilder(); String line; try { BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8")); while ((line = reader.readLine()) != null) { sb.append(line).append("\n"); } } finally { is.close(); } return sb.toString(); } else { return ""; } } private String getUniqueFileName( String prefix, String suffix ) { /* * imagecounter is a global variable that counts from 0 to the number of * extracted images */ String uniqueName = null; File f = null; while( f == null || f.exists() ) { uniqueName = prefix + "-" + imageCounter; f = new File( uniqueName + "." + suffix ); } imageCounter++; return uniqueName; } 

Nota: Esta é uma prova de conceito rápida e suja e não um código bem estilizado.

As Imagens devem ter Metadados XMP quando colocadas no InDesign antes de criar o documento PDF. O XMP-Metdadata pode ser definido usando o Photoshop, por exemplo. Por favor tenha em conta que nem todas as informações do IPTC / Exif / … são convertidas nos Metadados XMP. Apenas um pequeno número de campos é convertido.

Estou usando esse método em imagens JPG e PNG, colocadas em PDFs criados com o InDesign. Ele funciona bem e eu posso obter todas as informações da imagem após as etapas de produção dos PDFs prontos (revestimento da imagem).

As datas originais de criação e modificação geralmente não são salvas quando a imagem é incorporada ao PDF. Apenas os dados brutos de pixels são compactados e salvos. No entanto, de acordo com a Wikipedia :

Imagens rasterizadas em PDF (denominadas Image XObjects) são representadas por dictionarys com um stream associado.

O dictionary contém metadados, entre os quais você pode encontrar as datas.

Resposta curta

Talvez, mas provavelmente não.

Resposta longa

O PDF suporta nativamente JPEG, JPEG2000 (que está se tornando mais comum), CITT (fax) 3 e 4 e JBIG2 (realmente raro). Imagens nesses formatos podem ser copiadas byte-by-byte para o PDF, preservando quaisquer metadados dentro do arquivo. As datas de criação / alteração geralmente fazem parte do sistema de arquivos, não da imagem.

JPEG: não parece que suporta metadados internos.

JPEG2000: Sim. Muitas coisas lá potencialmente

CITT: não parece assim.

JBIG2: Err … Acho que sim, mas não é nada para esclarecer as especificações que eu acabei de ler.

Todos os outros formatos de imagem devem ser transformados em pixels e, em seguida, compactados de alguma forma (geralmente com Flate / ZIP). Essas conversões podem manter os metadados como parte dos metadados xml do PDF ou do dictionary da imagem, mas nunca ouvi falar disso. Apenas é lançado.

Obtenha o arquivo Meta Data From PDF usando a API SonwTide. Use PDFTextStream.jar No final, ele retornará todas as propriedades do PDF e imprimirá na linha de comando.

 public static void getPDFMetaData(String pdfFilePath) throws IOException{ // input pdf file with location Add PDFTextStream.jar from snowtide web site to your code build path PDFTextStream stream = new PDFTextStream(pdfFilePath); // get collection of all document attribute names Set attributeKeys = stream.getAttributeKeys(); // print the values of all document attributes to System.out Iterator iter = attributeKeys.iterator(); String attrKey; while (iter.hasNext()) { attrKey = (String)iter.next(); System.out.println(attrKey + " = " + stream.getAttribute(attrKey)); } }