/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.commons.imaging.formats.tiff;

import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.imaging.FormatCompliance;
import org.apache.commons.imaging.ImageFormats;
import org.apache.commons.imaging.ImageInfo;
import org.apache.commons.imaging.ImageParser;
import org.apache.commons.imaging.ImageReadException;
import org.apache.commons.imaging.ImageWriteException;
import org.apache.commons.imaging.common.ByteOrder;
import org.apache.commons.imaging.common.IImageMetadata;
import org.apache.commons.imaging.common.ImageBuilder;
import org.apache.commons.imaging.common.bytesource.ByteSource;
import org.apache.commons.imaging.formats.tiff.TiffDirectory.ImageDataElement;
import org.apache.commons.imaging.formats.tiff.constants.TiffConstants;
import org.apache.commons.imaging.formats.tiff.constants.TiffEpTagConstants;
import org.apache.commons.imaging.formats.tiff.constants.TiffTagConstants;
import org.apache.commons.imaging.formats.tiff.datareaders.DataReader;
import org.apache.commons.imaging.formats.tiff.photometricinterpreters.PhotometricInterpreter;
import org.apache.commons.imaging.formats.tiff.photometricinterpreters.PhotometricInterpreterBiLevel;
import org.apache.commons.imaging.formats.tiff.photometricinterpreters.PhotometricInterpreterCieLab;
import org.apache.commons.imaging.formats.tiff.photometricinterpreters.PhotometricInterpreterCmyk;
import org.apache.commons.imaging.formats.tiff.photometricinterpreters.PhotometricInterpreterLogLuv;
import org.apache.commons.imaging.formats.tiff.photometricinterpreters.PhotometricInterpreterPalette;
import org.apache.commons.imaging.formats.tiff.photometricinterpreters.PhotometricInterpreterRgb;
import org.apache.commons.imaging.formats.tiff.photometricinterpreters.PhotometricInterpreterYCbCr;
import org.apache.commons.imaging.formats.tiff.write.TiffImageWriterLossy;

public class TiffImageParser extends ImageParser implements TiffConstants {
    public TiffImageParser() {
        // setDebug(true);
    }

    @Override
    public String getName() {
        return "Tiff-Custom";
    }

    @Override
    public String getDefaultExtension() {
        return DEFAULT_EXTENSION;
    }

    private static final String DEFAULT_EXTENSION = ".tif";

    private static final String ACCEPTED_EXTENSIONS[] = { ".tif", ".tiff", };

    @Override
    protected String[] getAcceptedExtensions() {
        return ACCEPTED_EXTENSIONS;
    }

    @Override
    protected ImageFormats[] getAcceptedTypes() {
        return new ImageFormats[] { ImageFormats.TIFF, //
        };
    }

    @Override
    public byte[] getICCProfileBytes(final ByteSource byteSource, final Map<String,Object> params)
            throws ImageReadException, IOException {
        final FormatCompliance formatCompliance = FormatCompliance.getDefault();
        final TiffContents contents = new TiffReader(isStrict(params))
                .readFirstDirectory(byteSource, params, false, formatCompliance);
        final TiffDirectory directory = contents.directories.get(0);

        return directory.getFieldValue(TiffEpTagConstants.EXIF_TAG_INTER_COLOR_PROFILE,
                false);
    }

    @Override
    public Dimension getImageSize(final ByteSource byteSource, final Map<String,Object> params)
            throws ImageReadException, IOException {
        final FormatCompliance formatCompliance = FormatCompliance.getDefault();
        final TiffContents contents = new TiffReader(isStrict(params))
                .readFirstDirectory(byteSource, params, false, formatCompliance);
        final TiffDirectory directory = contents.directories.get(0);

        final TiffField widthField = directory.findField(
                TiffTagConstants.TIFF_TAG_IMAGE_WIDTH, true);
        final TiffField heightField = directory.findField(
                TiffTagConstants.TIFF_TAG_IMAGE_LENGTH, true);

        if ((widthField == null) || (heightField == null)) {
            throw new ImageReadException("TIFF image missing size info.");
        }

        final int height = heightField.getIntValue();
        final int width = widthField.getIntValue();

        return new Dimension(width, height);
    }

