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

import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
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.ImageInfo;
import org.apache.commons.imaging.ImageParser;
import org.apache.commons.imaging.ImageReadException;
import org.apache.commons.imaging.ImageWriteException;
import org.apache.commons.imaging.PixelDensity;
import org.apache.commons.imaging.common.BinaryOutputStream;
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.bmp.pixelparsers.PixelParser;
import org.apache.commons.imaging.formats.bmp.pixelparsers.PixelParserBitFields;
import org.apache.commons.imaging.formats.bmp.pixelparsers.PixelParserRgb;
import org.apache.commons.imaging.formats.bmp.pixelparsers.PixelParserRle;
import org.apache.commons.imaging.formats.bmp.writers.BmpWriter;
import org.apache.commons.imaging.formats.bmp.writers.BmpWriterPalette;
import org.apache.commons.imaging.formats.bmp.writers.BmpWriterRgb;
import org.apache.commons.imaging.palette.PaletteFactory;
import org.apache.commons.imaging.palette.SimplePalette;
import org.apache.commons.imaging.util.Debug;
import org.apache.commons.imaging.util.ParamMap;

public class BmpImageParser extends ImageParser
{

    public BmpImageParser()
    {
        super.setByteOrder(BYTE_ORDER_INTEL);
    }

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

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

    private static final String DEFAULT_EXTENSION = ".bmp";

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

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

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

    private static final byte BMP_HEADER_SIGNATURE[] = { 0x42, 0x4d, };

