1 /* 2 * Copyright (c) 2000, 2014, 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 PixelConverter()54 protected PixelConverter() {} 55 56 @SuppressWarnings("fallthrough") rgbToPixel(int rgb, ColorModel cm)57 public int rgbToPixel(int rgb, ColorModel cm) { 58 Object obj = cm.getDataElements(rgb, null); 59 switch (cm.getTransferType()) { 60 case DataBuffer.TYPE_BYTE: 61 byte[] bytearr = (byte[]) obj; 62 int pix = 0; 63 64 switch(bytearr.length) { 65 default: // bytearr.length >= 4 66 pix = bytearr[3] << 24; 67 // FALLSTHROUGH 68 case 3: 69 pix |= (bytearr[2] & 0xff) << 16; 70 // FALLSTHROUGH 71 case 2: 72 pix |= (bytearr[1] & 0xff) << 8; 73 // FALLSTHROUGH 74 case 1: 75 pix |= (bytearr[0] & 0xff); 76 } 77 78 return pix; 79 case DataBuffer.TYPE_SHORT: 80 case DataBuffer.TYPE_USHORT: 81 short[] shortarr = (short[]) obj; 82 83 return (((shortarr.length > 1) ? shortarr[1] << 16 : 0) | 84 shortarr[0] & 0xffff); 85 case DataBuffer.TYPE_INT: 86 return ((int[]) obj)[0]; 87 default: 88 return rgb; 89 } 90 } 91 pixelToRgb(int pixel, ColorModel cm)92 public int pixelToRgb(int pixel, ColorModel cm) { 93 // REMIND: Not yet implemented 94 return pixel; 95 } 96 getAlphaMask()97 public final int getAlphaMask() { 98 return alphaMask; 99 } 100 101 102 /** 103 * Subclasses of PixelConverter. These subclasses are 104 * specific to surface types where we can definitively 105 * calculate the conversions. Note that some conversions 106 * are lossy; that is, we cannot necessarily convert a 107 * value and then convert it back and wind up with the 108 * original value. For example, an rgb value that has 109 * an alpha != 1 cannot be converted to an Xrgb pixel 110 * without losing the information in the alpha component. 111 * 112 * The conversion strategies associated with the ThreeByte* 113 * and FourByte* surface types swap the components around 114 * due to the ordering used when the bytes are stored. The 115 * low order byte of a packed-byte pixel will be the first 116 * byte stored and the high order byte will be the last byte 117 * stored. For example, the ThreeByteBgr surface type is 118 * associated with an Xrgb conversion object because the 119 * three bytes are stored as follows: 120 * pixels[0] = b; // low order byte of an Xrgb pixel 121 * pixels[1] = g; 122 * pixels[2] = r; // high order byte of an Xrgb pixel 123 */ 124 125 public static class Rgbx extends PixelConverter { 126 public static final PixelConverter instance = new Rgbx(); 127 Rgbx()128 private Rgbx() {} 129 rgbToPixel(int rgb, ColorModel cm)130 public int rgbToPixel(int rgb, ColorModel cm) { 131 return (rgb << 8); 132 } 133 pixelToRgb(int pixel, ColorModel cm)134 public int pixelToRgb(int pixel, ColorModel cm) { 135 return (0xff000000 | (pixel >> 8)); 136 } 137 } 138 public static class Xrgb extends PixelConverter { 139 public static final PixelConverter instance = new Xrgb(); 140 Xrgb()141 private Xrgb() {} 142 rgbToPixel(int rgb, ColorModel cm)143 public int rgbToPixel(int rgb, ColorModel cm) { 144 return rgb; 145 } 146 pixelToRgb(int pixel, ColorModel cm)147 public int pixelToRgb(int pixel, ColorModel cm) { 148 return (0xff000000 | pixel); 149 } 150 } 151 public static class Argb extends PixelConverter { 152 public static final PixelConverter instance = new Argb(); 153 Argb()154 private Argb() { 155 alphaMask = 0xff000000; 156 } 157 rgbToPixel(int rgb, ColorModel cm)158 public int rgbToPixel(int rgb, ColorModel cm) { 159 return rgb; 160 } 161 pixelToRgb(int pixel, ColorModel cm)162 public int pixelToRgb(int pixel, ColorModel cm) { 163 return pixel; 164 } 165 } 166 public static class Ushort565Rgb extends PixelConverter { 167 public static final PixelConverter instance = new Ushort565Rgb(); 168 Ushort565Rgb()169 private Ushort565Rgb() {} 170 rgbToPixel(int rgb, ColorModel cm)171 public int rgbToPixel(int rgb, ColorModel cm) { 172 return (((rgb >> (16 + 3 - 11)) & 0xf800) | 173 ((rgb >> ( 8 + 2 - 5)) & 0x07e0) | 174 ((rgb >> ( 0 + 3 - 0)) & 0x001f)); 175 } 176 pixelToRgb(int pixel, ColorModel cm)177 public int pixelToRgb(int pixel, ColorModel cm) { 178 int r, g, b; 179 r = (pixel >> 11) & 0x1f; 180 r = (r << 3) | (r >> 2); 181 g = (pixel >> 5) & 0x3f; 182 g = (g << 2) | (g >> 4); 183 b = (pixel ) & 0x1f; 184 b = (b << 3) | (b >> 2); 185 return (0xff000000 | (r << 16) | (g << 8) | (b)); 186 } 187 } 188 public static class Ushort555Rgbx extends PixelConverter { 189 public static final PixelConverter instance = new Ushort555Rgbx(); 190 Ushort555Rgbx()191 private Ushort555Rgbx() {} 192 rgbToPixel(int rgb, ColorModel cm)193 public int rgbToPixel(int rgb, ColorModel cm) { 194 return (((rgb >> (16 + 3 - 11)) & 0xf800) | 195 ((rgb >> ( 8 + 3 - 6)) & 0x07c0) | 196 ((rgb >> ( 0 + 3 - 1)) & 0x003e)); 197 } 198 pixelToRgb(int pixel, ColorModel cm)199 public int pixelToRgb(int pixel, ColorModel cm) { 200 int r, g, b; 201 r = (pixel >> 11) & 0x1f; 202 r = (r << 3) | (r >> 2); 203 g = (pixel >> 6) & 0x1f; 204 g = (g << 3) | (g >> 2); 205 b = (pixel >> 1) & 0x1f; 206 b = (b << 3) | (b >> 2); 207 return (0xff000000 | (r << 16) | (g << 8) | (b)); 208 } 209 } 210 public static class Ushort555Rgb extends PixelConverter { 211 public static final PixelConverter instance = new Ushort555Rgb(); 212 Ushort555Rgb()213 private Ushort555Rgb() {} 214 rgbToPixel(int rgb, ColorModel cm)215 public int rgbToPixel(int rgb, ColorModel cm) { 216 return (((rgb >> (16 + 3 - 10)) & 0x7c00) | 217 ((rgb >> ( 8 + 3 - 5)) & 0x03e0) | 218 ((rgb >> ( 0 + 3 - 0)) & 0x001f)); 219 } 220 pixelToRgb(int pixel, ColorModel cm)221 public int pixelToRgb(int pixel, ColorModel cm) { 222 int r, g, b; 223 r = (pixel >> 10) & 0x1f; 224 r = (r << 3) | (r >> 2); 225 g = (pixel >> 5) & 0x1f; 226 g = (g << 3) | (g >> 2); 227 b = (pixel ) & 0x1f; 228 b = (b << 3) | (b >> 2); 229 return (0xff000000 | (r << 16) | (g << 8) | (b)); 230 } 231 } 232 public static class Ushort4444Argb extends PixelConverter { 233 public static final PixelConverter instance = new Ushort4444Argb(); 234 Ushort4444Argb()235 private Ushort4444Argb() { 236 alphaMask = 0xf000; 237 } 238 rgbToPixel(int rgb, ColorModel cm)239 public int rgbToPixel(int rgb, ColorModel cm) { 240 // use upper 4 bits for each color 241 // 0xAaRrGgBb -> 0x0000ARGB 242 int a = (rgb >> 16) & 0xf000; 243 int r = (rgb >> 12) & 0x0f00; 244 int g = (rgb >> 8) & 0x00f0; 245 int b = (rgb >> 4) & 0x000f; 246 247 return (a | r | g | b); 248 } 249 pixelToRgb(int pixel, ColorModel cm)250 public int pixelToRgb(int pixel, ColorModel cm) { 251 int a, r, g, b; 252 // replicate 4 bits for each color 253 // 0xARGB -> 0xAARRGGBB 254 a = pixel & 0xf000; 255 a = ((pixel << 16) | (pixel << 12)) & 0xff000000; 256 r = pixel & 0x0f00; 257 r = ((pixel << 12) | (pixel << 8)) & 0x00ff0000; 258 g = pixel & 0x00f0; 259 g = ((pixel << 8) | (pixel << 4)) & 0x0000ff00; 260 b = pixel & 0x000f; 261 b = ((pixel << 4) | (pixel << 0)) & 0x000000ff; 262 263 return (a | r | g | b); 264 } 265 } 266 public static class Xbgr extends PixelConverter { 267 public static final PixelConverter instance = new Xbgr(); 268 Xbgr()269 private Xbgr() {} 270 rgbToPixel(int rgb, ColorModel cm)271 public int rgbToPixel(int rgb, ColorModel cm) { 272 return (((rgb & 0xff) << 16) | 273 (rgb & 0xff00) | 274 ((rgb >> 16) & 0xff)); 275 } 276 pixelToRgb(int pixel, ColorModel cm)277 public int pixelToRgb(int pixel, ColorModel cm) { 278 return (0xff000000 | 279 ((pixel & 0xff) << 16) | 280 (pixel & 0xff00) | 281 ((pixel >> 16) & 0xff)); 282 } 283 } 284 public static class Bgrx extends PixelConverter { 285 public static final PixelConverter instance = new Bgrx(); 286 Bgrx()287 private Bgrx() {} 288 rgbToPixel(int rgb, ColorModel cm)289 public int rgbToPixel(int rgb, ColorModel cm) { 290 return ((rgb << 24) | 291 ((rgb & 0xff00) << 8) | 292 ((rgb >> 8) & 0xff00)); 293 } 294 pixelToRgb(int pixel, ColorModel cm)295 public int pixelToRgb(int pixel, ColorModel cm) { 296 return (0xff000000 | 297 ((pixel & 0xff00) << 8) | 298 ((pixel >> 8) & 0xff00) | 299 (pixel >>> 24)); 300 } 301 } 302 public static class Rgba extends PixelConverter { 303 public static final PixelConverter instance = new Rgba(); 304 Rgba()305 private Rgba() { 306 alphaMask = 0x000000ff; 307 } 308 rgbToPixel(int rgb, ColorModel cm)309 public int rgbToPixel(int rgb, ColorModel cm) { 310 return ((rgb << 8) | (rgb >>> 24)); 311 } 312 pixelToRgb(int pixel, ColorModel cm)313 public int pixelToRgb(int pixel, ColorModel cm) { 314 return ((pixel << 24) | (pixel >>> 8)); 315 } 316 } 317 public static class RgbaPre extends PixelConverter { 318 public static final PixelConverter instance = new RgbaPre(); 319 RgbaPre()320 private RgbaPre() { 321 alphaMask = 0x000000ff; 322 } 323 rgbToPixel(int rgb, ColorModel cm)324 public int rgbToPixel(int rgb, ColorModel cm) { 325 if ((rgb >> 24) == -1) { 326 return ((rgb << 8) | (rgb >>> 24)); 327 } 328 int a = rgb >>> 24; 329 int r = (rgb >> 16) & 0xff; 330 int g = (rgb >> 8) & 0xff; 331 int b = (rgb ) & 0xff; 332 int a2 = a + (a >> 7); 333 r = (r * a2) >> 8; 334 g = (g * a2) >> 8; 335 b = (b * a2) >> 8; 336 return ((r << 24) | (g << 16) | (b << 8) | (a)); 337 } 338 pixelToRgb(int pixel, ColorModel cm)339 public int pixelToRgb(int pixel, ColorModel cm) { 340 int a = pixel & 0xff; 341 if ((a == 0xff) || (a == 0)) { 342 return ((pixel >>> 8) | (pixel << 24)); 343 } 344 int r = pixel >>> 24; 345 int g = (pixel >> 16) & 0xff; 346 int b = (pixel >> 8) & 0xff; 347 r = ((r << 8) - r) / a; 348 g = ((g << 8) - g) / a; 349 b = ((b << 8) - b) / a; 350 return ((r << 24) | (g << 16) | (b << 8) | (a)); 351 } 352 } 353 public static class ArgbPre extends PixelConverter { 354 public static final PixelConverter instance = new ArgbPre(); 355 ArgbPre()356 private ArgbPre() { 357 alphaMask = 0xff000000; 358 } 359 rgbToPixel(int rgb, ColorModel cm)360 public int rgbToPixel(int rgb, ColorModel cm) { 361 if ((rgb >> 24) == -1) { 362 return rgb; 363 } 364 int a = rgb >>> 24; 365 int r = (rgb >> 16) & 0xff; 366 int g = (rgb >> 8) & 0xff; 367 int b = (rgb ) & 0xff; 368 int a2 = a + (a >> 7); 369 r = (r * a2) >> 8; 370 g = (g * a2) >> 8; 371 b = (b * a2) >> 8; 372 return ((a << 24) | (r << 16) | (g << 8) | (b)); 373 } 374 pixelToRgb(int pixel, ColorModel cm)375 public int pixelToRgb(int pixel, ColorModel cm) { 376 int a = pixel >>> 24; 377 if ((a == 0xff) || (a == 0)) { 378 return pixel; 379 } 380 int r = (pixel >> 16) & 0xff; 381 int g = (pixel >> 8) & 0xff; 382 int b = (pixel ) & 0xff; 383 r = ((r << 8) - r) / a; 384 g = ((g << 8) - g) / a; 385 b = ((b << 8) - b) / a; 386 return ((a << 24) | (r << 16) | (g << 8) | (b)); 387 } 388 } 389 public static class ArgbBm extends PixelConverter { 390 public static final PixelConverter instance = new ArgbBm(); 391 ArgbBm()392 private ArgbBm() {} 393 rgbToPixel(int rgb, ColorModel cm)394 public int rgbToPixel(int rgb, ColorModel cm) { 395 return (rgb | ((rgb >> 31) << 24)); 396 } 397 pixelToRgb(int pixel, ColorModel cm)398 public int pixelToRgb(int pixel, ColorModel cm) { 399 return ((pixel << 7) >> 7); 400 } 401 } 402 public static class ByteGray extends PixelConverter { 403 static final double RED_MULT = 0.299; 404 static final double GRN_MULT = 0.587; 405 static final double BLU_MULT = 0.114; 406 public static final PixelConverter instance = new ByteGray(); 407 ByteGray()408 private ByteGray() {} 409 rgbToPixel(int rgb, ColorModel cm)410 public int rgbToPixel(int rgb, ColorModel cm) { 411 int red = (rgb >> 16) & 0xff; 412 int grn = (rgb >> 8) & 0xff; 413 int blu = (rgb ) & 0xff; 414 return (int) (red * RED_MULT + 415 grn * GRN_MULT + 416 blu * BLU_MULT + 417 0.5); 418 } 419 pixelToRgb(int pixel, ColorModel cm)420 public int pixelToRgb(int pixel, ColorModel cm) { 421 return ((((((0xff << 8) | pixel) << 8) | pixel) << 8) | pixel); 422 } 423 } 424 public static class UshortGray extends ByteGray { 425 static final double SHORT_MULT = 257.0; // (65535.0 / 255.0); 426 static final double USHORT_RED_MULT = RED_MULT * SHORT_MULT; 427 static final double USHORT_GRN_MULT = GRN_MULT * SHORT_MULT; 428 static final double USHORT_BLU_MULT = BLU_MULT * SHORT_MULT; 429 public static final PixelConverter instance = new UshortGray(); 430 UshortGray()431 private UshortGray() {} 432 rgbToPixel(int rgb, ColorModel cm)433 public int rgbToPixel(int rgb, ColorModel cm) { 434 int red = (rgb >> 16) & 0xff; 435 int grn = (rgb >> 8) & 0xff; 436 int blu = (rgb ) & 0xff; 437 return (int) (red * USHORT_RED_MULT + 438 grn * USHORT_GRN_MULT + 439 blu * USHORT_BLU_MULT + 440 0.5); 441 } 442 pixelToRgb(int pixel, ColorModel cm)443 public int pixelToRgb(int pixel, ColorModel cm) { 444 pixel = pixel >> 8; 445 return ((((((0xff << 8) | pixel) << 8) | pixel) << 8) | pixel); 446 } 447 } 448 } 449