    public byte[] embedICCProfile(final byte image[], final byte profile[]) {
        return null;
    }

    @Override
    public boolean embedICCProfile(final File src, final File dst, final byte profile[]) {
        return false;
    }

    @Override
    public IImageMetadata getMetadata(final ByteSource byteSource, final Map<String,Object> params)
            throws ImageReadException, IOException {
        final FormatCompliance formatCompliance = FormatCompliance.getDefault();
        final TiffReader tiffReader = new TiffReader(isStrict(params));
        final TiffContents contents = tiffReader.readContents(byteSource, params,
                formatCompliance);

        final List<TiffDirectory> directories = contents.directories;

        final TiffImageMetadata result = new TiffImageMetadata(contents);

        for (int i = 0; i < directories.size(); i++) {
            final TiffDirectory dir = directories.get(i);

            final TiffImageMetadata.Directory metadataDirectory = new TiffImageMetadata.Directory(
                    tiffReader.getByteOrder(), dir);

            final List<TiffField> entries = dir.getDirectoryEntries();

            for (int j = 0; j < entries.size(); j++) {
                final TiffField entry = entries.get(j);
                metadataDirectory.add(entry);
            }

            result.add(metadataDirectory);
        }

        return result;
    }

    @Override
    public ImageInfo getImageInfo(final ByteSource byteSource, final Map<String,Object> params)
            throws ImageReadException, IOException {
        final FormatCompliance formatCompliance = FormatCompliance.getDefault();
        final TiffContents contents = new TiffReader(isStrict(params))
                .readDirectories(byteSource, false, formatCompliance);
        final TiffDirectory directory = contents.directories.get(0);

        final TiffField widthField = directory.findField(
                TiffTagConstants.TIFF_TAG_IMAGE_WIDTH, true);
        final TiffField heightField = directory.findField(
                TiffTagConstants.TIFF_TAG_IMAGE_LENGTH, true);

        if ((widthField == null) || (heightField == null)) {
            throw new ImageReadException("TIFF image missing size info.");
        }

        final int height = heightField.getIntValue();
        final int width = widthField.getIntValue();

        // -------------------

        final TiffField resolutionUnitField = directory
                .findField(TiffTagConstants.TIFF_TAG_RESOLUTION_UNIT);
        int resolutionUnit = 2; // Inch
        if ((resolutionUnitField != null)
                && (resolutionUnitField.getValue() != null)) {
            resolutionUnit = resolutionUnitField.getIntValue();
        }

        double unitsPerInch = -1;
        switch (resolutionUnit) {
        case 1:
            break;
        case 2: // Inch
            unitsPerInch = 1.0;
            break;
        case 3: // Centimeter
            unitsPerInch = 2.54;
            break;
        default:
            break;

        }
        final TiffField xResolutionField = directory
                .findField(TiffTagConstants.TIFF_TAG_XRESOLUTION);
        final TiffField yResolutionField = directory
                .findField(TiffTagConstants.TIFF_TAG_YRESOLUTION);

        int physicalWidthDpi = -1;
        float physicalWidthInch = -1;
        int physicalHeightDpi = -1;
        float physicalHeightInch = -1;

        if (unitsPerInch > 0) {
            if ((xResolutionField != null)
                    && (xResolutionField.getValue() != null)) {
                final double XResolutionPixelsPerUnit = xResolutionField
                        .getDoubleValue();
                physicalWidthDpi = (int) Math
                        .round((XResolutionPixelsPerUnit * unitsPerInch));
                physicalWidthInch = (float) (width / (XResolutionPixelsPerUnit * unitsPerInch));
            }
            if ((yResolutionField != null)
                    && (yResolutionField.getValue() != null)) {
                final double YResolutionPixelsPerUnit = yResolutionField
                        .getDoubleValue();
                physicalHeightDpi = (int) Math
                        .round((YResolutionPixelsPerUnit * unitsPerInch));
                physicalHeightInch = (float) (height / (YResolutionPixelsPerUnit * unitsPerInch));
            }
        }

        // -------------------

        final TiffField bitsPerSampleField = directory
                .findField(TiffTagConstants.TIFF_TAG_BITS_PER_SAMPLE);

        int bitsPerSample = 1;
        if ((bitsPerSampleField != null)
                && (bitsPerSampleField.getValue() != null)) {
            bitsPerSample = bitsPerSampleField.getIntValueOrArraySum();
        }

        final int bitsPerPixel = bitsPerSample; // assume grayscale;
        // dunno if this handles colormapped images correctly.

        // -------------------

        final List<String> comments = new ArrayList<String>();
        final List<TiffField> entries = directory.entries;
        for (int i = 0; i < entries.size(); i++) {
            final TiffField field = entries.get(i);
            final String comment = field.toString();
            comments.add(comment);
        }

        final ImageFormats format = ImageFormats.TIFF;
        final String formatName = "TIFF Tag-based Image File Format";
        final String mimeType = "image/tiff";
        final int numberOfImages = contents.directories.size();
        // not accurate ... only reflects first
        final boolean isProgressive = false;
        // is TIFF ever interlaced/progressive?

        final String formatDetails = "Tiff v." + contents.header.tiffVersion;

        final boolean isTransparent = false; // TODO: wrong
        boolean usesPalette = false;
        final TiffField colorMapField = directory
                .findField(TiffTagConstants.TIFF_TAG_COLOR_MAP);
        if (colorMapField != null) {
            usesPalette = true;
        }

        final int colorType = ImageInfo.COLOR_TYPE_RGB;

        final int compression = 0xffff & directory
                .getSingleFieldValue(TiffTagConstants.TIFF_TAG_COMPRESSION);
        String compressionAlgorithm;

        switch (compression) {
        case TIFF_COMPRESSION_UNCOMPRESSED_1:
            compressionAlgorithm = ImageInfo.COMPRESSION_ALGORITHM_NONE;
            break;
        case TIFF_COMPRESSION_CCITT_1D:
            compressionAlgorithm = ImageInfo.COMPRESSION_ALGORITHM_CCITT_1D;
            break;
        case TIFF_COMPRESSION_CCITT_GROUP_3:
            compressionAlgorithm = ImageInfo.COMPRESSION_ALGORITHM_CCITT_GROUP_3;
            break;
        case TIFF_COMPRESSION_CCITT_GROUP_4:
            compressionAlgorithm = ImageInfo.COMPRESSION_ALGORITHM_CCITT_GROUP_4;
            break;
        case TIFF_COMPRESSION_LZW:
            compressionAlgorithm = ImageInfo.COMPRESSION_ALGORITHM_LZW;
            break;
        case TIFF_COMPRESSION_JPEG:
            compressionAlgorithm = ImageInfo.COMPRESSION_ALGORITHM_JPEG;
            break;
        case TIFF_COMPRESSION_UNCOMPRESSED_2:
            compressionAlgorithm = ImageInfo.COMPRESSION_ALGORITHM_NONE;
            break;
        case TIFF_COMPRESSION_PACKBITS:
            compressionAlgorithm = ImageInfo.COMPRESSION_ALGORITHM_PACKBITS;
            break;
        default:
            compressionAlgorithm = ImageInfo.COMPRESSION_ALGORITHM_UNKNOWN;
            break;
        }

        final ImageInfo result = new ImageInfo(formatDetails, bitsPerPixel, comments,
                format, formatName, height, mimeType, numberOfImages,
                physicalHeightDpi, physicalHeightInch, physicalWidthDpi,
                physicalWidthInch, width, isProgressive, isTransparent,
                usesPalette, colorType, compressionAlgorithm);

        return result;
    }

