/*
 * Copyright 2000-2002 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package sun.awt.image;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;

/**
 * This class provides utilities for converting between the standard
 * rgb colorspace specification and the equivalent value for a pixel
 * of a given surface type.  The class was designed for use by the
 * SurfaceType objects, since the conversion between pixel values
 * and rgb values is inherently tied to the type of surface we are
 * dealing with.  Some conversions cannot be done automatically,
 * however (for example, the AnyInt or AnyDCM surface types), so
 * we require the caller to pass in a ColorModel object so that
 * we can calculate the pixel values in these generic cases as well.
 */
public class PixelConverter {

    /**
     * Default object, used as a fallback for any surface types where
     * we do not know enough about the surface to calculate the
     * conversions directly.  We use the ColorModel object to assist
     * us in these cases.
     */
    public static final PixelConverter instance = new PixelConverter();


    protected int alphaMask = 0;

    protected PixelConverter() {}

    public int rgbToPixel(int rgb, ColorModel cm) {
        Object obj = cm.getDataElements(rgb, null);
        switch (cm.getTransferType()) {
        case DataBuffer.TYPE_BYTE:
            byte[] bytearr = (byte[]) obj;
            int pix = 0;

            switch(bytearr.length) {
            default: // bytearr.length >= 4
                pix = bytearr[3] << 24;
                // FALLSTHROUGH
            case 3:
                pix |= (bytearr[2] & 0xff) << 16;
                // FALLSTHROUGH
            case 2:
                pix |= (bytearr[1] & 0xff) << 8;
                // FALLSTHROUGH
            case 1:
                pix |= (bytearr[0] & 0xff);
            }

            return pix;
        case DataBuffer.TYPE_SHORT:
        case DataBuffer.TYPE_USHORT:
            short[] shortarr = (short[]) obj;

            return (((shortarr.length > 1) ? shortarr[1] << 16 : 0) |
                    shortarr[0] & 0xffff);
        case DataBuffer.TYPE_INT:
            return ((int[]) obj)[0];
        default:
            return rgb;
        }
    }

    public int pixelToRgb(int pixel, ColorModel cm) {
        // REMIND: Not yet implemented
        return pixel;
    }

    public final int getAlphaMask() {
        return alphaMask;
    }


    /**
     * Subclasses of PixelConverter.  These subclasses are
     * specific to surface types where we can definitively
     * calculate the conversions.  Note that some conversions
     * are lossy; that is, we cannot necessarily convert a
     * value and then convert it back and wind up with the
     * original value.  For example, an rgb value  that has
     * an alpha != 1 cannot be converted to an Xrgb pixel
     * without losing the information in the alpha component.
     *
     * The conversion strategies associated with the ThreeByte*
     * and FourByte* surface types swap the components around
     * due to the ordering used when the bytes are stored.  The
     * low order byte of a packed-byte pixel will be the first
     * byte stored and the high order byte will be the last byte
     * stored.  For example, the ThreeByteBgr surface type is
     * associated with an Xrgb conversion object because the
     * three bytes are stored as follows:
     *   pixels[0] = b;    // low order byte of an Xrgb pixel
     *   pixels[1] = g;
     *   pixels[2] = r;    // high order byte of an Xrgb pixel
     */

    public static class Rgbx extends PixelConverter {
        public static final PixelConverter instance = new Rgbx();

        private Rgbx() {}

        public int rgbToPixel(int rgb, ColorModel cm) {
            return (rgb << 8);
        }

        public int pixelToRgb(int pixel, ColorModel cm) {
            return (0xff000000 | (pixel >> 8));
        }
    }
    public static class Xrgb extends PixelConverter {
        public static final PixelConverter instance = new Xrgb();

        private Xrgb() {}

        public int rgbToPixel(int rgb, ColorModel cm) {
            return rgb;
        }

        public int pixelToRgb(int pixel, ColorModel cm) {
            return (0xff000000 | pixel);
        }
    }
    public static class Argb extends PixelConverter {
        public static final PixelConverter instance = new Argb();

        private Argb() {
            alphaMask = 0xff000000;
        }

        public int rgbToPixel(int rgb, ColorModel cm) {
            return rgb;
        }

        public int pixelToRgb(int pixel, ColorModel cm) {
            return pixel;
        }
    }
    public static class Ushort565Rgb extends PixelConverter {
        public static final PixelConverter instance = new Ushort565Rgb();

        private Ushort565Rgb() {}

        public int rgbToPixel(int rgb, ColorModel cm) {
            return (((rgb >> (16 + 3 - 11)) & 0xf800) |
                    ((rgb >> ( 8 + 2 -  5)) & 0x07e0) |
                    ((rgb >> ( 0 + 3 -  0)) & 0x001f));
        }

