001: /*
002: * Copyright 2000-2002 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.awt.image;
027:
028: import java.awt.image.ColorModel;
029: import java.awt.image.DataBuffer;
030:
031: /**
032: * This class provides utilities for converting between the standard
033: * rgb colorspace specification and the equivalent value for a pixel
034: * of a given surface type. The class was designed for use by the
035: * SurfaceType objects, since the conversion between pixel values
036: * and rgb values is inherently tied to the type of surface we are
037: * dealing with. Some conversions cannot be done automatically,
038: * however (for example, the AnyInt or AnyDCM surface types), so
039: * we require the caller to pass in a ColorModel object so that
040: * we can calculate the pixel values in these generic cases as well.
041: */
042: public class PixelConverter {
043:
044: /**
045: * Default object, used as a fallback for any surface types where
046: * we do not know enough about the surface to calculate the
047: * conversions directly. We use the ColorModel object to assist
048: * us in these cases.
049: */
050: public static final PixelConverter instance = new PixelConverter();
051:
052: protected int alphaMask = 0;
053:
054: protected PixelConverter() {
055: }
056:
057: public int rgbToPixel(int rgb, ColorModel cm) {
058: Object obj = cm.getDataElements(rgb, null);
059: switch (cm.getTransferType()) {
060: case DataBuffer.TYPE_BYTE:
061: byte[] bytearr = (byte[]) obj;
062: int pix = 0;
063:
064: switch (bytearr.length) {
065: default: // bytearr.length >= 4
066: pix = bytearr[3] << 24;
067: // FALLSTHROUGH
068: case 3:
069: pix |= (bytearr[2] & 0xff) << 16;
070: // FALLSTHROUGH
071: case 2:
072: pix |= (bytearr[1] & 0xff) << 8;
073: // FALLSTHROUGH
074: case 1:
075: pix |= (bytearr[0] & 0xff);
076: }
077:
078: return pix;
079: case DataBuffer.TYPE_SHORT:
080: case DataBuffer.TYPE_USHORT:
081: short[] shortarr = (short[]) obj;
082:
083: return (((shortarr.length > 1) ? shortarr[1] << 16 : 0) | shortarr[0] & 0xffff);
084: case DataBuffer.TYPE_INT:
085: return ((int[]) obj)[0];
086: default:
087: return rgb;
088: }
089: }
090:
091: public int pixelToRgb(int pixel, ColorModel cm) {
092: // REMIND: Not yet implemented
093: return pixel;
094: }
095:
096: public final int getAlphaMask() {
097: return alphaMask;
098: }
099:
100: /**
101: * Subclasses of PixelConverter. These subclasses are
102: * specific to surface types where we can definitively
103: * calculate the conversions. Note that some conversions
104: * are lossy; that is, we cannot necessarily convert a
105: * value and then convert it back and wind up with the
106: * original value. For example, an rgb value that has
107: * an alpha != 1 cannot be converted to an Xrgb pixel
108: * without losing the information in the alpha component.
109: *
110: * The conversion strategies associated with the ThreeByte*
111: * and FourByte* surface types swap the components around
112: * due to the ordering used when the bytes are stored. The
113: * low order byte of a packed-byte pixel will be the first
114: * byte stored and the high order byte will be the last byte
115: * stored. For example, the ThreeByteBgr surface type is
116: * associated with an Xrgb conversion object because the
117: * three bytes are stored as follows:
118: * pixels[0] = b; // low order byte of an Xrgb pixel
119: * pixels[1] = g;
120: * pixels[2] = r; // high order byte of an Xrgb pixel
121: */
122:
123: public static class Rgbx extends PixelConverter {
124: public static final PixelConverter instance = new Rgbx();
125:
126: private Rgbx() {
127: }
128:
129: public int rgbToPixel(int rgb, ColorModel cm) {
130: return (rgb << 8);
131: }
132:
133: public int pixelToRgb(int pixel, ColorModel cm) {
134: return (0xff000000 | (pixel >> 8));
135: }
136: }
137:
138: public static class Xrgb extends PixelConverter {
139: public static final PixelConverter instance = new Xrgb();
140:
141: private Xrgb() {
142: }
143:
144: public int rgbToPixel(int rgb, ColorModel cm) {
145: return rgb;
146: }
147:
148: public int pixelToRgb(int pixel, ColorModel cm) {
149: return (0xff000000 | pixel);
150: }
151: }
152:
153: public static class Argb extends PixelConverter {
154: public static final PixelConverter instance = new Argb();
155:
156: private Argb() {
157: alphaMask = 0xff000000;
158: }
159:
160: public int rgbToPixel(int rgb, ColorModel cm) {
161: return rgb;
162: }
163:
164: public int pixelToRgb(int pixel, ColorModel cm) {
165: return pixel;
166: }
167: }
168:
169: public static class Ushort565Rgb extends PixelConverter {
170: public static final PixelConverter instance = new Ushort565Rgb();
171:
172: private Ushort565Rgb() {
173: }
174:
175: public int rgbToPixel(int rgb, ColorModel cm) {
176: return (((rgb >> (16 + 3 - 11)) & 0xf800)
177: | ((rgb >> (8 + 2 - 5)) & 0x07e0) | ((rgb >> (0 + 3 - 0)) & 0x001f));
178: }
179:
180: public int pixelToRgb(int pixel, ColorModel cm) {
181: int r, g, b;
182: r = (pixel >> 11) & 0x1f;
183: r = (r << 3) | (r >> 2);
184: g = (pixel >> 5) & 0x3f;
185: g = (g << 2) | (g >> 4);
186: b = (pixel) & 0x1f;
187: b = (b << 3) | (b >> 2);
188: return (0xff000000 | (r << 16) | (g << 8) | (b));
189: }
190: }
191:
192: public static class Ushort555Rgbx extends PixelConverter {
193: public static final PixelConverter instance = new Ushort555Rgbx();
194:
195: private Ushort555Rgbx() {
196: }
197:
198: public int rgbToPixel(int rgb, ColorModel cm) {
199: return (((rgb >> (16 + 3 - 11)) & 0xf800)
200: | ((rgb >> (8 + 3 - 6)) & 0x07c0) | ((rgb >> (0 + 3 - 1)) & 0x003e));
201: }
202:
203: public int pixelToRgb(int pixel, ColorModel cm) {
204: int r, g, b;
205: r = (pixel >> 11) & 0x1f;
206: r = (r << 3) | (r >> 2);
207: g = (pixel >> 6) & 0x1f;
208: g = (g << 3) | (g >> 2);
209: b = (pixel >> 1) & 0x1f;
210: b = (b << 3) | (b >> 2);
211: return (0xff000000 | (r << 16) | (g << 8) | (b));
212: }
213: }
214:
215: public static class Ushort555Rgb extends PixelConverter {
216: public static final PixelConverter instance = new Ushort555Rgb();
217:
218: private Ushort555Rgb() {
219: }
220:
221: public int rgbToPixel(int rgb, ColorModel cm) {
222: return (((rgb >> (16 + 3 - 10)) & 0x7c00)
223: | ((rgb >> (8 + 3 - 5)) & 0x03e0) | ((rgb >> (0 + 3 - 0)) & 0x001f));
224: }
225:
226: public int pixelToRgb(int pixel, ColorModel cm) {
227: int r, g, b;
228: r = (pixel >> 10) & 0x1f;
229: r = (r << 3) | (r >> 2);
230: g = (pixel >> 5) & 0x1f;
231: g = (g << 3) | (g >> 2);
232: b = (pixel) & 0x1f;
233: b = (b << 3) | (b >> 2);
234: return (0xff000000 | (r << 16) | (g << 8) | (b));
235: }
236: }
237:
238: public static class Ushort4444Argb extends PixelConverter {
239: public static final PixelConverter instance = new Ushort4444Argb();
240:
241: private Ushort4444Argb() {
242: alphaMask = 0xf000;
243: }
244:
245: public int rgbToPixel(int rgb, ColorModel cm) {
246: // use upper 4 bits for each color
247: // 0xAaRrGgBb -> 0x0000ARGB
248: int a = (rgb >> 16) & 0xf000;
249: int r = (rgb >> 12) & 0x0f00;
250: int g = (rgb >> 8) & 0x00f0;
251: int b = (rgb >> 4) & 0x000f;
252:
253: return (a | r | g | b);
254: }
255:
256: public int pixelToRgb(int pixel, ColorModel cm) {
257: int a, r, g, b;
258: // replicate 4 bits for each color
259: // 0xARGB -> 0xAARRGGBB
260: a = pixel & 0xf000;
261: a = ((pixel << 16) | (pixel << 12)) & 0xff000000;
262: r = pixel & 0x0f00;
263: r = ((pixel << 12) | (pixel << 8)) & 0x00ff0000;
264: g = pixel & 0x00f0;
265: g = ((pixel << 8) | (pixel << 4)) & 0x0000ff00;
266: b = pixel & 0x000f;
267: b = ((pixel << 4) | (pixel << 0)) & 0x000000ff;
268:
269: return (a | r | g | b);
270: }
271: }
272:
273: public static class Xbgr extends PixelConverter {
274: public static final PixelConverter instance = new Xbgr();
275:
276: private Xbgr() {
277: }
278:
279: public int rgbToPixel(int rgb, ColorModel cm) {
280: return (((rgb & 0xff) << 16) | (rgb & 0xff00) | ((rgb >> 16) & 0xff));
281: }
282:
283: public int pixelToRgb(int pixel, ColorModel cm) {
284: return (0xff000000 | ((pixel & 0xff) << 16)
285: | (pixel & 0xff00) | ((pixel >> 16) & 0xff));
286: }
287: }
288:
289: public static class Bgrx extends PixelConverter {
290: public static final PixelConverter instance = new Bgrx();
291:
292: private Bgrx() {
293: }
294:
295: public int rgbToPixel(int rgb, ColorModel cm) {
296: return ((rgb << 24) | ((rgb & 0xff00) << 8) | ((rgb >> 8) & 0xff00));
297: }
298:
299: public int pixelToRgb(int pixel, ColorModel cm) {
300: return (0xff000000 | ((pixel & 0xff00) << 8)
301: | ((pixel >> 8) & 0xff00) | (pixel >>> 24));
302: }
303: }
304:
305: public static class Rgba extends PixelConverter {
306: public static final PixelConverter instance = new Rgba();
307:
308: private Rgba() {
309: alphaMask = 0x000000ff;
310: }
311:
312: public int rgbToPixel(int rgb, ColorModel cm) {
313: return ((rgb << 8) | (rgb >>> 24));
314: }
315:
316: public int pixelToRgb(int pixel, ColorModel cm) {
317: return ((pixel << 24) | (pixel >>> 8));
318: }
319: }
320:
321: public static class RgbaPre extends PixelConverter {
322: public static final PixelConverter instance = new RgbaPre();
323:
324: private RgbaPre() {
325: alphaMask = 0x000000ff;
326: }
327:
328: public int rgbToPixel(int rgb, ColorModel cm) {
329: if ((rgb >> 24) == -1) {
330: return ((rgb << 8) | (rgb >>> 24));
331: }
332: int a = rgb >>> 24;
333: int r = (rgb >> 16) & 0xff;
334: int g = (rgb >> 8) & 0xff;
335: int b = (rgb) & 0xff;
336: int a2 = a + (a >> 7);
337: r = (r * a2) >> 8;
338: g = (g * a2) >> 8;
339: b = (b * a2) >> 8;
340: return ((r << 24) | (g << 16) | (b << 8) | (a));
341: }
342:
343: public int pixelToRgb(int pixel, ColorModel cm) {
344: int a = pixel & 0xff;
345: if ((a == 0xff) || (a == 0)) {
346: return ((pixel >>> 8) | (pixel << 24));
347: }
348: int r = pixel >>> 24;
349: int g = (pixel >> 16) & 0xff;
350: int b = (pixel >> 8) & 0xff;
351: r = ((r << 8) - r) / a;
352: g = ((g << 8) - g) / a;
353: b = ((b << 8) - b) / a;
354: return ((r << 24) | (g << 16) | (b << 8) | (a));
355: }
356: }
357:
358: public static class ArgbPre extends PixelConverter {
359: public static final PixelConverter instance = new ArgbPre();
360:
361: private ArgbPre() {
362: alphaMask = 0xff000000;
363: }
364:
365: public int rgbToPixel(int rgb, ColorModel cm) {
366: if ((rgb >> 24) == -1) {
367: return rgb;
368: }
369: int a = rgb >>> 24;
370: int r = (rgb >> 16) & 0xff;
371: int g = (rgb >> 8) & 0xff;
372: int b = (rgb) & 0xff;
373: int a2 = a + (a >> 7);
374: r = (r * a2) >> 8;
375: g = (g * a2) >> 8;
376: b = (b * a2) >> 8;
377: return ((a << 24) | (r << 16) | (g << 8) | (b));
378: }
379:
380: public int pixelToRgb(int pixel, ColorModel cm) {
381: int a = pixel >>> 24;
382: if ((a == 0xff) || (a == 0)) {
383: return pixel;
384: }
385: int r = (pixel >> 16) & 0xff;
386: int g = (pixel >> 8) & 0xff;
387: int b = (pixel) & 0xff;
388: r = ((r << 8) - r) / a;
389: g = ((g << 8) - g) / a;
390: b = ((b << 8) - b) / a;
391: return ((a << 24) | (r << 16) | (g << 8) | (b));
392: }
393: }
394:
395: public static class ArgbBm extends PixelConverter {
396: public static final PixelConverter instance = new ArgbBm();
397:
398: private ArgbBm() {
399: }
400:
401: public int rgbToPixel(int rgb, ColorModel cm) {
402: return (rgb | ((rgb >> 31) << 24));
403: }
404:
405: public int pixelToRgb(int pixel, ColorModel cm) {
406: return ((pixel << 7) >> 7);
407: }
408: }
409:
410: public static class ByteGray extends PixelConverter {
411: static final double RED_MULT = 0.299;
412: static final double GRN_MULT = 0.587;
413: static final double BLU_MULT = 0.114;
414: public static final PixelConverter instance = new ByteGray();
415:
416: private ByteGray() {
417: }
418:
419: public int rgbToPixel(int rgb, ColorModel cm) {
420: int red = (rgb >> 16) & 0xff;
421: int grn = (rgb >> 8) & 0xff;
422: int blu = (rgb) & 0xff;
423: return (int) (red * RED_MULT + grn * GRN_MULT + blu
424: * BLU_MULT + 0.5);
425: }
426:
427: public int pixelToRgb(int pixel, ColorModel cm) {
428: return ((((((0xff << 8) | pixel) << 8) | pixel) << 8) | pixel);
429: }
430: }
431:
432: public static class UshortGray extends ByteGray {
433: static final double SHORT_MULT = 257.0; // (65535.0 / 255.0);
434: static final double USHORT_RED_MULT = RED_MULT * SHORT_MULT;
435: static final double USHORT_GRN_MULT = GRN_MULT * SHORT_MULT;
436: static final double USHORT_BLU_MULT = BLU_MULT * SHORT_MULT;
437: public static final PixelConverter instance = new UshortGray();
438:
439: private UshortGray() {
440: }
441:
442: public int rgbToPixel(int rgb, ColorModel cm) {
443: int red = (rgb >> 16) & 0xff;
444: int grn = (rgb >> 8) & 0xff;
445: int blu = (rgb) & 0xff;
446: return (int) (red * USHORT_RED_MULT + grn * USHORT_GRN_MULT
447: + blu * USHORT_BLU_MULT + 0.5);
448: }
449:
450: public int pixelToRgb(int pixel, ColorModel cm) {
451: pixel = pixel >> 8;
452: return ((((((0xff << 8) | pixel) << 8) | pixel) << 8) | pixel);
453: }
454: }
455: }
|