447 lines · 15.2 KB · Java
RawDownload
/* * Copyright (c) 2000, 2002, Oracle and/or its affiliates. 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.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.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);        }    }}