Package de.chris_soft.nanodoa

Source Code of de.chris_soft.nanodoa.FulltextRecognizer

/**
* NanoDoA - File based document archive
*
* Copyright (C) 2011-2012 Christian Packenius, christian.packenius@googlemail.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package de.chris_soft.nanodoa;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Properties;

import javax.imageio.ImageIO;

import com.google.zxing.Result;
import com.itextpdf.text.pdf.PRStream;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfObject;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStream;
import com.itextpdf.text.pdf.parser.PdfImageObject;

import de.chris_soft.nanoarchive.Metadata;
import de.chris_soft.utilities.BarcodeReader;
import de.chris_soft.utilities.FileUtils;
import de.chris_soft.utilities.IdUtils;
import de.chris_soft.utilities.LogUtils;
import de.chris_soft.utilities.OcrViaTesseractUtils;
import de.chris_soft.utilities.PdfUtils;
import de.chris_soft.utilities.TiffUtils;
import de.chris_soft.utilities.Utf8Utils;

/**
* Recognizer of full text of a document.
* @author Christian Packenius.
*/
public class FulltextRecognizer {
  private static Utf8Utils utf8 = new Utf8Utils();

  /**
   * Returns the full text of a document.
   * @param file Document file.
   * @param metadata Properties object with (and for) metadata to the document.
   * @return Full text of the document, including OCR results, real texts and
   *         barcodes.
   */
  public static String getFulltext(File file, Properties metadata) {
    String fulltext = "";
    try {
      String ocrtext = getOcrTextAndStoreBarcodes(file, metadata);
      metadata.setProperty(Metadata.OCRTEXT, ocrtext);
      fulltext += fulltext.length() == 0 ? ocrtext : "\r\n\r\n" + ocrtext;
    }
    catch (Exception e) {
      LogUtils.log(e);
    }

    try {
      String realtext = getRealText(file);
      metadata.setProperty(Metadata.REALTEXT, realtext);
      fulltext += fulltext.length() == 0 ? realtext : "\r\n\r\n" + realtext;
    }
    catch (IOException e) {
      LogUtils.log(e);
    }

    return fulltext;
  }

  /**
   * Get the real text from the file. Bitmaps don't have real text, but maybe
   * PDFs have.
   * @param file Document file.
   * @return Real text of the document.
   * @throws IOException
   */
  public static String getRealText(File file) throws IOException {
    if (PdfUtils.isPdfFile(file)) {
      return PdfUtils.getTextFromPdfFile(file);
    }
    return "";
  }

  /**
   * Get the OCR result of the given document.
   * @param file Document file.
   * @param metadata Properties object with (and for) metadata of the document.
   * @return OCR result as single string.
   * @throws Exception
   */
  public static String getOcrTextAndStoreBarcodes(File file, Properties metadata) throws Exception {
    OcrViaTesseractUtils ocr = new OcrViaTesseractUtils();
    String ext = FileUtils.getFileExtension(file).toLowerCase();
    String imageName = file.getCanonicalPath();
    File tmpDirectory = new File("tmp");
    tmpDirectory.mkdirs();
    String ocrName = new File(tmpDirectory, "" + IdUtils.getUniqueID()).getCanonicalPath();
    String text = "";
    if (ext.equals("pdf")) {
      text = workPdfFile(ocr, imageName, ocrName, metadata);
    }
    else if (ext.equals("tif") || ext.equals("tiff")) {
      text = workTiffFile(ocr, file, metadata);
    }
    else {
      text = workSingleImageFile(ocr, imageName, ocrName, metadata);
    }
    FileUtils.deleteFile(new File(ocrName + ".txt"));
    FileUtils.deleteFile(new File(ocrName));
    return text;
  }

