/*
 * 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.sanselan.formats.ico;

import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
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.sanselan.ImageFormat;
import org.apache.commons.sanselan.ImageInfo;
import org.apache.commons.sanselan.ImageParser;
import org.apache.commons.sanselan.ImageReadException;
import org.apache.commons.sanselan.ImageWriteException;
import org.apache.commons.sanselan.Sanselan;
import org.apache.commons.sanselan.common.BinaryOutputStream;
import org.apache.commons.sanselan.common.IImageMetadata;
import org.apache.commons.sanselan.common.bytesource.ByteSource;
import org.apache.commons.sanselan.formats.bmp.BmpImageParser;
import org.apache.commons.sanselan.palette.PaletteFactory;
import org.apache.commons.sanselan.palette.SimplePalette;
import org.apache.commons.sanselan.util.Debug;

public class IcoImageParser extends ImageParser
{

    public IcoImageParser()
    {
        super.setByteOrder(BYTE_ORDER_LSB);
    }

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

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

    private static final String DEFAULT_EXTENSION = ".ico";

    private static final String ACCEPTED_EXTENSIONS[] = {
            ".ico", ".cur",
    };

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

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

    @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;
    }

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

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

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

    private static class FileHeader
    {
        public final int reserved; // Reserved (2 bytes), always 0
        public final int iconType; // IconType (2 bytes), if the image is an icon it?s 1, for cursors the value is 2.
        public final int iconCount; //IconCount (2 bytes), number of icons in this file.

        public FileHeader(final int reserved, final int iconType,
                final int iconCount)
        {
            this.reserved = reserved;
            this.iconType = iconType;
            this.iconCount = iconCount;
        }

        public void dump(PrintWriter pw)
        {
            pw.println("FileHeader");
            pw.println("Reserved: " + reserved);
            pw.println("IconType: " + iconType);
            pw.println("IconCount: " + iconCount);
            pw.println();
        }
    }

    private FileHeader readFileHeader(InputStream is)
            throws ImageReadException, IOException
    {
        int Reserved = read2Bytes("Reserved", is, "Not a Valid ICO File");
        int IconType = read2Bytes("IconType", is, "Not a Valid ICO File");
        int IconCount = read2Bytes("IconCount", is, "Not a Valid ICO File");

        if (Reserved != 0)
            throw new ImageReadException("Not a Valid ICO File: reserved is " + Reserved);
        if (IconType != 1 && IconType != 2)
            throw new ImageReadException("Not a Valid ICO File: icon type is " + IconType);

        return new FileHeader(Reserved, IconType, IconCount);

    }

    private static class IconInfo
    {
        public final byte Width;
        public final byte Height;
        public final byte ColorCount;
        public final byte Reserved;
        public final int Planes;
        public final int BitCount;
        public final int ImageSize;
        public final int ImageOffset;

        public IconInfo(final byte width, final byte height,
                final byte colorCount, final byte reserved, final int planes,
                final int bitCount, final int imageSize, final int imageOffset)
        {
            Width = width;
            Height = height;
            ColorCount = colorCount;
            Reserved = reserved;
            Planes = planes;
            BitCount = bitCount;
            ImageSize = imageSize;
            ImageOffset = imageOffset;
        }

        public void dump(PrintWriter pw)
        {
            pw.println("IconInfo");
            pw.println("Width: " + Width);
            pw.println("Height: " + Height);
            pw.println("ColorCount: " + ColorCount);
            pw.println("Reserved: " + Reserved);
            pw.println("Planes: " + Planes);
            pw.println("BitCount: " + BitCount);
            pw.println("ImageSize: " + ImageSize);
            pw.println("ImageOffset: " + ImageOffset);
        }
    }

    private IconInfo readIconInfo(InputStream is) throws ImageReadException,
            IOException
    {
        byte Width = readByte("Width", is, "Not a Valid ICO File"); // Width (1 byte), Width of Icon (1 to 255)
        byte Height = readByte("Height", is, "Not a Valid ICO File"); // Height (1 byte), Height of Icon (1 to 255)
        byte ColorCount = readByte("ColorCount", is, "Not a Valid ICO File"); // ColorCount (1 byte), Number of colors, either 0 for 24 bit or higher, 2 for monochrome or 16 for 16 color images.
        byte Reserved = readByte("Reserved", is, "Not a Valid ICO File"); // Reserved (1 byte), Not used (always 0)
        int Planes = read2Bytes("Planes", is, "Not a Valid ICO File"); // Planes (2 bytes), always 1
        int BitCount = read2Bytes("BitCount", is, "Not a Valid ICO File"); // BitCount (2 bytes), number of bits per pixel (1 for monochrome, 4 for 16 colors, 8 for 256 colors, 24 for true colors, 32 for true colors + alpha channel)
        int ImageSize = read4Bytes("ImageSize", is, "Not a Valid ICO File"); // ImageSize (4 bytes), Length of resource in bytes
        int ImageOffset = read4Bytes("ImageOffset", is, "Not a Valid ICO File"); // ImageOffset (4 bytes), start of the image in the file.

        return new IconInfo(Width, Height, ColorCount, Reserved, Planes,
                BitCount, ImageSize, ImageOffset);
    }

    private static class BitmapHeader
    {
        public final int Size;
        public final int Width;
        public final int Height;
        public final int Planes;
        public final int BitCount;
        public final int Compression;
        public final int SizeImage;
        public final int XPelsPerMeter;
        public final int YPelsPerMeter;
        public final int ColorsUsed;
        public final int ColorsImportant;

        public BitmapHeader(final int size, final int width, final int height,
                final int planes, final int bitCount, final int compression,
                final int sizeImage, final int pelsPerMeter,
                final int pelsPerMeter2, final int colorsUsed,
                final int colorsImportant)
        {
            Size = size;
            Width = width;
            Height = height;
            Planes = planes;
            BitCount = bitCount;
            Compression = compression;
            SizeImage = sizeImage;
            XPelsPerMeter = pelsPerMeter;
            YPelsPerMeter = pelsPerMeter2;
            ColorsUsed = colorsUsed;
            ColorsImportant = colorsImportant;
        }

        public void dump(PrintWriter pw)
        {
            pw.println("BitmapHeader");

            pw.println("Size: " + Size);
            pw.println("Width: " + Width);
            pw.println("Height: " + Height);
            pw.println("Planes: " + Planes);
            pw.println("BitCount: " + BitCount);
            pw.println("Compression: " + Compression);
            pw.println("SizeImage: " + SizeImage);
            pw.println("XPelsPerMeter: " + XPelsPerMeter);
            pw.println("YPelsPerMeter: " + YPelsPerMeter);
            pw.println("ColorsUsed: " + ColorsUsed);
            pw.println("ColorsImportant: " + ColorsImportant);
        }
    }

    private static abstract class IconData
    {
        public final IconInfo iconInfo;

        public IconData(final IconInfo iconInfo)
        {
            this.iconInfo = iconInfo;
        }

        public void dump(PrintWriter pw)
        {
            iconInfo.dump(pw);
            pw.println();
            dumpSubclass(pw);
        }

        protected abstract void dumpSubclass(PrintWriter pw);
        public abstract BufferedImage readBufferedImage() throws ImageReadException;
    }

    private static class BitmapIconData extends IconData
    {
        public final BitmapHeader header;
        public final BufferedImage bufferedImage;

        public BitmapIconData(final IconInfo iconInfo, final BitmapHeader header,
                final BufferedImage bufferedImage)
        {
            super(iconInfo);
            this.header = header;
            this.bufferedImage = bufferedImage;
        }

        @Override
        public BufferedImage readBufferedImage() throws ImageReadException
        {
            return bufferedImage;
        }

        @Override
        protected void dumpSubclass(PrintWriter pw)
        {
            pw.println("BitmapIconData");
            header.dump(pw);
            pw.println();
        }
    }

    private static class PNGIconData extends IconData
    {
        public final BufferedImage bufferedImage;

        public PNGIconData(final IconInfo iconInfo, final BufferedImage bufferedImage)
        {
            super(iconInfo);
            this.bufferedImage = bufferedImage;
        }

        @Override
        public BufferedImage readBufferedImage()
        {
            return bufferedImage;
        }

        @Override
        protected void dumpSubclass(PrintWriter pw)
        {
            pw.println("PNGIconData");
            pw.println();
        }
    }

    private IconData readBitmapIconData(byte[] iconData, IconInfo fIconInfo) throws ImageReadException, IOException
    {
        ByteArrayInputStream is = new ByteArrayInputStream(iconData);
        int Size = read4Bytes("Size", is, "Not a Valid ICO File"); // Size (4 bytes), size of this structure (always 40)
        int Width = read4Bytes("Width", is, "Not a Valid ICO File"); // Width (4 bytes), width of the image (same as iconinfo.width)
        int Height = read4Bytes("Height", is, "Not a Valid ICO File"); // Height (4 bytes), scanlines in the color map + transparent map (iconinfo.height * 2)
        int Planes = read2Bytes("Planes", is, "Not a Valid ICO File"); // Planes (2 bytes), always 1
        int BitCount = read2Bytes("BitCount", is, "Not a Valid ICO File"); // BitCount (2 bytes), 1,4,8,16,24,32 (see iconinfo for details)
        int Compression = read4Bytes("Compression", is, "Not a Valid ICO File"); // Compression (4 bytes), we don?t use this (0)
        int SizeImage = read4Bytes("SizeImage", is, "Not a Valid ICO File"); // SizeImage (4 bytes), we don?t use this (0)
        int XPelsPerMeter = read4Bytes("XPelsPerMeter", is,
                "Not a Valid ICO File"); // XPelsPerMeter (4 bytes), we don?t use this (0)
        int YPelsPerMeter = read4Bytes("YPelsPerMeter", is,
                "Not a Valid ICO File"); // YPelsPerMeter (4 bytes), we don?t use this (0)
        int ColorsUsed = read4Bytes("ColorsUsed", is, "Not a Valid ICO File"); // ColorsUsed (4 bytes), we don?t use this (0)
        int ColorsImportant = read4Bytes("ColorsImportant", is,
                "Not a Valid ICO File"); // ColorsImportant (4 bytes), we don?t use this (0)
        int RedMask = 0;
        int GreenMask = 0;
        int BlueMask = 0;
        int AlphaMask = 0;
        if (Compression == 3)
        {
            RedMask = read4Bytes("RedMask", is, "Not a Valid ICO File");
            GreenMask = read4Bytes("GreenMask", is, "Not a Valid ICO File");
            BlueMask = read4Bytes("BlueMask", is, "Not a Valid ICO File");
        }
        byte[] RestOfFile = readByteArray("RestOfFile", is.available(), is);

        if (Size != 40)
            throw new ImageReadException("Not a Valid ICO File: Wrong bitmap header size " + Size);
        if (Planes != 1)
            throw new ImageReadException("Not a Valid ICO File: Planes can't be " + Planes);

        if (Compression == 0 && BitCount == 32)
        {
            // 32 BPP RGB icons need an alpha channel, but BMP files don't have
            // one unless BI_BITFIELDS is used...
            Compression = 3;
            RedMask = 0x00ff0000;
            GreenMask = 0x0000ff00;
            BlueMask = 0x000000ff;
            AlphaMask = 0xff000000;
        }

        BitmapHeader header = new BitmapHeader(Size, Width, Height, Planes,
                BitCount, Compression, SizeImage, XPelsPerMeter, YPelsPerMeter,
                ColorsUsed, ColorsImportant);

        int bitmapPixelsOffset = 14 + 56 +
                4 * ((ColorsUsed == 0 && BitCount <= 8) ? (1 << BitCount) : ColorsUsed);
        int bitmapSize = 14 + 56 + RestOfFile.length;

        ByteArrayOutputStream baos = new ByteArrayOutputStream(bitmapSize);
        BinaryOutputStream bos = new BinaryOutputStream(baos,
                BinaryOutputStream.BYTE_ORDER_LITTLE_ENDIAN);

        bos.write('B');
        bos.write('M');
        bos.write4Bytes(bitmapSize);
        bos.write4Bytes(0);
        bos.write4Bytes(bitmapPixelsOffset);

        bos.write4Bytes(56);
        bos.write4Bytes(Width);
        bos.write4Bytes(Height / 2);
        bos.write2Bytes(Planes);
        bos.write2Bytes(BitCount);
        bos.write4Bytes(Compression);
        bos.write4Bytes(SizeImage);
        bos.write4Bytes(XPelsPerMeter);
        bos.write4Bytes(YPelsPerMeter);
        bos.write4Bytes(ColorsUsed);
        bos.write4Bytes(ColorsImportant);
        bos.write4Bytes(RedMask);
        bos.write4Bytes(GreenMask);
        bos.write4Bytes(BlueMask);
        bos.write4Bytes(AlphaMask);
        bos.write(RestOfFile);
        bos.flush();

        ByteArrayInputStream bmpInputStream = new ByteArrayInputStream(baos.toByteArray());
        BufferedImage bmpImage = new BmpImageParser().getBufferedImage(bmpInputStream, null);

        // Transparency map is optional with 32 BPP icons, because they already have
        // an alpha channel, and Windows only uses the transparency map when it has to
        // display the icon on a < 32 BPP screen. But it's still used instead of alpha
        // if the image would be completely transparent with alpha...
        int t_scanline_size = (Width + 7) / 8;
        if ((t_scanline_size % 4) != 0)
            t_scanline_size += 4 - (t_scanline_size % 4); // pad scanline to 4 byte size.
        int tcolor_map_size_bytes = t_scanline_size * (Height/2);
        byte[] transparency_map = null;
        try
        {
            transparency_map = this.readByteArray("transparency_map",
                    tcolor_map_size_bytes, bmpInputStream, "Not a Valid ICO File");
        }
        catch (IOException ioEx)
        {
            if (BitCount != 32)
            throw ioEx;
        }

        boolean allAlphasZero = true;
        if (BitCount == 32)
        {
            for (int y = 0; allAlphasZero && y < bmpImage.getHeight(); y++)
            {
                for (int x = 0; x < bmpImage.getWidth(); x++)
                {
                    if ((bmpImage.getRGB(x, y) & 0xff000000) != 0)
                    {
                        allAlphasZero = false;
                        break;
                    }
                }
            }
        }
        BufferedImage resultImage;
        if (allAlphasZero)
        {
            resultImage = new BufferedImage(bmpImage.getWidth(), bmpImage.getHeight(),
                    BufferedImage.TYPE_INT_ARGB);
            for (int y = 0; y < resultImage.getHeight(); y++)
            {
                for (int x = 0; x < resultImage.getWidth(); x++)
                {
                    int alpha = 0xff;
                    if (transparency_map != null)
                    {
                        int alpha_byte = 0xff & transparency_map[t_scanline_size
                                * (bmpImage.getHeight() - y - 1) + (x / 8)];
                        alpha = 0x01 & (alpha_byte >> (7 - (x % 8)));
                        alpha = (alpha == 0) ? 0xff : 0x00;
                    }
                    resultImage.setRGB(x, y, (alpha << 24) | (0xffffff & bmpImage.getRGB(x, y)));
                }
            }
        }
        else
            resultImage = bmpImage;
        return new BitmapIconData(fIconInfo, header, resultImage);
    }

    private IconData readIconData(byte[] iconData, IconInfo fIconInfo)
            throws ImageReadException, IOException
    {
        ImageFormat imageFormat = Sanselan.guessFormat(iconData);
        if (imageFormat.equals(ImageFormat.IMAGE_FORMAT_PNG))
        {
            BufferedImage bufferedImage = Sanselan.getBufferedImage(iconData);
            PNGIconData pngIconData = new PNGIconData(fIconInfo, bufferedImage);
            return pngIconData;
        }
        else
        {
            return readBitmapIconData(iconData, fIconInfo);
        }
    }

    private static class ImageContents
    {
        public final FileHeader fileHeader;
        public final IconData iconDatas[];

        public ImageContents(final FileHeader fileHeader,
                final IconData[] iconDatas)
        {
            super();
            this.fileHeader = fileHeader;
            this.iconDatas = iconDatas;
        }
    }

    private ImageContents readImage(ByteSource byteSource)
            throws ImageReadException, IOException
    {
        InputStream is = null;
        try
        {
            is = byteSource.getInputStream();
            FileHeader fileHeader = readFileHeader(is);

            IconInfo fIconInfos[] = new IconInfo[fileHeader.iconCount];
            for (int i = 0; i < fileHeader.iconCount; i++)
            {
                fIconInfos[i] = readIconInfo(is);
            }

            IconData fIconDatas[] = new IconData[fileHeader.iconCount];
            for (int i = 0; i < fileHeader.iconCount; i++)
            {
                byte[] iconData = byteSource.getBlock(fIconInfos[i].ImageOffset,
                        fIconInfos[i].ImageSize);
                fIconDatas[i] = readIconData(iconData, fIconInfos[i]);
            }

            return new ImageContents(fileHeader, fIconDatas);
        }
        finally
        {
            try
            {
                if (is != null) {
                    is.close();
                }
            }
            catch (Exception e)
            {
                Debug.debug(e);
            }

        }
    }

    @Override
    public boolean dumpImageFile(PrintWriter pw, ByteSource byteSource)
            throws ImageReadException, IOException
    {
        ImageContents contents = readImage(byteSource);
        contents.fileHeader.dump(pw);
        for (int i = 0; i < contents.iconDatas.length; i++)
            contents.iconDatas[i].dump(pw);
        return true;
    }

    @Override
    public final BufferedImage getBufferedImage(ByteSource byteSource,
            Map params) throws ImageReadException, IOException
    {
        ImageContents contents = readImage(byteSource);
        FileHeader fileHeader = contents.fileHeader;
        if (fileHeader.iconCount > 0)
            return contents.iconDatas[0].readBufferedImage();
        else
            throw new ImageReadException("No icons in ICO file");
    }

    @Override
    public List<BufferedImage> getAllBufferedImages(ByteSource byteSource)
            throws ImageReadException, IOException
    {
        List<BufferedImage> result = new ArrayList<BufferedImage>();
        ImageContents contents = readImage(byteSource);

        FileHeader fileHeader = contents.fileHeader;
        for (int i = 0; i < fileHeader.iconCount; i++)
        {
            IconData iconData = contents.iconDatas[i];

            BufferedImage image = iconData.readBufferedImage();

            result.add(image);
        }

        return result;
    }

    //    public boolean extractImages(ByteSource byteSource, File dst_dir,
    //            String dst_root, ImageParser encoder) throws ImageReadException,
    //            IOException, ImageWriteException
    //    {
    //        ImageContents contents = readImage(byteSource);
    //
    //        FileHeader fileHeader = contents.fileHeader;
    //        for (int i = 0; i < fileHeader.iconCount; i++)
    //        {
    //            IconData iconData = contents.iconDatas[i];
    //
    //            BufferedImage image = readBufferedImage(iconData);
    //
    //            int size = Math.max(iconData.iconInfo.Width,
    //                    iconData.iconInfo.Height);
    //            File file = new File(dst_dir, dst_root + "_" + size + "_"
    //                    + iconData.iconInfo.BitCount
    //                    + encoder.getDefaultExtension());
    //            encoder.writeImage(image, new FileOutputStream(file), null);
    //        }
    //
    //        return true;
    //    }

    @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);

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

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

        final PaletteFactory paletteFactory = new PaletteFactory();
        final SimplePalette palette = paletteFactory.makePaletteSimple(src, 256);
        final int bitCount;
        final boolean hasTransparency = paletteFactory.hasTransparency(src);
        if (palette == null)
        {
            if (hasTransparency)
                bitCount = 32;
            else
                bitCount = 24;
        }
        else if (palette.length() <= 2)
            bitCount = 1;
        else if (palette.length() <= 16)
            bitCount = 4;
        else
            bitCount = 8;

        BinaryOutputStream bos = new BinaryOutputStream(os, BYTE_ORDER_INTEL);

        int scanline_size = (bitCount * src.getWidth() + 7) / 8;
        if ((scanline_size % 4) != 0)
            scanline_size += 4 - (scanline_size % 4); // pad scanline to 4 byte size.
        int t_scanline_size = (src.getWidth() + 7) / 8;
        if ((t_scanline_size % 4) != 0)
            t_scanline_size += 4 - (t_scanline_size % 4); // pad scanline to 4 byte size.
        int imageSize = 40 + 4 * (bitCount <= 8 ? (1 << bitCount) : 0) +
                src.getHeight() * scanline_size +
                src.getHeight() * t_scanline_size;

        // ICONDIR
        bos.write2Bytes(0); // reserved
        bos.write2Bytes(1); // 1=ICO, 2=CUR
        bos.write2Bytes(1); // count

        // ICONDIRENTRY
        int iconDirEntryWidth = src.getWidth();
        int iconDirEntryHeight = src.getHeight();
        if (iconDirEntryWidth > 255 || iconDirEntryHeight > 255)
        {
            iconDirEntryWidth = 0;
            iconDirEntryHeight = 0;
        }
        bos.write(iconDirEntryWidth);
        bos.write(iconDirEntryHeight);
        bos.write((bitCount >= 8) ? 0 : (1 << bitCount));
        bos.write(0); // reserved
        bos.write2Bytes(1); // color planes
        bos.write2Bytes(bitCount);
        bos.write4Bytes(imageSize);
        bos.write4Bytes(22); // image offset

        // BITMAPINFOHEADER
        bos.write4Bytes(40); // size
        bos.write4Bytes(src.getWidth());
        bos.write4Bytes(2 * src.getHeight());
        bos.write2Bytes(1); // planes
        bos.write2Bytes(bitCount);
        bos.write4Bytes(0); // compression
        bos.write4Bytes(0); // image size
        bos.write4Bytes(0); // x pixels per meter
        bos.write4Bytes(0); // y pixels per meter
        bos.write4Bytes(0); // colors used, 0 = (1 << bitCount) (ignored)
        bos.write4Bytes(0); // colors important

        if (palette != null)
        {
            for (int i = 0; i < (1 << bitCount); i++)
            {
                if (i < palette.length())
                {
                    int argb = palette.getEntry(i);
                    bos.write(0xff & argb);
                    bos.write(0xff & (argb >> 8));
                    bos.write(0xff & (argb >> 16));
                    bos.write(0);
                }
                else
                {
                    bos.write(0);
                    bos.write(0);
                    bos.write(0);
                    bos.write(0);
                }
            }
        }

        int bit_cache = 0;
        int bits_in_cache = 0;
        int row_padding = scanline_size - (bitCount * src.getWidth() + 7) / 8;
        for (int y = src.getHeight() - 1; y >= 0; y--)
        {
            for (int x = 0; x < src.getWidth(); x++)
            {
                int argb = src.getRGB(x, y);
                if (bitCount < 8)
                {
                    int rgb = 0xffffff & argb;
                    int index = palette.getPaletteIndex(rgb);
                    bit_cache <<= bitCount;
                    bit_cache |= index;
                    bits_in_cache += bitCount;
                    if (bits_in_cache >= 8)
                    {
                        bos.write(0xff & bit_cache);
                        bit_cache = 0;
                        bits_in_cache = 0;
                    }
                }
                else if (bitCount == 8)
                {
                    int rgb = 0xffffff & argb;
                    int index = palette.getPaletteIndex(rgb);
                    bos.write(0xff & index);
                }
                else if (bitCount == 24)
                {
                    bos.write(0xff & argb);
                    bos.write(0xff & (argb >> 8));
                    bos.write(0xff & (argb >> 16));
                }
                else if (bitCount == 32)
                {
                    bos.write(0xff & argb);
                    bos.write(0xff & (argb >> 8));
                    bos.write(0xff & (argb >> 16));
                    bos.write(0xff & (argb >> 24));
                }
            }

            if (bits_in_cache > 0)
            {
                bit_cache <<= (8 - bits_in_cache);
                bos.write(0xff & bit_cache);
                bit_cache = 0;
                bits_in_cache = 0;
            }

            for (int x = 0; x < row_padding; x++)
                bos.write(0);
        }

        int t_row_padding = t_scanline_size - (src.getWidth() + 7) / 8;
        for (int y = src.getHeight() - 1; y >= 0; y--)
        {
            for (int x = 0; x < src.getWidth(); x++)
            {
                int argb = src.getRGB(x, y);
                int alpha = 0xff & (argb >> 24);
                bit_cache <<= 1;
                if (alpha == 0)
                    bit_cache |= 1;
                bits_in_cache++;
                if (bits_in_cache >= 8)
                {
                    bos.write(0xff & bit_cache);
                    bit_cache = 0;
                    bits_in_cache = 0;
                }
            }

            if (bits_in_cache > 0)
            {
                bit_cache <<= (8 - bits_in_cache);
                bos.write(0xff & bit_cache);
                bit_cache = 0;
                bits_in_cache = 0;
            }

            for (int x = 0; x < t_row_padding; x++)
                bos.write(0);
        }
    }

    /**
     * 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;
    }
}
