/*
 * 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.gif;

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

import org.apache.commons.imaging.FormatCompliance;
import org.apache.commons.imaging.ImageFormat;
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.BinaryOutputStream;
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.common.mylzw.MyLzwCompressor;
import org.apache.commons.imaging.common.mylzw.MyLzwDecompressor;
import org.apache.commons.imaging.palette.Palette;
import org.apache.commons.imaging.palette.PaletteFactory;
import org.apache.commons.imaging.util.IoUtils;
import org.apache.commons.imaging.util.ParamMap;

public class GifImageParser extends ImageParser {

    public GifImageParser() {
        super.setByteOrder(ByteOrder.LITTLE_ENDIAN);
    }

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

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

    private static final String DEFAULT_EXTENSION = ".gif";

    private static final String ACCEPTED_EXTENSIONS[] = { DEFAULT_EXTENSION, };

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

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

    private static final byte GIF_HEADER_SIGNATURE[] = { 71, 73, 70 };

    private GifHeaderInfo readHeader(final InputStream is,
            final FormatCompliance formatCompliance) throws ImageReadException,
            IOException {
        final byte identifier1 = readByte("identifier1", is, "Not a Valid GIF File");
        final byte identifier2 = readByte("identifier2", is, "Not a Valid GIF File");
        final byte identifier3 = readByte("identifier3", is, "Not a Valid GIF File");

        final byte version1 = readByte("version1", is, "Not a Valid GIF File");
        final byte version2 = readByte("version2", is, "Not a Valid GIF File");
        final byte version3 = readByte("version3", is, "Not a Valid GIF File");

        if (formatCompliance != null) {
            formatCompliance.compare_bytes("Signature", GIF_HEADER_SIGNATURE,
                    new byte[] { identifier1, identifier2, identifier3, });
            formatCompliance.compare("version", 56, version1);
            formatCompliance
                    .compare("version", new int[] { 55, 57, }, version2);
            formatCompliance.compare("version", 97, version3);
        }

        if (getDebug()) {
            printCharQuad("identifier: ", ((identifier1 << 16)
                    | (identifier2 << 8) | (identifier3 << 0)));
            printCharQuad("version: ",
                    ((version1 << 16) | (version2 << 8) | (version3 << 0)));
        }

        final int logicalScreenWidth = read2Bytes("Logical Screen Width", is,
                "Not a Valid GIF File");
        final int logicalScreenHeight = read2Bytes("Logical Screen Height", is,
                "Not a Valid GIF File");

        if (formatCompliance != null) {
            formatCompliance.checkBounds("Width", 1, Integer.MAX_VALUE,
                    logicalScreenWidth);
            formatCompliance.checkBounds("Height", 1, Integer.MAX_VALUE,
                    logicalScreenHeight);
        }

        final byte packedFields = readByte("Packed Fields", is,
                "Not a Valid GIF File");
        final byte backgroundColorIndex = readByte("Background Color Index", is,
                "Not a Valid GIF File");
        final byte pixelAspectRatio = readByte("Pixel Aspect Ratio", is,
                "Not a Valid GIF File");

        if (getDebug()) {
            printByteBits("PackedFields bits", packedFields);
        }

        final boolean globalColorTableFlag = ((packedFields & 128) > 0);
        if (getDebug()) {
            System.out.println("GlobalColorTableFlag: " + globalColorTableFlag);
        }
        final byte colorResolution = (byte) ((packedFields >> 4) & 7);
        if (getDebug()) {
            System.out.println("ColorResolution: " + colorResolution);
        }
        final boolean sortFlag = ((packedFields & 8) > 0);
        if (getDebug()) {
            System.out.println("SortFlag: " + sortFlag);
        }
        final byte sizeofGlobalColorTable = (byte) (packedFields & 7);
        if (getDebug()) {
            System.out.println("SizeofGlobalColorTable: "
                    + sizeofGlobalColorTable);
        }

        if (formatCompliance != null) {
            if (globalColorTableFlag && backgroundColorIndex != -1) {
                formatCompliance.checkBounds("Background Color Index", 0,
                        convertColorTableSize(sizeofGlobalColorTable),
                        backgroundColorIndex);
            }
        }

        return new GifHeaderInfo(identifier1, identifier2, identifier3,
                version1, version2, version3, logicalScreenWidth,
                logicalScreenHeight, packedFields, backgroundColorIndex,
                pixelAspectRatio, globalColorTableFlag, colorResolution,
                sortFlag, sizeofGlobalColorTable);
    }

    private GraphicControlExtension readGraphicControlExtension(final int code,
            final InputStream is) throws IOException {
        readByte("block_size", is, "GIF: corrupt GraphicControlExt");
        final int packed = readByte("packed fields", is,
                "GIF: corrupt GraphicControlExt");

        final int dispose = (packed & 0x1c) >> 2; // disposal method
        final boolean transparency = (packed & 1) != 0;

        final int delay = read2Bytes("delay in milliseconds", is,
                "GIF: corrupt GraphicControlExt");
        final int transparentColorIndex = 0xff & readByte("transparent color index",
                is, "GIF: corrupt GraphicControlExt");
        readByte("block terminator", is, "GIF: corrupt GraphicControlExt");

        return new GraphicControlExtension(code, packed, dispose, transparency,
                delay, transparentColorIndex);
    }

    private byte[] readSubBlock(final InputStream is) throws IOException {
        final int block_size = 0xff & readByte("block_size", is, "GIF: corrupt block");

        final byte bytes[] = readBytes("block", is, block_size,
                "GIF: corrupt block");

        return bytes;
    }

    protected GenericGifBlock readGenericGIFBlock(final InputStream is, final int code)
            throws IOException {
        return readGenericGIFBlock(is, code, null);
    }

    protected GenericGifBlock readGenericGIFBlock(final InputStream is, final int code,
            final byte first[]) throws IOException {
        final List<byte[]> subblocks = new ArrayList<byte[]>();

        if (first != null) {
            subblocks.add(first);
        }

        while (true) {
            final byte bytes[] = readSubBlock(is);
            if (bytes.length < 1) {
                break;
            }
            subblocks.add(bytes);
        }

        return new GenericGifBlock(code, subblocks);
    }

    private final static int EXTENSION_CODE = 0x21;
    private final static int IMAGE_SEPARATOR = 0x2C;
    private final static int GRAPHIC_CONTROL_EXTENSION = (EXTENSION_CODE << 8) | 0xf9;
    private final static int COMMENT_EXTENSION = 0xfe;
    private final static int PLAIN_TEXT_EXTENSION = 0x01;
    private final static int XMP_EXTENSION = 0xff;
    private final static int TERMINATOR_BYTE = 0x3b;
    private final static int APPLICATION_EXTENSION_LABEL = 0xff;
    private final static int XMP_COMPLETE_CODE = (EXTENSION_CODE << 8)
            | XMP_EXTENSION;

    private List<GifBlock> readBlocks(final GifHeaderInfo ghi, final InputStream is,
            final boolean stopBeforeImageData, final FormatCompliance formatCompliance)
            throws ImageReadException, IOException {
        final List<GifBlock> result = new ArrayList<GifBlock>();

        while (true) {
            final int code = is.read();

            switch (code) {
            case -1:
                throw new ImageReadException("GIF: unexpected end of data");

            case IMAGE_SEPARATOR:
                final ImageDescriptor id = readImageDescriptor(ghi, code, is,
                        stopBeforeImageData, formatCompliance);
                result.add(id);
                // if(stopBeforeImageData)
                // return result;

                break;

            case EXTENSION_CODE: // extension
            {
                final int extensionCode = is.read();
                final int completeCode = ((0xff & code) << 8)
                        | (0xff & extensionCode);

                switch (extensionCode) {
                case 0xf9:
                    final GraphicControlExtension gce = readGraphicControlExtension(
                            completeCode, is);
                    result.add(gce);
                    break;

                case COMMENT_EXTENSION:
                case PLAIN_TEXT_EXTENSION: {
                    final GenericGifBlock block = readGenericGIFBlock(is,
                            completeCode);
                    result.add(block);
                    break;
                }

                case APPLICATION_EXTENSION_LABEL: // 255 (hex 0xFF) Application
                    // Extension Label
                {
                    final byte label[] = readSubBlock(is);

                    if (formatCompliance != null) {
                        formatCompliance.addComment(
                                "Unknown Application Extension ("
                                        + new String(label, "US-ASCII") + ")",
                                completeCode);
                    }

                    // if (label == new String("ICCRGBG1"))
                    {
                        // GIF's can have embedded ICC Profiles - who knew?
                    }

                    if ((label != null) && (label.length > 0)) {
                        final GenericGifBlock block = readGenericGIFBlock(is,
                                completeCode, label);
                        result.add(block);
                    }
                    break;
                }

                default: {

                    if (formatCompliance != null) {
                        formatCompliance.addComment("Unknown block",
                                completeCode);
                    }

                    final GenericGifBlock block = readGenericGIFBlock(is,
                            completeCode);
                    result.add(block);
                    break;
                }
                }
            }
                break;

            case TERMINATOR_BYTE:
                return result;

            case 0x00: // bad byte, but keep going and see what happens
                break;

            default:
                throw new ImageReadException("GIF: unknown code: " + code);
            }
        }
    }

    private ImageDescriptor readImageDescriptor(final GifHeaderInfo ghi,
            final int blockCode, final InputStream is, final boolean stopBeforeImageData,
            final FormatCompliance formatCompliance) throws ImageReadException,
            IOException {
        final int ImageLeftPosition = read2Bytes("Image Left Position", is,
                "Not a Valid GIF File");
        final int ImageTopPosition = read2Bytes("Image Top Position", is,
                "Not a Valid GIF File");
        final int imageWidth = read2Bytes("Image Width", is, "Not a Valid GIF File");
        final int imageHeight = read2Bytes("Image Height", is, "Not a Valid GIF File");
        final byte PackedFields = readByte("Packed Fields", is,
                "Not a Valid GIF File");

        if (formatCompliance != null) {
            formatCompliance.checkBounds("Width", 1, ghi.logicalScreenWidth,
                    imageWidth);
            formatCompliance.checkBounds("Height", 1, ghi.logicalScreenHeight,
                    imageHeight);
            formatCompliance.checkBounds("Left Position", 0,
                    ghi.logicalScreenWidth - imageWidth, ImageLeftPosition);
            formatCompliance.checkBounds("Top Position", 0,
                    ghi.logicalScreenHeight - imageHeight, ImageTopPosition);
        }

        if (getDebug()) {
            printByteBits("PackedFields bits", PackedFields);
        }

        final boolean LocalColorTableFlag = (((PackedFields >> 7) & 1) > 0);
        if (getDebug()) {
            System.out.println("LocalColorTableFlag: " + LocalColorTableFlag);
        }
        final boolean InterlaceFlag = (((PackedFields >> 6) & 1) > 0);
        if (getDebug()) {
            System.out.println("Interlace Flag: " + InterlaceFlag);
        }
        final boolean SortFlag = (((PackedFields >> 5) & 1) > 0);
        if (getDebug()) {
            System.out.println("Sort  Flag: " + SortFlag);
        }

        final byte SizeofLocalColorTable = (byte) (PackedFields & 7);
        if (getDebug()) {
            System.out.println("SizeofLocalColorTable: "
                    + SizeofLocalColorTable);
        }

        byte LocalColorTable[] = null;
        if (LocalColorTableFlag) {
            LocalColorTable = readColorTable(is, SizeofLocalColorTable,
                    formatCompliance);
        }

        byte imageData[] = null;
        if (!stopBeforeImageData) {
            final int LZWMinimumCodeSize = is.read();

            final GenericGifBlock block = readGenericGIFBlock(is, -1);
            final byte bytes[] = block.appendSubBlocks();
            final InputStream bais = new ByteArrayInputStream(bytes);

            final int size = imageWidth * imageHeight;
            final MyLzwDecompressor myLzwDecompressor = new MyLzwDecompressor(
                    LZWMinimumCodeSize, ByteOrder.LITTLE_ENDIAN);
            imageData = myLzwDecompressor.decompress(bais, size);
        } else {
            final int LZWMinimumCodeSize = is.read();
            if (getDebug()) {
                System.out.println("LZWMinimumCodeSize: " + LZWMinimumCodeSize);
            }

            readGenericGIFBlock(is, -1);
        }

        final ImageDescriptor result = new ImageDescriptor(blockCode,
                ImageLeftPosition, ImageTopPosition, imageWidth, imageHeight,
                PackedFields, LocalColorTableFlag, InterlaceFlag, SortFlag,
                SizeofLocalColorTable, LocalColorTable, imageData);

        return result;
    }

    private int simple_pow(final int base, final int power) {
        int result = 1;

        for (int i = 0; i < power; i++) {
            result *= base;
        }

        return result;
    }

    private int convertColorTableSize(final int ct_size) {
        return 3 * simple_pow(2, ct_size + 1);
    }

    private byte[] readColorTable(final InputStream is, final int ct_size,
            final FormatCompliance formatCompliance) throws IOException {
        final int actual_size = convertColorTableSize(ct_size);

        final byte bytes[] = readBytes("block", is, actual_size,
                "GIF: corrupt Color Table");

        return bytes;
    }

    private GifBlock findBlock(final List<GifBlock> v, final int code) {
        for (int i = 0; i < v.size(); i++) {
            final GifBlock gifBlock = v.get(i);
            if (gifBlock.blockCode == code) {
                return gifBlock;
            }
        }
        return null;
    }

    private ImageContents readFile(final ByteSource byteSource,
            final boolean stopBeforeImageData) throws ImageReadException, IOException {
        return readFile(byteSource, stopBeforeImageData,
                FormatCompliance.getDefault());
    }

    private ImageContents readFile(final ByteSource byteSource,
            final boolean stopBeforeImageData, final FormatCompliance formatCompliance)
            throws ImageReadException, IOException {
        InputStream is = null;
        boolean canThrow = false;
        try {
            is = byteSource.getInputStream();

            final GifHeaderInfo ghi = readHeader(is, formatCompliance);

            byte globalColorTable[] = null;
            if (ghi.globalColorTableFlag) {
                globalColorTable = readColorTable(is,
                        ghi.sizeOfGlobalColorTable, formatCompliance);
            }

            final List<GifBlock> blocks = readBlocks(ghi, is, stopBeforeImageData,
                    formatCompliance);

            final ImageContents result = new ImageContents(ghi, globalColorTable,
                    blocks);
            canThrow = true;
            return result;
        } finally {
            IoUtils.closeQuietly(canThrow, is);
        }
    }

    @Override
    public byte[] getICCProfileBytes(final ByteSource byteSource, final Map<String,Object> params)
            throws ImageReadException, IOException {
        return null;
    }

    @Override
    public Dimension getImageSize(final ByteSource byteSource, final Map<String,Object> params)
            throws ImageReadException, IOException {
        final ImageContents blocks = readFile(byteSource, false);

        if (blocks == null) {
            throw new ImageReadException("GIF: Couldn't read blocks");
        }

        final GifHeaderInfo bhi = blocks.gifHeaderInfo;
        if (bhi == null) {
            throw new ImageReadException("GIF: Couldn't read Header");
        }

        final ImageDescriptor id = (ImageDescriptor) findBlock(blocks.blocks,
                IMAGE_SEPARATOR);
        if (id == null) {
            throw new ImageReadException("GIF: Couldn't read ImageDescriptor");
        }

        // Prefer the size information in the ImageDescriptor; it is more
        // reliable
        // than the size information in the header.
        return new Dimension(id.imageWidth, id.imageHeight);
    }

    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 {
        return null;
    }

    private List<String> getComments(final List<GifBlock> v) throws IOException {
        final List<String> result = new ArrayList<String>();
        final int code = 0x21fe;

        for (int i = 0; i < v.size(); i++) {
            final GifBlock block = v.get(i);
            if (block.blockCode == code) {
                final byte bytes[] = ((GenericGifBlock) block).appendSubBlocks();
                result.add(new String(bytes, "US-ASCII"));
            }
        }

        return result;
    }

    @Override
    public ImageInfo getImageInfo(final ByteSource byteSource, final Map<String,Object> params)
            throws ImageReadException, IOException {
        final ImageContents blocks = readFile(byteSource, false);

        if (blocks == null) {
            throw new ImageReadException("GIF: Couldn't read blocks");
        }

        final GifHeaderInfo bhi = blocks.gifHeaderInfo;
        if (bhi == null) {
            throw new ImageReadException("GIF: Couldn't read Header");
        }

        final ImageDescriptor id = (ImageDescriptor) findBlock(blocks.blocks,
                IMAGE_SEPARATOR);
        if (id == null) {
            throw new ImageReadException("GIF: Couldn't read ImageDescriptor");
        }

        final GraphicControlExtension gce = (GraphicControlExtension) findBlock(
                blocks.blocks, GRAPHIC_CONTROL_EXTENSION);

        // Prefer the size information in the ImageDescriptor; it is more
        // reliable than the size information in the header.
        final int height = id.imageHeight;
        final int width = id.imageWidth;

        final List<String> comments = getComments(blocks.blocks);
        final int bitsPerPixel = (bhi.colorResolution + 1);
        final ImageFormat format = ImageFormats.GIF;
        final String formatName = "GIF Graphics Interchange Format";
        final String mimeType = "image/gif";
        // we ought to count images, but don't yet.
        final int numberOfImages = -1;

        final boolean isProgressive = id.interlaceFlag;

        final int physicalWidthDpi = 72;
        final float physicalWidthInch = (float) ((double) width / (double) physicalWidthDpi);
        final int physicalHeightDpi = 72;
        final float physicalHeightInch = (float) ((double) height / (double) physicalHeightDpi);

        final String formatDetails = "Gif " + ((char) blocks.gifHeaderInfo.version1)
                + ((char) blocks.gifHeaderInfo.version2)
                + ((char) blocks.gifHeaderInfo.version3);

        boolean isTransparent = false;
        if (gce != null && gce.transparency) {
            isTransparent = true;
        }

        final boolean usesPalette = true;
        final int colorType = ImageInfo.COLOR_TYPE_RGB;
        final String compressionAlgorithm = ImageInfo.COMPRESSION_ALGORITHM_LZW;

        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 boolean dumpImageFile(final PrintWriter pw, final ByteSource byteSource)
            throws ImageReadException, IOException {
        pw.println("gif.dumpImageFile");

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

        imageData.toString(pw, "");
        
        final ImageContents blocks = readFile(byteSource, false);

        pw.println("gif.blocks: " + blocks.blocks.size());
        for (int i = 0; i < blocks.blocks.size(); i++) {
            final GifBlock gifBlock = blocks.blocks.get(i);
            this.debugNumber(pw, "\t" + i + " ("
                    + gifBlock.getClass().getName() + ")",
                    gifBlock.blockCode, 4);
        }

        pw.println("");

        return true;
    }

    private int[] getColorTable(final byte bytes[]) throws ImageReadException {
        if ((bytes.length % 3) != 0) {
            throw new ImageReadException("Bad Color Table Length: "
                    + bytes.length);
        }
        final int length = bytes.length / 3;

        final int result[] = new int[length];

        for (int i = 0; i < length; i++) {
            final int red = 0xff & bytes[(i * 3) + 0];
            final int green = 0xff & bytes[(i * 3) + 1];
            final int blue = 0xff & bytes[(i * 3) + 2];

            final int alpha = 0xff;

            final int rgb = (alpha << 24) | (red << 16) | (green << 8) | (blue << 0);
            result[i] = rgb;
        }

        return result;
    }

    @Override
    public FormatCompliance getFormatCompliance(final ByteSource byteSource)
            throws ImageReadException, IOException {
        final FormatCompliance result = new FormatCompliance(
                byteSource.getDescription());

        readFile(byteSource, false, result);

        return result;
    }

    @Override
    public BufferedImage getBufferedImage(final ByteSource byteSource, final Map<String,Object> params)
            throws ImageReadException, IOException {
        final ImageContents imageContents = readFile(byteSource, false);

        if (imageContents == null) {
            throw new ImageReadException("GIF: Couldn't read blocks");
        }

        final GifHeaderInfo ghi = imageContents.gifHeaderInfo;
        if (ghi == null) {
            throw new ImageReadException("GIF: Couldn't read Header");
        }

        final ImageDescriptor id = (ImageDescriptor) findBlock(imageContents.blocks,
                IMAGE_SEPARATOR);
        if (id == null) {
            throw new ImageReadException("GIF: Couldn't read Image Descriptor");
        }
        final GraphicControlExtension gce = (GraphicControlExtension) findBlock(
                imageContents.blocks, GRAPHIC_CONTROL_EXTENSION);

        // Prefer the size information in the ImageDescriptor; it is more
        // reliable
        // than the size information in the header.
        final int width = id.imageWidth;
        final int height = id.imageHeight;

        boolean hasAlpha = false;
        if (gce != null && gce.transparency) {
            hasAlpha = true;
        }

        final ImageBuilder imageBuilder = new ImageBuilder(width, height, hasAlpha);

        int colorTable[];
        if (id.localColorTable != null) {
            colorTable = getColorTable(id.localColorTable);
        } else if (imageContents.globalColorTable != null) {
            colorTable = getColorTable(imageContents.globalColorTable);
        } else {
            throw new ImageReadException("Gif: No Color Table");
        }

        int transparentIndex = -1;
        if (hasAlpha) {
            transparentIndex = gce.transparentColorIndex;
        }

        int counter = 0;

        final int rowsInPass1 = (height + 7) / 8;
        final int rowsInPass2 = (height + 3) / 8;
        final int rowsInPass3 = (height + 1) / 4;
        final int rowsInPass4 = (height) / 2;

        for (int row = 0; row < height; row++) {
            int y;
            if (id.interlaceFlag) {
                int the_row = row;
                if (the_row < rowsInPass1) {
                    y = the_row * 8;
                } else {
                    the_row -= rowsInPass1;
                    if (the_row < (rowsInPass2)) {
                        y = 4 + (the_row * 8);
                    } else {
                        the_row -= rowsInPass2;
                        if (the_row < (rowsInPass3)) {
                            y = 2 + (the_row * 4);
                        } else {
                            the_row -= rowsInPass3;
                            if (the_row < (rowsInPass4)) {
                                y = 1 + (the_row * 2);
                            } else {
                                throw new ImageReadException(
                                        "Gif: Strange Row");
                            }
                        }
                    }
                }
            } else {
                y = row;
            }

            for (int x = 0; x < width; x++) {
                final int index = 0xff & id.imageData[counter++];
                int rgb = colorTable[index];

                if (transparentIndex == index) {
                    rgb = 0x00;
                }

                imageBuilder.setRGB(x, y, rgb);
            }

        }

        return imageBuilder.getBufferedImage();

    }

    private void writeAsSubBlocks(final OutputStream os, final byte bytes[])
            throws IOException {
        int index = 0;

        while (index < bytes.length) {
            final int block_size = Math.min(bytes.length - index, 255);
            os.write(block_size);
            os.write(bytes, index, block_size);
            index += block_size;
        }
        os.write(0); // last block
    }

    private static final int LOCAL_COLOR_TABLE_FLAG_MASK = 1 << 7;
    private static final int INTERLACE_FLAG_MASK = 1 << 6;
    private static final int SORT_FLAG_MASK = 1 << 5;

    @Override
    public void writeImage(final BufferedImage src, final OutputStream os, Map<String,Object> params)
            throws ImageWriteException, IOException {
        // make copy of params; we'll clear keys as we consume them.
        params = new HashMap<String,Object>(params);

        final boolean verbose = ParamMap.getParamBoolean(params, PARAM_KEY_VERBOSE,
                false);

        // clear format key.
        if (params.containsKey(PARAM_KEY_FORMAT)) {
            params.remove(PARAM_KEY_FORMAT);
        }
        if (params.containsKey(PARAM_KEY_VERBOSE)) {
            params.remove(PARAM_KEY_VERBOSE);
        }

        String xmpXml = null;
        if (params.containsKey(PARAM_KEY_XMP_XML)) {
            xmpXml = (String) params.get(PARAM_KEY_XMP_XML);
            params.remove(PARAM_KEY_XMP_XML);
        }

        if (params.size() > 0) {
            final Object firstKey = params.keySet().iterator().next();
            throw new ImageWriteException("Unknown parameter: " + firstKey);
        }

        final int width = src.getWidth();
        final int height = src.getHeight();

        final boolean hasAlpha = new PaletteFactory().hasTransparency(src);

        final int max_colors = hasAlpha ? 255 : 256;

        Palette palette2 = new PaletteFactory().makeExactRgbPaletteSimple(src,
                max_colors);
        // int palette[] = new PaletteFactory().makePaletteSimple(src, 256);
        // Map palette_map = paletteToMap(palette);

        if (palette2 == null) {
            palette2 = new PaletteFactory().makeQuantizedRgbPalette(src,
                    max_colors);
            if (verbose) {
                System.out.println("quantizing");
            }
        } else if (verbose) {
            System.out.println("exact palette");
        }

        if (palette2 == null) {
            throw new ImageWriteException(
                    "Gif: can't write images with more than 256 colors");
        }
        final int palette_size = palette2.length() + (hasAlpha ? 1 : 0);

        final BinaryOutputStream bos = new BinaryOutputStream(os, ByteOrder.LITTLE_ENDIAN);

        // write Header
        os.write(0x47); // G magic numbers
        os.write(0x49); // I
        os.write(0x46); // F

        os.write(0x38); // 8 version magic numbers
        os.write(0x39); // 9
        os.write(0x61); // a

        // Logical Screen Descriptor.

        bos.write2Bytes(width);
        bos.write2Bytes(height);

        final int colorTableScaleLessOne = (palette_size > 128) ? 7
                : (palette_size > 64) ? 6 : (palette_size > 32) ? 5
                        : (palette_size > 16) ? 4 : (palette_size > 8) ? 3
                                : (palette_size > 4) ? 2
                                        : (palette_size > 2) ? 1 : 0;

        final int colorTableSizeInFormat = 1 << (colorTableScaleLessOne + 1);
        {
            final byte colorResolution = (byte) colorTableScaleLessOne; // TODO:

            final boolean globalColorTableFlag = false;
            final boolean sortFlag = false;
            final int globalColorTableFlagMask = 1 << 7;
            final int sortFlagMask = 8;
            final int sizeOfGlobalColorTable = 0;

            final int packedFields = ((globalColorTableFlag ? globalColorTableFlagMask
                    : 0)
                    | (sortFlag ? sortFlagMask : 0)
                    | ((7 & colorResolution) << 4) | (7 & sizeOfGlobalColorTable));
            bos.write(packedFields); // one byte
        }
        {
            final byte BackgroundColorIndex = 0;
            bos.write(BackgroundColorIndex);
        }
        {
            final byte PixelAspectRatio = 0;
            bos.write(PixelAspectRatio);
        }

        { // write Global Color Table.

        }

        { // ALWAYS write GraphicControlExtension
            bos.write(EXTENSION_CODE);
            bos.write((byte) 0xf9);
            // bos.write(0xff & (kGraphicControlExtension >> 8));
            // bos.write(0xff & (kGraphicControlExtension >> 0));

            bos.write((byte) 4); // block size;
            final int packedFields = hasAlpha ? 1 : 0; // transparency flag
            bos.write((byte) packedFields);
            bos.write((byte) 0); // Delay Time
            bos.write((byte) 0); // Delay Time
            bos.write((byte) (hasAlpha ? palette2.length() : 0)); // Transparent
            // Color
            // Index
            bos.write((byte) 0); // terminator
        }

        if (null != xmpXml) {
            bos.write(EXTENSION_CODE);
            bos.write(APPLICATION_EXTENSION_LABEL);

            bos.write(XMP_APPLICATION_ID_AND_AUTH_CODE.length); // 0x0B
            bos.write(XMP_APPLICATION_ID_AND_AUTH_CODE);

            final byte xmpXmlBytes[] = xmpXml.getBytes("utf-8");
            bos.write(xmpXmlBytes);

            // write "magic trailer"
            for (int magic = 0; magic <= 0xff; magic++) {
                bos.write(0xff - magic);
            }

            bos.write((byte) 0); // terminator

        }

        { // Image Descriptor.
            bos.write(IMAGE_SEPARATOR);
            bos.write2Bytes(0); // Image Left Position
            bos.write2Bytes(0); // Image Top Position
            bos.write2Bytes(width); // Image Width
            bos.write2Bytes(height); // Image Height

            {
                final boolean LocalColorTableFlag = true;
                // boolean LocalColorTableFlag = false;
                final boolean InterlaceFlag = false;
                final boolean SortFlag = false;
                final int SizeOfLocalColorTable = colorTableScaleLessOne;

                // int SizeOfLocalColorTable = 0;

                final int PackedFields = ((LocalColorTableFlag ? LOCAL_COLOR_TABLE_FLAG_MASK
                        : 0)
                        | (InterlaceFlag ? INTERLACE_FLAG_MASK : 0)
                        | (SortFlag ? SORT_FLAG_MASK : 0) | (7 & SizeOfLocalColorTable));
                bos.write(PackedFields); // one byte
            }
        }

        { // write Local Color Table.
            for (int i = 0; i < colorTableSizeInFormat; i++) {
                if (i < palette2.length()) {
                    final int rgb = palette2.getEntry(i);

                    final int red = 0xff & (rgb >> 16);
                    final int green = 0xff & (rgb >> 8);
                    final int blue = 0xff & (rgb >> 0);

                    bos.write(red);
                    bos.write(green);
                    bos.write(blue);
                } else {
                    bos.write(0);
                    bos.write(0);
                    bos.write(0);
                }
            }
        }

        { // get Image Data.
//            int image_data_total = 0;

            int LZWMinimumCodeSize = colorTableScaleLessOne + 1;
            // LZWMinimumCodeSize = Math.max(8, LZWMinimumCodeSize);
            if (LZWMinimumCodeSize < 2) {
                LZWMinimumCodeSize = 2;
            }

            // TODO:
            // make
            // better
            // choice
            // here.
            bos.write(LZWMinimumCodeSize);

            final MyLzwCompressor compressor = new MyLzwCompressor(
                    LZWMinimumCodeSize, ByteOrder.LITTLE_ENDIAN, false); // GIF
            // Mode);

            final byte imagedata[] = new byte[width * height];
            for (int y = 0; y < height; y++) {
                for (int x = 0; x < width; x++) {
                    final int argb = src.getRGB(x, y);
                    final int rgb = 0xffffff & argb;
                    int index;

                    if (hasAlpha) {
                        final int alpha = 0xff & (argb >> 24);
                        final int alphaThreshold = 255;
                        if (alpha < alphaThreshold) {
                            index = palette2.length(); // is transparent
                        } else {
                            index = palette2.getPaletteIndex(rgb);
                        }
                    } else {
                        index = palette2.getPaletteIndex(rgb);
                    }

                    imagedata[y * width + x] = (byte) index;
                }
            }

            final byte compressed[] = compressor.compress(imagedata);
            writeAsSubBlocks(bos, compressed);
//            image_data_total += compressed.length;
        }

        // palette2.dump();

        bos.write(TERMINATOR_BYTE);

        bos.close();
        os.close();
    }

    private static final byte XMP_APPLICATION_ID_AND_AUTH_CODE[] = { 0x58, // X
            0x4D, // M
            0x50, // P
            0x20, //
            0x44, // D
            0x61, // a
            0x74, // t
            0x61, // a
            0x58, // X
            0x4D, // M
            0x50, // P
    };

    /**
     * Extracts embedded XML metadata as XML string.
     * <p>
     * 
     * @param byteSource
     *            File containing image data.
     * @param params
     *            Map of optional parameters, defined in ImagingConstants.
     * @return Xmp Xml as String, if present. Otherwise, returns null.
     */
    @Override
    public String getXmpXml(final ByteSource byteSource, final Map<String,Object> params)
            throws ImageReadException, IOException {

        InputStream is = null;
        boolean canThrow = false;
        try {
            is = byteSource.getInputStream();

            final FormatCompliance formatCompliance = null;
            final GifHeaderInfo ghi = readHeader(is, formatCompliance);

            if (ghi.globalColorTableFlag) {
                readColorTable(is, ghi.sizeOfGlobalColorTable, formatCompliance);
            }

            final List<GifBlock> blocks = readBlocks(ghi, is, true, formatCompliance);

            final List<String> result = new ArrayList<String>();
            for (int i = 0; i < blocks.size(); i++) {
                final GifBlock block = blocks.get(i);
                if (block.blockCode != XMP_COMPLETE_CODE) {
                    continue;
                }

                final GenericGifBlock genericBlock = (GenericGifBlock) block;

                final byte blockBytes[] = genericBlock.appendSubBlocks(true);
                if (blockBytes.length < XMP_APPLICATION_ID_AND_AUTH_CODE.length) {
                    continue;
                }

                if (!compareBytes(blockBytes, 0,
                        XMP_APPLICATION_ID_AND_AUTH_CODE, 0,
                        XMP_APPLICATION_ID_AND_AUTH_CODE.length)) {
                    continue;
                }

                final byte GIF_MAGIC_TRAILER[] = new byte[256];
                for (int magic = 0; magic <= 0xff; magic++) {
                    GIF_MAGIC_TRAILER[magic] = (byte) (0xff - magic);
                }

                if (blockBytes.length < XMP_APPLICATION_ID_AND_AUTH_CODE.length
                        + GIF_MAGIC_TRAILER.length) {
                    continue;
                }
                if (!compareBytes(blockBytes, blockBytes.length
                        - GIF_MAGIC_TRAILER.length, GIF_MAGIC_TRAILER, 0,
                        GIF_MAGIC_TRAILER.length)) {
                    throw new ImageReadException(
                            "XMP block in GIF missing magic trailer.");
                }

                try {
                    // XMP is UTF-8 encoded xml.
                    final String xml = new String(
                            blockBytes,
                            XMP_APPLICATION_ID_AND_AUTH_CODE.length,
                            blockBytes.length
                                    - (XMP_APPLICATION_ID_AND_AUTH_CODE.length + GIF_MAGIC_TRAILER.length),
                            "utf-8");
                    result.add(xml);
                } catch (final UnsupportedEncodingException e) {
                    throw new ImageReadException("Invalid XMP Block in GIF.");
                }
            }

            if (result.size() < 1) {
                return null;
            }
            if (result.size() > 1) {
                throw new ImageReadException("More than one XMP Block in GIF.");
            }
            canThrow = true;
            return result.get(0);

        } finally {
            IoUtils.closeQuietly(canThrow, is);
        }
    }
}