    private BmpHeaderInfo readBmpHeaderInfo(InputStream is,
            FormatCompliance formatCompliance, boolean verbose)
            throws ImageReadException, IOException
    {
        byte identifier1 = readByte("Identifier1", is, "Not a Valid BMP File");
        byte identifier2 = readByte("Identifier2", is, "Not a Valid BMP File");

        if (formatCompliance != null)
        {
            formatCompliance.compare_bytes("Signature", BMP_HEADER_SIGNATURE,
                    new byte[] { identifier1, identifier2, });
        }

        int fileSize = read4Bytes("File Size", is, "Not a Valid BMP File");
        int reserved = read4Bytes("Reserved", is, "Not a Valid BMP File");
        int bitmapDataOffset = read4Bytes("Bitmap Data Offset", is,
                "Not a Valid BMP File");

        int bitmapHeaderSize = read4Bytes("Bitmap Header Size", is,
                "Not a Valid BMP File");
        int width = 0;
        int height = 0;
        int planes = 0;
        int bitsPerPixel = 0;
        int compression = 0;
        int bitmapDataSize = 0;
        int hResolution = 0;
        int vResolution = 0;
        int colorsUsed = 0;
        int colorsImportant = 0;
        int redMask = 0;
        int greenMask = 0;
        int blueMask = 0;
        int alphaMask = 0;
        int colorSpaceType = 0;
        BmpHeaderInfo.ColorSpace colorSpace = new BmpHeaderInfo.ColorSpace();
        colorSpace.red = new BmpHeaderInfo.ColorSpaceCoordinate();
        colorSpace.green = new BmpHeaderInfo.ColorSpaceCoordinate();
        colorSpace.blue = new BmpHeaderInfo.ColorSpaceCoordinate();
        int gammaRed = 0;
        int gammaGreen = 0;
        int gammaBlue = 0;
        int intent = 0;
        int profileData = 0;
        int profileSize = 0;
        int reservedV5 = 0;
        
        if (bitmapHeaderSize >= 40)
        {
            // BITMAPINFOHEADER
            width = read4Bytes("Width", is, "Not a Valid BMP File");
            height = read4Bytes("Height", is, "Not a Valid BMP File");
            planes = read2Bytes("Planes", is, "Not a Valid BMP File");
            bitsPerPixel = read2Bytes("Bits Per Pixel", is,
                    "Not a Valid BMP File");
            compression = read4Bytes("Compression", is, "Not a Valid BMP File");
            bitmapDataSize = read4Bytes("Bitmap Data Size", is,
                    "Not a Valid BMP File");
            hResolution = read4Bytes("HResolution", is, "Not a Valid BMP File");
            vResolution = read4Bytes("VResolution", is, "Not a Valid BMP File");
            colorsUsed = read4Bytes("ColorsUsed", is, "Not a Valid BMP File");
            colorsImportant = read4Bytes("ColorsImportant", is,
                    "Not a Valid BMP File");
            if (bitmapHeaderSize >= 52 || compression == BI_BITFIELDS)
            {
                // 52 = BITMAPV2INFOHEADER, now undocumented
                // see http://en.wikipedia.org/wiki/BMP_file_format
                redMask = read4Bytes("RedMask", is, "Not a Valid BMP File");
                greenMask = read4Bytes("GreenMask", is, "Not a Valid BMP File");
                blueMask = read4Bytes("BlueMask", is, "Not a Valid BMP File");
            }
            if (bitmapHeaderSize >= 56)
            {
                // 56 = the now undocumented BITMAPV3HEADER sometimes used by Photoshop
                // see http://forums.adobe.com/thread/751592?tstart=1
                alphaMask = read4Bytes("AlphaMask", is, "Not a Valid BMP File");
            }
            if (bitmapHeaderSize >= 108)
            {
                // BITMAPV4HEADER
                colorSpaceType = read4Bytes("ColorSpaceType", is, "Not a Valid BMP File");
                colorSpace.red.x = read4Bytes("ColorSpaceRedX", is, "Not a Valid BMP File");
                colorSpace.red.y = read4Bytes("ColorSpaceRedY", is, "Not a Valid BMP File");
                colorSpace.red.z = read4Bytes("ColorSpaceRedZ", is, "Not a Valid BMP File");
                colorSpace.green.x = read4Bytes("ColorSpaceGreenX", is, "Not a Valid BMP File");
                colorSpace.green.y = read4Bytes("ColorSpaceGreenY", is, "Not a Valid BMP File");
                colorSpace.green.z = read4Bytes("ColorSpaceGreenZ", is, "Not a Valid BMP File");
                colorSpace.blue.x = read4Bytes("ColorSpaceBlueX", is, "Not a Valid BMP File");
                colorSpace.blue.y = read4Bytes("ColorSpaceBlueY", is, "Not a Valid BMP File");
                colorSpace.blue.z = read4Bytes("ColorSpaceBlueZ", is, "Not a Valid BMP File");
                gammaRed = read4Bytes("GammaRed", is, "Not a Valid BMP File");
                gammaGreen = read4Bytes("GammaGreen", is, "Not a Valid BMP File");
                gammaBlue = read4Bytes("GammaBlue", is, "Not a Valid BMP File");
            }
            if (bitmapHeaderSize >= 124)
            {
                // BITMAPV5HEADER
                intent = read4Bytes("Intent", is, "Not a Valid BMP File");
                profileData = read4Bytes("ProfileData", is, "Not a Valid BMP File");
                profileSize = read4Bytes("ProfileSize", is, "Not a Valid BMP File");
                reservedV5 = read4Bytes("Reserved", is, "Not a Valid BMP File");
            }
        }
        else
        {
            throw new ImageReadException("Invalid/unsupported BMP file");
        }

        if (verbose)
        {
            this.debugNumber("identifier1", identifier1, 1);
            this.debugNumber("identifier2", identifier2, 1);
            this.debugNumber("fileSize", fileSize, 4);
            this.debugNumber("reserved", reserved, 4);
            this.debugNumber("bitmapDataOffset", bitmapDataOffset, 4);
            this.debugNumber("bitmapHeaderSize", bitmapHeaderSize, 4);
            this.debugNumber("width", width, 4);
            this.debugNumber("height", height, 4);
            this.debugNumber("planes", planes, 2);
            this.debugNumber("bitsPerPixel", bitsPerPixel, 2);
            this.debugNumber("compression", compression, 4);
            this.debugNumber("bitmapDataSize", bitmapDataSize, 4);
            this.debugNumber("hResolution", hResolution, 4);
            this.debugNumber("vResolution", vResolution, 4);
            this.debugNumber("colorsUsed", colorsUsed, 4);
            this.debugNumber("colorsImportant", colorsImportant, 4);
            if (bitmapHeaderSize >= 52 || compression == BI_BITFIELDS)
            {
                this.debugNumber("redMask", redMask, 4);
                this.debugNumber("greenMask", greenMask, 4);
                this.debugNumber("blueMask", blueMask, 4);
            }
            if (bitmapHeaderSize >= 56)
            {
                this.debugNumber("alphaMask", alphaMask, 4);
            }
            if (bitmapHeaderSize >= 108)
            {
                this.debugNumber("colorSpaceType", colorSpaceType, 4);
                this.debugNumber("gammaRed", gammaRed, 4);
                this.debugNumber("gammaGreen", gammaGreen, 4);
                this.debugNumber("gammaBlue", gammaBlue, 4);
            }
            if (bitmapHeaderSize >= 124)
            {
                this.debugNumber("intent", intent, 4);
                this.debugNumber("profileData", profileData, 4);
                this.debugNumber("profileSize", profileSize, 4);
                this.debugNumber("reservedV5", reservedV5, 4);
            }
        }

        BmpHeaderInfo result = new BmpHeaderInfo(identifier1, identifier2,
                fileSize, reserved, bitmapDataOffset, bitmapHeaderSize, width,
                height, planes, bitsPerPixel, compression, bitmapDataSize,
                hResolution, vResolution, colorsUsed, colorsImportant,
                redMask, greenMask, blueMask, alphaMask, colorSpaceType,
                colorSpace, gammaRed, gammaGreen, gammaBlue, intent,
                profileData, profileSize, reservedV5);
        return result;
    }

