| 1 7 8 package java.awt.image; 9 10 import java.awt.Transparency ; 11 import java.awt.color.ColorSpace ; 12 import java.math.BigInteger ; 13 14 98 public class IndexColorModel extends ColorModel { 99 private int rgb[]; 100 private int map_size; 101 private int transparent_index = -1; 102 private boolean allgrayopaque; 103 private BigInteger validBits; 104 105 private static int[] opaqueBits = {8, 8, 8}; 106 private static int[] alphaBits = {8, 8, 8, 8}; 107 108 static private native void initIDs(); 109 static { 110 ColorModel.loadLibraries(); 111 initIDs(); 112 } 113 136 public IndexColorModel(int bits, int size, 137 byte r[], byte g[], byte b[]) { 138 super(bits, opaqueBits, 139 ColorSpace.getInstance(ColorSpace.CS_sRGB), 140 false, false, OPAQUE, 141 ColorModel.getDefaultTransferType(bits)); 142 if (bits < 1 || bits > 16) { 143 throw new IllegalArgumentException ("Number of bits must be between" 144 +" 1 and 16."); 145 } 146 setRGBs(size, r, g, b, null); 147 } 148 149 175 public IndexColorModel(int bits, int size, 176 byte r[], byte g[], byte b[], int trans) { 177 super(bits, opaqueBits, 178 ColorSpace.getInstance(ColorSpace.CS_sRGB), 179 false, false, OPAQUE, 180 ColorModel.getDefaultTransferType(bits)); 181 if (bits < 1 || bits > 16) { 182 throw new IllegalArgumentException ("Number of bits must be between" 183 +" 1 and 16."); 184 } 185 setRGBs(size, r, g, b, null); 186 setTransparentPixel(trans); 187 } 188 189 213 public IndexColorModel(int bits, int size, 214 byte r[], byte g[], byte b[], byte a[]) { 215 super (bits, alphaBits, 216 ColorSpace.getInstance(ColorSpace.CS_sRGB), 217 true, false, TRANSLUCENT, 218 ColorModel.getDefaultTransferType(bits)); 219 if (bits < 1 || bits > 16) { 220 throw new IllegalArgumentException ("Number of bits must be between" 221 +" 1 and 16."); 222 } 223 setRGBs (size, r, g, b, a); 224 } 225 226 252 public IndexColorModel(int bits, int size, byte cmap[], int start, 253 boolean hasalpha) { 254 this(bits, size, cmap, start, hasalpha, -1); 255 if (bits < 1 || bits > 16) { 256 throw new IllegalArgumentException ("Number of bits must be between" 257 +" 1 and 16."); 258 } 259 } 260 261 289 public IndexColorModel(int bits, int size, byte cmap[], int start, 290 boolean hasalpha, int trans) { 291 super(bits, opaqueBits, 293 ColorSpace.getInstance(ColorSpace.CS_sRGB), 294 false, false, OPAQUE, 295 ColorModel.getDefaultTransferType(bits)); 296 297 if (bits < 1 || bits > 16) { 298 throw new IllegalArgumentException ("Number of bits must be between" 299 +" 1 and 16."); 300 } 301 if (size < 1) { 302 throw new IllegalArgumentException ("Map size ("+size+ 303 ") must be >= 1"); 304 } 305 map_size = size; 306 rgb = new int[calcRealMapSize(bits, size)]; 307 int j = start; 308 int alpha = 0xff; 309 boolean allgray = true; 310 int transparency = OPAQUE; 311 for (int i = 0; i < size; i++) { 312 int r = cmap[j++] & 0xff; 313 int g = cmap[j++] & 0xff; 314 int b = cmap[j++] & 0xff; 315 allgray = allgray && (r == g) && (g == b); 316 if (hasalpha) { 317 alpha = cmap[j++] & 0xff; 318 if (alpha != 0xff) { 319 if (alpha == 0x00) { 320 if (transparency == OPAQUE) { 321 transparency = BITMASK; 322 } 323 if (transparent_index < 0) { 324 transparent_index = i; 325 } 326 } else { 327 transparency = TRANSLUCENT; 328 } 329 allgray = false; 330 } 331 } 332 rgb[i] = (alpha << 24) | (r << 16) | (g << 8) | b; 333 } 334 this.allgrayopaque = allgray; 335 setTransparency(transparency); 336 setTransparentPixel(trans); 337 } 338 339 372 public IndexColorModel(int bits, int size, 373 int cmap[], int start, 374 boolean hasalpha, int trans, int transferType) { 375 super(bits, opaqueBits, 377 ColorSpace.getInstance(ColorSpace.CS_sRGB), 378 false, false, OPAQUE, 379 transferType); 380 381 if (bits < 1 || bits > 16) { 382 throw new IllegalArgumentException ("Number of bits must be between" 383 +" 1 and 16."); 384 } 385 if (size < 1) { 386 throw new IllegalArgumentException ("Map size ("+size+ 387 ") must be >= 1"); 388 } 389 if ((transferType != DataBuffer.TYPE_BYTE) && 390 (transferType != DataBuffer.TYPE_USHORT)) { 391 throw new IllegalArgumentException ("transferType must be either" + 392 "DataBuffer.TYPE_BYTE or DataBuffer.TYPE_USHORT"); 393 } 394 395 setRGBs(size, cmap, start, hasalpha); 396 setTransparentPixel(trans); 397 } 398 399 437 public IndexColorModel(int bits, int size, int cmap[], int start, 438 int transferType, BigInteger validBits) { 439 super (bits, alphaBits, 440 ColorSpace.getInstance(ColorSpace.CS_sRGB), 441 true, false, TRANSLUCENT, 442 transferType); 443 444 if (bits < 1 || bits > 16) { 445 throw new IllegalArgumentException ("Number of bits must be between" 446 +" 1 and 16."); 447 } 448 if (size < 1) { 449 throw new IllegalArgumentException ("Map size ("+size+ 450 ") must be >= 1"); 451 } 452 if ((transferType != DataBuffer.TYPE_BYTE) && 453 (transferType != DataBuffer.TYPE_USHORT)) { 454 throw new IllegalArgumentException ("transferType must be either" + 455 "DataBuffer.TYPE_BYTE or DataBuffer.TYPE_USHORT"); 456 } 457 458 if (validBits != null) { 459 for (int i=0; i < size; i++) { 461 if (!validBits.testBit(i)) { 462 this.validBits = validBits; 463 break; 464 } 465 } 466 } 467 468 setRGBs(size, cmap, start, true); 469 } 470 471 private void setRGBs(int size, byte r[], byte g[], byte b[], byte a[]) { 472 if (size < 1) { 473 throw new IllegalArgumentException ("Map size ("+size+ 474 ") must be >= 1"); 475 } 476 map_size = size; 477 rgb = new int[calcRealMapSize(pixel_bits, size)]; 478 int alpha = 0xff; 479 int transparency = OPAQUE; 480 boolean allgray = true; 481 for (int i = 0; i < size; i++) { 482 int rc = r[i] & 0xff; 483 int gc = g[i] & 0xff; 484 int bc = b[i] & 0xff; 485 allgray = allgray && (rc == gc) && (gc == bc); 486 if (a != null) { 487 alpha = a[i] & 0xff; 488 if (alpha != 0xff) { 489 if (alpha == 0x00) { 490 if (transparency == OPAQUE) { 491 transparency = BITMASK; 492 } 493 if (transparent_index < 0) { 494 transparent_index = i; 495 } 496 } else { 497 transparency = TRANSLUCENT; 498 } 499 allgray = false; 500 } 501 } 502 rgb[i] = (alpha << 24) | (rc << 16) | (gc << 8) | bc; 503 } 504 this.allgrayopaque = allgray; 505 setTransparency(transparency); 506 } 507 508 private void setRGBs(int size, int cmap[], int start, boolean hasalpha) { 509 map_size = size; 510 rgb = new int[calcRealMapSize(pixel_bits, size)]; 511 int j = start; 512 int transparency = OPAQUE; 513 boolean allgray = true; 514 BigInteger validBits = this.validBits; 515 for (int i = 0; i < size; i++, j++) { 516 if (validBits != null && !validBits.testBit(i)) { 517 continue; 518 } 519 int cmaprgb = cmap[j]; 520 int r = (cmaprgb >> 16) & 0xff; 521 int g = (cmaprgb >> 8) & 0xff; 522 int b = (cmaprgb ) & 0xff; 523 allgray = allgray && (r == g) && (g == b); 524 if (hasalpha) { 525 int alpha = cmaprgb >>> 24; 526 if (alpha != 0xff) { 527 if (alpha == 0x00) { 528 if (transparency == OPAQUE) { 529 transparency = BITMASK; 530 } 531 if (transparent_index < 0) { 532 transparent_index = i; 533 } 534 } else { 535 transparency = TRANSLUCENT; 536 } 537 allgray = false; 538 } 539 } else { 540 cmaprgb |= 0xff000000; 541 } 542 rgb[i] = cmaprgb; 543 } 544 this.allgrayopaque = allgray; 545 setTransparency(transparency); 546 } 547 548 private int calcRealMapSize(int bits, int size) { 549 int newSize = Math.max(1 << bits, size); 550 return Math.max(newSize, 256); 551 } 552 553 private BigInteger getAllValid() { 554 int numbytes = (map_size+7)/8; 555 byte[] valid = new byte[numbytes]; 556 java.util.Arrays.fill(valid, (byte)0xff); 557 valid[0] = (byte)(0xff >>> (numbytes*8 - map_size)); 558 559 return new BigInteger (1, valid); 560 } 561 562 570 public int getTransparency() { 571 return transparency; 572 } 573 574 581 public int[] getComponentSize() { 582 if (nBits == null) { 583 if (supportsAlpha) { 584 nBits = new int[4]; 585 nBits[3] = 8; 586 } 587 else { 588 nBits = new int[3]; 589 } 590 nBits[0] = nBits[1] = nBits[2] = 8; 591 } 592 return nBits; 593 } 594 595 600 final public int getMapSize() { 601 return map_size; 602 } 603 604 616 final public int getTransparentPixel() { 617 return transparent_index; 618 } 619 620 627 final public void getReds(byte r[]) { 628 for (int i = 0; i < map_size; i++) { 629 r[i] = (byte) (rgb[i] >> 16); 630 } 631 } 632 633 640 final public void getGreens(byte g[]) { 641 for (int i = 0; i < map_size; i++) { 642 g[i] = (byte) (rgb[i] >> 8); 643 } 644 } 645 646 653 final public void getBlues(byte b[]) { 654 for (int i = 0; i < map_size; i++) { 655 b[i] = (byte) rgb[i]; 656 } 657 } 658 659 666 final public void getAlphas(byte a[]) { 667 for (int i = 0; i < map_size; i++) { 668 a[i] = (byte) (rgb[i] >> 24); 669 } 670 } 671 672 683 final public void getRGBs(int rgb[]) { 684 System.arraycopy(this.rgb, 0, rgb, 0, map_size); 685 } 686 687 private void setTransparentPixel(int trans) { 688 if (trans >= 0 && trans < map_size) { 689 rgb[trans] &= 0x00ffffff; 690 transparent_index = trans; 691 allgrayopaque = false; 692 if (this.transparency == OPAQUE) { 693 setTransparency(BITMASK); 694 } 695 } 696 } 697 698 private void setTransparency(int transparency) { 699 if (this.transparency != transparency) { 700 this.transparency = transparency; 701 if (transparency == OPAQUE) { 702 supportsAlpha = false; 703 numComponents = 3; 704 nBits = opaqueBits; 705 } else { 706 supportsAlpha = true; 707 numComponents = 4; 708 nBits = alphaBits; 709 } 710 } 711 } 712 713 721 final public int getRed(int pixel) { 722 return (rgb[pixel] >> 16) & 0xff; 723 } 724 725 733 final public int getGreen(int pixel) { 734 return (rgb[pixel] >> 8) & 0xff; 735 } 736 737 745 final public int getBlue(int pixel) { 746 return rgb[pixel] & 0xff; 747 } 748 749 755 final public int getAlpha(int pixel) { 756 return (rgb[pixel] >> 24) & 0xff; 757 } 758 759 767 final public int getRGB(int pixel) { 768 return rgb[pixel]; 769 } 770 771 private static final int CACHESIZE = 40; 772 private int lookupcache[] = new int[CACHESIZE]; 773 774 808 public synchronized Object getDataElements(int rgb, Object pixel) { 809 int red = (rgb>>16) & 0xff; 810 int green = (rgb>>8) & 0xff; 811 int blue = rgb & 0xff; 812 int alpha = (rgb>>>24); 813 int pix = 0; 814 815 for (int i = CACHESIZE - 2; i >= 0; i -= 2) { 816 if ((pix = lookupcache[i]) == 0) { 817 break; 818 } 819 if (rgb == lookupcache[i+1]) { 820 return installpixel(pixel, ~pix); 821 } 822 } 823 824 if (allgrayopaque) { 825 int minDist = 256; 826 int d; 827 int gray = (int) (red*77 + green*150 + blue*29 + 128)/256; 828 829 for (int i = 0; i < map_size; i++) { 830 if (this.rgb[i] == 0x0) { 831 continue; 835 } 836 d = (this.rgb[i] & 0xff) - gray; 837 if (d < 0) d = -d; 838 if (d < minDist) { 839 pix = i; 840 if (d == 0) { 841 break; 842 } 843 minDist = d; 844 } 845 } 846 } else if (alpha == 0) { 847 if (transparent_index >= 0) { 849 pix = transparent_index; 850 } 851 else { 852 int smallestAlpha = 256; 854 for (int i = 0; i < map_size; i++) { 855 int a = this.rgb[i] >>> 24; 856 if (smallestAlpha > alpha && 857 (validBits == null || validBits.testBit(i))) 858 { 859 smallestAlpha = alpha; 860 pix = i; 861 } 862 } 863 } 864 } else { 865 int smallestError = 255 * 255 * 255; int smallestAlphaError = 255; 873 874 if (false && red == green && green == blue) { 875 } 877 878 for (int i=0; i < map_size; i++) { 879 int lutrgb = this.rgb[i]; 880 if (lutrgb == rgb) { 881 pix = i; 882 break; 883 } 884 int tmp = (lutrgb>>>24) - alpha; 885 if (tmp < 0) { 886 tmp = -tmp; 887 } 888 if (tmp <= smallestAlphaError) { 889 smallestAlphaError = tmp; 890 tmp = ((lutrgb>>16) & 0xff) - red; 891 <
|