    @Override
    public String getXmpXml(final ByteSource byteSource, final Map<String,Object> params)
            throws ImageReadException, IOException {
        final FormatCompliance formatCompliance = FormatCompliance.getDefault();
        final TiffContents contents = new TiffReader(isStrict(params))
                .readDirectories(byteSource, false, formatCompliance);
        final TiffDirectory directory = contents.directories.get(0);

        final byte bytes[] = directory.getFieldValue(TiffTagConstants.TIFF_TAG_XMP,
                false);
        if (bytes == null) {
            return null;
        }

        try {
            // segment data is UTF-8 encoded xml.
            final String xml = new String(bytes, "utf-8");
            return xml;
        } catch (final UnsupportedEncodingException e) {
            throw new ImageReadException("Invalid JPEG XMP Segment.");
        }
    }

    @Override
    public boolean dumpImageFile(final PrintWriter pw, final ByteSource byteSource)
            throws ImageReadException, IOException {
        try {
            pw.println("tiff.dumpImageFile");

            {
                final ImageInfo imageData = getImageInfo(byteSource);
                if (imageData == null) {
                    return false;
                }

                imageData.toString(pw, "");
            }

            pw.println("");

            // try
            {
                final FormatCompliance formatCompliance = FormatCompliance
                        .getDefault();
                final Map<String,Object> params = null;
                final TiffContents contents = new TiffReader(true).readContents(
                        byteSource, params, formatCompliance);

                final List<TiffDirectory> directories = contents.directories;

                if (directories == null) {
                    return false;
                }

                for (int d = 0; d < directories.size(); d++) {
                    final TiffDirectory directory = directories.get(d);

                    final List<TiffField> entries = directory.entries;

                    if (entries == null) {
                        return false;
                    }

                    // Debug.debug("directory offset", directory.offset);

                    for (int i = 0; i < entries.size(); i++) {
                        final TiffField field = entries.get(i);

                        field.dump(pw, d + "");
                    }
                }

                pw.println("");
            }
            // catch (Exception e)
            // {
            // Debug.debug(e);
            // pw.println("");
            // return false;
            // }

            return true;
        } finally {
            pw.println("");
        }
    }

