1 50 51 package org.openlaszlo.iv.flash.util; 52 53 import java.io.EOFException ; 54 import java.io.IOException ; 55 import java.io.InputStream ; 56 import java.io.DataInputStream ; 57 import java.io.BufferedInputStream ; 58 import java.io.ByteArrayInputStream ; 59 import java.util.zip.InflaterInputStream ; 60 import java.util.zip.Deflater ; 61 import java.util.zip.CRC32 ; 62 import java.util.Hashtable ; 63 import org.openlaszlo.iv.flash.parser.DataMarker; 64 65 70 public class PNGHelper 71 { 72 73 private static final int CHUNK_IHDR = 0x49484452; 74 75 private static final int CHUNK_PLTE = 0x504c5445; 76 77 private static final int CHUNK_IDAT = 0x49444154; 78 79 private static final int CHUNK_IEND = 0x49454e44; 80 81 private static final int CHUNK_tRNS = 0x74524e53; 82 83 84 private static final int CHUNK_bKGD = 0x624b4744; 85 86 private static final int CHUNK_cHRM = 0x6348524d; 87 88 private static final int CHUNK_fRAc = 0x66524163; 89 90 private static final int CHUNK_gAMA = 0x67414d41; 91 92 private static final int CHUNK_gIFg = 0x67494667; 93 94 private static final int CHUNK_gIFt = 0x67494674; 95 96 private static final int CHUNK_gIFx = 0x67494678; 97 98 private static final int CHUNK_hIST = 0x68495354; 99 100 private static final int CHUNK_iCCP = 0x69434350; 101 102 private static final int CHUNK_iTXt = 0x69545874; 103 104 private static final int CHUNK_oFFs = 0x6f464673; 105 106 private static final int CHUNK_pCAL = 0x7043414c; 107 108 private static final int CHUNK_pHYs = 0x70485973; 109 110 private static final int CHUNK_sBIT = 0x73424954; 111 112 private static final int CHUNK_sCAL = 0x7343414c; 113 114 private static final int CHUNK_sPLT = 0x73504c54; 115 116 private static final int CHUNK_sRGB = 0x73524742; 117 118 private static final int CHUNK_tEXt = 0x74455874; 119 120 private static final int CHUNK_tIME = 0x74494d45; 121 122 private static final int CHUNK_zTXt = 0x7a545874; 123 124 125 private static final int[] PNG_SIGN = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a }; 126 127 128 private boolean flagIHDR = false; 129 130 private boolean flagIDAT = false; 131 132 private boolean flagPLTE = false; 133 134 135 private boolean tRNSPassRequired = false; 136 137 private RGB tRNSKeyColor = null; 138 139 private boolean flagtRNS = false; 140 141 142 private int colorType_components= -1; 143 144 145 private int compressionMethod = -1; 146 153 private int filterMethod = -1; 154 158 private int interlaceMethod = -1; 159 160 161 private int width = -1; 162 163 private int height = -1; 164 165 private int bitDepth = -1; 166 167 168 private long gamma = 45455; 169 170 177 private int colorType = -1; 178 179 180 private boolean colorType_hasPalette= false; 181 182 private boolean colorType_hasAlpha = false; 183 184 private boolean colorType_hasColor = false; 185 186 187 private RGB[] palette; 188 189 190 private int colorsUsed = 0; 191 192 193 private byte[] buffer; 194 195 196 198 199 private CRCInputStream source; 200 201 207 public class CRCInputStream extends DataInputStream 209 { 210 211 private CRC32 crc = new CRC32 (); 212 213 217 public CRCInputStream(InputStream inputStream) 218 { 219 super(inputStream); 220 } 221 222 226 public long getCRC() 227 { 228 return crc.getValue(); 229 } 230 231 234 public void reset() 235 { 236 crc.reset(); 237 } 238 239 243 public int read() throws IOException 244 { 245 int x = super.read(); 246 crc.update(x); 247 return x; 248 } 249 250 254 public int read2() throws IOException , EOFException 255 { 256 int a = read(); 257 int b = read(); 258 return a | b << 8; 259 } 260 261 265 public int read2n() throws IOException , EOFException 266 { 267 int b = read(); 268 int a = read(); 269 return a | b << 8; 270 } 271 272 276 public long read4n() throws IOException , EOFException 277 { 278 long b = (long)read2n(); 279 long a = (long)read2n(); 280 return a | b << 16; 281 } 282 } 283 284 285 290 public class RGB 292 { 293 294 private static final int FORMAT_RGB5 = 0x8050; 295 296 private static final int FORMAT_RGB8 = 0x8051; 297 298 private static final int FORMAT_RGB5_A1 = 0x8057; 299 300 private static final int FORMAT_RGBA8 = 0x8058; 301 302 303 private static final int NO_ALPHA = -1; 304 305 306 private static final float DEFAULT_ALPHA = 1.0f; 307 308 private static final float DEFAULT_FORMAT = 255.0f; 309 310 311 private float red; 312 313 private float green; 314 315 private float blue; 316 317 private float alpha; 318 319 323 public RGB(float gray) 324 { 325 set(gray, gray, gray, DEFAULT_ALPHA); 326 } 327 328 332 public RGB(int gray) 333 { 334 set(gray, gray, gray, NO_ALPHA, NO_ALPHA); 335 } 336 337 342 public RGB(int gray, int a) 343 { 344 set(gray, gray, gray, a, DEFAULT_FORMAT); 345 } 346 347 352 public RGB(float gray, float a) 353 { 354 set(gray, gray, gray, a); 355 } 356 357 363 public RGB(float r, float g, float b) 364 { 365 set(r, g, b, DEFAULT_ALPHA); 366 } 367 368 374 public RGB(int r, int g, int b) 375 { 376 set(r, g, b, NO_ALPHA, NO_ALPHA); 377 } 378 379 386 public RGB(int r, int g, int b, int a) 387 { 388 set((float)r / DEFAULT_FORMAT, (float)g / DEFAULT_FORMAT, (float)b / DEFAULT_FORMAT, (float) a/ DEFAULT_FORMAT); 389 } 390 391 398 public RGB(float r, float g, float b, float a) 399 { 400 set(r, g, b, a); 401 } 402 403 410 public void set(float r, float g, float b, float a) 411 { 412 red = r > 1.0f ? 1.0f : (r < 0.0f ? 0.0f : r); 413 green = g > 1.0f ? 1.0f : (g < 0.0f ? 0.0f : g); 414 blue = b > 1.0f ? 1.0f : (b < 0.0f ? 0.0f : b); 415 alpha = a > 1.0f ? 1.0f : (a < 0.0f ? 0.0f : a); 416 } 417 418 426 public void set(int r, int g, int b, int a, float format) 427 { 428 set((float)r / DEFAULT_FORMAT, (float)g / DEFAULT_FORMAT, (float)b / DEFAULT_FORMAT, 429 format == NO_ALPHA ? DEFAULT_ALPHA : (float)a / format); 430 } 431 432 437 public int[] getPacked(int format) 438 { 439 int r; 440 int g; 441 int b; 442 switch(format) 443 { 444 case FORMAT_RGB5: 445 r = (int)(red * 32.0f); 446 g = (int)(green * 32.0f); 447 b = (int)(blue * 32.0f); 448 return new int[] 449 { 450 r + (g & 0x07) << 5, 451 (g & 0x18) >> 3 + (b & 0x1f) << 2 452 }; 453 case FORMAT_RGB8: 454 return new int[] 455 { 456 (int)(red * 255.0f), 457 (int)(green * 255.0f), 458 (int)(blue * 255.0f) 459 }; 460 case FORMAT_RGB5_A1: 461 r = (int)(red * 32.0f); 462 g = (int)(green * 32.0f); 463 b = (int)(blue * 32.0f); 464 return new int[] 465 { 466 r + (g & 0x07) << 5, 467 (g & 0x18) >> 3 + (b & 0x1f) << 2 + (alpha > 0.5f ? 128 : 0) 468 }; 469 case FORMAT_RGBA8: 470 return new int[] 471 { 472 (int)(red * 255.0f), 473 (int)(green * 255.0f), 474 (int)(blue * 255.0f), 475 (int)(alpha * 255.0f) 476 }; 477 default: 478 throw new IllegalArgumentException ("Unknown color format "+format); 479 } 480 } 481 482 486 public float getRed() 487 { 488 return red; 489 } 490 491 495 public float getGreen() 496 { 497 return green; 498 } 499 500 504 public float getBlue() 505 { 506 return blue; 507 } 508 509 513 public float getAlpha() 514 { 515 return alpha; 516 } 517 518 522 public void setAlpha(float alpha) 523 { 524 this.alpha = alpha; 525 } 526 527 533 public boolean compareTo(RGB rgb, boolean compareAlpha) 534 { 535 if (rgb.getRed() == red && rgb.getGreen() == green && rgb.getBlue() == blue) 536 if (!compareAlpha || (compareAlpha && rgb.getAlpha() == alpha)) 537 return true; 538 return false; 539 } 540 } 541 542 547 public PNGHelper() 548 { } 549 550 554 public PNGHelper(byte[] inputBuffer) 555 { 556 setInputBuffer(inputBuffer); 557 } 558 559 564 public void setInputBuffer(byte[] inputBuffer) 565 { 566 source = new CRCInputStream(new ByteArrayInputStream (inputBuffer)); 567 } 568 569 574 public void setInputBuffer(FlashBuffer fob) 575 { 576 source = new CRCInputStream(fob.getInputStream()); 578 } 579 580 584 public int getWidth() 585 { 586 return width; 587 } 588 589 594 public int getHeight() 595 { 596 return height; 597 } 598 599 603 public int getColorTableSize() 604 { 605 return (colorsUsed -1); 606 } 607 608 614 public boolean hasTransparency() 615 { 616 return (colorType>3 || flagtRNS); 617 } 618 619 626 public int getFormat() 627 { 628 int format; 629 switch (colorType_components) 630 { 631 case 1: 632 format = 3; if (colorType == 0) 634 format = 5; 635 if (bitDepth == 16) 636 format = 5; 637 break; 638 default: 642 format = 5; break; 644 } 645 return format; 646 } 647 648 659 public DataMarker getZlibData() throws IOException ,EOFException ,IVException 660 { 661 RGB[][] rgb = read(); 662 boolean transparency = hasTransparency(); 663 int format = getFormat(); 664 int mult = 1; 665 switch (format) 666 { 667 case 4: 668 mult = 2; 669 break; 670 case 5: 671 mult = 4; 672 } 673 byte[] tempData; 674 int plus = 3; 675 int[] pixel; 676 int idx = 0; 677 int falsewidth = width; 678 int added = 0; 679 int maxpixels = width * height; 680 if ((mult == 1) && (width % 4 > 0)) 682 { 683 while (falsewidth % 4 > 0) 684 { 685 falsewidth++; 686 added++; 687 } 688 maxpixels = falsewidth * height; 689 } 690 691 if (colorType_hasPalette) 692 { 693 if (transparency) plus++; 695 696 tempData = new byte[(maxpixels) + (colorsUsed*plus)]; for (int i = 0; i < colorsUsed; i++) 698 { 699 if (transparency) 700 pixel = palette[i].getPacked(RGB.FORMAT_RGBA8); 701 else 702 pixel = palette[i].getPacked(RGB.FORMAT_RGB8); 703 704 if (transparency && pixel[3] == 0x00) { 706 tempData[idx++] = 0; 707 tempData[idx++] = 0; 708 tempData[idx++] = 0; 709 } 710 else 711 { 712 tempData[idx++] = (byte) ((pixel[0])); 713 tempData[idx++] = (byte) ((pixel[1])); 714 tempData[idx++] = (byte) ((pixel[2])); 715 } 716 if (transparency) 717 tempData[idx++] = (byte) ((pixel[3])); 718 } 719 } 720 else 721 { 722 if (transparency) 723 mult = 4; 724 tempData = new byte[(maxpixels * mult)]; } 726 727 for (int y = 0; y < height; y++) 728 { 729 for (int x = 0; x < width; x++) 730 { 731 if (colorType_hasPalette) 732 { 733 if (transparency) 734 pixel = rgb[y][x].getPacked(RGB.FORMAT_RGBA8); 735 else 736 pixel = rgb[y][x].getPacked(RGB.FORMAT_RGB8); 737 int b = 0; 738 for (int i = 0; i < palette.length; i++) 739 { 740 if (palette[i].compareTo(rgb[y][x],false)) 741 { 742 b = i; 743 break; 744 } 745 } 746 tempData[idx++] = (byte) b; 747 } 748 else 749 { 750 if (mult == 4) 751 pixel = rgb[y][x].getPacked(RGB.FORMAT_RGBA8); 752 else if (mult == 2) 753 pixel = rgb[y][x].getPacked(RGB.FORMAT_RGB5_A1); 754 else 755 pixel = rgb[y][x].getPacked(RGB.FORMAT_RGB8); 756 757 if (pixel != null) 758 { 759 if (mult == 4) 760 tempData[idx++] = (byte) ((pixel[3])); 761 tempData[idx++] = (byte) ((pixel[0])); 762 if (mult > 1) 763 tempData[idx++] = (byte) ((pixel[1])); 764 if (mult == 4) 765 tempData[idx++] = (byte) ((pixel[2])); 766 } 767 } 768 } 769 if (added > 0) { 771 for (int i = 0; i < added; i++) 772 { 773 tempData[idx++] = 0x00; 774 } 775 } 776 } 777 Deflater deflater = new Deflater (9); deflater.setInput(tempData); 779 byte[] data = new byte[(maxpixels * mult) + (colorsUsed*plus)]; 780 deflater.finish(); 781 int defsize = deflater.deflate(data); 782 byte[] buff = new byte[defsize]; 783 System.arraycopy(data,0,buff,0,defsize); 784 DataMarker zlibDatas = new DataMarker(buff,0,defsize); 785 return zlibDatas; 786 } 787 788 791 792 798 private RGB[][] read() throws IOException ,EOFException ,IVException 799 { 800 if (source == null) 801 throw new IOException ("Null input stream"); 802 source.mark(Integer.MAX_VALUE); 803 buffer = new byte[0]; 804 try 805 { 806 for (int i = 0; i < 8; i++) 807 if (source.read() != PNG_SIGN[i]) 808 throw new IOException ("Not a valid PNG file"); 809 810 int length; 811 int id; 812 while(true) 813 { 814 length = (int)source.read4n(); 815 source.reset(); 816 id = (int)source.read4n(); 817 switch(id) 818 { 819 case CHUNK_IHDR: readChunk_IHDR(length); break; 821 case CHUNK_PLTE: readChunk_PLTE(length); break; 822 case CHUNK_tRNS: readChunk_tRNS(length); break; 823 case CHUNK_IDAT: readChunk_IDAT(length); break; 824 case CHUNK_IEND: 825 if (!flagIHDR || !flagIDAT) 826 throw new IOException ("No header or data chunk found"); 827 return decode(buffer); 828 829 case CHUNK_gAMA: readChunk_gAMA(length); break; case CHUNK_bKGD: 832 case CHUNK_cHRM: case CHUNK_fRAc: 834 case CHUNK_gIFg: 835 case CHUNK_gIFt: 836 case CHUNK_gIFx: 837 case CHUNK_hIST: 838 case CHUNK_iCCP: case CHUNK_iTXt: 840 case CHUNK_oFFs: 841 case CHUNK_pCAL: 842 case CHUNK_pHYs: 843 case CHUNK_sBIT: 844 case CHUNK_sCAL: 845 case CHUNK_sPLT: case CHUNK_sRGB: case CHUNK_tEXt: 848 case CHUNK_tIME: 849 case CHUNK_zTXt: 850 source.skipBytes(length + 4); break; 852 default: 853 if ( (id & 0x20000000) == 0) 855 throw new IOException ("Unknown critical chunk "+ 857 (char)((id >> 24) & 0xff) + (char)((id >> 16) & 0xff) + 858 (char)((id >> 8) & 0xff) + (char)(id & 0xff)); 859 source.skipBytes(length + 4); 861 } 862 } 863 } 864 catch (EOFException eofe) 865 { 866 throw new EOFException ("Reached unexpected EOF"); 867 } 868 catch(IOException ioe) 869 { 870 throw new IOException ("Error while reading file"); 871 } 872 } 873 874 879 private void readChunk_gAMA(int length) throws IOException 880 { 881 if (flagIDAT || flagPLTE) 882 throw new IOException ("gAMA chunk must precede IDAT and PLTE chunks"); 883 884 if (length != 4) 885 throw new IOException ("Invalid length " + length + " for gAMA chunk"); 886 887 gamma = source.read4n(); 889 long okCRC = source.getCRC(); 890 if (source.read4n() != okCRC) 891 throw new IOException ("Invalid CRC for gAMA chunk " + length); 892 } 893 894 899 private void readChunk_tRNS(int length) throws IOException 900 { 901 if (!flagIHDR || flagIDAT) 902 throw new IOException ("Misplaced transparency chunk"); 903 904 switch(colorType) 905 { 906 case 0: int tmp1 = source.read(); 908 int tmp2 = source.read(); 909 910 if (bitDepth < 16) 911 { 912 int max = 1; 913 switch (bitDepth) 914 { 915 case 1: 916 max = 256; 917 break; 918 case 2: 919 max = 256/4; 920 break; 921 case 4: 922 max = 256/16; 923 break; 924 } 925 if (bitDepth == 1) tRNSKeyColor = new RGB(tmp2*max); 927 else 928 { 929 tmp1 = ((tmp2 + 1) * max) - 1; 930 tmp1 = (tmp1 < 0) ? 0 : tmp1; 931 tRNSKeyColor = new RGB(tmp1); 932 } 933 } 934 else 935 tRNSKeyColor = new RGB((float)(tmp1 << 8 | tmp2) / 65535.0f); 936 937 tRNSKeyColor.setAlpha(0.0f); 938 tRNSPassRequired = true; 939 break; 940 case 2: int tmp; 942 int cr1 = source.read(); 943 int cr2 = source.read(); 944 int cg1 = source.read(); 945 int cg2 = source.read(); 946 int cb1 = source.read(); 947 int cb2 = source.read(); 948 if (bitDepth < 16) 949 { 950 tRNSKeyColor = new RGB(cr2, cg2, cb2); 951 } 952 else 953 tRNSKeyColor = new RGB((float)(cr1 << 8 | cr2) / 65535.0f, 954 (float)(cg1 << 8 | cg2) / 65535.0f, (float)(cb1 << 8 | cb2) / 65535.0f); 955 tRNSKeyColor.setAlpha(0.0f); 956 tRNSPassRequired = true; 957 break; 958 case 3: for (int i = 0; i < length; i++) 961 palette[i].setAlpha((float)source.read() / 255.0f); 962 break; 963 default: throw new IOException ("Unexpected transparency chunk"); 965 } 966 flagtRNS = true; 967 968 long okCRC = source.getCRC(); 969 if (source.read4n() != okCRC) 970 throw new IOException ("Invalid CRC for tRNS chunk " + length); 971 } 972 973 978 private void readChunk_PLTE(int length) throws IOException 979 { 980 if (!flagIHDR || flagIDAT) 981 throw new IOException ("Misplaced palette chunk"); 982 983 if (length % 3 != 0) 984 throw new IOException ("Invalid palette size: "+ length +" bytes"); 985 if (colorType != 3) 986 { 987 int tmp; 990 for (int i = 0; i < length; i++) 991 tmp = source.read(); 992 } 993 else 994 { 995 flagPLTE = true; 996 int entries = length / 3; 997 colorsUsed = entries; 998 palette = new RGB[entries]; 999 for (int i = 0; i < entries; i++) 1000 palette[i] = new RGB(source.read(), source.read(), source.read()); 1001 } 1002 long okCRC = source.getCRC(); 1003 if (source.read4n() != okCRC) 1004 throw new IOException ("Invalid CRC for PLTE chunk"); 1005 } 1006 1007 1012 private void readChunk_IHDR(int length) throws IOException 1013 { 1014 if (flagIHDR) 1015 throw new IOException ("Duplicate header chunks"); 1016 flagIHDR = true; 1017 1018 width = (int)source.read4n(); 1019 height = (int)source.read4n(); 1020 bitDepth = source.read(); 1021 colorType = source.read(); 1022 compressionMethod = source.read(); 1023 filterMethod = source.read(); 1024 interlaceMethod = source.read(); 1025 1026 if ( (width == 0) || (height == 0) ) 1027 throw new IOException ("Invalid image size: "+width+"x"+height); 1028 switch(colorType) 1029 { 1030 case 0: if ( (bitDepth != 1) && (bitDepth != 2) && (bitDepth != 4) && 1032 (bitDepth != 8) && (bitDepth != 16) ) 1033 throw new IOException 1034 ("Invalid bit depth: "+ bitDepth +" for color type: grayscale"); 1035 colorType_components = 1; 1036 break; 1040 case 3: if ( (bitDepth != 1) && (bitDepth != 2) && (bitDepth != 4) && (bitDepth != 8) ) 1042 throw new IOException 1043 ("Invalid bit depth: "+ bitDepth +" for color type: paletted"); 1044 colorType_components = 1; 1045 colorType_hasPalette = true; 1046 colorType_hasColor = true; 1047 break; 1049 case 2: if ( (bitDepth != 8) && (bitDepth != 16) ) 1051 throw new IOException 1052 ("Invalid bit depth: "+ bitDepth +" for color type: RGB"); 1053 colorType_components = 3; 1054 colorType_hasColor = true; 1056 break; 1058 case 4: if ( (bitDepth != 8) && (bitDepth != 16) ) 1060 throw new IOException 1061 ("Invalid bit depth: "+ bitDepth +" for color type: gray + alpha"); 1062 colorType_components = 2; 1063 colorType_hasAlpha = true; 1066 break; 1067 case 6: if ( (bitDepth != 8) && (bitDepth != 16) ) 1069 throw new IOException 1070 ("Invalid bit depth: "+ bitDepth +" for color type: RGB + alpha"); 1071 colorType_components = 4; 1072 colorType_hasColor = true; 1074 colorType_hasAlpha = true; 1075 break; 1076 default: 1077 throw new IOException ("Invalid color type: "+ colorType); 1078 } 1079 if (compressionMethod != 0) 1080 throw new IOException 1081 ("Unsupported compression method: "+ compressionMethod); 1082 if (filterMethod != 0) 1083 throw new IOException ("Unsupported filter method: "+ compressionMethod); 1084 if ( (interlaceMethod != 0) && (interlaceMethod != 1) ) 1085 throw new IOException ("Unsupported interlace method: "+ interlaceMethod); 1086 1087 long okCRC = source.getCRC(); 1088 if (source.read4n() != okCRC) 1089 throw new IOException ("Invalid CRC for IHDR chunk"); 1090 } 1091 1092 1097 private void readChunk_IDAT(int length) throws IOException 1098 { 1099 if (!flagIHDR) 1100 throw new IOException ("Data chunks before header"); 1101 if ( (colorType == 3) && (!flagPLTE) ) 1102 throw new IOException ("Missing palette"); 1103 flagIDAT = true; 1104 1105 int oldLength = buffer.length; 1106 int newLength = oldLength + length; 1107 byte[] zlibNew = new byte[newLength]; 1108 System.arraycopy(buffer, 0, zlibNew, 0, oldLength); 1109 1110 for (int i = oldLength; i < newLength; i++) 1111 zlibNew[i] = (byte)source.read(); 1112 1113 buffer = zlibNew; 1114 1115 long okCRC = source.getCRC(); 1116 if (source.read4n() != okCRC) 1117 throw new IOException ("Invalid CRC for IDAT chunk"); 1118 } 1119 1120 1128 private RGB[][] decode(byte[] zlibStream) throws IOException 1129 { 1130 InflaterInputStream inflater = new InflaterInputStream ( 1131 new java.io.ByteArrayInputStream (zlibStream)); 1132 1133 int bytesPerScanline = (int)( (float)width * 1134 (float)bitDepth * 1135 (float)colorType_components / 8.0f ); 1136 1137 if (colorType==3) 1139 { 1140 switch (bitDepth) 1142 { 1143 case 1: 1144 if ((width%8)>0) 1145 bytesPerScanline++; 1146 break; 1147 case 2: 1148 if ((width%4)>0) 1149 bytesPerScanline++; 1150 break; 1151 case 4: 1152 if ((width%2)>0) 1153 bytesPerScanline++; 1154 break; 1155 } 1156 } 1157 1158 RGB[][] rgb = new RGB[height][width]; 1159 1160 if (interlaceMethod == 1 && bitDepth < 8) 1162 { 1163 rgb = deCompressSpecial(rgb, inflater); 1165 } 1166 else 1167 { 1168 int bytesPerPixel = bitDepth * colorType_components / 8; 1169 bytesPerPixel = (bytesPerPixel == 0) ? 1 : bytesPerPixel; 1170 1171 int[][] scanlines = new int[height][bytesPerScanline]; 1172 scanlines = deCompress(scanlines, inflater, bytesPerPixel); 1173 1174 int b, bb; int cr, cg, cb, ca; 1177 switch(colorType) 1178 { 1179 1180 case 0: switch(bitDepth) 1182 { 1183 case 1: 1184 for (int y = 0; y < height; y++) 1185 { 1186 int scanX = 0; 1187 for (int x = 0; x < width;) 1188 { 1189 b = scanlines[y][scanX++]; 1190 for (int z = 7; ((x < width) && (z > -1)) ; z--) 1191 { 1192 bb = ((b >> z) & 0x01) * 256; 1193 RGB color = new RGB(bb, bb, bb); 1194 if (tRNSPassRequired) { 1196 if (color.compareTo(tRNSKeyColor,false)) { 1198 color = new RGB(0); 1199 color.setAlpha(0.0f); 1200 } 1201 } 1202 rgb[y][x++] = color; 1203 } 1204 } 1205 } 1206 break; 1207 case 2: 1208 for (int y = 0; y < height; y++) 1209 { 1210 int scanX = 0; 1211 for (int x = 0; x < width;) 1212 { 1213 b = scanlines[y][scanX++]; 1214 for (int z = 6; ((x < width) && (z > -1)) ; z -= 2) 1215 { 1216 bb = ((((b >> z) & 0x03) + 1) * 64) - 1; 1217 bb = (bb < 0) ? 0 : bb; 1218 RGB color = new RGB(bb, bb, bb); 1219 if (tRNSPassRequired) { 1221 if (color.compareTo(tRNSKeyColor,false)) { 1223 color = new RGB(0); 1224 color.setAlpha(0.0f); 1225 } 1226 } 1227 rgb[y][x++] = color; 1228 } 1229 } 1230 } 1231 break; 1232 case 4: 1233 for (int y = 0; y < height; y++) 1234 { 1235 int scanX = 0; 1236 for (int x = 0; x < width;) 1237 { 1238 b = scanlines[y][scanX++]; 1239 bb = ((((b >> 4) & 0x0f) + 1) * 16) - 1; 1240 bb = (bb < 0) ? 0 : bb; 1241 RGB color = new RGB(bb, bb, bb); 1242 if (tRNSPassRequired) { 1244 if (color.compareTo(tRNSKeyColor,false)) { 1246 color = new RGB(0); 1247 color.setAlpha(0.0f); 1248 } 1249 } 1250 rgb[y][x++] = color; 1251 if (x < width) 1252 { 1253 bb = ((( b & 0x0f) + 1) * 16) -1; 1254 bb = (bb < 0) ? 0 : bb; 1255 color = new RGB(bb, bb, bb); 1256 if (tRNSPassRequired) { 1258 if (color.compareTo(tRNSKeyColor,false)) { 1260 color = new RGB(0); 1261 color.setAlpha(0.0f); 1262 } 1263 } 1264 rgb[y][x++] = color; 1265 } 1266 } 1267 } 1268 break; 1269 case 8: 1270 for (int y = 0; y < height; y++) 1271 { 1272 for (int x = 0; x < width; x++) 1273 { 1274 RGB color = new RGB(scanlines[y][x]); 1275 if (tRNSPassRequired) { 1277 if (color.compareTo(tRNSKeyColor,false)) { 1279 color = new RGB(0); 1280 color.setAlpha(0.0f); 1281 } 1282 } 1283 rgb[y][x] = color; 1284 } 1285 } 1286 break; 1287 case 16: 1288 for (int y = 0; y < height; y++) 1289 { 1290 int scanX = 0; 1291 for (int x = 0; x < width; x++) 1292 { 1293 RGB color = new RGB ((float)(scanlines[y][scanX++] << 8 | 1294 scanlines[y][scanX++]) / 65535.0f); 1295 if (tRNSPassRequired) { 1297 if (color.compareTo(tRNSKeyColor,false)) { 1299 color = new RGB(0); 1300 color.setAlpha(0.0f); 1301 } 1302 } 1303 rgb[y][x] = color; 1304 } 1305 } 1306 break; 1307 } 1308 break; 1309 1310 case 2: switch(bitDepth) 1312 { 1313 case 8: 1314 for (int y = 0; y < height; y++) 1315 { 1316 int scanX = 0; 1317 for (int x = 0; x < width; x++) 1318 { 1319 RGB color = new RGB(scanlines[y][scanX++], 1320 scanlines[y][scanX++], 1321 scanlines[y][scanX++]); 1322 if (tRNSPassRequired) { 1324 if (color.compareTo(tRNSKeyColor,false)) { 1326 color = new RGB(0); 1327 color.setAlpha(0.0f); 1328 } 1329 } 1330 rgb[y][x] = color; 1331 } 1332 } 1333 break; 1334 case 16: 1335 for (int y = 0; y < height; y++) 1337 { 1338 int scanX = 0; 1339 for (int x = 0; x < width; x++) 1340 { 1341 float aa = (float)(scanlines[y][scanX++] << 8 | 1342 scanlines[y][scanX++]) / 65535.0f; 1343 float ab = (float)(scanlines[y][scanX++] << 8 | 1344 scanlines[y][scanX++]) / 65535.0f; 1345 float ac = (float)(scanlines[y][scanX++] << 8 | 1346 scanlines[y][scanX++]) / 65535.0f; 1347 RGB color = new RGB(aa, ab, ac); 1348 1349 if (tRNSPassRequired) { 1351 if (color.compareTo(tRNSKeyColor,false)) { 1353 color = new RGB(0); 1354 color.setAlpha(0.0f); 1355 } 1356 } 1357 rgb[x][y] = color; 1358 } 1359 } 1360 break; 1361 } 1362 break; 1363 case 3: switch(bitDepth) 1365 { 1366 case 1: 1367 for (int y = 0; y < height; y++) 1368 { 1369 int scanX = 0; 1370 for (int x = 0; x < width;) 1371 { 1372 if (scanX < bytesPerScanline) 1373 { 1374 b = scanlines[y][scanX++]; 1375 for (int z = 7; ((x < width) && (z > -1)) ; z--) 1376 { 1377 bb = (b >> z) & 0x01; 1378 rgb[y][x++] = palette[bb]; 1379 } 1380 } 1381 else 1382 break; 1383 } 1384 } 1385 break; 1386 case 2: 1387 for (int y = 0; y < height; y++) 1388 { 1389 int scanX = 0; 1390 for (int x = 0; x < width;) 1391 { 1392 if (scanX < bytesPerScanline) 1393 { 1394 b = scanlines[y][scanX++]; 1395 for (int z = 6; ((x < width) && (z > -1)) ; z -= 2) 1396 { 1397 bb = (b >> z) & 0x03; 1398 rgb[y][x++] = palette[bb]; 1399 } 1400 } 1401 else 1402 break; 1403 } 1404 } 1405 break; 1406 case 4: 1407 for (int y = 0; y < height; y++) 1408 { 1409 int scanX = 0; 1410 for (int x = 0; x < width;) 1411 { 1412 if (scanX <= bytesPerScanline) 1413 { 1414 b = scanlines[y][scanX++]; 1415 bb = (b >> 4) & 0x0f; 1416 rgb[y][x++] = palette[bb]; 1417 if (x < width) 1418 { 1419 bb = b & 0x0f; 1420 rgb[y][x++] = palette[bb]; 1421 } 1422 } 1423 else 1424 break; 1425 } 1426 } 1427 break; 1428 case 8: 1429 for (int y = 0; y < height; y++) 1430 { 1431 for (int x = 0; x < width; x++) 1432 { 1433 b = scanlines[y][x]; 1434 b = (b < palette.length) ? b : 0; 1436 rgb[y][x] = palette[b]; 1437 } 1438 } 1439 break; 1440 } 1441 break; 1442 case 4: switch(bitDepth) 1444 { 1445 case 8: 1446 for (int y = 0; y < height; y++) 1447 { 1448 int scanX = 0; 1449 for (int x = 0; x < width; x++) 1450 { 1451 cr = scanlines[y][scanX++]; 1453 ca = scanlines[y][scanX++]; 1454 1455 float fa = (float)ca/255.0f; 1457 cr = (int)(cr*fa); 1458 1459 rgb[y][x] = new RGB(cr, ca); 1460 } 1461 } 1462 break; 1463 case 16: 1464 for (int y = 0; y < height; y++) 1465 { 1466 int scanX = 0; 1467 for (int x = 0; x < width; x++) 1468 { 1469 float aa = (float)(scanlines[y][scanX++] << 8 | 1471 scanlines[y][scanX++]) / 65535.0f; 1472 float ab = (float)(scanlines[y][scanX++] << 8 | 1473 scanlines[y][scanX++]) / 65535.0f; 1474 1475 aa *= ab; 1477 1478 rgb[y][x] = new RGB(aa, ab); 1479 } 1480 } 1481 break; 1482 } 1483 break; 1484 case 6: switch(bitDepth) 1486 { 1487 case 8: 1488 int idx = 0; 1489 for (int y = 0; y < height; y++) 1490 { 1491 int scanX = 0; 1492 for (int x = 0; x < width; x++) 1493 { 1494 cr = scanlines[y][scanX++]; 1495 cg = scanlines[y][scanX++]; 1496 cb = scanlines[y][scanX++]; 1497 ca = scanlines[y][scanX++]; 1498 1499 if (ca == 0) { 1501 cr = cg = cb = 0; 1502 } else { 1503 float fa = (float)ca/255.0f; 1504 cr = (int)((cr)*fa); 1505 cg = (int)((cg)*fa); 1506 cb = (int)((cb)*fa); 1507 } 1508 1509 rgb[y][x] = new RGB(cr, cg, cb, ca); 1510 } 1511 } 1512 break; 1513 case 16: 1514 for (int y = 0; y < height; y++) 1515 { 1516 int scanX = 0; 1517 for (int x = 0; x < width; x++) 1518 { 1519 float aa = (float)(scanlines[y][scanX++] << 8 | 1520 scanlines[y][scanX++]) / 65535.0f; 1521 float ab = (float)(scanlines[y][scanX++] << 8 | 1522 scanlines[y][scanX++]) / 65535.0f; 1523 float ac = (float)(scanlines[y][scanX++] << 8 | 1524 scanlines[y][scanX++]) / 65535.0f; 1525 float ad = (float)(scanlines[y][scanX++] << 8 | 1526 scanlines[y][scanX++]) / 65535.0f; 1527 1528 aa *= ad; 1530 ab *= ad; 1531 ac *= ad; 1532 1533 rgb[y][x] = new RGB(aa, ab, ac, ad); 1534 } 1535 } 1536 break; 1537 } 1538 } 1539 } 1540 return rgb; 1541 } 1542 1543 1549 private int getPreviousRow(int row, int pass) 1550 { 1551 if (interlaceMethod == 1) 1552 { 1553 int[] starting_Row = { 0, 0, 4, 0, 2, 0, 1 }; 1554 int[] row_Increment = { 8, 8, 8, 4, 4, 2, 2 }; 1555 int currentPassMin = starting_Row[pass]; 1556 if (row == currentPassMin) 1557 return 0; 1558 else 1559 return ((row > (row - row_Increment[pass])) ? (row - row_Increment[pass]) : 0); 1560 } 1561 else 1562 { 1563 return ((row > 0) ? (row - 1) : 0); 1564 } 1565 } 1566 1567 1573 private int getPreviousCol(int col, int pass) 1574 { 1575 if (interlaceMethod == 1) 1576 { 1577 int[] starting_Col = { 0, 4, 0, 2, 0, 1, 0 }; 1578 int[] col_Increment = { 8, 8, 4, 4, 2, 2, 1 }; 1579 int currentPassMin = starting_Col[pass]; 1580 if (col == currentPassMin) 1581 return 0; 1582 else 1583 return ((col > (col - col_Increment[pass])) ? (col - col_Increment[pass]) : 0); 1584 } 1585 else 1586 { 1587 return ((col > 0) ? (col - 1) : 0); 1588 } 1589 } 1590 1591 1599 private RGB[][] deCompressSpecial(RGB[][] rgb, InputStream inflater) throws IOException 1600 { 1601 int[] starting_Row = { 0, 0, 4, 0, 2, 0, 1 }; 1602 int[] starting_Col = { 0, 4, 0, 2, 0, 1, 0 }; 1603 int[] row_Increment = { 8, 8, 8, 4, 4, 2, 2 }; 1604 int[] col_Increment = { 8, 8, 4, 4, 2, 2, 1 }; 1605 int[] block_Height = { 8, 8, 4, 4, 2, 2, 1 }; 1606 int[] block_Width = { 8, 4, 4, 2, 2, 1, 1 }; 1607 1608 int row, col, filter; 1609 1610 int [][] pixels = new int[height][width]; 1611 1612 int a, b, c, pa, pb, pc, p; 1614 for (int pass = 0; pass < 7; pass++) 1615 { 1616 row = starting_Row[pass]; 1617 while (row < height) 1618 { 1619 int minHeight = (block_Height[pass] < (height - row)) ? block_Height[pass] : (height - row); 1620 b = inflater.read(); 1621 if (b > -1) 1622 { 1623 filter = (b >> 4) & 0x03; 1624 1625 col = starting_Col[pass]; 1626 while (col < width) 1627 { 1628 int minWidth = (block_Width[pass] < (width - col)) ? block_Width[pass] : (width - col); 1629 b = inflater.read(); 1630 if (b > -1) 1631 { 1632 switch (bitDepth) 1633 { 1634 case 1: 1635 for (int i = 7; i > -1; i--) 1636 { 1637 if (col < width) 1638 { 1639 a = (b >> i) & 0x01; 1640 for (int x = 0; x < minHeight; x++) 1641 { 1642 int rowx = row + x; 1643 if (rowx < height) 1644 { 1645 for (int y = 0; y < minWidth; y++) 1646 { 1647 int coly = col + y; 1648 if (coly < width) 1649 pixels[rowx][coly] = a; 1650 else 1651 break; 1652 } 1653 } 1654 else 1655 break; 1656 } 1657 } 1658 else 1659 break; 1660 col += col_Increment[pass]; 1661 } 1662 break; 1663 case 2: 1664 for (int i = 6; i > -1; i -= 2) 1665 { 1666 if (col < width) 1667 { 1668 a = (b >> i) & 0x03; 1669 for (int x = 0; x < minHeight; x++) 1670 { 1671 int rowx = row + x; 1672 if (rowx < height) 1673 { 1674 for (int y = 0; y < minWidth; y++) 1675 { 1676 int coly = col + y; 1677 if (coly < width) 1678 pixels[rowx][coly] = a; 1679 else 1680 break; 1681 } 1682 } 1683 else 1684 break; 1685 } 1686 } 1687 else 1688 break; 1689 col += col_Increment[pass]; 1690 } 1691 break; 1692 case 4: 1693 for (int i = 4; i > -1; i -= 4) 1694 { 1695 if (col < width) 1696 { 1697 a = (b >> i) & 0x0f; 1698 for (int x = 0; x < minHeight; x++) 1699 { 1700 int rowx = row + x; 1701 if (rowx < height) 1702 { 1703 for (int y = 0; y < minWidth; y++) 1704 { 1705 int coly = col + y; 1706 if (coly < width) 1707 pixels[rowx][coly] = a; 1708 else 1709 break; 1710 } 1711 } 1712 else 1713 break; 1714 } 1715 } 1716 else 1717 break; 1718 col += col_Increment[pass]; 1719 } 1720 break; 1721 } 1722 } 1723 else 1724 break; 1725 } 1726 1727 int nbboucle = 8/bitDepth; 1729 switch(filter) 1730 { 1731 case 0: 1732 break; 1734 case 1: col = starting_Col[pass] + col_Increment[pass]; 1736 while (col < width) 1737 { 1738 for (int i = 0; i < nbboucle; i++) 1739 { 1740 if (col < width) 1741 { 1742 pixels[row][col] = (byte)(pixels[row][col] + 1743 pixels[row][getPreviousCol(col,pass)]) 1744 & 0xff; 1745 } 1746 col += col_Increment[pass]; 1747 } 1748 } 1749 break; 1750 case 2: if (row == 0) 1752 break; 1753 col = starting_Col[pass]; 1754 while (col < width) 1755 { 1756 for (int i = 0; i < nbboucle; i++) 1757 { 1758 if (col < width) 1759 { 1760 pixels[row][col] = (byte)(pixels[row][col] + 1761 pixels[getPreviousRow(row,pass)][col]) 1762 & 0xff; 1763 } 1764 col += col_Increment[pass]; 1765 } 1766 } 1767 break; 1768 case 3: col = starting_Col[pass]; 1770 pixels[row][col] = (byte)(pixels[row][col] + (((row == 0) ? 0 : pixels[getPreviousRow(row,pass)][col]) / 2) ) & 0xff; 1771 col += col_Increment[pass]; 1772 while (col < width) 1773 { 1774 pixels[row][col] = (byte)(pixels[row][col] + 1775 (pixels[row][getPreviousCol(col,pass)] + 1776 ((row == 0) ? 0 : pixels[getPreviousRow(row,pass)][col])) / 2) & 0xff; 1777 1778 col += col_Increment[pass]; 1779 } 1780 break; 1781 case 4: if (row == 0) 1783 { 1784 col = starting_Col[pass]; 1785 pixels[row][col] = 0xff & pixels[row][col]; 1786 col += col_Increment[pass]; 1787 1788 while (col < width) 1789 { 1790 p = pixels[row][getPreviousCol(col,pass)]; 1791 pixels[row][col] = 0xff & (byte)(p + pixels[row][col]); 1792 col += col_Increment[pass]; 1793 } 1794 } 1795 else 1796 { 1797 col = starting_Col[pass]; 1798 pixels[row][col] = 0xff & (byte)(pixels[getPreviousRow(row,pass)][col] + pixels[row][col]); 1799 col += col_Increment[pass]; 1800 1801 while (col < width) 1802 { 1803 a = pixels[row][getPreviousCol(col,pass)]; b = pixels[getPreviousRow(row,pass)][col]; c = pixels[getPreviousRow(row,pass)][getPreviousCol(col,pass)]; 1807 p = (a + b) - c; pa = p > a ? p - a : a - p; pb = p > b ? p - b : b - p; pc = p > c ? p - c : c - p; 1813 if ((pa <= pb) && (pa <= pc)) 1814 p = a; 1815 else if (pb <= pc) 1816 p = b; 1817 else 1818 p = c; 1819 1820 pixels[row][col] = 0xff & (byte)(p + pixels[row][col]); 1821 1822 col += col_Increment[pass]; 1823 } 1824 } 1825 break; 1826 } 1827 } 1828 row += row_Increment[pass]; 1829 } 1830 } 1831 1832 p = 256/(bitDepth*bitDepth); row = 0; 1834 while (row < height) 1835 { 1836 col = 0; 1837 while (col < width) 1838 { 1839 if (colorType == 0) { 1841 RGB color; 1842 if (bitDepth == 1) 1843 color = new RGB(pixels[row][col] * p); 1844 else 1845 color = new RGB(((pixels[row][col] + 1) * p) -1); 1846 if (tRNSPassRequired) { 1848 if (color.compareTo(tRNSKeyColor,false)) { 1850 color = new RGB(0); 1851 color.setAlpha(0.0f); 1852 } 1853 } 1854 rgb[row][col] = color; 1855 } 1856 else rgb[row][col] = palette[pixels[row][col]]; 1859 col++; 1860 } 1861 row++; 1862 } 1863 1864 return rgb; 1865 } 1866 1867 1876 private int[][] deCompress(int[][] scanlines, InputStream inflater, int bytesPerPixel) throws IOException 1877 { 1878 int[] starting_Row = { 0, 0, 4, 0, 2, 0, 1 }; 1879 int[] starting_Col = { 0, 4, 0, 2, 0, 1, 0 }; 1880 int[] row_Increment = { 8, 8, 8, 4, 4, 2, 2 }; 1881 int[] col_Increment = { 8, 8, 4, 4, 2, 2, 1 }; 1882 1883 int a, b, c, pa, pb, pc, p; int maxPass = 7; 1885 if (interlaceMethod==0) 1886 maxPass = 1; 1887 1888 int row, col; 1889 for (int pass = 0; pass < maxPass; pass++) 1890 { 1891 if (interlaceMethod == 1) 1892 row = starting_Row[pass]; 1893 else 1894 row = 0; 1895 1896 while (row < height) 1897 { 1898 int filter = inflater.read(); 1899 if (interlaceMethod == 1) 1900 col = starting_Col[pass]; 1901 else 1902 col = 0; 1903 while (col < width) 1904 { 1905 for (int i = 0; i < bytesPerPixel; i++) 1906 { 1907 int bitcol = (col*bytesPerPixel)+i; 1908 if (bitcol < scanlines[row].length) 1909 scanlines[row][bitcol] = inflater.read(); 1910 } 1911 if (interlaceMethod == 1) 1912 col += col_Increment[pass]; 1913 else 1914 col++; 1915 } 1916 1917 switch(filter) 1919 { 1920 case 0: 1921 break; 1923 case 1: if (interlaceMethod == 1) 1925 col = starting_Col[pass] + col_Increment[pass]; 1926 else 1927 col = 1; 1928 while (col < width) 1929 { 1930 for (int i = 0; i < bytesPerPixel; i++) 1931 { 1932 int bitcol = (col*bytesPerPixel)+i; 1933 if (bitcol < scanlines[row].length) 1934 { 1935 scanlines[row][bitcol] = (byte)(scanlines[row][bitcol] + 1936 scanlines[row][(getPreviousCol(col,pass)*bytesPerPixel)+i]) 1937 & 0xff; 1938 } 1939 } 1940 if (interlaceMethod == 1) 1941 col += col_Increment[pass]; 1942 else 1943 col++; 1944 } 1945 break; 1946 case 2: if (row == 0) 1948 break; 1949 if (interlaceMethod == 1) 1950 col = starting_Col[pass]; 1951 else 1952 col = 0; 1953 while (col < width) 1954 { 1955 for (int i = 0; i < bytesPerPixel; i++) 1956 { 1957 int bitcol = (col*bytesPerPixel)+i; 1958 if (bitcol < scanlines[row].length) 1959 { 1960 scanlines[row][bitcol] = (byte)(scanlines[row][bitcol] + 1961 scanlines[getPreviousRow(row,pass)][bitcol]) 1962 & 0xff; 1963 } 1964 } 1965 if (interlaceMethod == 1) 1966 col += col_Increment[pass]; 1967 else 1968 col++; 1969 } 1970 break; 1971 case 3: if (interlaceMethod == 1) 1973 col = starting_Col[pass]; 1974 else 1975 col = 0; 1976 if (row > 0) 1977 { 1978 for (int i = 0; i < bytesPerPixel; i++) 1979 { 1980 int bitcol = (col*bytesPerPixel)+i; 1981 if (bitcol < scanlines[row].length) 1982 { 1983 scanlines[row][bitcol] = (byte)(scanlines[row][bitcol] + (scanlines[getPreviousRow(row,pass)][bitcol] / 2) ) & 0xff; 1984 } 1985 } 1986 } 1987 if (interlaceMethod == 1) 1988 col += col_Increment[pass]; 1989 else 1990 col++; 1991 while (col < width) 1992 { 1993 for (int i = 0; i < bytesPerPixel; i++) 1994 { 1995 int bitcol = (col*bytesPerPixel)+i; 1996 if (bitcol < scanlines[row].length) 1997 { 1998 scanlines[row][bitcol] = (byte)(scanlines[row][bitcol] + 1999 (scanlines[row][(getPreviousCol(col,pass)*bytesPerPixel)+i] + 2000 ((row == 0) ? 0 : scanlines[getPreviousRow(row,pass)][bitcol])) / 2) & 0xff; 2001 } 2002 } 2003 if (interlaceMethod == 1) 2004 col += col_Increment[pass]; 2005 else 2006 col++; 2007 } 2008 break; 2009 case 4: if (row == 0) 2011 { 2012 if (interlaceMethod == 1) 2013 col = starting_Col[pass]; 2014 else 2015 col = 0; 2016 for (int i = 0; i < bytesPerPixel; i++) 2017 { 2018 int bitcol = (col*bytesPerPixel)+i; 2019 if (bitcol < scanlines[row].length) 2020 scanlines[row][bitcol] = 0xff & scanlines[row][bitcol]; 2021 } 2022 if (interlaceMethod == 1) 2023 col += col_Increment[pass]; 2024 else 2025 col++; 2026 2027 while (col < width) 2028 { 2029 for (int i = 0; i < bytesPerPixel; i++) 2030 { 2031 int bitcol = (col*bytesPerPixel)+i; 2032 if (bitcol < scanlines[row].length) 2033 { 2034 p = scanlines[row][(getPreviousCol(col,pass)*bytesPerPixel)+i]; 2035 scanlines[row][bitcol] = 0xff & (byte)(p + scanlines[row][bitcol]); 2036 } 2037 } 2038 if (interlaceMethod == 1) 2039 col += col_Increment[pass]; 2040 else 2041 col++; 2042 } 2043 } 2044 else 2045 { 2046 if (interlaceMethod == 1) 2047 col = starting_Col[pass]; 2048 else 2049 col = 0; 2050 for (int i = 0; i < bytesPerPixel; i++) 2051 { 2052 int bitcol = (col*bytesPerPixel)+i; 2053 if (bitcol < scanlines[row].length) 2054 scanlines[row][bitcol] = 0xff & (byte)(scanlines[getPreviousRow(row,pass)][bitcol] + scanlines[row][bitcol]); 2055 } 2056 if (interlaceMethod == 1) 2057 col += col_Increment[pass]; 2058 else 2059 col++; 2060 2061 while (col < width) 2062 { 2063 for (int i = 0; i < bytesPerPixel; i++) 2064 { 2065 int bitcol = (col*bytesPerPixel)+i; 2066 if (bitcol < scanlines[row].length) 2067 { 2068 a = scanlines[row][(getPreviousCol(col,pass)*bytesPerPixel)+i]; b = scanlines[getPreviousRow(row,pass)][bitcol]; c = scanlines[getPreviousRow(row,pass)][(getPreviousCol(col,pass)*bytesPerPixel)+i]; 2072 p = (a + b) - c; pa = p > a ? p - a : a - p; pb = p > b ? p - b : b - p; pc = p > c ? p - c : c - p; 2078 if ((pa <= pb) && (pa <= pc)) 2079 p = a; 2080 else if (pb <= pc) 2081 p = b; 2082 else 2083 p = c; 2084 2085 scanlines[row][bitcol] = 0xff & (byte)(p + scanlines[row][bitcol]); 2086 } 2087 } 2088 if (interlaceMethod == 1) 2089 col += col_Increment[pass]; 2090 else 2091 col++; 2092 } 2093 } 2094 break; 2095 } 2096 if (interlaceMethod == 1) 2097 row += row_Increment[pass]; 2098 else 2099 row++; 2100 } 2101 } 2102 return scanlines; 2103 } 2104} 2105 | Popular Tags |