  private static String workTiffFile(OcrViaTesseractUtils ocr, File tiffFile, Properties metadata) throws IOException {
    List<File> list = TiffUtils.convertTiffFileToPngFiles(tiffFile, new File("tmp"));
    StringBuilder text = new StringBuilder();
    StringBuilder barcodes = new StringBuilder();
    StringBuilder textBarcodes = new StringBuilder();
    while (!list.isEmpty()) {
      File pngPageFile = list.remove(0);
      String pngPageName = pngPageFile.getCanonicalPath();
      recognizeAndStoreOcrTextOfTiffPngFile(ocr, list, text, pngPageName);
      recognizeAndStoreBarcodesOfTiffPngFile(barcodes, textBarcodes, pngPageFile);
      removeTemporaryTiffPngPageFiles(pngPageName);
    }
    metadata.setProperty(Metadata.BARCODES, barcodes.toString());
    return text.toString() + textBarcodes.toString();
  }

  private static void recognizeAndStoreOcrTextOfTiffPngFile(OcrViaTesseractUtils ocr, List<File> list,
      StringBuilder text, String pngPageName) throws IOException {
    try {
      if (ocr.toFile(pngPageName, pngPageName) == 0) {
        text.append(utf8.read(pngPageName + ".txt"));
        if (!list.isEmpty()) {
          text.append("\r\n\r\n");
        }
      }
    }
    catch (InterruptedException exception) {
      // Ignore.
    }
  }

  private static void recognizeAndStoreBarcodesOfTiffPngFile(StringBuilder barcodes, StringBuilder textBarcodes,
      File pngPageFile) {
    try {
      BufferedImage image = ImageIO.read(pngPageFile);
      appendBarcodes(barcodes, textBarcodes, image);
    }
    catch (Exception exception) {
      // Ignore.
    }
  }

  private static void appendBarcodes(StringBuilder barcodes, StringBuilder textBarcodes, BufferedImage image) {
    Result[] results = BarcodeReader.getBarcodeResults(image);
    if (results != null) {
      for (Result result : results) {
        if (barcodes.length() > 0) {
          barcodes.append("\r\n\r\n");
        }
        barcodes.append(result.getBarcodeFormat().getName() + ": \r\n" + result.getText());
        textBarcodes.append("\r\n\r\n" + result.getText());
      }
    }
  }

  private static void removeTemporaryTiffPngPageFiles(String pngPageName) {
    FileUtils.deleteFile(new File(pngPageName + ".txt"));
    FileUtils.deleteFile(new File(pngPageName));
  }

  private static String workPdfFile(OcrViaTesseractUtils ocr, String pdfName, String ocrName, Properties metadata)
      throws Exception {
    PdfReader reader = new PdfReader(pdfName);
    StringBuilder pdfContent = new StringBuilder();
    StringBuilder barcodes = new StringBuilder();
    StringBuilder textBarcodes = new StringBuilder();
    for (int i = 0; i < reader.getXrefSize(); i++) {
      PdfObject pdfobj = reader.getPdfObject(i);
      if (pdfobj != null) {
        if (pdfobj.isStream()) {
          PdfStream stream = (PdfStream) pdfobj;
          PdfObject pdfsubtype = stream.get(PdfName.SUBTYPE);
          if (pdfsubtype != null) {
            if (pdfsubtype.toString().equals(PdfName.IMAGE.toString())) {
              System.out.println("OCR on PDF object " + i);
              getImageFromPageAndAddOcrResultToContent(ocr, pdfContent, barcodes, textBarcodes, ocrName, stream);
            }
          }
        }
      }
    }
    reader.close();
    metadata.setProperty(Metadata.BARCODES, barcodes.toString());
    return pdfContent.toString() + textBarcodes.toString();
  }

  private static void getImageFromPageAndAddOcrResultToContent(OcrViaTesseractUtils ocr, StringBuilder pdfContent,
      StringBuilder barcodes, StringBuilder textBarcodes, String ocrName, PdfStream stream) throws Exception {
    final File tmpJpegFile = new File(ocrName + ".jpg");
    writePdfImageFromStreamIntoFile(stream, tmpJpegFile);
    if (tmpJpegFile.exists()) {
      getBarcodesFromTemporaryImageFile(tmpJpegFile, barcodes, textBarcodes);
      String pdfPageContent = getOcrResultFromTemporaryImageFile(ocr, tmpJpegFile);
      if (pdfPageContent != null && pdfPageContent.trim().length() > 0) {
        if (pdfContent.length() > 0) {
          pdfContent.append("\r\n\r\n");
        }
        pdfContent.append(pdfPageContent);
      }
    }
    FileUtils.deleteFile(tmpJpegFile);
  }