    @Override
    public FormatCompliance getFormatCompliance(final ByteSource byteSource)
            throws ImageReadException, IOException {
        final FormatCompliance formatCompliance = FormatCompliance.getDefault();
        final Map<String,Object> params = null;
        new TiffReader(isStrict(params)).readContents(byteSource, params,
                formatCompliance);
        return formatCompliance;
    }

    public List<byte[]> collectRawImageData(final ByteSource byteSource, final Map<String,Object> params)
            throws ImageReadException, IOException {
        final FormatCompliance formatCompliance = FormatCompliance.getDefault();
        final TiffContents contents = new TiffReader(isStrict(params))
                .readDirectories(byteSource, true, formatCompliance);

        final List<byte[]> result = new ArrayList<byte[]>();
        for (int i = 0; i < contents.directories.size(); i++) {
            final TiffDirectory directory = contents.directories.get(i);
            final List<ImageDataElement> dataElements = directory
                    .getTiffRawImageDataElements();
            for (int j = 0; j < dataElements.size(); j++) {
                final TiffDirectory.ImageDataElement element = dataElements.get(j);
                final byte bytes[] = byteSource.getBlock(element.offset,
                        element.length);
                result.add(bytes);
            }
        }
        return result;
    }

     /**
     * Gets a buffered image specified by the byte source.
     * The TiffImageParser class features support for a number of options that
     * are unique to the TIFF format.  These options can be specified by
     * supplying the appropriate parameters using the keys from the
     * TiffConstants class and the params argument for this method.
     * <h4>Loading Partial Images</h4>
     * The TIFF parser includes support for loading partial images without
     * committing significantly more memory resources than are necessary
     * to store the image. This feature is useful for conserving memory
     * in applications that require a relatively small sub image from a 
     * very large TIFF file.  The specifications for partial images are
     * as follows:
     * <code><pre>
     *   HashMap<String, Object> params = new HashMap<String, Object>();
     *   params.put(TiffConstants.PARAM_KEY_SUBIMAGE_X, new Integer(x));
     *   params.put(TiffConstants.PARAM_KEY_SUBIMAGE_Y, new Integer(y));
     *   params.put(TiffConstants.PARAM_KEY_SUBIMAGE_WIDTH, new Integer(width));
     *   params.put(TiffConstants.PARAM_KEY_SUBIMAGE_HEIGHT, new Integer(height));
     * </pre></code>
     * Note that the arguments x, y, width, and height must specify a
     * valid rectangular region that is fully contained within the 
     * source TIFF image.
     * @param byteSource A valid instance of ByteSource
     * @param params Optional instructions for special-handling or 
     * interpretation of the input data (null objects are permitted and 
     * must be supported by implementations).
     * @return A valid instance of BufferedImage.
     * @throws ImageReadException In the event that the the specified 
     * content does not conform to the format of the specific parser
     * implementation.
     * @throws IOException In the event of unsuccessful read or
     * access operation.
     */
    @Override
    public BufferedImage getBufferedImage(final ByteSource byteSource, final Map<String,Object> params)
            throws ImageReadException, IOException {
        final FormatCompliance formatCompliance = FormatCompliance.getDefault();
        final TiffReader reader = new TiffReader(isStrict(params));
        final TiffContents contents = reader.readFirstDirectory(byteSource, params,
                true, formatCompliance);
        final ByteOrder byteOrder = reader.getByteOrder();
        final TiffDirectory directory = contents.directories.get(0);
        final BufferedImage result = directory.getTiffImage(byteOrder, params);
        if (null == result) {
            throw new ImageReadException("TIFF does not contain an image.");
        }
        return result;
    }

