1   package ch.ige.edossier.util;
2   
3   import java.io.ByteArrayInputStream;
4   import java.io.IOException;
5   import java.util.HashMap;
6   import java.util.Map;
7   import java.awt.image.RenderedImage;
8   import org.apache.log4j.Logger;
9   import com.sun.media.jai.codec.*;
10  import com.sun.media.jai.codecimpl.TIFFImageDecoder;
11  
12  /**
13   * B32.03 - eDossier-Interceptions - Diplomarbeit an der Software-Schule Schweiz<br>
14   * MUSS-ZIEL [M4] - Detail-Dossier (Pflichtenheft b32.03_PF_eDossier.pdf, Seite 16)<br>
15   * KANN-ZIEL [K6] - Attachement (Pflichtenheft b32.03_PF_eDossier.pdf, Seite 17)<br>
16   * Implementierung der ImageWriter-Klasse für TIFF-Bilder
17   * <p>
18   * Copyright (c) 2004, Eidgenössisches Institut für Geistiges Eigentum
19   * @author    Johannes Lang
20   * @version   $Id: TIFFImageWriter.java,v 1.2 2004/11/01 14:18:27 bouquet Exp $
21   */
22  public class TIFFImageWriter extends ImageWriter
23  {
24    // Attribute für Log4j-Logging
25    private static final Logger LOG = Logger.getLogger( TIFFImageWriter.class );
26  
27    /**
28     * Standard-Konstruktor
29     */
30    public TIFFImageWriter()
31    {}
32  
33    /**
34     * @param outputPath = Pfad der zu Schreibenden TIFF-Datei
35     * @param image byte[] Bild als byte-Array
36     * @return dimensions Map mit den Parameterwerten zum Bild
37     * @throws IOException Unerwarteter IO-Fehler
38     */
39    public Map processImage( String outputPath, byte[] image ) throws IOException
40    {
41      processTIFFImage( image, outputPath );
42      Map dimensions = new HashMap();
43      dimensions.put( "width", String.valueOf( this.imageWidthInPixel ) );
44      dimensions.put( "height", String.valueOf( this.imageHeigthInPixel ) );
45      return dimensions;
46    }
47  
48    private void processTIFFImage( byte[] image, String path ) throws IOException
49    {
50      MemoryCacheSeekableStream memSeekStream = new MemoryCacheSeekableStream( new ByteArrayInputStream( image ) );
51      extractImageSize( memSeekStream );
52      extractDensity( memSeekStream );
53      String tiffPath = path.substring( 0, path.length() - 3 ) + "tiff";
54      writeToFile( image, tiffPath );
55      callServlet( tiffPath, "tiff" );
56      memSeekStream = null;
57    }
58  
59    /**
60     * Decodierung des Tiff-Bildes und Ermittlung der Grössen in Pixel
61     * @param memSeekStream MemoryCacheSeekableStream
62     * @throws IOException Möglich aus decodeAsRenderedImage
63     */
64    private void extractImageSize( MemoryCacheSeekableStream memSeekStream ) throws IOException
65    {
66      TIFFDecodeParam tiffparam = new TIFFDecodeParam();
67      ImageCodec imCodec = ImageCodec.getCodec( "tiff" );
68      ImageDecoderImpl imDecoder = ( ImageDecoderImpl )imCodec.createImageDecoder( "tiff", memSeekStream, tiffparam );
69      RenderedImage renderedImage = imDecoder.decodeAsRenderedImage();
70      imageHeigthInPixel = renderedImage.getHeight();
71      imageWidthInPixel = renderedImage.getWidth();
72    }
73  
74    /**
75     * Via Tiff-Directory und den ermittelten Tiff-Feldern werden die x und y
76     * Auflösung des ersten (= 0) Tiffbildes innerhalb einer Tiff-Datei ermittelt.
77     * @param memSeekStream MemoryCacheSeekableStream
78     * @throws IOException Unerwarteter IO-Fehler
79     */
80    private void extractDensity( MemoryCacheSeekableStream memSeekStream ) throws IOException
81    {
82      TIFFDirectory tiffDirectory = new TIFFDirectory( memSeekStream, 0 );
83      TIFFField res_Unit = tiffDirectory.getField( TIFFImageDecoder.TIFF_RESOLUTION_UNIT );
84      xDensity = getDensity( tiffDirectory.getField( TIFFImageDecoder.TIFF_X_RESOLUTION ), res_Unit.getAsInt( 0 ) );
85      yDensity = getDensity( tiffDirectory.getField( TIFFImageDecoder.TIFF_Y_RESOLUTION ), res_Unit.getAsInt( 0 ) );
86    }
87  
88    /**
89     * Aus den Tiff-Feldern 282 und 283 werden die Auflösungsdaten ausgelesen
90     * @param xDensityField Tiff-Feld
91     * @param resolution_unit int
92     * @return int Auflösung
93     */
94    private int getDensity( TIFFField xDensityField, int resolution_unit )
95    {
96      try
97      {
98        long[] arr = xDensityField.getAsRational( 0 );
99        int a = new Long( arr[ 0 ] ).intValue();
100       int b = new Long( arr[ 1 ] ).intValue();
101       if( b != 0 )
102       {
103         int rel = ( int ) ( a / b );
104         switch( resolution_unit )
105         {
106           case 3: // Auflösung in pixel pro Centimeter --> Umrechnen in pixel pro Inch
107             return( int ) ( rel * this.CONVERSION_DPCM_TO_DPI );
108           case 2: // Auflösung in pixel pro Inch
109             return rel;
110           default:
111             return rel;
112         }
113       }
114       else
115       {
116         return 0;
117       }
118     }
119     catch( Exception ex )
120     {
121       LOG.error( "Auflösungsdaten des TIFF können nicht gelesen werden: " + ex.getMessage() );
122       return 0;
123     }
124   }
125 
126 }
127