1 /* 2 * Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.awt.image; 27 import java.awt.image.ColorModel; 28 import java.awt.image.DataBuffer; 29 30 /** 31 * This class provides utilities for converting between the standard 32 * rgb colorspace specification and the equivalent value for a pixel 33 * of a given surface type. The class was designed for use by the 34 * SurfaceType objects, since the conversion between pixel values 35 * and rgb values is inherently tied to the type of surface we are 36 * dealing with. Some conversions cannot be done automatically, 37 * however (for example, the AnyInt or AnyDCM surface types), so 38 * we require the caller to pass in a ColorModel object so that 39 * we can calculate the pixel values in these generic cases as well. 40 */ 41 public class PixelConverter { 42 43 /** 44 * Default object, used as a fallback for any surface types where 45 * we do not know enough about the surface to calculate the 46 * conversions directly. We use the ColorModel object to assist 47 * us in these cases. 48 */ 49 public static final PixelConverter instance = new PixelConverter(); 50 51 52 protected int alphaMask = 0; 53 54 protected PixelConverter() {} 55 56 public int rgbToPixel(int rgb, ColorModel cm) { 57 Object obj = cm.getDataElements(rgb, null); 58 switch (cm.getTransferType()) { 59 case DataBuffer.TYPE_BYTE: 60 byte[] bytearr = (byte[]) obj; 61 int pix = 0; 62 63 switch(bytearr.length) { 64 default: // bytearr.length >= 4 65 pix = bytearr[3] << 24; 66 // FALLSTHROUGH 67 case 3: 68 pix |= (bytearr[2] & 0xff) << 16; 69 // FALLSTHROUGH 70 case 2: 71 pix |= (bytearr[1] & 0xff) << 8; 72 // FALLSTHROUGH 73 case 1: 74 pix |= (bytearr[0] & 0xff); 75 } 76 77 return pix; 78 case DataBuffer.TYPE_SHORT: 79 case DataBuffer.TYPE_USHORT: 80 short[] shortarr = (short[]) obj; 81 82 return (((shortarr.length > 1) ? shortarr[1] << 16 : 0) | 83 shortarr[0] & 0xffff); 84 case DataBuffer.TYPE_INT: 85 return ((int[]) obj)[0]; 86 default: 87 return rgb; 88 } 89 } 90 91 public int pixelToRgb(int pixel, ColorModel cm) { 92 // REMIND: Not yet implemented 93 return pixel; 94 } 95 96 public final int getAlphaMask() { 97 return alphaMask; 98 } 99 100 101 /** 102 * Subclasses of PixelConverter. These subclasses are 103 * specific to surface types where we can definitively 104 * calculate the conversions. Note that some conversions 105 * are lossy; that is, we cannot necessarily convert a 106 * value and then convert it back and wind up with the 107 * original value. For example, an rgb value that has 108 * an alpha != 1 cannot be converted to an Xrgb pixel 109 * without losing the information in the alpha component. 110 * 111 * The conversion strategies associated with the ThreeByte* 112 * and FourByte* surface types swap the components around 113 * due to the ordering used when the bytes are stored. The 114 * low order byte of a packed-byte pixel will be the first 115 * byte stored and the high order byte will be the last byte 116 * stored. For example, the ThreeByteBgr surface type is 117 * associated with an Xrgb conversion object because the 118 * three bytes are stored as follows: 119 * pixels[0] = b; // low order byte of an Xrgb pixel 120 * pixels[1] = g; 121 * pixels[2] = r; // high order byte of an Xrgb pixel 122 */ 123 124 public static class Rgbx extends PixelConverter { 125 public static final PixelConverter instance = new Rgbx(); 126 127 private Rgbx() {} 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 public static class Xrgb extends PixelConverter { 138 public static final PixelConverter instance = new Xrgb(); 139 140 private Xrgb() {} 141 142 public int rgbToPixel(int rgb, ColorModel cm) { 143 return rgb; 144 } 145 146 public int pixelToRgb(int pixel, ColorModel cm) { 147 return (0xff000000 | pixel); 148 } 149 } 150 public static class Argb extends PixelConverter { 151 public static final PixelConverter instance = new Argb(); 152 153 private Argb() { 154 alphaMask = 0xff000000; 155 } 156 157 public int rgbToPixel(int rgb, ColorModel cm) { 158 return rgb; 159 } 160 161 public int pixelToRgb(int pixel, ColorModel cm) { 162 return pixel; 163 } 164 } 165 public static class Ushort565Rgb extends PixelConverter { 166 public static final PixelConverter instance = new Ushort565Rgb(); 167 168 private Ushort565Rgb() {} 169 170 public int rgbToPixel(int rgb, ColorModel cm) { 171 return (((rgb >> (16 + 3 - 11)) & 0xf800) | 172 ((rgb >> ( 8 + 2 - 5)) & 0x07e0) | 173 ((rgb >> ( 0 + 3 - 0)) & 0x001f)); 174 } 175 176 public int pixelToRgb(int pixel, ColorModel cm) { 177 int r, g, b; 178 r = (pixel >> 11) & 0x1f; 179 r = (r << 3) | (r >> 2); 180 g = (pixel >> 5) & 0x3f; 181 g = (g << 2) | (g >> 4); 182 b = (pixel ) & 0x1f; 183 b = (b << 3) | (b >> 2); 184 return (0xff000000 | (r << 16) | (g << 8) | (b)); 185 } 186 } 187 public static class Ushort555Rgbx extends PixelConverter { 188 public static final PixelConverter instance = new Ushort555Rgbx(); 189 190 private Ushort555Rgbx() {} 191 192 public int rgbToPixel(int rgb, ColorModel cm) { 193 return (((rgb >> (16 + 3 - 11)) & 0xf800) | 194 ((rgb >> ( 8 + 3 - 6)) & 0x07c0) | 195 ((rgb >> ( 0 + 3 - 1)) & 0x003e)); 196 } 197 198 public int pixelToRgb(int pixel, ColorModel cm) { 199 int r, g, b; 200 r = (pixel >> 11) & 0x1f; 201 r = (r << 3) | (r >> 2); 202 g = (pixel >> 6) & 0x1f; 203 g = (g << 3) | (g >> 2); 204 b = (pixel >> 1) & 0x1f; 205 b = (b << 3) | (b >> 2); 206 return (0xff000000 | (r << 16) | (g << 8) | (b)); 207 } 208 } 209 public static class Ushort555Rgb extends PixelConverter { 210 public static final PixelConverter instance = new Ushort555Rgb(); 211 212 private Ushort555Rgb() {} 213 214 public int rgbToPixel(int rgb, ColorModel cm) { 215 return (((rgb >> (16 + 3 - 10)) & 0x7c00) | 216 ((rgb >> ( 8 + 3 - 5)) & 0x03e0) | 217 ((rgb >> ( 0 + 3 - 0)) & 0x001f)); 218 } 219 220 public int pixelToRgb(int pixel, ColorModel cm) { 221 int r, g, b; 222 r = (pixel >> 10) & 0x1f; 223 r = (r << 3) | (r >> 2); 224 g = (pixel >> 5) & 0x1f; 225 g = (g << 3) | (g >> 2); 226 b = (pixel ) & 0x1f; 227 b = (b << 3) | (b >> 2); 228 return (0xff000000 | (r << 16) | (g << 8) | (b)); 229 } 230 } 231 public static class Ushort4444Argb extends PixelConverter { 232 public static final PixelConverter instance = new Ushort4444Argb(); 233 234 private Ushort4444Argb() { 235 alphaMask = 0xf000; 236 } 237 238 public int rgbToPixel(int rgb, ColorModel cm) { 239 // use upper 4 bits for each color 240 // 0xAaRrGgBb -> 0x0000ARGB 241 int a = (rgb >> 16) & 0xf000; 242 int r = (rgb >> 12) & 0x0f00; 243 int g = (rgb >> 8) & 0x00f0; 244 int b = (rgb >> 4) & 0x000f; 245 246 return (a | r | g | b); 247 } 248 249 public int pixelToRgb(int pixel, ColorModel cm) { 250 int a, r, g, b; 251 // replicate 4 bits for each color 252 // 0xARGB -> 0xAARRGGBB 253 a = pixel & 0xf000; 254 a = ((pixel << 16) | (pixel << 12)) & 0xff000000; 255 r = pixel & 0x0f00; 256 r = ((pixel << 12) | (pixel << 8)) & 0x00ff0000; 257 g = pixel & 0x00f0; 258 g = ((pixel << 8) | (pixel << 4)) & 0x0000ff00; 259 b = pixel & 0x000f; 260 b = ((pixel << 4) | (pixel << 0)) & 0x000000ff; 261 262 return (a | r | g | b); 263 } 264 } 265 public static class Xbgr extends PixelConverter { 266 public static final PixelConverter instance = new Xbgr(); 267 268 private Xbgr() {} 269 270 public int rgbToPixel(int rgb, ColorModel cm) { 271 return (((rgb & 0xff) << 16) | 272 (rgb & 0xff00) | 273 ((rgb >> 16) & 0xff)); 274 } 275 276 public int pixelToRgb(int pixel, ColorModel cm) { 277 return (0xff000000 | 278 ((pixel & 0xff) << 16) | 279 (pixel & 0xff00) | 280 ((pixel >> 16) & 0xff)); 281 } 282 } 283 public static class Bgrx extends PixelConverter { 284 public static final PixelConverter instance = new Bgrx(); 285 286 private Bgrx() {} 287 288 public int rgbToPixel(int rgb, ColorModel cm) { 289 return ((rgb << 24) | 290 ((rgb & 0xff00) << 8) | 291 ((rgb >> 8) & 0xff00)); 292 } 293 294 public int pixelToRgb(int pixel, ColorModel cm) { 295 return (0xff000000 | 296 ((pixel & 0xff00) << 8) | 297 ((pixel >> 8) & 0xff00) | 298 (pixel >>> 24)); 299 } 300 } 301 public static class Rgba extends PixelConverter { 302 public static final PixelConverter instance = new Rgba(); 303 304 private Rgba() { 305 alphaMask = 0x000000ff; 306 } 307 308 public int rgbToPixel(int rgb, ColorModel cm) { 309 return ((rgb << 8) | (rgb >>> 24)); 310 } 311 312 public int pixelToRgb(int pixel, ColorModel cm) { 313 return ((pixel << 24) | (pixel >>> 8)); 314 } 315 } 316 public static class RgbaPre extends PixelConverter { 317 public static final PixelConverter instance = new RgbaPre(); 318 319 private RgbaPre() { 320 alphaMask = 0x000000ff; 321 } 322 323 public int rgbToPixel(int rgb, ColorModel cm) { 324 if ((rgb >> 24) == -1) { 325 return ((rgb << 8) | (rgb >>> 24)); 326 } 327 int a = rgb >>> 24; 328 int r = (rgb >> 16) & 0xff; 329 int g = (rgb >> 8) & 0xff; 330 int b = (rgb ) & 0xff; 331 int a2 = a + (a >> 7); 332 r = (r * a2) >> 8; 333 g = (g * a2) >> 8; 334 b = (b * a2) >> 8; 335 return ((r << 24) | (g << 16) | (b << 8) | (a)); 336 } 337 338 public int pixelToRgb(int pixel, ColorModel cm) { 339 int a = pixel & 0xff; 340 if ((a == 0xff) || (a == 0)) { 341 return ((pixel >>> 8) | (pixel << 24)); 342 } 343 int r = pixel >>> 24; 344 int g = (pixel >> 16) & 0xff; 345 int b = (pixel >> 8) & 0xff; 346 r = ((r << 8) - r) / a; 347 g = ((g << 8) - g) / a; 348 b = ((b << 8) - b) / a; 349 return ((r << 24) | (g << 16) | (b << 8) | (a)); 350 } 351 } 352 public static class ArgbPre extends PixelConverter { 353 public static final PixelConverter instance = new ArgbPre(); 354 355 private ArgbPre() { 356 alphaMask = 0xff000000; 357 } 358 359 public int rgbToPixel(int rgb, ColorModel cm) { 360 if ((rgb >> 24) == -1) { 361 return rgb; 362 } 363 int a = rgb >>> 24; 364 int r = (rgb >> 16) & 0xff; 365 int g = (rgb >> 8) & 0xff; 366 int b = (rgb ) & 0xff; 367 int a2 = a + (a >> 7); 368 r = (r * a2) >> 8; 369 g = (g * a2) >> 8; 370 b = (b * a2) >> 8; 371 return ((a << 24) | (r << 16) | (g << 8) | (b)); 372 } 373 374 public int pixelToRgb(int pixel, ColorModel cm) { 375 int a = pixel >>> 24; 376 if ((a == 0xff) || (a == 0)) { 377 return pixel; 378 } 379 int r = (pixel >> 16) & 0xff; 380 int g = (pixel >> 8) & 0xff; 381 int b = (pixel ) & 0xff; 382 r = ((r << 8) - r) / a; 383 g = ((g << 8) - g) / a; 384 b = ((b << 8) - b) / a; 385 return ((a << 24) | (r << 16) | (g << 8) | (b)); 386 } 387 } 388 public static class ArgbBm extends PixelConverter { 389 public static final PixelConverter instance = new ArgbBm(); 390 391 private ArgbBm() {} 392 393 public int rgbToPixel(int rgb, ColorModel cm) { 394 return (rgb | ((rgb >> 31) << 24)); 395 } 396 397 public int pixelToRgb(int pixel, ColorModel cm) { 398 return ((pixel << 7) >> 7); 399 } 400 } 401 public static class ByteGray extends PixelConverter { 402 static final double RED_MULT = 0.299; 403 static final double GRN_MULT = 0.587; 404 static final double BLU_MULT = 0.114; 405 public static final PixelConverter instance = new ByteGray(); 406 407 private ByteGray() {} 408 409 public int rgbToPixel(int rgb, ColorModel cm) { 410 int red = (rgb >> 16) & 0xff; 411 int grn = (rgb >> 8) & 0xff; 412 int blu = (rgb ) & 0xff; 413 return (int) (red * RED_MULT + 414 grn * GRN_MULT + 415 blu * BLU_MULT + 416 0.5); 417 } 418 419 public int pixelToRgb(int pixel, ColorModel cm) { 420 return ((((((0xff << 8) | pixel) << 8) | pixel) << 8) | pixel); 421 } 422 } 423 public static class UshortGray extends ByteGray { 424 static final double SHORT_MULT = 257.0; // (65535.0 / 255.0); 425 static final double USHORT_RED_MULT = RED_MULT * SHORT_MULT; 426 static final double USHORT_GRN_MULT = GRN_MULT * SHORT_MULT; 427 static final double USHORT_BLU_MULT = BLU_MULT * SHORT_MULT; 428 public static final PixelConverter instance = new UshortGray(); 429 430 private UshortGray() {} 431 432 public int rgbToPixel(int rgb, ColorModel cm) { 433 int red = (rgb >> 16) & 0xff; 434 int grn = (rgb >> 8) & 0xff; 435 int blu = (rgb ) & 0xff; 436 return (int) (red * USHORT_RED_MULT + 437 grn * USHORT_GRN_MULT + 438 blu * USHORT_BLU_MULT + 439 0.5); 440 } 441 442 public int pixelToRgb(int pixel, ColorModel cm) { 443 pixel = pixel >> 8; 444 return ((((((0xff << 8) | pixel) << 8) | pixel) << 8) | pixel); 445 } 446 } 447 }