    @Override
    public List<BufferedImage> getAllBufferedImages(final ByteSource byteSource)
            throws ImageReadException, IOException {
        final FormatCompliance formatCompliance = FormatCompliance.getDefault();
        final TiffReader tiffReader = new TiffReader(true);
        final TiffContents contents = tiffReader.readDirectories(byteSource, true,
                formatCompliance);
        final List<BufferedImage> results = new ArrayList<BufferedImage>();
        for (int i = 0; i < contents.directories.size(); i++) {
            final TiffDirectory directory = contents.directories.get(i);
            final BufferedImage result = directory.getTiffImage(
                    tiffReader.getByteOrder(), null);
            if (result != null) {
                results.add(result);
            }
        }
        return results;
    }

    private Integer getIntegerParameter(
            final String key, final Map<String, Object>params)
            throws ImageReadException
    {
        if (params == null) {
            return null;
        }
       
        if(!params.containsKey(key)) {
            return null;
        }
        
        final Object obj = params.get(key);
        
        if(obj instanceof Integer){
            return (Integer)obj;
        }
        throw new ImageReadException(
                "Non-Integer parameter "+key);
    }
    
    private Rectangle checkForSubImage(
            final Map<String, Object> params)
            throws ImageReadException
    {
        Integer ix0, iy0, iwidth, iheight;
        ix0 = getIntegerParameter(
                TiffConstants.PARAM_KEY_SUBIMAGE_X, params);
        iy0 = getIntegerParameter(
                TiffConstants.PARAM_KEY_SUBIMAGE_Y, params);
        iwidth = getIntegerParameter(
                TiffConstants.PARAM_KEY_SUBIMAGE_WIDTH, params);
        iheight = getIntegerParameter(
                TiffConstants.PARAM_KEY_SUBIMAGE_HEIGHT, params);
        if (ix0 == null && iy0 == null && iwidth == null && iheight == null) {
            return null;
        }

        final StringBuilder sb = new StringBuilder();
        if (ix0 == null) {
            sb.append(" x0,");
        }
        if (iy0 == null) {
            sb.append(" y0,");
        }
        if (iwidth == null) {
            sb.append(" width,");
        }
        if (iheight == null) {
            sb.append(" height,");
        }
        if (sb.length() > 0) {
            sb.setLength(sb.length() - 1);
            throw new ImageReadException(
                    "Incomplete subimage parameters, missing"
                    + sb.toString());
        }
        
        final int x0 = ix0.intValue();
        final int y0 = iy0.intValue();
        final int width = iwidth.intValue();
        final int height = iheight.intValue();

        return new Rectangle(x0, y0, width, height);
    }
    