    private static final int BI_RGB = 0;
    private static final int BI_RLE4 = 2;
    private static final int BI_RLE8 = 1;
    private static final int BI_BITFIELDS = 3;

    private byte[] getRLEBytes(InputStream is, int RLESamplesPerByte)
            throws IOException
    {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        // this.setDebug(true);

        boolean done = false;
        while (!done)
        {
            int a = 0xff & this.readByte("RLE a", is, "BMP: Bad RLE");
            baos.write(a);
            int b = 0xff & this.readByte("RLE b", is, "BMP: Bad RLE");
            baos.write(b);

            if (a == 0)
            {
                switch (b)
                {
                case 0: // EOL
                    break;
                case 1: // EOF
                    // System.out.println("xXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
                    // );
                    done = true;
                    break;
                case 2: {
                    // System.out.println("xXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
                    // );
                    int c = 0xff & this.readByte("RLE c", is, "BMP: Bad RLE");
                    baos.write(c);
                    int d = 0xff & this.readByte("RLE d", is, "BMP: Bad RLE");
                    baos.write(d);

                }
                    break;
                default: {
                    int size = b / RLESamplesPerByte;
                    if ((b % RLESamplesPerByte) > 0)
                        size++;
                    if ((size % 2) != 0)
                        size++;

                    // System.out.println("b: " + b);
                    // System.out.println("size: " + size);
                    // System.out.println("RLESamplesPerByte: " +
                    // RLESamplesPerByte);
                    // System.out.println("xXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
                    // );
                    byte bytes[] = this.readByteArray("bytes", size, is,
                            "RLE: Absolute Mode");
                    baos.write(bytes);
                }
                    break;
                }
            }
        }

        return baos.toByteArray();
    }