        public int pixelToRgb(int pixel, ColorModel cm) {
            int r, g, b;
            r = (pixel >> 11) & 0x1f;
            r = (r << 3) | (r >> 2);
            g = (pixel >>  5) & 0x3f;
            g = (g << 2) | (g >> 4);
            b = (pixel      ) & 0x1f;
            b = (b << 3) | (b >> 2);
            return (0xff000000 | (r << 16) | (g << 8) | (b));
        }
    }
    public static class Ushort555Rgbx extends PixelConverter {
        public static final PixelConverter instance = new Ushort555Rgbx();

        private Ushort555Rgbx() {}

        public int rgbToPixel(int rgb, ColorModel cm) {
            return (((rgb >> (16 + 3 - 11)) & 0xf800) |
                    ((rgb >> ( 8 + 3 -  6)) & 0x07c0) |
                    ((rgb >> ( 0 + 3 -  1)) & 0x003e));
        }

        public int pixelToRgb(int pixel, ColorModel cm) {
            int r, g, b;
            r = (pixel >> 11) & 0x1f;
            r = (r << 3) | (r >> 2);
            g = (pixel >>  6) & 0x1f;
            g = (g << 3) | (g >> 2);
            b = (pixel >>  1) & 0x1f;
            b = (b << 3) | (b >> 2);
            return (0xff000000 | (r << 16) | (g << 8) | (b));
        }
    }
    public static class Ushort555Rgb extends PixelConverter {
        public static final PixelConverter instance = new Ushort555Rgb();

        private Ushort555Rgb() {}

        public int rgbToPixel(int rgb, ColorModel cm) {
            return (((rgb >> (16 + 3 - 10)) & 0x7c00) |
                    ((rgb >> ( 8 + 3 -  5)) & 0x03e0) |
                    ((rgb >> ( 0 + 3 -  0)) & 0x001f));
        }

        public int pixelToRgb(int pixel, ColorModel cm) {
            int r, g, b;
            r = (pixel >> 10) & 0x1f;
            r = (r << 3) | (r >> 2);
            g = (pixel >>  5) & 0x1f;
            g = (g << 3) | (g >> 2);
            b = (pixel      ) & 0x1f;
            b = (b << 3) | (b >> 2);
            return (0xff000000 | (r << 16) | (g << 8) | (b));
        }
    }
    public static class Ushort4444Argb extends PixelConverter {
        public static final PixelConverter instance = new Ushort4444Argb();

        private Ushort4444Argb() {
            alphaMask = 0xf000;
        }

        public int rgbToPixel(int rgb, ColorModel cm) {
            // use upper 4 bits for each color
            // 0xAaRrGgBb -> 0x0000ARGB
            int a = (rgb >> 16) & 0xf000;
            int r = (rgb >> 12) & 0x0f00;
            int g = (rgb >>  8) & 0x00f0;
            int b = (rgb >>  4) & 0x000f;

            return (a | r | g | b);
        }

        public int pixelToRgb(int pixel, ColorModel cm) {
            int a, r, g, b;
            // replicate 4 bits for each color
            // 0xARGB -> 0xAARRGGBB
            a = pixel & 0xf000;
            a = ((pixel << 16) | (pixel << 12)) & 0xff000000;
            r = pixel & 0x0f00;
            r = ((pixel << 12) | (pixel <<  8)) & 0x00ff0000;
            g = pixel & 0x00f0;
            g = ((pixel <<  8) | (pixel <<  4)) & 0x0000ff00;
            b = pixel & 0x000f;
            b = ((pixel <<  4) | (pixel <<  0)) & 0x000000ff;

            return (a | r | g | b);
        }
    }
    public static class Xbgr extends PixelConverter {
        public static final PixelConverter instance = new Xbgr();

        private Xbgr() {}

        public int rgbToPixel(int rgb, ColorModel cm) {
            return (((rgb & 0xff) << 16) |
                    (rgb & 0xff00) |
                    ((rgb >> 16) & 0xff));
        }

        public int pixelToRgb(int pixel, ColorModel cm) {
            return (0xff000000 |
                    ((pixel & 0xff) << 16) |
                    (pixel & 0xff00) |
                    ((pixel >> 16) & 0xff));
        }
    }
    public static class Bgrx extends PixelConverter {
        public static final PixelConverter instance = new Bgrx();

        private Bgrx() {}

        public int rgbToPixel(int rgb, ColorModel cm) {
            return ((rgb << 24) |
                    ((rgb & 0xff00) << 8) |
                    ((rgb >> 8) & 0xff00));
        }

        public int pixelToRgb(int pixel, ColorModel cm) {
            return (0xff000000                   |
                    ((pixel & 0xff00) << 8) |
                    ((pixel >> 8) & 0xff00) |
                    (pixel >>> 24));
        }
    }
    public static class Rgba extends PixelConverter {
        public static final PixelConverter instance = new Rgba();

        private Rgba() {
            alphaMask = 0x000000ff;
        }

        public int rgbToPixel(int rgb, ColorModel cm) {
            return ((rgb << 8) | (rgb >>> 24));
        }