    protected BufferedImage getBufferedImage(final TiffDirectory directory,
            final ByteOrder byteOrder, final Map<String,Object> params) 
            throws ImageReadException, IOException
    {
        final List<TiffField> entries = directory.entries;

        if (entries == null) {
            throw new ImageReadException("TIFF missing entries");
        }

        final int photometricInterpretation = 0xffff & directory.getSingleFieldValue(
                TiffTagConstants.TIFF_TAG_PHOTOMETRIC_INTERPRETATION);
        final int compression = 0xffff & directory.getSingleFieldValue(
                TiffTagConstants.TIFF_TAG_COMPRESSION);
        final int width = directory.getSingleFieldValue(
                TiffTagConstants.TIFF_TAG_IMAGE_WIDTH);
        final int height = directory.getSingleFieldValue(
                TiffTagConstants.TIFF_TAG_IMAGE_LENGTH);      
        Rectangle subImage = checkForSubImage(params);
        if(subImage!=null){
            // Check for valid subimage specification. The following checks
            // are consistent with BufferedImage.getSubimage()
            if (subImage.width <= 0) {
                throw new ImageReadException("negative or zero subimage width");
            }
            if (subImage.height <= 0) {
                throw new ImageReadException("negative or zero subimage height");
            }
            if(subImage.x<0 || subImage.x>=width){
                throw new ImageReadException("subimage x is outside raster");
            }
            if(subImage.x+subImage.width>width){
                throw new ImageReadException(
                        "subimage (x+width) is outside raster");
            }
            if(subImage.y<0 || subImage.y>=height){
                throw new ImageReadException("subimage y is outside raster");
            }
            if(subImage.y+subImage.height>height){
                throw new ImageReadException(
                        "subimage (y+height) is outside raster");
            }            
            
            // if the subimage is just the same thing as the whole
            // image, suppress the subimage processing
            if(subImage.x==0 
                    && subImage.y==0 
                    && subImage.width==width 
                    && subImage.height==height){
                subImage = null;
            }
        }

        
        int samplesPerPixel = 1;
        final TiffField samplesPerPixelField = directory.findField(
                TiffTagConstants.TIFF_TAG_SAMPLES_PER_PIXEL);
        if (samplesPerPixelField != null) {
            samplesPerPixel = samplesPerPixelField.getIntValue();
        }
        int bitsPerSample[] = { 1 };
        int bitsPerPixel = samplesPerPixel;
        final TiffField bitsPerSampleField = directory.findField(
                TiffTagConstants.TIFF_TAG_BITS_PER_SAMPLE);
        if (bitsPerSampleField != null) {
            bitsPerSample = bitsPerSampleField.getIntArrayValue();
            bitsPerPixel = bitsPerSampleField.getIntValueOrArraySum();
        }

        // int bitsPerPixel = getTagAsValueOrArraySum(entries,
        // TIFF_TAG_BITS_PER_SAMPLE);

        int predictor = -1;
        {
            // dumpOptionalNumberTag(entries, TIFF_TAG_FILL_ORDER);
            // dumpOptionalNumberTag(entries, TIFF_TAG_FREE_BYTE_COUNTS);
            // dumpOptionalNumberTag(entries, TIFF_TAG_FREE_OFFSETS);
            // dumpOptionalNumberTag(entries, TIFF_TAG_ORIENTATION);
            // dumpOptionalNumberTag(entries, TIFF_TAG_PLANAR_CONFIGURATION);
            final TiffField predictorField = directory.findField(
                    TiffTagConstants.TIFF_TAG_PREDICTOR);
            if (null != predictorField) {
                predictor = predictorField.getIntValueOrArraySum();
            }
        }

        if (samplesPerPixel != bitsPerSample.length) {
            throw new ImageReadException("Tiff: samplesPerPixel ("
                    + samplesPerPixel + ")!=fBitsPerSample.length ("
                    + bitsPerSample.length + ")");
        }



        final PhotometricInterpreter photometricInterpreter = getPhotometricInterpreter(
                directory, photometricInterpretation, bitsPerPixel,
                bitsPerSample, predictor, samplesPerPixel, width, height);

        final TiffImageData imageData = directory.getTiffImageData();

        final DataReader dataReader = imageData.getDataReader(directory,
                photometricInterpreter, bitsPerPixel, bitsPerSample, predictor,
                samplesPerPixel, width, height, compression, byteOrder);

        BufferedImage result = null;
        if (subImage != null) {
            result = dataReader.readImageData(subImage);
        } else {
            final boolean hasAlpha = false;
            final ImageBuilder imageBuilder = new ImageBuilder(width, height, hasAlpha);

            dataReader.readImageData(imageBuilder);
            result =  imageBuilder.getBufferedImage();
        }
        photometricInterpreter.dumpstats();
        return result;     
    }