    private ImageContents readImageContents(InputStream is,
            FormatCompliance formatCompliance, boolean verbose)
            throws ImageReadException, IOException
    {
        BmpHeaderInfo bhi = readBmpHeaderInfo(is, formatCompliance, verbose);

        int colorTableSize = bhi.colorsUsed;
        if (colorTableSize == 0)
            colorTableSize = (1 << bhi.bitsPerPixel);

        if (verbose)
        {
            this.debugNumber("ColorsUsed", bhi.colorsUsed, 4);
            this.debugNumber("BitsPerPixel", bhi.bitsPerPixel, 4);
            this.debugNumber("ColorTableSize", colorTableSize, 4);
            this.debugNumber("bhi.colorsUsed", bhi.colorsUsed, 4);
            this.debugNumber("Compression", bhi.compression, 4);
        }

        // A palette is always valid, even for images that don't need it
        // (like 32 bpp), it specifies the "optimal color palette" for
        // when the image is displayed on a <= 256 color graphics card.
        int paletteLength;
        int rleSamplesPerByte = 0;
        boolean rle = false;

        switch (bhi.compression)
        {
        case BI_RGB:
            if (verbose)
                System.out.println("Compression: BI_RGB");
            if (bhi.bitsPerPixel <= 8)
                paletteLength = 4 * colorTableSize;
            else
                paletteLength = 0;
            // BytesPerPaletteEntry = 0;
            // System.out.println("Compression: BI_RGBx2: " + bhi.BitsPerPixel);
            // System.out.println("Compression: BI_RGBx2: " + (bhi.BitsPerPixel
            // <= 16));
            break;

        case BI_RLE4:
            if (verbose)
                System.out.println("Compression: BI_RLE4");
            paletteLength = 4 * colorTableSize;
            rleSamplesPerByte = 2;
            // ExtraBitsPerPixel = 4;
            rle = true;
            // // BytesPerPixel = 2;
            // // BytesPerPaletteEntry = 0;
            break;
        //
        case BI_RLE8:
            if (verbose)
                System.out.println("Compression: BI_RLE8");
            paletteLength = 4 * colorTableSize;
            rleSamplesPerByte = 1;
            // ExtraBitsPerPixel = 8;
            rle = true;
            // BytesPerPixel = 2;
            // BytesPerPaletteEntry = 0;
            break;
        //
        case BI_BITFIELDS:
            if (verbose)
                System.out.println("Compression: BI_BITFIELDS");
            if (bhi.bitsPerPixel <= 8)
                paletteLength = 4 * colorTableSize;
            else
                paletteLength = 0;
            // BytesPerPixel = 2;
            // BytesPerPaletteEntry = 4;
            break;

        default:
            throw new ImageReadException("BMP: Unknown Compression: "
                    + bhi.compression);
        }

        byte colorTable[] = null;
        if (paletteLength > 0)
            colorTable = this.readByteArray("ColorTable", paletteLength, is,
                    "Not a Valid BMP File");

        if (verbose)
        {
            this.debugNumber("paletteLength", paletteLength, 4);
            System.out.println("ColorTable: "
                    + ((colorTable == null) ? "null" : "" + colorTable.length));
        }

        int pixelCount = bhi.width * bhi.height;

        int imageLineLength = ((((bhi.bitsPerPixel) * bhi.width) + 7) / 8);

        if (verbose)
        {
            // this.debugNumber("Total BitsPerPixel",
            // (ExtraBitsPerPixel + bhi.BitsPerPixel), 4);
            // this.debugNumber("Total Bit Per Line",
            // ((ExtraBitsPerPixel + bhi.BitsPerPixel) * bhi.Width), 4);
            // this.debugNumber("ExtraBitsPerPixel", ExtraBitsPerPixel, 4);
            this.debugNumber("bhi.Width", bhi.width, 4);
            this.debugNumber("bhi.Height", bhi.height, 4);
            this.debugNumber("ImageLineLength", imageLineLength, 4);
            // this.debugNumber("imageDataSize", imageDataSize, 4);
            this.debugNumber("PixelCount", pixelCount, 4);
        }
        // int ImageLineLength = BytesPerPixel * bhi.Width;
        while ((imageLineLength % 4) != 0)
            imageLineLength++;

        final int headerSize = BITMAP_FILE_HEADER_SIZE
                + bhi.bitmapHeaderSize
                + (bhi.bitmapHeaderSize == 40 &&  bhi.compression == BI_BITFIELDS ? 3*4 : 0);
        int expectedDataOffset = headerSize + paletteLength;

        if (verbose)
        {
            this.debugNumber("bhi.BitmapDataOffset", bhi.bitmapDataOffset, 4);
            this.debugNumber("expectedDataOffset", expectedDataOffset, 4);
        }
        int extraBytes = bhi.bitmapDataOffset - expectedDataOffset;
        if (extraBytes < 0)
            throw new ImageReadException("BMP has invalid image data offset: "
                    + bhi.bitmapDataOffset + " (expected: "
                    + expectedDataOffset + ", paletteLength: " + paletteLength
                    + ", headerSize: " + headerSize + ")");
        else if (extraBytes > 0)
            this.readByteArray("BitmapDataOffset", extraBytes, is,
                    "Not a Valid BMP File");

        int imageDataSize = bhi.height * imageLineLength;

        if (verbose)
            this.debugNumber("imageDataSize", imageDataSize, 4);

        byte imageData[];
        if (rle)
            imageData = getRLEBytes(is, rleSamplesPerByte);
        else
            imageData = this.readByteArray("ImageData", imageDataSize, is,
                    "Not a Valid BMP File");

        if (verbose)
            this.debugNumber("ImageData.length", imageData.length, 4);

        PixelParser pixelParser;

        switch (bhi.compression)
        {
        case BI_RLE4:
        case BI_RLE8:
            pixelParser = new PixelParserRle(bhi, colorTable, imageData);
            break;
        case BI_RGB:
            pixelParser = new PixelParserRgb(bhi, colorTable, imageData);
            break;
        case BI_BITFIELDS:
            pixelParser = new PixelParserBitFields(bhi, colorTable, imageData);
            break;
        default:
            throw new ImageReadException("BMP: Unknown Compression: "
                    + bhi.compression);
        }

        return new ImageContents(bhi, colorTable, imageData, pixelParser);
    }

