001    /*
002     * RGBA
003     * 
004     * Copyright (c) 2001, 2002, 2003 Marco Schmidt.
005     * All rights reserved.
006     */
007    
008    package net.sourceforge.jiu.gui.awt;
009    
010    /**
011     * This class converts between the 32 bit RGBA int values (used throughout the AWT) and 
012     * various standard pixel formats like 24 bits RGB, 8 bits gray, 16 bits gray, 1 bit black and white.
013     * <p>
014     * The conversion is done in a number of static methods.
015     * This class is not supposed to be instantiated.
016     * <p>
017     * The method names of this class can be interpreted as follows.
018     * If they contain
019     * <code>fromXYZ</code> (where XYZ is a pixel format type like Gray8, RGB24 etc.), 
020     * a conversion from another pixel format to RGBA is done.
021     * If the names contains <code>toXYZ</code>, a conversion from RGBA to that pixel
022     * format will be performed.
023     * <p>
024     * Not all conversions are lossless or well-defined.
025     * If 48 bpp RGB truecolor is used as source, only the top eight bits of each
026     * 16 bit sample will be used (thus, the procedure is lossy).
027     * If RGBA data is to be converted to bilevel (black and white), the conversion
028     * is undefined if there are input RGBA pixels that are neither black nor white.
029     *
030     * @author Marco Schmidt
031     */
032    public class RGBA
033    {
034            /**
035             * The default value for the alpha part of RGBA.
036             * The alpha value is eight bits long left-shifted by 24.
037             * This default value is <em>no transparency</em> - the underlying image
038             * cannot be seen: <code>0xff000000</code>.
039             */
040            public static final int DEFAULT_ALPHA = 0xff000000;
041    
042            private RGBA()
043            {
044            }
045    
046            /**
047             * Converts pixels from bilevel packed bytes to RGBA format.
048             * A byte is supposed to store eight pixels, the most significant bit being the leftmost pixel.
049             * @param src the array with the packed bytes
050             * @param srcOffset the index of the first byte to be converted from src
051             * @param alpha the alpha value to be used for the destination RGBA values
052             * @param dest the array where the destination RGBA pixels will be stored
053             * @param destOffset the index of the first destination pixel in the dest array; 
054             *  that array must be at least destOffset + ((num + 7) / 8) large
055             * @param num the number of pixels (not bytes) to be converted
056             */
057            public static void convertFromPackedBilevel(byte[] src, int srcOffset, int alpha,
058                    int[] dest, int destOffset, int num)
059            {
060                    final int BLACK = alpha;
061                    final int WHITE = alpha | 0x00ffffff;
062                    int mask = 1;
063                    int value = 0; // 0 will never be used; value will be assigned a value in the first pass of the loop
064                    while (num-- > 0)
065                    {
066                            if (mask == 1)
067                            {       
068                                    mask = 128;
069                                    value = src[srcOffset++] & 0xff;
070                            }
071                            else
072                            {
073                                    mask >>= 1;
074                            }
075                            if ((value & mask) == 0)
076                            {
077                                    dest[destOffset++] = BLACK;
078                            }
079                            else
080                            {
081                                    dest[destOffset++] = WHITE;
082                            }
083                    }
084            }
085    
086            /**
087             * Convert a number of 8 bit grayscale pixels, shades of gray between 0 (for black)
088             * and 255 (for white), given as bytes, to RGBA type int pixels, adding the given
089             * alpha value.
090             * @param src array with grayscale pixels
091             * @param srcOffset index of first entry of src to be converted
092             * @param alpha transparency value to be used in resulting RGBA array (only top eight bits can be set)
093             * @param dest array to store resulting RGBA pixels
094             * @param destOffset index of first entry in dest to be used
095             * @param num number of pixels to be converted
096             */
097            public static void convertFromGray8(byte[] src, int srcOffset, int alpha,
098                    int[] dest, int destOffset, int num)
099            {
100                    while (num-- > 0)
101                    {
102                            int grayValue = src[srcOffset++] & 0xff;
103                            dest[destOffset++] = alpha | grayValue | (grayValue << 8) | (grayValue << 16);
104                    }
105            }
106    
107            /**
108             * Convert a number of 16 bit grayscale pixels to RGBA type int pixels, adding the given
109             * alpha value.
110             * Note that the lower 8 bits of each grayscale value are dropped.
111             * @param src array with grayscale pixels
112             * @param srcOffset index of first entry of src to be converted
113             * @param alpha transparency value to be used in resulting RGBA array (only top eight bits can be set)
114             * @param dest array to store resulting RGBA pixels
115             * @param destOffset index of first entry in dest to be used
116             * @param num number of pixels to be converted
117             */
118            public static void convertFromGray16(short[] src, int srcOffset, int alpha,
119                    int[] dest, int destOffset, int num)
120            {
121                    while (num-- > 0)
122                    {
123                            int grayValue = (src[srcOffset++] & 0xffff) >> 8;
124                            dest[destOffset++] = alpha | grayValue | (grayValue << 8) | (grayValue << 16);
125                    }
126            }
127    
128            /**
129             * Converts a byte array of palette index values to an array of RGBA values,
130             * using palette color data.
131             * @param src the byte array with the palette index values
132             * @param srcOffset index of the first entry of src to be used
133             * @param alpha transparency value to be used (only top eight bits should be set)
134             * @param red the red palette values
135             * @param green the green palette values
136             * @param blue the blue palette values
137             * @param dest the destination array to store the RGBA values
138             * @param destOffset the first entry of dest to be used
139             * @param num the number of pixels to be converted
140             */
141            public static void convertFromPaletted8(byte[] src, int srcOffset, int alpha, 
142                    int[] red, int[] green, int[] blue, int[] dest, int destOffset, int num)
143            {
144                    while (num-- > 0)
145                    {
146                            int index = src[srcOffset++] & 0xff;
147                            dest[destOffset++] = alpha | (blue[index]) | (green[index] << 8) | (red[index] << 16);
148                    }
149            }
150    
151            /**
152             * Converts 24 bit RGB truecolor data to RGBA int values.
153             * @param srcRed the red pixel values
154             * @param srcRedOffset the first entry of srcRed to be used
155             * @param srcGreen the green pixel values
156             * @param srcGreenOffset the first entry of srcGreen to be used
157             * @param srcBlue the blue pixel values
158             * @param srcBlueOffset the first entry of srcBlue to be used
159             * @param alpha the transpancy value to be used in the destination RGBA array (only top 8 bits should be set)
160             * @param dest array to store RGBA pixel values
161             * @param destOffset first entry of dest to be used
162             * @param num number of pixels to be converted
163             */
164            public static void convertFromRGB24(byte[] srcRed, int srcRedOffset, byte[] srcGreen, 
165                    int srcGreenOffset, byte[] srcBlue, int srcBlueOffset, int alpha, 
166                    int[] dest, int destOffset, int num)
167            {
168                    while (num-- > 0)
169                    {
170                            dest[destOffset++] =
171                                    alpha |
172                                    (srcBlue[srcBlueOffset++] & 0xff) |
173                                    ((srcGreen[srcGreenOffset++] & 0xff) << 8) |
174                                    ((srcRed[srcRedOffset++] & 0xff) << 16);
175                    }
176            }
177    
178            /**
179             * Converts 48 bit RGB truecolor data to RGBA int values, dropping the least
180             * significant eight bits of each short sample.
181             * @param srcRed the red pixel values
182             * @param srcRedOffset the first entry of srcRed to be used
183             * @param srcGreen the green pixel values
184             * @param srcGreenOffset the first entry of srcGreen to be used
185             * @param srcBlue the blue pixel values
186             * @param srcBlueOffset the first entry of srcBlue to be used
187             * @param alpha the transpancy value to be used in the destination RGBA array (only top 8 bits should be set)
188             * @param dest array to store RGBA pixel values
189             * @param destOffset first entry of dest to be used
190             * @param num number of pixels to be converted
191             * @since 0.12.0
192             */
193            public static void convertFromRGB48(short[] srcRed, int srcRedOffset, short[] srcGreen, 
194                    int srcGreenOffset, short[] srcBlue, int srcBlueOffset, int alpha, 
195                    int[] dest, int destOffset, int num)
196            {
197                    while (num-- > 0)
198                    {
199                            dest[destOffset++] =
200                                    alpha |
201                                    ((srcBlue[srcBlueOffset++] & 0xff00) >> 8) |
202                                    ((srcGreen[srcGreenOffset++] & 0xff00)) |
203                                    ((srcRed[srcRedOffset++] & 0xff00) << 8);
204                    }
205            }
206    }