Package com.lightcrafts.media.jai.codec

Examples of com.lightcrafts.media.jai.codec.TIFFDirectory


  }

  decodePaletteAsShorts = param.getDecodePaletteAsShorts();

        // Read the specified directory.
        TIFFDirectory dir = param.getIFDOffset() == null ?
            new TIFFDirectory(stream, directory) :
            new TIFFDirectory(stream, param.getIFDOffset().longValue(),
                              directory);

        // Set a property "tiff_directory".
        properties.put("tiff_directory", dir);

  // Get the number of samples per pixel
  TIFFField sfield =
      dir.getField(TIFFImageDecoder.TIFF_SAMPLES_PER_PIXEL);
        int samplesPerPixel = sfield == null ? 1 : (int)sfield.getAsLong(0);

  // Read the TIFF_PLANAR_CONFIGURATION field
  TIFFField planarConfigurationField =
      dir.getField(TIFFImageDecoder.TIFF_PLANAR_CONFIGURATION);
  char[] planarConfiguration = planarConfigurationField == null ?
            new char[] {1} :
            planarConfigurationField.getAsChars();

        // Support planar format (band sequential) only for 1 sample/pixel.
        if (planarConfiguration[0] != 1 && samplesPerPixel != 1) {
            throw new RuntimeException(JaiI18N.getString("TIFFImage0"));
        }

  // Read the TIFF_BITS_PER_SAMPLE field
  TIFFField bitsField =
      dir.getField(TIFFImageDecoder.TIFF_BITS_PER_SAMPLE);
        char[] bitsPerSample = null;
        if(bitsField != null) {
            bitsPerSample = bitsField.getAsChars();
        } else {
            bitsPerSample = new char[] {1};

            // Ensure that all samples have the same bit depth.
            for (int i = 1; i < bitsPerSample.length; i++) {
                if (bitsPerSample[i] != bitsPerSample[0]) {
                    throw new RuntimeException(
               JaiI18N.getString("TIFFImage1"));
                }
            }
        }
        sampleSize = (int)bitsPerSample[0];

  // Read the TIFF_SAMPLE_FORMAT tag to see whether the data might be
  // signed or floating point
  TIFFField sampleFormatField =
      dir.getField(TIFFImageDecoder.TIFF_SAMPLE_FORMAT);

        char[] sampleFormat = null;
  if (sampleFormatField != null) {
      sampleFormat = sampleFormatField.getAsChars();

      // Check that all the samples have the same format
      for (int l=1; l<sampleFormat.length; l++) {
    if (sampleFormat[l] != sampleFormat[0]) {
        throw new RuntimeException(
               JaiI18N.getString("TIFFImage2"));
    }
      }

  } else {
      sampleFormat = new char[] {1};
  }

        // Set the data type based on the sample size and format.
        boolean isValidDataFormat = false;
        switch(sampleSize) {
        case 1:
        case 4:
        case 8:
            if(sampleFormat[0] != 3) {
                // Ignore whether signed or unsigned: treat all as unsigned.
    dataType = DataBuffer.TYPE_BYTE;
                isValidDataFormat = true;
            }
            break;
        case 16:
            if(sampleFormat[0] != 3) {
                dataType = sampleFormat[0] == 2 ?
                    DataBuffer.TYPE_SHORT : DataBuffer.TYPE_USHORT;
                isValidDataFormat = true;
            }
            break;
        case 32:
            dataType = sampleFormat[0] == 3 ?
                DataBuffer.TYPE_FLOAT : DataBuffer.TYPE_INT;
            isValidDataFormat = true;
            break;
        }

        if(!isValidDataFormat) {
            throw new RuntimeException(JaiI18N.getString("TIFFImage3"));
        }

  // Figure out what compression if any, is being used.
  TIFFField compField = dir.getField(TIFFImageDecoder.TIFF_COMPRESSION);
        compression = compField == null ? COMP_NONE : compField.getAsInt(0);

        // Get the photometric interpretation field.
        TIFFField photoInterpField =
            dir.getField(TIFFImageDecoder.TIFF_PHOTOMETRIC_INTERPRETATION);

        // Set the photometric interpretation variable.
        int photometricType;
        if(photoInterpField != null) {
            // Set the variable from the photometric interpretation field.
            photometricType = (int)photoInterpField.getAsLong(0);
        } else {
            // The photometric interpretation field is missing; attempt
            // to infer the type from other information.
            if(dir.getField(TIFFImageDecoder.TIFF_COLORMAP) != null) {
                // There is a colormap so most likely a palette color image.
                photometricType = 3; // RGB Palette
            } else if(sampleSize == 1) {
                // Bilevel image so most likely a document; switch based
                // on the compression type of the image.
                if(compression == COMP_FAX_G3_1D ||
                   compression == COMP_FAX_G3_2D ||
                   compression == COMP_FAX_G4_2D) {
                    photometricType = 0; // WhiteIsZero
                } else {
                    photometricType = 1; // BlackIsZero
                }
            } else if(samplesPerPixel == 3 || samplesPerPixel == 4) {
                // Assume 3 bands is RGB and 4 bands is RGBA.
                photometricType = 2; // RGB
            } else {
                // Default to multi-band grayscale.
                photometricType = 1; // BlackIsZero
            }
        }

        // Determine which kind of image we are dealing with.
        imageType = TYPE_UNSUPPORTED;
  switch(photometricType) {
        case 0: // WhiteIsZero
            isWhiteZero = true;
        case 1: // BlackIsZero
            if(sampleSize == 1 && samplesPerPixel == 1) {
                imageType = TYPE_BILEVEL;
            } else if(sampleSize == 4 && samplesPerPixel == 1) {
                imageType = TYPE_GRAY_4BIT;
            } else if(sampleSize % 8 == 0) {
                if(samplesPerPixel == 1) {
                    imageType = TYPE_GRAY;
                } else if(samplesPerPixel == 2) {
                    imageType = TYPE_GRAY_ALPHA;
                } else {
                    imageType = TYPE_GENERIC;
                }
            }
            break;
        case 2: // RGB
            if(sampleSize % 8 == 0) {
                if(samplesPerPixel == 3) {
                    imageType = TYPE_RGB;
                } else if(samplesPerPixel == 4) {
                    imageType = TYPE_RGB_ALPHA;
                } else {
                    imageType = TYPE_GENERIC;
                }
            }
            break;
        case 3: // RGB Palette
            if(samplesPerPixel == 1 &&
               (sampleSize == 4 || sampleSize == 8 || sampleSize == 16)) {
                imageType = TYPE_PALETTE;
            }
            break;
        case 4: // Transparency mask
            if(sampleSize == 1 && samplesPerPixel == 1) {
                imageType = TYPE_BILEVEL;
            }
            break;
  case 5: // Separated image, usually CMYK
      if (sampleSize == 8 && samplesPerPixel == 4) {
    imageType = TYPE_CMYK;
      }
        case 6: // YCbCr
            if(compression == COMP_JPEG_TTN2 &&
               sampleSize == 8 && samplesPerPixel == 3) {
                // Set color conversion flag.
                colorConvertJPEG = param.getJPEGDecompressYCbCrToRGB();

                // Set type to RGB if color converting.
                imageType = colorConvertJPEG ? TYPE_RGB : TYPE_GENERIC;
            } else {
                TIFFField chromaField = dir.getField(TIFF_YCBCR_SUBSAMPLING);
                if(chromaField != null) {
                    chromaSubH = chromaField.getAsInt(0);
                    chromaSubV = chromaField.getAsInt(1);
                } else {
                    chromaSubH = chromaSubV = 2;
                }

                if(chromaSubH*chromaSubV == 1) {
                    imageType = TYPE_GENERIC;
                } else if(sampleSize == 8 && samplesPerPixel == 3) {
                    imageType = TYPE_YCBCR_SUB;
                }
            }
            break;
        default: // Other including CIE L*a*b*, unknown.
            if(sampleSize % 8 == 0) {
                imageType = TYPE_GENERIC;
            }
        }

        // Bail out if not one of the supported types.
        if(imageType == TYPE_UNSUPPORTED) {
            throw new RuntimeException(JaiI18N.getString("TIFFImage4"));
        }

  // Set basic image layout
        minX = minY = 0;
  width = (int)(getField(dir,
             TIFFImageDecoder.TIFF_IMAGE_WIDTH,
             "Image Width").getAsLong(0));

  height = (int)(getField(dir,
        TIFFImageDecoder.TIFF_IMAGE_LENGTH,
        "Image Length").getAsLong(0));

        // Set a preliminary band count. This may be changed later as needed.
        numBands = samplesPerPixel;

  // Figure out if any extra samples are present.
  TIFFField efield = dir.getField(TIFFImageDecoder.TIFF_EXTRA_SAMPLES);
        int extraSamples = efield == null ? 0 : (int)efield.getAsLong(0);

  if (dir.getField(TIFFImageDecoder.TIFF_TILE_OFFSETS) != null) {
      // Image is in tiled format
            isTiled = true;

            tileWidth = (int)(getField(dir,
               TIFFImageDecoder.TIFF_TILE_WIDTH,
               "Tile Width").getAsLong(0));
      tileHeight = (int)(getField(dir,
          TIFFImageDecoder.TIFF_TILE_LENGTH,
          "Tile Length").getAsLong(0));
      tileOffsets =
    (getField(dir,
       TIFFImageDecoder.TIFF_TILE_OFFSETS,
       "Tile Offsets")).getAsLongs();

      tileByteCounts = getFieldAsLongs(
                 getField(dir,
                          TIFFImageDecoder.TIFF_TILE_BYTE_COUNTS,
                          "Tile Byte Counts"));

        } else {

            // Image is in stripped format, looks like tiles to us
            isTiled = false;

            // Note: Some legacy files may have tile width and height
            // written but use the strip offsets and byte counts fields
            // instead of the tile offsets and byte counts. Therefore
            // we default here to the tile dimensions if they are written.
            tileWidth =
                dir.getField(TIFFImageDecoder.TIFF_TILE_WIDTH) != null ?
                (int)dir.getFieldAsLong(TIFFImageDecoder.TIFF_TILE_WIDTH) :
                width;
      TIFFField field =
                dir.getField(TIFFImageDecoder.TIFF_ROWS_PER_STRIP);
      if (field == null) {
    // Default is infinity (2^32 -1), basically the entire image
    // TODO: Can do a better job of tiling here
    tileHeight =
                    dir.getField(TIFFImageDecoder.TIFF_TILE_LENGTH) != null ?
                    (int)dir.getFieldAsLong(TIFFImageDecoder.TIFF_TILE_LENGTH):
                    height;
      } else {
    long l = field.getAsLong(0);
    long infinity = 1;
    infinity = (infinity << 32) - 1;
    if (l == infinity || l > height) {
        // 2^32 - 1 (effectively infinity, entire image is 1 strip)
                    // or RowsPerStrip > ImageLength so clamp as having a tile
                    // larger than the image is pointless.
        tileHeight = height;
    } else {
        tileHeight = (int)l;
    }
      }

      TIFFField tileOffsetsField =
    getField(dir,
       TIFFImageDecoder.TIFF_STRIP_OFFSETS,
       "Strip Offsets");
      tileOffsets = getFieldAsLongs(tileOffsetsField);

      TIFFField tileByteCountsField =
                dir.getField(TIFFImageDecoder.TIFF_STRIP_BYTE_COUNTS);
            if(tileByteCountsField == null) {
                // Attempt to infer the number of bytes in each strip.
                int totalBytes = ((sampleSize+7)/8)*numBands*width*height;
                int bytesPerStrip =
                    ((sampleSize+7)/8)*numBands*width*tileHeight;
                int cumulativeBytes = 0;
                tileByteCounts = new long[tileOffsets.length];
                for(int i = 0; i < tileOffsets.length; i++) {
                    tileByteCounts[i] =
                        Math.min(totalBytes - cumulativeBytes,
                                 bytesPerStrip);
                    cumulativeBytes += bytesPerStrip;
                }

                if(compression != COMP_NONE) {
                    // Replace the stream with one that will not throw
                    // an EOFException when it runs past the end.
                    this.stream = new NoEOFStream(stream);
                }
            } else {
                tileByteCounts = getFieldAsLongs(tileByteCountsField);
            }

            // Uncompressed image provided in a single tile: clamp to max bytes.
            int maxBytes = width*height*numBands*((sampleSize + 7)/8);
            if(tileByteCounts.length == 1 &&
               compression == COMP_NONE &&
               tileByteCounts[0] > maxBytes) {
                tileByteCounts[0] = maxBytes;
            }
  }

  // Calculate number of tiles and the tileSize in bytes
        tilesX = (width + tileWidth - 1)/tileWidth;
        tilesY = (height + tileHeight - 1)/tileHeight;
        tileSize = tileWidth * tileHeight * numBands;

  // Check whether big endian or little endian format is used.
  isBigEndian = dir.isBigEndian();

  TIFFField fillOrderField =
      dir.getField(TIFFImageDecoder.TIFF_FILL_ORDER);
  if (fillOrderField != null) {
      fillOrder = fillOrderField.getAsInt(0);
  } else {
      // Default Fill Order
      fillOrder = 1;
  }

  switch(compression) {
        case COMP_NONE:
        case COMP_PACKBITS:
            // Do nothing.
            break;
        case COMP_DEFLATE:
            inflater = new Inflater();
            break;
        case COMP_FAX_G3_1D:
        case COMP_FAX_G3_2D:
        case COMP_FAX_G4_2D:
            if(sampleSize != 1) {
                throw new RuntimeException(JaiI18N.getString("TIFFImage7"));
            }

            // Fax T.4 compression options
            if (compression == 3) {
                TIFFField t4OptionsField =
                    dir.getField(TIFFImageDecoder.TIFF_T4_OPTIONS);
                if (t4OptionsField != null) {
                    tiffT4Options = t4OptionsField.getAsLong(0);
                } else {
                    // Use default value
                    tiffT4Options = 0;
                }
            }

            // Fax T.6 compression options
            if (compression == 4) {
                TIFFField t6OptionsField =
                    dir.getField(TIFFImageDecoder.TIFF_T6_OPTIONS);
                if (t6OptionsField != null) {
                    tiffT6Options = t6OptionsField.getAsLong(0);
                } else {
                    // Use default value
                    tiffT6Options = 0;
                }
            }

            // Fax encoding, need to create the Fax decoder.
            decoder = new TIFFFaxDecoder(fillOrder,
                                         tileWidth, tileHeight);
            break;

        case COMP_LZW:
            // LZW compression used, need to create the LZW decoder.
            TIFFField predictorField =
                dir.getField(TIFFImageDecoder.TIFF_PREDICTOR);

            if (predictorField == null) {
                predictor = 1;
            } else {
                predictor = predictorField.getAsInt(0);

                if (predictor != 1 && predictor != 2) {
                    throw new RuntimeException(JaiI18N.getString("TIFFImage8"));
                }

                if (predictor == 2 && sampleSize != 8) {
                    throw new RuntimeException(sampleSize +
                                               JaiI18N.getString("TIFFImage9"));
                }
            }

            lzwDecoder = new TIFFLZWDecoder(tileWidth, predictor,
                                            samplesPerPixel);
            break;

        case COMP_JPEG_OLD:
            throw new RuntimeException(JaiI18N.getString("TIFFImage15"));

        case COMP_JPEG_TTN2:
            if(!(sampleSize == 8 &&
                 ((imageType == TYPE_GRAY && samplesPerPixel == 1) ||
                  (imageType == TYPE_PALETTE && samplesPerPixel == 1) ||
                  (imageType == TYPE_RGB && samplesPerPixel == 3)))) {
                throw new RuntimeException(JaiI18N.getString("TIFFImage16"));
            }

            // Create decodeParam from JPEGTables field if present.
            if(dir.isTagPresent(TIFF_JPEG_TABLES)) {
                TIFFField jpegTableField = dir.getField(TIFF_JPEG_TABLES);
                byte[] jpegTable = jpegTableField.getAsBytes();
                ByteArrayInputStream tableStream =
                    new ByteArrayInputStream(jpegTable);
                JPEGImageDecoder decoder =
                    JPEGCodec.createJPEGDecoder(tableStream);
View Full Code Here


     * Reads a private IFD from a given offset in the stream.  This
     * method may be used to obtain IFDs that are referenced
     * only by private tag values.
     */
    public TIFFDirectory getPrivateIFD(long offset) throws IOException {
        return new TIFFDirectory(stream, offset, 0);
    }
View Full Code Here

TOP

Related Classes of com.lightcrafts.media.jai.codec.TIFFDirectory

Copyright © 2018 www.massapicom. 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.