    private BmpHeaderInfo readBmpHeaderInfo(ByteSource byteSource,
            boolean verbose) throws ImageReadException, IOException
    {
        InputStream is = null;
        try
        {
            is = byteSource.getInputStream();

            // readSignature(is);
            return readBmpHeaderInfo(is, null, verbose);
        } finally
        {
            try
            {
                if (is != null) {
                    is.close();
                }
            } catch (Exception e)
            {
                Debug.debug(e);
            }

        }
    }

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

    @Override
    public Dimension getImageSize(ByteSource byteSource, Map params)
            throws ImageReadException, IOException
    {
        // make copy of params; we'll clear keys as we consume them.
        params = (params == null) ? new HashMap() : new HashMap(params);

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

        if (params.containsKey(PARAM_KEY_VERBOSE))
            params.remove(PARAM_KEY_VERBOSE);

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

        BmpHeaderInfo bhi = readBmpHeaderInfo(byteSource, verbose);

        if (bhi == null)
            throw new ImageReadException("BMP: couldn't read header");

        return new Dimension(bhi.width, bhi.height);

    }

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

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

    @Override
    public IImageMetadata getMetadata(ByteSource byteSource, Map params)
            throws ImageReadException, IOException
    {
        return null;
    }

    private String getBmpTypeDescription(int Identifier1, int Identifier2)
    {
        if ((Identifier1 == 'B') && (Identifier2 == 'M'))
            return "Windows 3.1x, 95, NT,";
        if ((Identifier1 == 'B') && (Identifier2 == 'A'))
            return "OS/2 Bitmap Array";
        if ((Identifier1 == 'C') && (Identifier2 == 'I'))
            return "OS/2 Color Icon";
        if ((Identifier1 == 'C') && (Identifier2 == 'P'))
            return "OS/2 Color Pointer";
        if ((Identifier1 == 'I') && (Identifier2 == 'C'))
            return "OS/2 Icon";
        if ((Identifier1 == 'P') && (Identifier2 == 'T'))
            return "OS/2 Pointer";

        return "Unknown";
    }

