2013-07-21 19 views
9

Ich habe mir dabei die Haare gerissen.Teilen eines mehrseitigen TIFF-Bildes in einzelne Bilder (Java)

Wie kann ich ein mehrseitiges/mehrschichtiges TIFF-Bild in mehrere Einzelbilder aufteilen?

Demo Bild verfügbar here.

(Würde eine reine Java (dh nicht-native) Lösung bevorzugen. Egal, ob die Lösung auf kommerziellen Bibliotheken angewiesen ist.)

+1

Wenn Ihre TIFF-Dateien konsistent und wie die Probe sein werden, können Sie eine Quick-n-dirty-Methode zu tun, die nicht schwer zu schreiben ist. Eine verallgemeinerte Routine zur Handhabung aller TIFFs wäre komplizierter. – BitBank

Antwort

19

Sie die Bibliothek Java Advanced Imaging verwenden können, JAI, aufzuspalten ein mutlipage TIFF, indem sie einen Imagereader mit:

ImageInputStream is = ImageIO.createImageInputStream(new File(pathToImage)); 
if (is == null || is.length() == 0){ 
    // handle error 
} 
Iterator<ImageReader> iterator = ImageIO.getImageReaders(is); 
if (iterator == null || !iterator.hasNext()) { 
    throw new IOException("Image file format not supported by ImageIO: " + pathToImage); 
} 
// We are just looking for the first reader compatible: 
ImageReader reader = (ImageReader) iterator.next(); 
iterator = null; 
reader.setInput(is); 

Dann können Sie die Anzahl der Seiten erhalten:

nbPages = reader.getNumImages(true); 

und lesen Seiten separatly:

reader.read(numPage) 
+2

Tatsächlich ist eine großartige Sache über den Code, den Sie gepostet haben, dass JAI nicht einmal zur Kompilierungszeit benötigt wird, und JAI kann zur Laufzeit durch ein anderes TIFF-Plugin ersetzt werden. :-) – haraldK

1

ich verwendet, um dieses Beispiel oben mit einem TIFF-Plugin i ImageIO-tiff genannt gefunden.

Maven Abhängigkeit:

<dependency> 
     <groupId>com.tomgibara.imageio</groupId> 
     <artifactId>imageio-tiff</artifactId> 
     <version>1.0</version> 
     </dependency> 

konnte ich die gepufferten Bilder von einer tiff-Ressource erhalten:

Resource img3 = new ClassPathResource(TIFF4); 
      ImageInputStream is = ImageIO.createImageInputStream(img3.getInputStream()); 

      Iterator<ImageReader> iterator = ImageIO.getImageReaders(is); 
      if (iterator == null || !iterator.hasNext()) { 
       throw new IOException("Image file format not supported by ImageIO: "); 
      } 
      // We are just looking for the first reader compatible: 
      ImageReader reader = (ImageReader) iterator.next(); 
      iterator = null; 
      reader.setInput(is); 
      int nbPages = reader.getNumImages(true); 

      LOGGER.info("No. of pages for tiff file is {}", nbPages); 
    BufferedImage image1 = reader.read(0); 
     BufferedImage image2 = reader.read(1); 
     BufferedImage image3 = reader.read(2); 

Aber dann fand ich ein weiteres Projekt Apache Commons Imaging Maven Abhängigkeit genannt:

<dependency> 
      <groupId>org.apache.commons</groupId> 
      <artifactId>commons-imaging</artifactId> 
      <version>1.0-SNAPSHOT</version> 
     </dependency> 

In einer Zeile können Sie die gepufferten Bilder erhalten:

List<BufferedImage> bufferedImages = Imaging.getAllBufferedImages(img3.getInputStream(), TIFF4); 
     LOGGER.info("No. of pages for tiff file is {} using apache commons imaging", bufferedImages.size()); 

schreiben Dann Probe in Datei:

final Map<String, Object> params = new HashMap<String, Object>(); 
     // set optional parameters if you like 
     params.put(ImagingConstants.PARAM_KEY_COMPRESSION, new Integer(TiffConstants.TIFF_COMPRESSION_CCITT_GROUP_4)); 
     int i = 0; 
     for (Iterator<BufferedImage> iterator1 = bufferedImages.iterator(); iterator1.hasNext(); i++) { 
      BufferedImage bufferedImage = iterator1.next(); 
      LOGGER.info("Image type {}", bufferedImage.getType()); 
      File outFile = new File("C:\\tmp" + File.separator + "shane" + i + ".tiff"); 
      Imaging.writeImage(bufferedImage, outFile, ImageFormats.TIFF, params); 
     } 

Eigentlich Testen Leistung, Apache ist viel langsamer ...

oder eine alte Version von iText verwenden, die viel schneller ist:

private ByteArrayOutputStream convertTiffToPdf(InputStream imageStream) throws IOException, DocumentException { 
    Image image; 
    ByteArrayOutputStream out = new ByteArrayOutputStream(); 
    Document document = new Document(); 
    PdfWriter writer = PdfWriter.getInstance(document, out); 
    writer.setStrictImageSequence(true); 
    document.open(); 

    RandomAccessFileOrArray ra = new RandomAccessFileOrArray(imageStream); 
    int pages = TiffImage.getNumberOfPages(ra); 
    for (int i = 1; i <= pages; i++) { 
     image = TiffImage.getTiffImage(ra, i); 
     image.setAbsolutePosition(0, 0); 
     image.scaleToFit(PageSize.A4.getWidth(), PageSize.A4.getHeight()); 
     document.setPageSize(PageSize.A4); 
     document.newPage(); 
     document.add(image); 
    } 
    document.close(); 
    out.flush(); 
    return out; 
} 
2

Eine schnelle, aber keine JAVA-Lösung ist tiffsplit. Es ist Teil der libtiff-Bibliothek.

Ein Beispiel Befehl, um eine TIFF-Datei in allen seinen Schichten wäre zu spalten:

tiffsplit image.tif

Die manpage sagt alles:

NAME 
     tiffsplit - split a multi-image TIFF into single-image TIFF files 

SYNOPSIS 
     tiffsplit src.tif [ prefix ] 

DESCRIPTION 
     tiffsplit takes a multi-directory (page) TIFF file and creates one or more single-directory (page) TIFF files 
     from it. The output files are given names created by concatenating a prefix, a lexically ordered suffix in the 
     range [aaa-zzz], the suffix .tif (e.g. xaaa.tif, xaab.tif, xzzz.tif). If a prefix is not specified on the 
     command line, the default prefix of x is used. 

OPTIONS 
     None. 

BUGS 
     Only a select set of ‘‘known tags’’ is copied when splitting. 

SEE ALSO 
     tiffcp(1), tiffinfo(1), libtiff(3TIFF) 

     Libtiff library home page: http://www.remotesensing.org/libtiff/ 
1

Alle vorgeschlagenen Lösungen erfordern die mehrseitige Bildlese Seite für Seite und schreibe die Seiten zurück in neue TIFF-Bilder. Wenn Sie die einzelnen Seiten nicht in einem anderen Bildformat speichern möchten, ist es nicht sinnvoll, das Bild zu decodieren. Aufgrund der speziellen Struktur des TIFF-Bildes können Sie ein mehrseitiges TIFF in einzelne TIFF-Bilder ohne Entschlüsselung aufteilen.

Das TIFF-Optimierungstool (Teil einer größeren bildbezogenen Bibliothek - "icafe") wird von Grund auf mit reinem Java geschrieben. Es kann Seiten löschen, Seiten einfügen, bestimmte Seiten beibehalten und Seiten aus einer mehrseitigen TIFF-Datei aufteilen . als Multipage-TIFF-Bilder in ein TIFF-Bild verschmelzen, ohne sie zu dekomprimieren

mit dem TIFF-Tweaking-Tool nach dem Versuch, ich bin in der Lage, das Bild in 3-Seiten aufgeteilt: page#0, page#1 und page#2

NOTE1: Das ursprüngliche Demobild enthält aus irgendeinem Grund "falsche" St ripByteCounts Wert 1, der nicht die tatsächlichen Bytes ist, die für den Bildstreifen benötigt werden. Es stellt sich heraus, dass die Bilddaten nicht komprimiert sind, so dass das Ist-Bytes für jedes Bildstreifens heraus durch andere TIFF-Feldwerte werden könnte, wie beispielsweise RowsPerStrip, SamplesPerPixel, Width usw.

Hinweis 2: Da der in Aufspalten TIFF, die oben genannte Bibliothek muss das Bild nicht decodieren und neu codieren. So ist es schnell und es behält auch die ursprüngliche Kodierung und zusätzliche Metadaten jeder Seite bei!

0

Dies ist, wie ich es mit ImageIO tat:

von this blog
public List<BufferedImage> extractImages(InputStream fileInput) throws Exception { 
    List<BufferedImage> extractedImages = new ArrayList<BufferedImage>(); 

    try (ImageInputStream iis = ImageIO.createImageInputStream(fileInput)) { 

     ImageReader reader = getTiffImageReader(); 
     reader.setInput(iis); 

     int pages = reader.getNumImages(true); 
     for (int imageIndex = 0; imageIndex < pages; imageIndex++) { 
      BufferedImage bufferedImage = reader.read(imageIndex); 
      extractedImages.add(bufferedImage); 
     } 
    } 

    return extractedImages; 
} 

private ImageReader getTiffImageReader() { 
    Iterator<ImageReader> imageReaders = ImageIO.getImageReadersByFormatName("TIFF"); 
    if (!imageReaders.hasNext()) { 
     throw new UnsupportedOperationException("No TIFF Reader found!"); 
    } 
    return imageReaders.next(); 
} 

ich Teil des Codes hat.

0

Der folgende Code konvertiert das multiple tiff in individuals und erzeugt ein Excel-Blatt mit einer Liste von TIFF-Bildern.

Sie müssen einen Ordner mit dem Namen "FAX" im C-Laufwerk erstellen und Ihre TIFF-Bilder in sie einfügen und dann diesen Code ausführen. Sie können die konvertierten Bilder in finden "C: \ Final_FAX \"