  private static void getBarcodesFromTemporaryImageFile(File tmpJpegFile, StringBuilder barcodes,
      StringBuilder textBarcodes) {
    try {
      BufferedImage image = ImageIO.read(tmpJpegFile);
      appendBarcodes(barcodes, textBarcodes, image);
    }
    catch (Exception e) {
      LogUtils.log(e);
    }
  }

  private static void writePdfImageFromStreamIntoFile(PdfStream stream, final File tmpJpegFile) {
    try {
      PdfObject filterObject = stream.get(PdfName.FILTER);
      String filterName = filterObject.toString();
      if (filterName.equals("/DCTDecode")) {
        writePdfImageFromStreamViaRawImage(stream, tmpJpegFile);
      }
      else {
        writePdfImageFromStreamViaBufferedImage(stream, tmpJpegFile);
      }
    }
    catch (Exception e) {
      // Hier k�nnen vielf�ltige Fehler entstehen: Der Stream kann nicht
      // ausgelesen werden, was zum NullPointer f�hrt, es kann zu
      // Decodingfehlern des Images f�hren oder zu IO-Fehlern beim Wegschreiben.
      // All das f�hrt schlicht zu einem einzelnen Ergebnis: Das JPEG-File
      // sollte nicht angelegt werden.
      FileUtils.deleteFile(tmpJpegFile);
    }
  }

  private static void writePdfImageFromStreamViaRawImage(PdfStream stream, final File tmpJpegFile) throws IOException {
    byte[] img = PdfReader.getStreamBytesRaw((PRStream) stream);
    if (img != null) {
      FileOutputStream out = new FileOutputStream(tmpJpegFile);
      out.write(img);
      out.flush();
      out.close();
    }
  }

  private static void writePdfImageFromStreamViaBufferedImage(PdfStream stream, final File tmpJpegFile)
      throws IOException {
    PdfImageObject image = new PdfImageObject((PRStream) stream);
    BufferedImage bufferedImage = image.getBufferedImage();
    if (bufferedImage != null) {
      FileOutputStream out = new FileOutputStream(tmpJpegFile);
      ImageIO.write(bufferedImage, "jpg", out);
      out.close();
    }
  }

  private static String getOcrResultFromTemporaryImageFile(OcrViaTesseractUtils ocr, File tmpJpegFile)
      throws IOException, InterruptedException, Exception {
    String tmpName = tmpJpegFile.getCanonicalPath();
    int ocrRC;
    if ((ocrRC = ocr.toFile(tmpName, tmpName)) != 0) {
      throw new Exception("OCR (Tesseract) result of a pdf image was " + ocrRC);
    }
    String pdfPageContent = utf8.read(tmpName + ".txt");
    FileUtils.deleteFile(tmpJpegFile);
    FileUtils.deleteFile(new File(tmpName + ".txt"));
    return pdfPageContent;
  }

  private static String workSingleImageFile(OcrViaTesseractUtils ocr, String imageName, String ocrName,
      Properties metadata) throws IOException, InterruptedException {
    BufferedImage image = ImageIO.read(new File(imageName));
    StringBuilder barcodes = new StringBuilder();
    StringBuilder textBarcodes = new StringBuilder();
    metadata.setProperty(Metadata.BARCODES, barcodes.toString());
    appendBarcodes(barcodes, textBarcodes, image);
    if (ocr.toFile(imageName, ocrName) == 0) {
      return utf8.read(ocrName + ".txt") + textBarcodes.toString();
    }
    return textBarcodes.toString();
  }
}
TOP

Related Classes of de.chris_soft.nanodoa.FulltextRecognizer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.