    private PhotometricInterpreter getPhotometricInterpreter(
            final TiffDirectory directory, final int photometricInterpretation,
            final int bitsPerPixel, final int bitsPerSample[], final int predictor,
            final int samplesPerPixel, final int width, final int height)
            throws ImageReadException {
        switch (photometricInterpretation) {
        case 0:
        case 1:
            final boolean invert = photometricInterpretation == 0;

            return new PhotometricInterpreterBiLevel(bitsPerPixel,
                    samplesPerPixel, bitsPerSample, predictor, width, height,
                    invert);
        case 3: // Palette
        {
            final int colorMap[] = directory.findField(
                    TiffTagConstants.TIFF_TAG_COLOR_MAP, true)
                    .getIntArrayValue();

            final int expected_colormap_size = 3 * (1 << bitsPerPixel);

            if (colorMap.length != expected_colormap_size) {
                throw new ImageReadException("Tiff: fColorMap.length ("
                        + colorMap.length + ")!=expected_colormap_size ("
                        + expected_colormap_size + ")");
            }

            return new PhotometricInterpreterPalette(samplesPerPixel,
                    bitsPerSample, predictor, width, height, colorMap);
        }
        case 2: // RGB
            return new PhotometricInterpreterRgb(samplesPerPixel,
                    bitsPerSample, predictor, width, height);
        case 5: // CMYK
            return new PhotometricInterpreterCmyk(samplesPerPixel,
                    bitsPerSample, predictor, width, height);
        case 6: //
        {
            final double yCbCrCoefficients[] = directory.findField(
                    TiffTagConstants.TIFF_TAG_YCBCR_COEFFICIENTS, true)
                    .getDoubleArrayValue();

            final int yCbCrPositioning[] = directory.findField(
                    TiffTagConstants.TIFF_TAG_YCBCR_POSITIONING, true)
                    .getIntArrayValue();
            final int yCbCrSubSampling[] = directory.findField(
                    TiffTagConstants.TIFF_TAG_YCBCR_SUB_SAMPLING, true)
                    .getIntArrayValue();

            final double referenceBlackWhite[] = directory.findField(
                    TiffTagConstants.TIFF_TAG_REFERENCE_BLACK_WHITE, true)
                    .getDoubleArrayValue();

            return new PhotometricInterpreterYCbCr(yCbCrCoefficients,
                    yCbCrPositioning, yCbCrSubSampling, referenceBlackWhite,
                    samplesPerPixel, bitsPerSample, predictor, width, height);
        }

        case 8:
            return new PhotometricInterpreterCieLab(samplesPerPixel,
                    bitsPerSample, predictor, width, height);

        case 32844:
        case 32845: {
            final boolean yonly = (photometricInterpretation == 32844);
            return new PhotometricInterpreterLogLuv(samplesPerPixel,
                    bitsPerSample, predictor, width, height, yonly);
        }

        default:
            throw new ImageReadException(
                    "TIFF: Unknown fPhotometricInterpretation: "
                            + photometricInterpretation);
        }
    }

    @Override
    public void writeImage(final BufferedImage src, final OutputStream os, final Map<String,Object> params)
            throws ImageWriteException, IOException {
        new TiffImageWriterLossy().writeImage(src, os, params);
    }

}
