Save This Page
Home » iText-src-2.1.3 » com.lowagie » text » pdf » codec » [javadoc | source]
    1   /*
    2    * Copyright 2003-2005 by Paulo Soares.
    3    *
    4    * The contents of this file are subject to the Mozilla Public License Version 1.1
    5    * (the "License"); you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at http://www.mozilla.org/MPL/
    7    *
    8    * Software distributed under the License is distributed on an "AS IS" basis,
    9    * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
   10    * for the specific language governing rights and limitations under the License.
   11    *
   12    * The Original Code is 'iText, a free JAVA-PDF library'.
   13    *
   14    * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
   15    * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
   16    * All Rights Reserved.
   17    * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
   18    * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
   19    *
   20    * Contributor(s): all the names of the contributors are added in the source code
   21    * where applicable.
   22    *
   23    * Alternatively, the contents of this file may be used under the terms of the
   24    * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
   25    * provisions of LGPL are applicable instead of those above.  If you wish to
   26    * allow use of your version of this file only under the terms of the LGPL
   27    * License and not to allow others to use your version of this file under
   28    * the MPL, indicate your decision by deleting the provisions above and
   29    * replace them with the notice and other provisions required by the LGPL.
   30    * If you do not delete the provisions above, a recipient may use your version
   31    * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
   32    *
   33    * This library is free software; you can redistribute it and/or modify it
   34    * under the terms of the MPL as stated above or under the terms of the GNU
   35    * Library General Public License as published by the Free Software Foundation;
   36    * either version 2 of the License, or any later version.
   37    *
   38    * This library is distributed in the hope that it will be useful, but WITHOUT
   39    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   40    * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
   41    * details.
   42    *
   43    * If you didn't download this code from the following link, you should check if
   44    * you aren't using an obsolete version:
   45    * http://www.lowagie.com/iText/
   46    */
   47   package com.lowagie.text.pdf.codec;
   48   import java.awt.color.ICC_Profile;
   49   import java.io.ByteArrayOutputStream;
   50   import java.io.IOException;
   51   import java.util.zip.DataFormatException;
   52   import java.util.zip.DeflaterOutputStream;
   53   import java.util.zip.Inflater;
   54   
   55   import com.lowagie.text.ExceptionConverter;
   56   import com.lowagie.text.Image;
   57   import com.lowagie.text.Jpeg;
   58   import com.lowagie.text.pdf.PdfArray;
   59   import com.lowagie.text.pdf.PdfDictionary;
   60   import com.lowagie.text.pdf.PdfName;
   61   import com.lowagie.text.pdf.PdfNumber;
   62   import com.lowagie.text.pdf.PdfString;
   63   import com.lowagie.text.pdf.RandomAccessFileOrArray;
   64   
   65   /** Reads TIFF images
   66    * @author Paulo Soares (psoares@consiste.pt)
   67    */
   68   public class TiffImage {
   69       
   70       /** Gets the number of pages the TIFF document has.
   71        * @param s the file source
   72        * @return the number of pages
   73        */    
   74       public static int getNumberOfPages(RandomAccessFileOrArray s) {
   75           try {
   76               return TIFFDirectory.getNumDirectories(s);
   77           }
   78           catch (Exception e) {
   79               throw new ExceptionConverter(e);
   80           }
   81       }
   82   
   83       static int getDpi(TIFFField fd, int resolutionUnit) {
   84           if (fd == null)
   85               return 0;
   86           long res[] = fd.getAsRational(0);
   87           float frac = (float)res[0] / (float)res[1];
   88           int dpi = 0;
   89           switch (resolutionUnit) {
   90               case TIFFConstants.RESUNIT_INCH:
   91               case TIFFConstants.RESUNIT_NONE:
   92                   dpi = (int)(frac + 0.5);
   93                   break;
   94               case TIFFConstants.RESUNIT_CENTIMETER:
   95                   dpi = (int)(frac * 2.54 + 0.5);
   96                   break;
   97           }
   98           return dpi;
   99       }
  100       
  101       /** Reads a page from a TIFF image. Direct mode is not used.
  102        * @param s the file source
  103        * @param page the page to get. The first page is 1
  104        * @return the <CODE>Image</CODE>
  105        */    
  106       public static Image getTiffImage(RandomAccessFileOrArray s, int page) {
  107           return getTiffImage(s, page, false);
  108       }
  109       
  110       /** Reads a page from a TIFF image.
  111        * @param s the file source
  112        * @param page the page to get. The first page is 1
  113        * @param direct for single strip, CCITT images, generate the image
  114        * by direct byte copying. It's faster but may not work
  115        * every time
  116        * @return the <CODE>Image</CODE>
  117        */    
  118       public static Image getTiffImage(RandomAccessFileOrArray s, int page, boolean direct) {
  119           if (page < 1)
  120               throw new IllegalArgumentException("The page number must be >= 1.");
  121           try {
  122               TIFFDirectory dir = new TIFFDirectory(s, page - 1);
  123               if (dir.isTagPresent(TIFFConstants.TIFFTAG_TILEWIDTH))
  124                   throw new IllegalArgumentException("Tiles are not supported.");
  125               int compression = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_COMPRESSION);
  126               switch (compression) {
  127                   case TIFFConstants.COMPRESSION_CCITTRLEW:
  128                   case TIFFConstants.COMPRESSION_CCITTRLE:
  129                   case TIFFConstants.COMPRESSION_CCITTFAX3:
  130                   case TIFFConstants.COMPRESSION_CCITTFAX4:
  131                       break;
  132                   default:
  133                       return getTiffImageColor(dir, s);
  134               }
  135               float rotation = 0;
  136               if (dir.isTagPresent(TIFFConstants.TIFFTAG_ORIENTATION)) {
  137                   int rot = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_ORIENTATION);
  138                   if (rot == TIFFConstants.ORIENTATION_BOTRIGHT || rot == TIFFConstants.ORIENTATION_BOTLEFT)
  139                       rotation = (float)Math.PI;
  140                   else if (rot == TIFFConstants.ORIENTATION_LEFTTOP || rot == TIFFConstants.ORIENTATION_LEFTBOT)
  141                       rotation = (float)(Math.PI / 2.0);
  142                   else if (rot == TIFFConstants.ORIENTATION_RIGHTTOP || rot == TIFFConstants.ORIENTATION_RIGHTBOT)
  143                       rotation = -(float)(Math.PI / 2.0);
  144               }
  145   
  146               Image img = null;
  147               long tiffT4Options = 0;
  148               long tiffT6Options = 0;
  149               int fillOrder = 1;
  150               int h = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_IMAGELENGTH);
  151               int w = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_IMAGEWIDTH);
  152               int dpiX = 0;
  153               int dpiY = 0;
  154               float XYRatio = 0;
  155               int resolutionUnit = TIFFConstants.RESUNIT_INCH;
  156               if (dir.isTagPresent(TIFFConstants.TIFFTAG_RESOLUTIONUNIT))
  157                   resolutionUnit = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_RESOLUTIONUNIT);
  158               dpiX = getDpi(dir.getField(TIFFConstants.TIFFTAG_XRESOLUTION), resolutionUnit);
  159               dpiY = getDpi(dir.getField(TIFFConstants.TIFFTAG_YRESOLUTION), resolutionUnit);
  160               if (resolutionUnit == TIFFConstants.RESUNIT_NONE) {
  161                   if (dpiY != 0)
  162                       XYRatio = (float)dpiX / (float)dpiY;
  163                   dpiX = 0;
  164                   dpiY = 0;
  165               }
  166               int rowsStrip = h;
  167               if (dir.isTagPresent(TIFFConstants.TIFFTAG_ROWSPERSTRIP))
  168                   rowsStrip = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_ROWSPERSTRIP);
  169               if (rowsStrip <= 0 || rowsStrip > h)
  170                   rowsStrip = h;
  171               long offset[] = getArrayLongShort(dir, TIFFConstants.TIFFTAG_STRIPOFFSETS);
  172               long size[] = getArrayLongShort(dir, TIFFConstants.TIFFTAG_STRIPBYTECOUNTS);
  173               if ((size == null || (size.length == 1 && (size[0] == 0 || size[0] + offset[0] > s.length()))) && h == rowsStrip) { // some TIFF producers are really lousy, so...
  174                   size = new long[]{s.length() - (int)offset[0]};
  175               }
  176               boolean reverse = false;
  177               TIFFField fillOrderField =  dir.getField(TIFFConstants.TIFFTAG_FILLORDER);
  178               if (fillOrderField != null)
  179                   fillOrder = fillOrderField.getAsInt(0);
  180               reverse = (fillOrder == TIFFConstants.FILLORDER_LSB2MSB);
  181               int params = 0;
  182               if (dir.isTagPresent(TIFFConstants.TIFFTAG_PHOTOMETRIC)) {
  183                   long photo = dir.getFieldAsLong(TIFFConstants.TIFFTAG_PHOTOMETRIC);
  184                   if (photo == TIFFConstants.PHOTOMETRIC_MINISBLACK)
  185                       params |= Image.CCITT_BLACKIS1;
  186               }
  187               int imagecomp = 0;
  188               switch (compression) {
  189                   case TIFFConstants.COMPRESSION_CCITTRLEW:
  190                   case TIFFConstants.COMPRESSION_CCITTRLE:
  191                       imagecomp = Image.CCITTG3_1D;
  192                       params |= Image.CCITT_ENCODEDBYTEALIGN | Image.CCITT_ENDOFBLOCK;
  193                       break;
  194                   case TIFFConstants.COMPRESSION_CCITTFAX3:
  195                       imagecomp = Image.CCITTG3_1D;
  196                       params |= Image.CCITT_ENDOFLINE | Image.CCITT_ENDOFBLOCK;
  197                       TIFFField t4OptionsField = dir.getField(TIFFConstants.TIFFTAG_GROUP3OPTIONS);
  198                       if (t4OptionsField != null) {
  199                           tiffT4Options = t4OptionsField.getAsLong(0);
  200                       if ((tiffT4Options & TIFFConstants.GROUP3OPT_2DENCODING) != 0)
  201                           imagecomp = Image.CCITTG3_2D;
  202                       if ((tiffT4Options & TIFFConstants.GROUP3OPT_FILLBITS) != 0)
  203                           params |= Image.CCITT_ENCODEDBYTEALIGN;
  204                       }
  205                       break;
  206                   case TIFFConstants.COMPRESSION_CCITTFAX4:
  207                       imagecomp = Image.CCITTG4;
  208                       TIFFField t6OptionsField = dir.getField(TIFFConstants.TIFFTAG_GROUP4OPTIONS);
  209                       if (t6OptionsField != null)
  210                           tiffT6Options = t6OptionsField.getAsLong(0);
  211                       break;
  212               }
  213               if (direct && rowsStrip == h) { //single strip, direct
  214                   byte im[] = new byte[(int)size[0]];
  215                   s.seek(offset[0]);
  216                   s.readFully(im);
  217                   img = Image.getInstance(w, h, false, imagecomp, params, im);
  218                   img.setInverted(true);
  219               }
  220               else {
  221                   int rowsLeft = h;
  222                   CCITTG4Encoder g4 = new CCITTG4Encoder(w);
  223                   for (int k = 0; k < offset.length; ++k) {
  224                       byte im[] = new byte[(int)size[k]];
  225                       s.seek(offset[k]);
  226                       s.readFully(im);
  227                       int height = Math.min(rowsStrip, rowsLeft);
  228                       TIFFFaxDecoder decoder = new TIFFFaxDecoder(fillOrder, w, height);
  229                       byte outBuf[] = new byte[(w + 7) / 8 * height];
  230                       switch (compression) {
  231                           case TIFFConstants.COMPRESSION_CCITTRLEW:
  232                           case TIFFConstants.COMPRESSION_CCITTRLE:
  233                               decoder.decode1D(outBuf, im, 0, height);
  234                               g4.fax4Encode(outBuf,height);
  235                               break;
  236                           case TIFFConstants.COMPRESSION_CCITTFAX3:
  237                               try {
  238                                   decoder.decode2D(outBuf, im, 0, height, tiffT4Options);
  239                               }
  240                               catch (RuntimeException e) {
  241                                   // let's flip the fill bits and try again...
  242                                   tiffT4Options ^= TIFFConstants.GROUP3OPT_FILLBITS;
  243                                   try {
  244                                       decoder.decode2D(outBuf, im, 0, height, tiffT4Options);
  245                                   }
  246                                   catch (RuntimeException e2) {
  247                                       throw e;
  248                                   }
  249                               }
  250                               g4.fax4Encode(outBuf, height);
  251                               break;
  252                           case TIFFConstants.COMPRESSION_CCITTFAX4:
  253                               decoder.decodeT6(outBuf, im, 0, height, tiffT6Options);
  254                               g4.fax4Encode(outBuf, height);
  255                               break;
  256                       }
  257                       rowsLeft -= rowsStrip;
  258                   }
  259                   byte g4pic[] = g4.close();
  260                   img = Image.getInstance(w, h, false, Image.CCITTG4, params & Image.CCITT_BLACKIS1, g4pic);
  261               }
  262               img.setDpi(dpiX, dpiY);
  263               img.setXYRatio(XYRatio);
  264               if (dir.isTagPresent(TIFFConstants.TIFFTAG_ICCPROFILE)) {
  265                   try {
  266                       TIFFField fd = dir.getField(TIFFConstants.TIFFTAG_ICCPROFILE);
  267                       ICC_Profile icc_prof = ICC_Profile.getInstance(fd.getAsBytes());
  268                       if (icc_prof.getNumComponents() == 1)
  269                           img.tagICC(icc_prof);
  270                   }
  271                   catch (RuntimeException e) {
  272                       //empty
  273                   }
  274               }
  275               img.setOriginalType(Image.ORIGINAL_TIFF);
  276               if (rotation != 0)
  277                   img.setInitialRotation(rotation);
  278               return img;
  279           }
  280           catch (Exception e) {
  281               throw new ExceptionConverter(e);
  282           }
  283       }
  284       
  285       protected static Image getTiffImageColor(TIFFDirectory dir, RandomAccessFileOrArray s) {
  286           try {
  287               int compression = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_COMPRESSION);
  288               int predictor = 1;
  289               TIFFLZWDecoder lzwDecoder = null;
  290               switch (compression) {
  291                   case TIFFConstants.COMPRESSION_NONE:
  292                   case TIFFConstants.COMPRESSION_LZW:
  293                   case TIFFConstants.COMPRESSION_PACKBITS:
  294                   case TIFFConstants.COMPRESSION_DEFLATE:
  295                   case TIFFConstants.COMPRESSION_ADOBE_DEFLATE:
  296                   case TIFFConstants.COMPRESSION_OJPEG:
  297                   case TIFFConstants.COMPRESSION_JPEG:
  298                       break;
  299                   default:
  300                       throw new IllegalArgumentException("The compression " + compression + " is not supported.");
  301               }
  302               int photometric = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_PHOTOMETRIC);
  303               switch (photometric) {
  304                   case TIFFConstants.PHOTOMETRIC_MINISWHITE:
  305                   case TIFFConstants.PHOTOMETRIC_MINISBLACK:
  306                   case TIFFConstants.PHOTOMETRIC_RGB:
  307                   case TIFFConstants.PHOTOMETRIC_SEPARATED:
  308                   case TIFFConstants.PHOTOMETRIC_PALETTE:
  309                       break;
  310                   default:
  311                       if (compression != TIFFConstants.COMPRESSION_OJPEG && compression != TIFFConstants.COMPRESSION_JPEG)
  312                           throw new IllegalArgumentException("The photometric " + photometric + " is not supported.");
  313               }
  314               float rotation = 0;
  315               if (dir.isTagPresent(TIFFConstants.TIFFTAG_ORIENTATION)) {
  316                   int rot = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_ORIENTATION);
  317                   if (rot == TIFFConstants.ORIENTATION_BOTRIGHT || rot == TIFFConstants.ORIENTATION_BOTLEFT)
  318                       rotation = (float)Math.PI;
  319                   else if (rot == TIFFConstants.ORIENTATION_LEFTTOP || rot == TIFFConstants.ORIENTATION_LEFTBOT)
  320                       rotation = (float)(Math.PI / 2.0);
  321                   else if (rot == TIFFConstants.ORIENTATION_RIGHTTOP || rot == TIFFConstants.ORIENTATION_RIGHTBOT)
  322                       rotation = -(float)(Math.PI / 2.0);
  323               }
  324               if (dir.isTagPresent(TIFFConstants.TIFFTAG_PLANARCONFIG)
  325                   && dir.getFieldAsLong(TIFFConstants.TIFFTAG_PLANARCONFIG) == TIFFConstants.PLANARCONFIG_SEPARATE)
  326                   throw new IllegalArgumentException("Planar images are not supported.");
  327               if (dir.isTagPresent(TIFFConstants.TIFFTAG_EXTRASAMPLES))
  328                   throw new IllegalArgumentException("Extra samples are not supported.");
  329               int samplePerPixel = 1;
  330               if (dir.isTagPresent(TIFFConstants.TIFFTAG_SAMPLESPERPIXEL)) // 1,3,4
  331                   samplePerPixel = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_SAMPLESPERPIXEL);
  332               int bitsPerSample = 1;
  333               if (dir.isTagPresent(TIFFConstants.TIFFTAG_BITSPERSAMPLE))
  334                   bitsPerSample = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_BITSPERSAMPLE);
  335               switch (bitsPerSample) {
  336                   case 1:
  337                   case 2:
  338                   case 4:
  339                   case 8:
  340                       break;
  341                   default:
  342                       throw new IllegalArgumentException("Bits per sample " + bitsPerSample + " is not supported.");
  343               }
  344               Image img = null;
  345   
  346               int h = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_IMAGELENGTH);
  347               int w = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_IMAGEWIDTH);
  348               int dpiX = 0;
  349               int dpiY = 0;
  350               int resolutionUnit = TIFFConstants.RESUNIT_INCH;
  351               if (dir.isTagPresent(TIFFConstants.TIFFTAG_RESOLUTIONUNIT))
  352                   resolutionUnit = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_RESOLUTIONUNIT);
  353               dpiX = getDpi(dir.getField(TIFFConstants.TIFFTAG_XRESOLUTION), resolutionUnit);
  354               dpiY = getDpi(dir.getField(TIFFConstants.TIFFTAG_YRESOLUTION), resolutionUnit);
  355               int fillOrder = 1;
  356               boolean reverse = false;
  357               TIFFField fillOrderField =  dir.getField(TIFFConstants.TIFFTAG_FILLORDER);
  358               if (fillOrderField != null)
  359                   fillOrder = fillOrderField.getAsInt(0);
  360               reverse = (fillOrder == TIFFConstants.FILLORDER_LSB2MSB);
  361               int rowsStrip = h;
  362               if (dir.isTagPresent(TIFFConstants.TIFFTAG_ROWSPERSTRIP)) //another hack for broken tiffs
  363                   rowsStrip = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_ROWSPERSTRIP);
  364               if (rowsStrip <= 0 || rowsStrip > h)
  365                   rowsStrip = h;
  366               long offset[] = getArrayLongShort(dir, TIFFConstants.TIFFTAG_STRIPOFFSETS);
  367               long size[] = getArrayLongShort(dir, TIFFConstants.TIFFTAG_STRIPBYTECOUNTS);
  368               if ((size == null || (size.length == 1 && (size[0] == 0 || size[0] + offset[0] > s.length()))) && h == rowsStrip) { // some TIFF producers are really lousy, so...
  369                   size = new long[]{s.length() - (int)offset[0]};
  370               }
  371               if (compression == TIFFConstants.COMPRESSION_LZW) {
  372                   TIFFField predictorField = dir.getField(TIFFConstants.TIFFTAG_PREDICTOR);
  373                   if (predictorField != null) {
  374                       predictor = predictorField.getAsInt(0);
  375                       if (predictor != 1 && predictor != 2) {
  376                           throw new RuntimeException("Illegal value for Predictor in TIFF file."); 
  377                       }
  378                       if (predictor == 2 && bitsPerSample != 8) {
  379                           throw new RuntimeException(bitsPerSample + "-bit samples are not supported for Horizontal differencing Predictor.");
  380                       }
  381                   }
  382                   lzwDecoder = new TIFFLZWDecoder(w, predictor, 
  383                                                   samplePerPixel); 
  384               }
  385               int rowsLeft = h;
  386               ByteArrayOutputStream stream = null;
  387               DeflaterOutputStream zip = null;
  388               CCITTG4Encoder g4 = null;
  389               if (bitsPerSample == 1 && samplePerPixel == 1) {
  390                   g4 = new CCITTG4Encoder(w);
  391               }
  392               else {
  393                   stream = new ByteArrayOutputStream();
  394                   if (compression != TIFFConstants.COMPRESSION_OJPEG && compression != TIFFConstants.COMPRESSION_JPEG)
  395                       zip = new DeflaterOutputStream(stream);
  396               }
  397               if (compression == TIFFConstants.COMPRESSION_OJPEG) {
  398                   
  399                   // Assume that the TIFFTAG_JPEGIFBYTECOUNT tag is optional, since it's obsolete and 
  400                   // is often missing
  401   
  402                   if ((!dir.isTagPresent(TIFFConstants.TIFFTAG_JPEGIFOFFSET))) {
  403                       throw new IOException("Missing tag(s) for OJPEG compression.");
  404                   }
  405                   int jpegOffset = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_JPEGIFOFFSET);
  406                   int jpegLength = s.length() - jpegOffset;
  407   
  408                   if (dir.isTagPresent(TIFFConstants.TIFFTAG_JPEGIFBYTECOUNT)) {
  409                       jpegLength = (int)dir.getFieldAsLong(TIFFConstants.TIFFTAG_JPEGIFBYTECOUNT) +
  410                           (int)size[0];
  411                   }
  412                   
  413                   byte[] jpeg = new byte[Math.min(jpegLength, s.length() - jpegOffset)];
  414   
  415                   int posFilePointer = s.getFilePointer();
  416                   posFilePointer += jpegOffset;
  417                   s.seek(posFilePointer);
  418                   s.readFully(jpeg);
  419                   img = new Jpeg(jpeg);
  420               } 
  421               else if (compression == TIFFConstants.COMPRESSION_JPEG) {
  422                   if (size.length > 1)
  423                       throw new IOException("Compression JPEG is only supported with a single strip. This image has " + size.length + " strips.");
  424                   byte[] jpeg = new byte[(int)size[0]];
  425                   s.seek(offset[0]);
  426                   s.readFully(jpeg);
  427                   img = new Jpeg(jpeg);
  428               } 
  429               else {
  430                   for (int k = 0; k < offset.length; ++k) {
  431                       byte im[] = new byte[(int)size[k]];
  432                       s.seek(offset[k]);
  433                       s.readFully(im);
  434                       int height = Math.min(rowsStrip, rowsLeft);
  435                       byte outBuf[] = null;
  436                       if (compression != TIFFConstants.COMPRESSION_NONE)
  437                           outBuf = new byte[(w * bitsPerSample * samplePerPixel + 7) / 8 * height];
  438                       if (reverse)
  439                           TIFFFaxDecoder.reverseBits(im);
  440                       switch (compression) {
  441                           case TIFFConstants.COMPRESSION_DEFLATE:
  442                           case TIFFConstants.COMPRESSION_ADOBE_DEFLATE:
  443                               inflate(im, outBuf);
  444                               break;
  445                           case TIFFConstants.COMPRESSION_NONE:
  446                               outBuf = im;
  447                               break;
  448                           case TIFFConstants.COMPRESSION_PACKBITS:
  449                               decodePackbits(im,  outBuf);
  450                               break;
  451                           case TIFFConstants.COMPRESSION_LZW:
  452                               lzwDecoder.decode(im, outBuf, height);
  453                               break;
  454                       }
  455                       if (bitsPerSample == 1 && samplePerPixel == 1) {
  456                           g4.fax4Encode(outBuf, height);
  457                       }
  458                       else {
  459                           zip.write(outBuf);
  460                       }
  461                       rowsLeft -= rowsStrip;
  462                   }
  463                   if (bitsPerSample == 1 && samplePerPixel == 1) {
  464                       img = Image.getInstance(w, h, false, Image.CCITTG4, 
  465                           photometric == TIFFConstants.PHOTOMETRIC_MINISBLACK ? Image.CCITT_BLACKIS1 : 0, g4.close());
  466                   }
  467                   else {
  468                       zip.close();
  469                       img = Image.getInstance(w, h, samplePerPixel, bitsPerSample, stream.toByteArray());
  470                       img.setDeflated(true);
  471                   }
  472               }
  473               img.setDpi(dpiX, dpiY);
  474               if (compression != TIFFConstants.COMPRESSION_OJPEG && compression != TIFFConstants.COMPRESSION_JPEG) {
  475                   if (dir.isTagPresent(TIFFConstants.TIFFTAG_ICCPROFILE)) {
  476                       try {
  477                           TIFFField fd = dir.getField(TIFFConstants.TIFFTAG_ICCPROFILE);
  478                           ICC_Profile icc_prof = ICC_Profile.getInstance(fd.getAsBytes());
  479                           if (samplePerPixel == icc_prof.getNumComponents())
  480                               img.tagICC(icc_prof);
  481                       }
  482                       catch (RuntimeException e) {
  483                           //empty
  484                       }
  485                   }
  486                   if (dir.isTagPresent(TIFFConstants.TIFFTAG_COLORMAP)) {
  487                       TIFFField fd = dir.getField(TIFFConstants.TIFFTAG_COLORMAP);
  488                       char rgb[] = fd.getAsChars();
  489                       byte palette[] = new byte[rgb.length];
  490                       int gColor = rgb.length / 3;
  491                       int bColor = gColor * 2;
  492                       for (int k = 0; k < gColor; ++k) {
  493                           palette[k * 3] = (byte)(rgb[k] >>> 8);
  494                           palette[k * 3 + 1] = (byte)(rgb[k + gColor] >>> 8);
  495                           palette[k * 3 + 2] = (byte)(rgb[k + bColor] >>> 8);
  496                       }
  497                       PdfArray indexed = new PdfArray();
  498                       indexed.add(PdfName.INDEXED);
  499                       indexed.add(PdfName.DEVICERGB);
  500                       indexed.add(new PdfNumber(gColor - 1));
  501                       indexed.add(new PdfString(palette));
  502                       PdfDictionary additional = new PdfDictionary();
  503                       additional.put(PdfName.COLORSPACE, indexed);
  504                       img.setAdditional(additional);
  505                   }
  506                   img.setOriginalType(Image.ORIGINAL_TIFF);
  507               }
  508               if (photometric == TIFFConstants.PHOTOMETRIC_MINISWHITE)
  509                   img.setInverted(true);
  510               if (rotation != 0)
  511                   img.setInitialRotation(rotation);
  512               return img;
  513           }
  514           catch (Exception e) {
  515               throw new ExceptionConverter(e);
  516           }
  517       }
  518       
  519       static long[] getArrayLongShort(TIFFDirectory dir, int tag) {
  520           TIFFField field = dir.getField(tag);
  521           if (field == null)
  522               return null;
  523           long offset[];
  524           if (field.getType() == TIFFField.TIFF_LONG)
  525               offset = field.getAsLongs();
  526           else { // must be short
  527               char temp[] = field.getAsChars();
  528               offset = new long[temp.length];
  529               for (int k = 0; k < temp.length; ++k)
  530                   offset[k] = temp[k];
  531           }
  532           return offset;
  533       }
  534       
  535       // Uncompress packbits compressed image data.
  536       public static void decodePackbits(byte data[], byte[] dst) {
  537           int srcCount = 0, dstCount = 0;
  538           byte repeat, b;
  539           
  540           try {
  541               while (dstCount < dst.length) {
  542                   b = data[srcCount++];
  543                   if (b >= 0 && b <= 127) {
  544                       // literal run packet
  545                       for (int i=0; i<(b + 1); i++) {
  546                           dst[dstCount++] = data[srcCount++];
  547                       }
  548   
  549                   } else if (b <= -1 && b >= -127) {
  550                       // 2 byte encoded run packet
  551                       repeat = data[srcCount++];
  552                       for (int i=0; i<(-b + 1); i++) {
  553                           dst[dstCount++] = repeat;
  554                       }
  555                   } else {
  556                       // no-op packet. Do nothing
  557                       srcCount++;
  558                   }
  559               }
  560           }
  561           catch (Exception e) {
  562               // do nothing
  563           }
  564       }
  565   
  566       public static void inflate(byte[] deflated, byte[] inflated) {
  567           Inflater inflater = new Inflater();
  568           inflater.setInput(deflated);
  569           try {
  570               inflater.inflate(inflated);
  571           }
  572           catch(DataFormatException dfe) {
  573               throw new ExceptionConverter(dfe);
  574           }
  575       }
  576   
  577   }

Save This Page
Home » iText-src-2.1.3 » com.lowagie » text » pdf » codec » [javadoc | source]