    @Override
    public ImageInfo getImageInfo(ByteSource byteSource, Map params)
            throws ImageReadException, IOException
    {
        // make copy of params; we'll clear keys as we consume them.
        params = (params == null) ? new HashMap() : new HashMap(params);

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

        if (params.containsKey(PARAM_KEY_VERBOSE))
            params.remove(PARAM_KEY_VERBOSE);

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

        InputStream is = null;
        ImageContents ic = null;
        try {
            is = byteSource.getInputStream();
            ic = readImageContents(is, FormatCompliance.getDefault(), verbose);
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException ignore) {
                }
            }
        }

        if (ic == null)
            throw new ImageReadException("Couldn't read BMP Data");

        BmpHeaderInfo bhi = ic.bhi;
        byte colorTable[] = ic.colorTable;

        if (bhi == null)
            throw new ImageReadException("BMP: couldn't read header");

        int height = bhi.height;
        int width = bhi.width;

        List<String> comments = new ArrayList<String>();
        // TODO: comments...

        int bitsPerPixel = bhi.bitsPerPixel;
        ImageFormat format = ImageFormat.IMAGE_FORMAT_BMP;
        String name = "BMP Windows Bitmap";
        String mimeType = "image/x-ms-bmp";
        // we ought to count images, but don't yet.
        int numberOfImages = -1;
        // not accurate ... only reflects first
        boolean isProgressive = false;
        // boolean isProgressive = (fPNGChunkIHDR.InterlaceMethod != 0);
        //
        // pixels per meter
        int physicalWidthDpi = (int) (bhi.hResolution * 1000.0 / 2.54);
        float physicalWidthInch = (float) ((double) width / (double) physicalWidthDpi);
        // int physicalHeightDpi = 72;
        int physicalHeightDpi = (int) (bhi.vResolution * 1000.0 / 2.54);
        float physicalHeightInch = (float) ((double) height / (double) physicalHeightDpi);

        String formatDetails = "Bmp (" + (char) bhi.identifier1
                + (char) bhi.identifier2 + ": "
                + getBmpTypeDescription(bhi.identifier1, bhi.identifier2) + ")";

        boolean isTransparent = false;

        boolean usesPalette = colorTable != null;
        int colorType = ImageInfo.COLOR_TYPE_RGB;
        String compressionAlgorithm = ImageInfo.COMPRESSION_ALGORITHM_RLE;

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

        return result;
    }

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

        ImageInfo imageData = getImageInfo(byteSource, null);
        if (imageData == null)
            return false;

        imageData.toString(pw, "");

        pw.println("");

        return true;
    }

    @Override
    public FormatCompliance getFormatCompliance(ByteSource byteSource)
            throws ImageReadException, IOException
    {
        boolean verbose = false;

        FormatCompliance result = new FormatCompliance(byteSource
                .getDescription());

        InputStream is = null;
        try {
            is = byteSource.getInputStream();
            readImageContents(is, result, verbose);
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException ignore) {
                }
            }
        }

        return result;
    }

    @Override
    public BufferedImage getBufferedImage(ByteSource byteSource, Map params)
            throws ImageReadException, IOException
    {
        InputStream is = null;
        try {
            is = byteSource.getInputStream();
            return getBufferedImage(is, params);
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException ignore) {
                }
            }
        }
    }

    public BufferedImage getBufferedImage(InputStream inputStream, Map params)
            throws ImageReadException, IOException
    {
        // make copy of params; we'll clear keys as we consume them.
        params = (params == null) ? new HashMap() : new HashMap(params);

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

        if (params.containsKey(PARAM_KEY_VERBOSE))
            params.remove(PARAM_KEY_VERBOSE);
        if (params.containsKey(BUFFERED_IMAGE_FACTORY))
            params.remove(BUFFERED_IMAGE_FACTORY);

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

        ImageContents ic = readImageContents(inputStream,
                FormatCompliance.getDefault(), verbose);
        if (ic == null)
            throw new ImageReadException("Couldn't read BMP Data");

        BmpHeaderInfo bhi = ic.bhi;
        // byte colorTable[] = ic.colorTable;
        // byte imageData[] = ic.imageData;

        int width = bhi.width;
        int height = bhi.height;

        if (verbose)
        {
            System.out.println("width: " + width);
            System.out.println("height: " + height);
            System.out.println("width*height: " + width * height);
            System.out.println("width*height*4: " + width * height * 4);
        }

        PixelParser pixelParser = ic.pixelParser;
        ImageBuilder imageBuilder = new ImageBuilder(width, height, true);
        pixelParser.processImage(imageBuilder);

        return imageBuilder.getBufferedImage();

    }

    private static final int BITMAP_FILE_HEADER_SIZE = 14;
    private static final int BITMAP_INFO_HEADER_SIZE = 40;

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

        PixelDensity pixelDensity = null;
        
        // clear format key.
        if (params.containsKey(PARAM_KEY_FORMAT))
            params.remove(PARAM_KEY_FORMAT);
        if (params.containsKey(PARAM_KEY_PIXEL_DENSITY))
            pixelDensity = (PixelDensity) params.remove(PARAM_KEY_PIXEL_DENSITY);

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

        final SimplePalette palette = new PaletteFactory().makePaletteSimple(
                src, 256);

        BmpWriter writer = null;
        if (palette == null)
            writer = new BmpWriterRgb();
        else
            writer = new BmpWriterPalette(palette);

        byte imagedata[] = writer.getImageData(src);
        BinaryOutputStream bos = new BinaryOutputStream(os, BYTE_ORDER_INTEL);

        {
            // write BitmapFileHeader
            os.write(0x42); // B, Windows 3.1x, 95, NT, Bitmap
            os.write(0x4d); // M

            int filesize = BITMAP_FILE_HEADER_SIZE + BITMAP_INFO_HEADER_SIZE + // header
                    // size
                    4 * writer.getPaletteSize() + // palette size in bytes
                    imagedata.length;
            bos.write4Bytes(filesize);

            bos.write4Bytes(0); // reserved
            bos.write4Bytes(BITMAP_FILE_HEADER_SIZE + BITMAP_INFO_HEADER_SIZE
                    + 4 * writer.getPaletteSize()); // Bitmap Data Offset
        }

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

        { // write BitmapInfoHeader
            bos.write4Bytes(BITMAP_INFO_HEADER_SIZE); // Bitmap Info Header Size
            bos.write4Bytes(width); // width
            bos.write4Bytes(height); // height
            bos.write2Bytes(1); // Number of Planes
            bos.write2Bytes(writer.getBitsPerPixel()); // Bits Per Pixel

            bos.write4Bytes(BI_RGB); // Compression
            bos.write4Bytes(imagedata.length); // Bitmap Data Size
            bos.write4Bytes(pixelDensity != null ? (int)Math.round(pixelDensity.horizontalDensityMetres()) : 0); // HResolution
            bos.write4Bytes(pixelDensity != null ? (int)Math.round(pixelDensity.verticalDensityMetres()) : 0); // VResolution
            if (palette == null)
                bos.write4Bytes(0); // Colors
            else
                bos.write4Bytes(palette.length()); // Colors
            bos.write4Bytes(0); // Important Colors
            // bos.write_4_bytes(0); // Compression
        }

        { // write Palette
            writer.writePalette(bos);
        }
        { // write Image Data
            bos.writeByteArray(imagedata);
        }
    }

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

}