        public int pixelToRgb(int pixel, ColorModel cm) {
            return ((pixel << 24) | (pixel >>> 8));
        }
    }
    public static class RgbaPre extends PixelConverter {
        public static final PixelConverter instance = new RgbaPre();

        private RgbaPre() {
            alphaMask = 0x000000ff;
        }

        public int rgbToPixel(int rgb, ColorModel cm) {
            if ((rgb >> 24) == -1) {
                return ((rgb << 8) | (rgb >>> 24));
            }
            int a = rgb >>> 24;
            int r = (rgb >> 16) & 0xff;
            int g = (rgb >>  8) & 0xff;
            int b = (rgb      ) & 0xff;
            int a2 = a + (a >> 7);
            r = (r * a2) >> 8;
            g = (g * a2) >> 8;
            b = (b * a2) >> 8;
            return ((r << 24) | (g << 16) | (b << 8) | (a));
        }

        public int pixelToRgb(int pixel, ColorModel cm) {
            int a = pixel & 0xff;
            if ((a == 0xff) || (a == 0)) {
                return ((pixel >>> 8) | (pixel << 24));
            }
            int r = pixel >>> 24;
            int g = (pixel >> 16) & 0xff;
            int b = (pixel >>  8) & 0xff;
            r = ((r << 8) - r) / a;
            g = ((g << 8) - g) / a;
            b = ((b << 8) - b) / a;
            return ((r << 24) | (g << 16) | (b << 8) | (a));
        }
    }
    public static class ArgbPre extends PixelConverter {
        public static final PixelConverter instance = new ArgbPre();

        private ArgbPre() {
            alphaMask = 0xff000000;
        }

        public int rgbToPixel(int rgb, ColorModel cm) {
            if ((rgb >> 24) == -1) {
                return rgb;
            }
            int a = rgb >>> 24;
            int r = (rgb >> 16) & 0xff;
            int g = (rgb >>  8) & 0xff;
            int b = (rgb      ) & 0xff;
            int a2 = a + (a >> 7);
            r = (r * a2) >> 8;
            g = (g * a2) >> 8;
            b = (b * a2) >> 8;
            return ((a << 24) | (r << 16) | (g << 8) | (b));
        }

        public int pixelToRgb(int pixel, ColorModel cm) {
            int a = pixel >>> 24;
            if ((a == 0xff) || (a == 0)) {
                return pixel;
            }
            int r = (pixel >> 16) & 0xff;
            int g = (pixel >>  8) & 0xff;
            int b = (pixel      ) & 0xff;
            r = ((r << 8) - r) / a;
            g = ((g << 8) - g) / a;
            b = ((b << 8) - b) / a;
            return ((a << 24) | (r << 16) | (g << 8) | (b));
        }
    }
    public static class ArgbBm extends PixelConverter {
        public static final PixelConverter instance = new ArgbBm();

        private ArgbBm() {}

        public int rgbToPixel(int rgb, ColorModel cm) {
            return (rgb | ((rgb >> 31) << 24));
        }

        public int pixelToRgb(int pixel, ColorModel cm) {
            return ((pixel << 7) >> 7);
        }
    }
    public static class ByteGray extends PixelConverter {
        static final double RED_MULT = 0.299;
        static final double GRN_MULT = 0.587;
        static final double BLU_MULT = 0.114;
        public static final PixelConverter instance = new ByteGray();

        private ByteGray() {}

        public int rgbToPixel(int rgb, ColorModel cm) {
            int red = (rgb >> 16) & 0xff;
            int grn = (rgb >>  8) & 0xff;
            int blu = (rgb      ) & 0xff;
            return (int) (red * RED_MULT +
                          grn * GRN_MULT +
                          blu * BLU_MULT +
                          0.5);
        }

        public int pixelToRgb(int pixel, ColorModel cm) {
            return ((((((0xff << 8) | pixel) << 8) | pixel) << 8) | pixel);
        }
    }
    public static class UshortGray extends ByteGray {
        static final double SHORT_MULT = 257.0; // (65535.0 / 255.0);
        static final double USHORT_RED_MULT = RED_MULT * SHORT_MULT;
        static final double USHORT_GRN_MULT = GRN_MULT * SHORT_MULT;
        static final double USHORT_BLU_MULT = BLU_MULT * SHORT_MULT;
        public static final PixelConverter instance = new UshortGray();

        private UshortGray() {}

        public int rgbToPixel(int rgb, ColorModel cm) {
            int red = (rgb >> 16) & 0xff;
            int grn = (rgb >>  8) & 0xff;
            int blu = (rgb      ) & 0xff;
            return (int) (red * USHORT_RED_MULT +
                          grn * USHORT_GRN_MULT +
                          blu * USHORT_BLU_MULT +
                          0.5);
        }

        public int pixelToRgb(int pixel, ColorModel cm) {
            pixel = pixel >> 8;
            return ((((((0xff << 8) | pixel) << 8) | pixel) << 8) | pixel);
        }
    }
}