benötigen Sie die folgenden Gläser von http://www.java2s.com/Code/JarDownload/sun/

1.sun-as-jsr88-dm-4.0-Quellen

2. importieren/Sonnen jai_codec

3.sun-jai_core

import java.awt.AWTException; 
import java.awt.Robot; 
import java.awt.image.RenderedImage; 
import java.awt.image.renderable.ParameterBlock; 
import java.io.File; 
import java.io.IOException; 

import javax.media.jai.JAI; 
import javax.media.jai.RenderedOp; 

import com.sun.media.jai.codec.FileSeekableStream; 
import com.sun.media.jai.codec.ImageCodec; 
import com.sun.media.jai.codec.ImageDecoder; 
import com.sun.media.jai.codec.TIFFEncodeParam; 

import java.io.*; 
import java.text.SimpleDateFormat; 
import java.util.ArrayList; 
import java.util.Arrays; 
import java.util.Calendar; 

import javax.swing.JOptionPane; 

import org.apache.poi.hssf.usermodel.HSSFSheet; 
import org.apache.poi.hssf.usermodel.HSSFWorkbook; 
import org.apache.poi.ss.usermodel.Row; 

public class TIFF_Sepreator { 

    File folder = new File("C:/FAX/"); 


public static void infoBox(String infoMessage, String titleBar) 
    { 
     JOptionPane.showMessageDialog(null, infoMessage, "InfoBox: " + titleBar, JOptionPane.INFORMATION_MESSAGE); 
    } 

public void splitting() throws IOException, AWTException 
    {  
     boolean FinalFAXFolder = (new File("C:/Final_FAX")).mkdirs(); 
//  int ListOfFiles = new File("C:/Final_FAX/").listFiles().length; 
//  System.out.println(ListOfFiles); 

     File[] listOfFiles = folder.listFiles(); 
     String dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss").format(Calendar.getInstance().getTime()); 

    try{ 
     if (listOfFiles.length > 0) 
     { 
      for(int file=0; file<listOfFiles.length; file++) 
      { 
      System.out.println(listOfFiles[file]); 
      FileSeekableStream ss = new FileSeekableStream(listOfFiles[file]); 
      ImageDecoder dec = ImageCodec.createImageDecoder("tiff", ss, null); 
      int count = dec.getNumPages(); 
      TIFFEncodeParam param = new TIFFEncodeParam(); 
      param.setCompression(TIFFEncodeParam.COMPRESSION_GROUP4); 
      param.setLittleEndian(false); // Intel 
      System.out.println("This TIF has " + count + " image(s)"); 

       for (int i = 0; i < count; i++) 
       { 
        RenderedImage page = dec.decodeAsRenderedImage(i); 
        File f = new File("C:\\Final_FAX\\"+dateFormat+ file +i + ".tif"); 
        System.out.println("Saving " + f.getCanonicalPath()); 
        ParameterBlock pb = new ParameterBlock(); 
        pb.addSource(page); 
        pb.add(f.toString()); 
        pb.add("tiff"); 
        pb.add(param); 
        RenderedOp r = JAI.create("filestore",pb); 
        r.dispose(); 
       } 
      } 
      TIFF_Sepreator.infoBox("Find your splitted TIFF images in location 'C:/Final_FAX/' " , "Done :)"); 
      WriteListOFFilesIntoExcel(); 
     } 

     else 
     { 
      TIFF_Sepreator.infoBox("No files was found in location 'C:/FAX/' " , "Empty folder"); 
      System.out.println("No files found"); 
     } 
    } 

    catch(Exception e) 

     { 
      TIFF_Sepreator.infoBox("Unabe to run due to this error: " +e , "Error"); 
      System.out.println("Error: "+e); 
     } 
    } 

public void WriteListOFFilesIntoExcel(){ 

    File[] listOfFiles = folder.listFiles(); 
    ArrayList<File> files = new ArrayList<File>(Arrays.asList(folder.listFiles())); 


    try { 
    String filename = "C:/Final_FAX/List_Of_Fax_Files.xls" ; 
    HSSFWorkbook workbook = new HSSFWorkbook(); 
    HSSFSheet sheet = workbook.createSheet("FirstSheet"); 

    for (int file=0; file<listOfFiles.length; file++) { 
     System.out.println(listOfFiles[file]); 
      Row r = sheet.createRow(file); 
      r.createCell(0).setCellValue(files.get(file).toString()); 
     } 

    FileOutputStream fileOut = new FileOutputStream(filename); 
    workbook.write(fileOut); 
    fileOut.close(); 
    System.out.println("Your excel file has been generated!"); 

    } 
catch(Exception ex){ 
     TIFF_Sepreator.infoBox("Unabe to run due to this error: " +ex , "Error"); 
     System.out.println("Error: "+ex); 
} 
} 
    public static void main(String[] args) throws IOException, AWTException { 
     new TIFF_Sepreator().splitting(); 

    } 
} 
Verwandte Themen