< prev index next >

src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFDecompressor.java

Print this page




 139      * {@link BaselineTIFFTagSet#COMPRESSION_NONE}, {@link
 140      * BaselineTIFFTagSet#COMPRESSION_CCITT_RLE}, {@link
 141      * BaselineTIFFTagSet#COMPRESSION_CCITT_T_4}, {@link
 142      * BaselineTIFFTagSet#COMPRESSION_CCITT_T_6}, {@link
 143      * BaselineTIFFTagSet#COMPRESSION_LZW}, {@link
 144      * BaselineTIFFTagSet#COMPRESSION_OLD_JPEG}, {@link
 145      * BaselineTIFFTagSet#COMPRESSION_JPEG}, {@link
 146      * BaselineTIFFTagSet#COMPRESSION_ZLIB}, {@link
 147      * BaselineTIFFTagSet#COMPRESSION_PACKBITS}, {@link
 148      * BaselineTIFFTagSet#COMPRESSION_DEFLATE}, or other value
 149      * defined by a TIFF extension.
 150      */
 151     protected int compression;
 152 
 153     /**
 154      * {@code true} if the image is encoded using separate planes.
 155      */
 156     protected boolean planar;
 157 
 158     /**





 159      * The value of the {@code SamplesPerPixel} tag.
 160      */
 161     protected int samplesPerPixel;
 162 
 163     /**
 164      * The value of the {@code BitsPerSample} tag.
 165      *
 166      */
 167     protected int[] bitsPerSample;
 168 
 169     /**
 170      * The value of the {@code SampleFormat} tag.  Legal values
 171      * are {@link BaselineTIFFTagSet#SAMPLE_FORMAT_UNSIGNED_INTEGER},
 172      * {@link BaselineTIFFTagSet#SAMPLE_FORMAT_SIGNED_INTEGER}, {@link
 173      * BaselineTIFFTagSet#SAMPLE_FORMAT_FLOATING_POINT}, {@link
 174      * BaselineTIFFTagSet#SAMPLE_FORMAT_UNDEFINED}, or other value
 175      * defined by a TIFF extension.
 176      */
 177     protected int[] sampleFormat =
 178         new int[] {BaselineTIFFTagSet.SAMPLE_FORMAT_UNSIGNED_INTEGER};


 429      * @return A {@code PixelInterleavedSampleModel}.
 430      */
 431     static SampleModel createInterleavedSM(int dataType,
 432                                            int numBands) {
 433         int[] bandOffsets = new int[numBands];
 434         for(int i = 0; i < numBands; i++) {
 435             bandOffsets[i] = i;
 436         }
 437         return new PixelInterleavedSampleModel(dataType,
 438                                                1, // width
 439                                                1, // height
 440                                                numBands, // pixelStride,
 441                                                numBands, // scanlineStride
 442                                                bandOffsets);
 443     }
 444 
 445     /**
 446      * Create a {@code ComponentColorModel} for use in creating
 447      * an {@code ImageTypeSpecifier}.
 448      */
 449     // This code was copied from javax.imageio.ImageTypeSpecifier.

 450     static ColorModel createComponentCM(ColorSpace colorSpace,
 451                                         int numBands,

 452                                         int dataType,
 453                                         boolean hasAlpha,
 454                                         boolean isAlphaPremultiplied) {
 455         int transparency =
 456             hasAlpha ? Transparency.TRANSLUCENT : Transparency.OPAQUE;
 457 
 458         int[] numBits = new int[numBands];
 459         int bits = DataBuffer.getDataTypeSize(dataType);
 460 
 461         for (int i = 0; i < numBands; i++) {
 462             numBits[i] = bits;
 463         }
 464 
 465         return new ComponentColorModel(colorSpace,
 466                                        numBits,
 467                                        hasAlpha,
 468                                        isAlphaPremultiplied,
 469                                        transparency,
 470                                        dataType);
 471     }
 472 
 473     private static int createMask(int[] bitsPerSample, int band) {
 474         int mask = (1 << bitsPerSample[band]) - 1;
 475         for (int i = band + 1; i < bitsPerSample.length; i++) {
 476             mask <<= bitsPerSample[i];
 477         }
 478 
 479         return mask;
 480     }
 481 
 482     private static int getDataTypeFromNumBits(int numBits, boolean isSigned) {
 483         int dataType;
 484 
 485         if (numBits <= 8) {
 486             dataType = DataBuffer.TYPE_BYTE;


 564     private static boolean areSampleSizesEqual(SampleModel sm) {
 565         boolean allSameSize = true;
 566         int[] sampleSize = sm.getSampleSize();
 567         int sampleSize0 = sampleSize[0];
 568         int numBands = sampleSize.length;
 569 
 570         for(int i = 1; i < numBands; i++) {
 571             if(sampleSize[i] != sampleSize0) {
 572                 allSameSize = false;
 573                 break;
 574             }
 575         }
 576 
 577         return allSameSize;
 578     }
 579 
 580     /**
 581      * Determines whether the {@code DataBuffer} is filled without
 582      * any interspersed padding bits.
 583      */
 584     private static boolean isDataBufferBitContiguous(SampleModel sm)

 585         throws IIOException {
 586         int dataTypeSize = getDataTypeSize(sm.getDataType());
 587 
 588         if(sm instanceof ComponentSampleModel) {
 589             int numBands = sm.getNumBands();
 590             for(int i = 0; i < numBands; i++) {
 591                 if(sm.getSampleSize(i) != dataTypeSize) {
 592                     // Sample does not fill data element.
 593                     return false;
 594                 }
 595             }
 596         } else if(sm instanceof MultiPixelPackedSampleModel) {
 597             MultiPixelPackedSampleModel mppsm =
 598                 (MultiPixelPackedSampleModel)sm;
 599             if(dataTypeSize % mppsm.getPixelBitStride() != 0) {
 600                 // Pixels do not fill the data element.
 601                 return false;
 602             }
 603         } else if(sm instanceof SinglePixelPackedSampleModel) {
 604             SinglePixelPackedSampleModel sppsm =
 605                 (SinglePixelPackedSampleModel)sm;
 606             int numBands = sm.getNumBands();
 607             int numBits = 0;
 608             for(int i = 0; i < numBands; i++) {
 609                 numBits += sm.getSampleSize(i);
 610             }
 611             if(numBits != dataTypeSize) {


 665                     int shift = 24;
 666                     int ival = 0;
 667                     for(int b = 0; b < numExtraBytes; b++) {
 668                         ival |= (buf[inOffset++]&0xff) << shift;
 669                         shift -= 8;
 670                     }
 671                     intData[k++] = ival;
 672                 }
 673                 outOffset += outStride;
 674             }
 675         } else {
 676             throw new IIOException("shortData == null && intData == null!");
 677         }
 678     }
 679 
 680     /**
 681      * Reformats bit-discontiguous data into the {@code DataBuffer}
 682      * of the supplied {@code WritableRaster}.
 683      */
 684     private static void reformatDiscontiguousData(byte[] buf,

 685                                                   int stride,
 686                                                   int w,
 687                                                   int h,
 688                                                   WritableRaster raster)
 689         throws IOException {
 690 
 691         // Get SampleModel info.
 692         SampleModel sm = raster.getSampleModel();
 693         int numBands = sm.getNumBands();
 694         int[] sampleSize = sm.getSampleSize();
 695 
 696         // Initialize input stream.
 697         ByteArrayInputStream is = new ByteArrayInputStream(buf);
 698         ImageInputStream iis = new MemoryCacheImageInputStream(is);
 699 
 700         // Reformat.
 701         long iisPosition = 0L;
 702         int y = raster.getMinY();
 703         for(int j = 0; j < h; j++, y++) {
 704             iis.seek(iisPosition);
 705             int x = raster.getMinX();
 706             for(int i = 0; i < w; i++, x++) {
 707                 for(int b = 0; b < numBands; b++) {
 708                     long bits = iis.readBits(sampleSize[b]);
 709                     raster.setSample(x, y, b, (int)bits);
 710                 }
 711             }
 712             iisPosition += stride;
 713         }
 714     }
 715 
 716     /**
 717      * A utility method that returns an
 718      * {@code ImageTypeSpecifier} suitable for decoding an image
 719      * with the given parameters.
 720      *
 721      * @param photometricInterpretation the value of the
 722      * {@code PhotometricInterpretation} field.
 723      * @param compression the value of the {@code Compression} field.
 724      * @param samplesPerPixel the value of the
 725      * {@code SamplesPerPixel} field.
 726      * @param bitsPerSample the value of the {@code BitsPerSample} field.
 727      * @param sampleFormat the value of the {@code SampleFormat} field.
 728      * @param extraSamples the value of the {@code ExtraSamples} field.


 789                 }
 790 
 791                 return ImageTypeSpecifier.createGrayscale(bitsPerSample[0],
 792                                                           dataType,
 793                                                           isSigned);
 794             } else {
 795                 // Indexed
 796                 int mapSize = 1 << bitsPerSample[0];
 797                 byte[] redLut = new byte[mapSize];
 798                 byte[] greenLut = new byte[mapSize];
 799                 byte[] blueLut = new byte[mapSize];
 800                 byte[] alphaLut = null;
 801 
 802                 int idx = 0;
 803                 for (int i = 0; i < mapSize; i++) {
 804                     redLut[i] = (byte)((colorMap[i]*255)/65535);
 805                     greenLut[i] = (byte)((colorMap[mapSize + i]*255)/65535);
 806                     blueLut[i] = (byte)((colorMap[2*mapSize + i]*255)/65535);
 807                 }
 808 
 809                 int dataType = bitsPerSample[0] == 8 ?
 810                     DataBuffer.TYPE_BYTE : DataBuffer.TYPE_USHORT;







 811                 return ImageTypeSpecifier.createIndexed(redLut,
 812                                                         greenLut,
 813                                                         blueLut,
 814                                                         alphaLut,
 815                                                         bitsPerSample[0],
 816                                                         dataType);
 817             }
 818         }
 819 
 820         // 8-bit gray-alpha
 821         if (samplesPerPixel == 2 &&
 822             bitsPerSample[0] == 8 &&
 823             bitsPerSample[1] == 8) {
 824             int dataType = DataBuffer.TYPE_BYTE;
 825             boolean alphaPremultiplied = false;
 826             if (extraSamples != null &&
 827                 extraSamples[0] ==
 828                 BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA) {
 829                 alphaPremultiplied = true;
 830             }


1065                                                          samplesPerPixel);
1066 
1067                     // Create the ColorModel.
1068                     ColorModel cm;
1069                     if(samplesPerPixel >= 1 && samplesPerPixel <= 4 &&
1070                        (dataType == DataBuffer.TYPE_INT ||
1071                         dataType == DataBuffer.TYPE_FLOAT)) {
1072                         // Handle the 32-bit cases for 1-4 bands.
1073                         ColorSpace cs = samplesPerPixel <= 2 ?
1074                             ColorSpace.getInstance(ColorSpace.CS_GRAY) : rgb;
1075                         boolean hasAlpha = ((samplesPerPixel % 2) == 0);
1076                         boolean alphaPremultiplied = false;
1077                         if(hasAlpha && extraSamples != null &&
1078                            extraSamples[0] ==
1079                            BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA) {
1080                             alphaPremultiplied = true;
1081                         }
1082 
1083                         cm = createComponentCM(cs,
1084                                                samplesPerPixel,

1085                                                dataType,
1086                                                hasAlpha,
1087                                                alphaPremultiplied);
1088                     } else {
1089                         ColorSpace cs = new BogusColorSpace(samplesPerPixel);
1090                         cm = createComponentCM(cs,
1091                                                samplesPerPixel,

1092                                                dataType,
1093                                                false, // hasAlpha
1094                                                false); // alphaPremultiplied
1095                     }
1096                     return new ImageTypeSpecifier(cm, sm);
1097                 }
1098             }
1099         }
1100 
1101         // Other more bizarre cases including discontiguous DataBuffers
1102         // such as for the image in bug 4918959.
1103 
1104         if(colorMap == null &&
1105            sampleFormat[0] !=
1106            BaselineTIFFTagSet.SAMPLE_FORMAT_FLOATING_POINT) {
1107 
1108             // Determine size of largest sample.
1109             int maxBitsPerSample = 0;
1110             for(int i = 0; i < bitsPerSample.length; i++) {
1111                 if(bitsPerSample[i] > maxBitsPerSample) {
1112                     maxBitsPerSample = bitsPerSample[i];
1113                 }
1114             }
1115 
1116             // Determine whether data are signed.
1117             boolean isSigned =
1118                 (sampleFormat[0] ==
1119                  BaselineTIFFTagSet.SAMPLE_FORMAT_SIGNED_INTEGER);
1120 
1121             // Grayscale
1122             if(samplesPerPixel == 1) {
1123                 int dataType =
1124                     getDataTypeFromNumBits(maxBitsPerSample, isSigned);


1125 
1126                 return ImageTypeSpecifier.createGrayscale(maxBitsPerSample,
1127                                                           dataType,
1128                                                           isSigned);
1129             }
1130 
1131             // Gray-alpha
1132             if (samplesPerPixel == 2) {




1133                 boolean alphaPremultiplied = false;
1134                 if (extraSamples != null &&
1135                     extraSamples[0] ==
1136                     BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA) {
1137                     alphaPremultiplied = true;
1138                 }
1139 
1140                 int dataType =
1141                     getDataTypeFromNumBits(maxBitsPerSample, isSigned);
1142 
1143                 return ImageTypeSpecifier.createGrayscale(maxBitsPerSample,
1144                                                           dataType,
1145                                                           false,
1146                                                           alphaPremultiplied);
1147             }
1148 
1149             if (samplesPerPixel == 3 || samplesPerPixel == 4) {







1150                 if(totalBits <= 32 && !isSigned) {
1151                     // Packed RGB or RGBA
1152                     int redMask = createMask(bitsPerSample, 0);
1153                     int greenMask = createMask(bitsPerSample, 1);
1154                     int blueMask = createMask(bitsPerSample, 2);
1155                     int alphaMask = (samplesPerPixel == 4) ?
1156                         createMask(bitsPerSample, 3) : 0;
1157                     int transferType =
1158                         getDataTypeFromNumBits(totalBits, false);
1159                     boolean alphaPremultiplied = false;
1160                     if (extraSamples != null &&
1161                         extraSamples[0] ==
1162                         BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA) {
1163                         alphaPremultiplied = true;
1164                     }
1165                     return ImageTypeSpecifier.createPacked(rgb,
1166                                                            redMask,
1167                                                            greenMask,
1168                                                            blueMask,
1169                                                            alphaMask,
1170                                                            transferType,
1171                                                            alphaPremultiplied);
1172                 } else if(samplesPerPixel == 3) {



1173                     // Interleaved RGB
1174                     int[] bandOffsets = new int[] {0, 1, 2};
1175                     int dataType =
1176                         getDataTypeFromNumBits(maxBitsPerSample, isSigned);
1177                     return ImageTypeSpecifier.createInterleaved(rgb,
1178                                                                 bandOffsets,
1179                                                                 dataType,
1180                                                                 false,
1181                                                                 false);
1182                 } else if(samplesPerPixel == 4) {




1183                     // Interleaved RGBA
1184                     int[] bandOffsets = new int[] {0, 1, 2, 3};
1185                     int dataType =
1186                         getDataTypeFromNumBits(maxBitsPerSample, isSigned);
1187                     boolean alphaPremultiplied = false;
1188                     if (extraSamples != null &&
1189                         extraSamples[0] ==
1190                         BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA) {
1191                         alphaPremultiplied = true;
1192                     }
1193                     return ImageTypeSpecifier.createInterleaved(rgb,
1194                                                                 bandOffsets,
1195                                                                 dataType,
1196                                                                 true,
1197                                                                 alphaPremultiplied);
1198                 }
1199             } else {

1200                 // Arbitrary Interleaved.
1201                 int dataType =
1202                     getDataTypeFromNumBits(maxBitsPerSample, isSigned);
1203                 SampleModel sm = createInterleavedSM(dataType,
1204                                                      samplesPerPixel);
1205                 ColorSpace cs = new BogusColorSpace(samplesPerPixel);







1206                 ColorModel cm = createComponentCM(cs,
1207                                                   samplesPerPixel,

1208                                                   dataType,
1209                                                   false, // hasAlpha
1210                                                   false); // alphaPremultiplied
1211                 return new ImageTypeSpecifier(cm, sm);
1212             }
1213         }
1214 
1215         return null;
1216     }
1217 
1218     /**
1219      * Sets the value of the {@code reader} field.
1220      *
1221      * <p> If this method is called, the {@code beginDecoding}
1222      * method must be called prior to calling any of the decode
1223      * methods.
1224      *
1225      * @param reader the current {@code ImageReader}.
1226      */
1227     public void setReader(ImageReader reader) {
1228         this.reader = reader;
1229     }
1230 
1231     /**
1232      * Sets the value of the {@code metadata} field.
1233      *


1268      */
1269     public void setCompression(int compression) {
1270         this.compression = compression;
1271     }
1272 
1273     /**
1274      * Sets the value of the {@code planar} field.
1275      *
1276      * <p> If this method is called, the {@code beginDecoding}
1277      * method must be called prior to calling any of the decode
1278      * methods.
1279      *
1280      * @param planar {@code true} if the image to be decoded is
1281      * stored in planar format.
1282      */
1283     public void setPlanar(boolean planar) {
1284         this.planar = planar;
1285     }
1286 
1287     /**








1288      * Sets the value of the {@code samplesPerPixel} field.
1289      *
1290      * <p> If this method is called, the {@code beginDecoding}
1291      * method must be called prior to calling any of the decode
1292      * methods.
1293      *
1294      * @param samplesPerPixel the number of samples in each source
1295      * pixel.
1296      */
1297     public void setSamplesPerPixel(int samplesPerPixel) {
1298         this.samplesPerPixel = samplesPerPixel;
1299     }
1300 
1301     /**
1302      * Sets the value of the {@code bitsPerSample} field.
1303      *
1304      * <p> If this method is called, the {@code beginDecoding}
1305      * method must be called prior to calling any of the decode
1306      * methods.
1307      *


2471                     isSupportedType = true;
2472                 }
2473             }
2474 
2475             if(!isSupportedType) {
2476                 throw new IIOException
2477                     ("Unsupported raw image type: SampleModel = "+sm+
2478                      "; DataBuffer = "+db);
2479             }
2480         }
2481 
2482         if(isBilevel) {
2483             // Bilevel data are always in a contiguous byte buffer.
2484             decodeRaw(byteData, dstOffset, pixelBitStride, scanlineStride);
2485         } else {
2486             SampleModel sm = ras.getSampleModel();
2487 
2488             // Branch based on whether data are bit-contiguous, i.e.,
2489             // data are packaed as tightly as possible leaving no unused
2490             // bits except at the end of a row.
2491             if(isDataBufferBitContiguous(sm)) {
2492                 // Use byte or float data directly.
2493                 if (byteData != null) {
2494                     decodeRaw(byteData, dstOffset,
2495                               pixelBitStride, scanlineStride);
2496                 } else if (floatData != null) {
2497                     decodeRaw(floatData, dstOffset,
2498                               pixelBitStride, scanlineStride);
2499                 } else if (doubleData != null) {
2500                     decodeRaw(doubleData, dstOffset,
2501                               pixelBitStride, scanlineStride);
2502                 } else {
2503                     if (shortData != null) {
2504                         if(areSampleSizesEqual(sm) &&
2505                            sm.getSampleSize(0) == 16) {
2506                             // Decode directly into short data.
2507                             decodeRaw(shortData, dstOffset,
2508                                       pixelBitStride, scanlineStride);
2509                         } else {
2510                             // Decode into bytes and reformat into shorts.
2511                             int bpp = getBitsPerPixel(sm);


2520                         if(areSampleSizesEqual(sm) &&
2521                            sm.getSampleSize(0) == 32) {
2522                             // Decode directly into int data.
2523                             decodeRaw(intData, dstOffset,
2524                                       pixelBitStride, scanlineStride);
2525                         } else {
2526                             // Decode into bytes and reformat into ints.
2527                             int bpp = getBitsPerPixel(sm);
2528                             int bytesPerRow = (bpp*srcWidth + 7)/8;
2529                             byte[] buf = new byte[bytesPerRow*srcHeight];
2530                             decodeRaw(buf, 0, bpp, bytesPerRow);
2531                             reformatData(buf, bytesPerRow, srcHeight,
2532                                          null, intData,
2533                                          dstOffset, scanlineStride);
2534                         }
2535                     }
2536                 }
2537             } else {
2538                 // Read discontiguous data into bytes and set the samples
2539                 // into the Raster.
2540                 int bpp = getBitsPerPixel(sm);








2541                 int bytesPerRow = (bpp*srcWidth + 7)/8;
2542                 byte[] buf = new byte[bytesPerRow*srcHeight];
2543                 decodeRaw(buf, 0, bpp, bytesPerRow);
2544                 reformatDiscontiguousData(buf, bytesPerRow,
2545                                           srcWidth, srcHeight,
2546                                           ras);
2547             }
2548         }
2549 
2550         if (colorConverter != null) {
2551             float[] rgb = new float[3];
2552 
2553             if(byteData != null) {
2554                 for (int j = 0; j < dstHeight; j++) {
2555                     int idx = dstOffset;
2556                     for (int i = 0; i < dstWidth; i++) {
2557                         float x0 = (float)(byteData[idx] & 0xff);
2558                         float x1 = (float)(byteData[idx + 1] & 0xff);
2559                         float x2 = (float)(byteData[idx + 2] & 0xff);
2560 
2561                         colorConverter.toRGB(x0, x1, x2, rgb);
2562 
2563                         byteData[idx] = (byte)(rgb[0]);
2564                         byteData[idx + 1] = (byte)(rgb[1]);




 139      * {@link BaselineTIFFTagSet#COMPRESSION_NONE}, {@link
 140      * BaselineTIFFTagSet#COMPRESSION_CCITT_RLE}, {@link
 141      * BaselineTIFFTagSet#COMPRESSION_CCITT_T_4}, {@link
 142      * BaselineTIFFTagSet#COMPRESSION_CCITT_T_6}, {@link
 143      * BaselineTIFFTagSet#COMPRESSION_LZW}, {@link
 144      * BaselineTIFFTagSet#COMPRESSION_OLD_JPEG}, {@link
 145      * BaselineTIFFTagSet#COMPRESSION_JPEG}, {@link
 146      * BaselineTIFFTagSet#COMPRESSION_ZLIB}, {@link
 147      * BaselineTIFFTagSet#COMPRESSION_PACKBITS}, {@link
 148      * BaselineTIFFTagSet#COMPRESSION_DEFLATE}, or other value
 149      * defined by a TIFF extension.
 150      */
 151     protected int compression;
 152 
 153     /**
 154      * {@code true} if the image is encoded using separate planes.
 155      */
 156     protected boolean planar;
 157 
 158     /**
 159      * The planar band to decode; ignored for chunky (interleaved) images.
 160      */
 161     protected int planarBand = 0;
 162 
 163     /**
 164      * The value of the {@code SamplesPerPixel} tag.
 165      */
 166     protected int samplesPerPixel;
 167 
 168     /**
 169      * The value of the {@code BitsPerSample} tag.
 170      *
 171      */
 172     protected int[] bitsPerSample;
 173 
 174     /**
 175      * The value of the {@code SampleFormat} tag.  Legal values
 176      * are {@link BaselineTIFFTagSet#SAMPLE_FORMAT_UNSIGNED_INTEGER},
 177      * {@link BaselineTIFFTagSet#SAMPLE_FORMAT_SIGNED_INTEGER}, {@link
 178      * BaselineTIFFTagSet#SAMPLE_FORMAT_FLOATING_POINT}, {@link
 179      * BaselineTIFFTagSet#SAMPLE_FORMAT_UNDEFINED}, or other value
 180      * defined by a TIFF extension.
 181      */
 182     protected int[] sampleFormat =
 183         new int[] {BaselineTIFFTagSet.SAMPLE_FORMAT_UNSIGNED_INTEGER};


 434      * @return A {@code PixelInterleavedSampleModel}.
 435      */
 436     static SampleModel createInterleavedSM(int dataType,
 437                                            int numBands) {
 438         int[] bandOffsets = new int[numBands];
 439         for(int i = 0; i < numBands; i++) {
 440             bandOffsets[i] = i;
 441         }
 442         return new PixelInterleavedSampleModel(dataType,
 443                                                1, // width
 444                                                1, // height
 445                                                numBands, // pixelStride,
 446                                                numBands, // scanlineStride
 447                                                bandOffsets);
 448     }
 449 
 450     /**
 451      * Create a {@code ComponentColorModel} for use in creating
 452      * an {@code ImageTypeSpecifier}.
 453      */
 454     // This code was inspired by the method of the same name in
 455     // javax.imageio.ImageTypeSpecifier
 456     static ColorModel createComponentCM(ColorSpace colorSpace,
 457                                         int numBands,
 458                                         int[] bitsPerSample,
 459                                         int dataType,
 460                                         boolean hasAlpha,
 461                                         boolean isAlphaPremultiplied) {
 462         int transparency =
 463             hasAlpha ? Transparency.TRANSLUCENT : Transparency.OPAQUE;
 464 







 465         return new ComponentColorModel(colorSpace,
 466                                        bitsPerSample,
 467                                        hasAlpha,
 468                                        isAlphaPremultiplied,
 469                                        transparency,
 470                                        dataType);
 471     }
 472 
 473     private static int createMask(int[] bitsPerSample, int band) {
 474         int mask = (1 << bitsPerSample[band]) - 1;
 475         for (int i = band + 1; i < bitsPerSample.length; i++) {
 476             mask <<= bitsPerSample[i];
 477         }
 478 
 479         return mask;
 480     }
 481 
 482     private static int getDataTypeFromNumBits(int numBits, boolean isSigned) {
 483         int dataType;
 484 
 485         if (numBits <= 8) {
 486             dataType = DataBuffer.TYPE_BYTE;


 564     private static boolean areSampleSizesEqual(SampleModel sm) {
 565         boolean allSameSize = true;
 566         int[] sampleSize = sm.getSampleSize();
 567         int sampleSize0 = sampleSize[0];
 568         int numBands = sampleSize.length;
 569 
 570         for(int i = 1; i < numBands; i++) {
 571             if(sampleSize[i] != sampleSize0) {
 572                 allSameSize = false;
 573                 break;
 574             }
 575         }
 576 
 577         return allSameSize;
 578     }
 579 
 580     /**
 581      * Determines whether the {@code DataBuffer} is filled without
 582      * any interspersed padding bits.
 583      */
 584     private static boolean isDataBufferBitContiguous(SampleModel sm,
 585         int[] bitsPerSample)
 586         throws IIOException {
 587         int dataTypeSize = getDataTypeSize(sm.getDataType());
 588 
 589         if(sm instanceof ComponentSampleModel) {
 590             int numBands = sm.getNumBands();
 591             for(int i = 0; i < numBands; i++) {
 592                 if(bitsPerSample[i] != dataTypeSize) {
 593                     // Sample does not fill data element.
 594                     return false;
 595                 }
 596             }
 597         } else if(sm instanceof MultiPixelPackedSampleModel) {
 598             MultiPixelPackedSampleModel mppsm =
 599                 (MultiPixelPackedSampleModel)sm;
 600             if(dataTypeSize % mppsm.getPixelBitStride() != 0) {
 601                 // Pixels do not fill the data element.
 602                 return false;
 603             }
 604         } else if(sm instanceof SinglePixelPackedSampleModel) {
 605             SinglePixelPackedSampleModel sppsm =
 606                 (SinglePixelPackedSampleModel)sm;
 607             int numBands = sm.getNumBands();
 608             int numBits = 0;
 609             for(int i = 0; i < numBands; i++) {
 610                 numBits += sm.getSampleSize(i);
 611             }
 612             if(numBits != dataTypeSize) {


 666                     int shift = 24;
 667                     int ival = 0;
 668                     for(int b = 0; b < numExtraBytes; b++) {
 669                         ival |= (buf[inOffset++]&0xff) << shift;
 670                         shift -= 8;
 671                     }
 672                     intData[k++] = ival;
 673                 }
 674                 outOffset += outStride;
 675             }
 676         } else {
 677             throw new IIOException("shortData == null && intData == null!");
 678         }
 679     }
 680 
 681     /**
 682      * Reformats bit-discontiguous data into the {@code DataBuffer}
 683      * of the supplied {@code WritableRaster}.
 684      */
 685     private static void reformatDiscontiguousData(byte[] buf,
 686                                                   int[] bitsPerSample,
 687                                                   int stride,
 688                                                   int w,
 689                                                   int h,
 690                                                   WritableRaster raster)
 691         throws IOException {
 692 
 693         // Get SampleModel info.
 694         SampleModel sm = raster.getSampleModel();
 695         int numBands = sm.getNumBands();

 696 
 697         // Initialize input stream.
 698         ByteArrayInputStream is = new ByteArrayInputStream(buf);
 699         ImageInputStream iis = new MemoryCacheImageInputStream(is);
 700 
 701         // Reformat.
 702         long iisPosition = 0L;
 703         int y = raster.getMinY();
 704         for(int j = 0; j < h; j++, y++) {
 705             iis.seek(iisPosition);
 706             int x = raster.getMinX();
 707             for(int i = 0; i < w; i++, x++) {
 708                 for(int b = 0; b < numBands; b++) {
 709                     long bits = iis.readBits(bitsPerSample[b]);
 710                     raster.setSample(x, y, b, (int)bits);
 711                 }
 712             }
 713             iisPosition += stride;
 714         }
 715     }
 716 
 717     /**
 718      * A utility method that returns an
 719      * {@code ImageTypeSpecifier} suitable for decoding an image
 720      * with the given parameters.
 721      *
 722      * @param photometricInterpretation the value of the
 723      * {@code PhotometricInterpretation} field.
 724      * @param compression the value of the {@code Compression} field.
 725      * @param samplesPerPixel the value of the
 726      * {@code SamplesPerPixel} field.
 727      * @param bitsPerSample the value of the {@code BitsPerSample} field.
 728      * @param sampleFormat the value of the {@code SampleFormat} field.
 729      * @param extraSamples the value of the {@code ExtraSamples} field.


 790                 }
 791 
 792                 return ImageTypeSpecifier.createGrayscale(bitsPerSample[0],
 793                                                           dataType,
 794                                                           isSigned);
 795             } else {
 796                 // Indexed
 797                 int mapSize = 1 << bitsPerSample[0];
 798                 byte[] redLut = new byte[mapSize];
 799                 byte[] greenLut = new byte[mapSize];
 800                 byte[] blueLut = new byte[mapSize];
 801                 byte[] alphaLut = null;
 802 
 803                 int idx = 0;
 804                 for (int i = 0; i < mapSize; i++) {
 805                     redLut[i] = (byte)((colorMap[i]*255)/65535);
 806                     greenLut[i] = (byte)((colorMap[mapSize + i]*255)/65535);
 807                     blueLut[i] = (byte)((colorMap[2*mapSize + i]*255)/65535);
 808                 }
 809 
 810                 int dataType;
 811                 if (bitsPerSample[0] <= 8) {
 812                     dataType = DataBuffer.TYPE_BYTE;
 813                 } else if (sampleFormat[0] ==
 814                     BaselineTIFFTagSet.SAMPLE_FORMAT_SIGNED_INTEGER) {
 815                     dataType = DataBuffer.TYPE_SHORT;
 816                 } else {
 817                     dataType = DataBuffer.TYPE_USHORT;
 818                 }
 819                 return ImageTypeSpecifier.createIndexed(redLut,
 820                                                         greenLut,
 821                                                         blueLut,
 822                                                         alphaLut,
 823                                                         bitsPerSample[0],
 824                                                         dataType);
 825             }
 826         }
 827 
 828         // 8-bit gray-alpha
 829         if (samplesPerPixel == 2 &&
 830             bitsPerSample[0] == 8 &&
 831             bitsPerSample[1] == 8) {
 832             int dataType = DataBuffer.TYPE_BYTE;
 833             boolean alphaPremultiplied = false;
 834             if (extraSamples != null &&
 835                 extraSamples[0] ==
 836                 BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA) {
 837                 alphaPremultiplied = true;
 838             }


1073                                                          samplesPerPixel);
1074 
1075                     // Create the ColorModel.
1076                     ColorModel cm;
1077                     if(samplesPerPixel >= 1 && samplesPerPixel <= 4 &&
1078                        (dataType == DataBuffer.TYPE_INT ||
1079                         dataType == DataBuffer.TYPE_FLOAT)) {
1080                         // Handle the 32-bit cases for 1-4 bands.
1081                         ColorSpace cs = samplesPerPixel <= 2 ?
1082                             ColorSpace.getInstance(ColorSpace.CS_GRAY) : rgb;
1083                         boolean hasAlpha = ((samplesPerPixel % 2) == 0);
1084                         boolean alphaPremultiplied = false;
1085                         if(hasAlpha && extraSamples != null &&
1086                            extraSamples[0] ==
1087                            BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA) {
1088                             alphaPremultiplied = true;
1089                         }
1090 
1091                         cm = createComponentCM(cs,
1092                                                samplesPerPixel,
1093                                                bitsPerSample,
1094                                                dataType,
1095                                                hasAlpha,
1096                                                alphaPremultiplied);
1097                     } else {
1098                         ColorSpace cs = new BogusColorSpace(samplesPerPixel);
1099                         cm = createComponentCM(cs,
1100                                                samplesPerPixel,
1101                                                bitsPerSample,
1102                                                dataType,
1103                                                false, // hasAlpha
1104                                                false); // alphaPremultiplied
1105                     }
1106                     return new ImageTypeSpecifier(cm, sm);
1107                 }
1108             }
1109         }
1110 
1111         // Other more bizarre cases including discontiguous DataBuffers
1112         // such as for the image in bug 4918959.
1113 
1114         if(colorMap == null &&
1115            sampleFormat[0] !=
1116            BaselineTIFFTagSet.SAMPLE_FORMAT_FLOATING_POINT) {
1117 
1118             // Determine size of largest sample.
1119             int maxBitsPerSample = 0;
1120             for(int i = 0; i < bitsPerSample.length; i++) {
1121                 if(bitsPerSample[i] > maxBitsPerSample) {
1122                     maxBitsPerSample = bitsPerSample[i];
1123                 }
1124             }
1125 
1126             // Determine whether data are signed.
1127             boolean isSigned =
1128                 (sampleFormat[0] ==
1129                  BaselineTIFFTagSet.SAMPLE_FORMAT_SIGNED_INTEGER);
1130 
1131             // Grayscale
1132             if(samplesPerPixel == 1 &&
1133                 (bitsPerSample[0] == 1 || bitsPerSample[0] == 2 ||
1134                  bitsPerSample[0] == 4 || bitsPerSample[0] == 8 ||
1135                  bitsPerSample[0] == 16)) {
1136                 int dataType = getDataTypeFromNumBits(maxBitsPerSample, isSigned);
1137 
1138                 return ImageTypeSpecifier.createGrayscale(bitsPerSample[0],
1139                                                           dataType,
1140                                                           isSigned);
1141             }
1142 
1143             // Gray-alpha
1144             if (samplesPerPixel == 2 &&
1145                 bitsPerSample[0] == bitsPerSample[1] &&
1146                 (bitsPerSample[0] == 1 || bitsPerSample[0] == 2 ||
1147                  bitsPerSample[0] == 4 || bitsPerSample[0] == 8 ||
1148                  bitsPerSample[0] == 16)) {
1149                 boolean alphaPremultiplied = false;
1150                 if (extraSamples != null &&
1151                     extraSamples[0] ==
1152                     BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA) {
1153                     alphaPremultiplied = true;
1154                 }
1155 
1156                 int dataType =
1157                     getDataTypeFromNumBits(maxBitsPerSample, isSigned);
1158 
1159                 return ImageTypeSpecifier.createGrayscale(maxBitsPerSample,
1160                                                           dataType,
1161                                                           false,
1162                                                           alphaPremultiplied);
1163             }
1164 
1165             if (samplesPerPixel == 3 || samplesPerPixel == 4) {
1166                 int dataType = getDataTypeFromNumBits(maxBitsPerSample, isSigned);
1167                 int dataTypeSize;
1168                 try {
1169                     dataTypeSize = getDataTypeSize(dataType);
1170                 } catch (IIOException ignored) {
1171                     dataTypeSize = maxBitsPerSample;
1172                 }
1173                 if(totalBits <= 32 && !isSigned) {
1174                     // Packed RGB or RGBA
1175                     int redMask = createMask(bitsPerSample, 0);
1176                     int greenMask = createMask(bitsPerSample, 1);
1177                     int blueMask = createMask(bitsPerSample, 2);
1178                     int alphaMask = (samplesPerPixel == 4) ?
1179                         createMask(bitsPerSample, 3) : 0;
1180                     int transferType =
1181                         getDataTypeFromNumBits(totalBits, false);
1182                     boolean alphaPremultiplied = false;
1183                     if (extraSamples != null &&
1184                         extraSamples[0] ==
1185                         BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA) {
1186                         alphaPremultiplied = true;
1187                     }
1188                     return ImageTypeSpecifier.createPacked(rgb,
1189                                                            redMask,
1190                                                            greenMask,
1191                                                            blueMask,
1192                                                            alphaMask,
1193                                                            transferType,
1194                                                            alphaPremultiplied);
1195                 } else if(samplesPerPixel == 3 &&
1196                     dataTypeSize == bitsPerSample[0] &&
1197                     bitsPerSample[0] == bitsPerSample[1] &&
1198                     bitsPerSample[1] == bitsPerSample[2]) {
1199                     // Interleaved RGB
1200                     int[] bandOffsets = new int[] {0, 1, 2};


1201                     return ImageTypeSpecifier.createInterleaved(rgb,
1202                                                                 bandOffsets,
1203                                                                 dataType,
1204                                                                 false,
1205                                                                 false);
1206                 } else if(samplesPerPixel == 4 &&
1207                     dataTypeSize == bitsPerSample[0] &&
1208                     bitsPerSample[0] == bitsPerSample[1] &&
1209                     bitsPerSample[1] == bitsPerSample[2] &&
1210                     bitsPerSample[2] == bitsPerSample[3]) {
1211                     // Interleaved RGBA
1212                     int[] bandOffsets = new int[] {0, 1, 2, 3};


1213                     boolean alphaPremultiplied = false;
1214                     if (extraSamples != null &&
1215                         extraSamples[0] ==
1216                         BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA) {
1217                         alphaPremultiplied = true;
1218                     }
1219                     return ImageTypeSpecifier.createInterleaved(rgb,
1220                                                                 bandOffsets,
1221                                                                 dataType,
1222                                                                 true,
1223                                                                 alphaPremultiplied);
1224                 }
1225             }
1226 
1227             // Arbitrary Interleaved.
1228             int dataType =
1229                 getDataTypeFromNumBits(maxBitsPerSample, isSigned);
1230             SampleModel sm = createInterleavedSM(dataType,
1231                                                  samplesPerPixel);
1232             ColorSpace cs;
1233             if (samplesPerPixel <= 2) {
1234                 cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
1235             } else if (samplesPerPixel <= 4) {
1236                 cs = rgb;
1237             } else {
1238                 cs = new BogusColorSpace(samplesPerPixel);
1239             }
1240             ColorModel cm = createComponentCM(cs,
1241                                               samplesPerPixel,
1242                                               bitsPerSample,
1243                                               dataType,
1244                                               false, // hasAlpha
1245                                               false); // alphaPremultiplied
1246             return new ImageTypeSpecifier(cm, sm);
1247         }

1248 
1249         return null;
1250     }
1251 
1252     /**
1253      * Sets the value of the {@code reader} field.
1254      *
1255      * <p> If this method is called, the {@code beginDecoding}
1256      * method must be called prior to calling any of the decode
1257      * methods.
1258      *
1259      * @param reader the current {@code ImageReader}.
1260      */
1261     public void setReader(ImageReader reader) {
1262         this.reader = reader;
1263     }
1264 
1265     /**
1266      * Sets the value of the {@code metadata} field.
1267      *


1302      */
1303     public void setCompression(int compression) {
1304         this.compression = compression;
1305     }
1306 
1307     /**
1308      * Sets the value of the {@code planar} field.
1309      *
1310      * <p> If this method is called, the {@code beginDecoding}
1311      * method must be called prior to calling any of the decode
1312      * methods.
1313      *
1314      * @param planar {@code true} if the image to be decoded is
1315      * stored in planar format.
1316      */
1317     public void setPlanar(boolean planar) {
1318         this.planar = planar;
1319     }
1320 
1321     /**
1322      * Sets the index of the planar configuration band to be decoded. This value
1323      * is ignored for chunky (interleaved) images.
1324      *
1325      * @param the index of the planar band to decode
1326      */
1327     public void setPlanarBand(int planarBand) { this.planarBand = planarBand; }
1328 
1329     /**
1330      * Sets the value of the {@code samplesPerPixel} field.
1331      *
1332      * <p> If this method is called, the {@code beginDecoding}
1333      * method must be called prior to calling any of the decode
1334      * methods.
1335      *
1336      * @param samplesPerPixel the number of samples in each source
1337      * pixel.
1338      */
1339     public void setSamplesPerPixel(int samplesPerPixel) {
1340         this.samplesPerPixel = samplesPerPixel;
1341     }
1342 
1343     /**
1344      * Sets the value of the {@code bitsPerSample} field.
1345      *
1346      * <p> If this method is called, the {@code beginDecoding}
1347      * method must be called prior to calling any of the decode
1348      * methods.
1349      *


2513                     isSupportedType = true;
2514                 }
2515             }
2516 
2517             if(!isSupportedType) {
2518                 throw new IIOException
2519                     ("Unsupported raw image type: SampleModel = "+sm+
2520                      "; DataBuffer = "+db);
2521             }
2522         }
2523 
2524         if(isBilevel) {
2525             // Bilevel data are always in a contiguous byte buffer.
2526             decodeRaw(byteData, dstOffset, pixelBitStride, scanlineStride);
2527         } else {
2528             SampleModel sm = ras.getSampleModel();
2529 
2530             // Branch based on whether data are bit-contiguous, i.e.,
2531             // data are packaed as tightly as possible leaving no unused
2532             // bits except at the end of a row.
2533             if(isDataBufferBitContiguous(sm, bitsPerSample)) {
2534                 // Use byte or float data directly.
2535                 if (byteData != null) {
2536                     decodeRaw(byteData, dstOffset,
2537                               pixelBitStride, scanlineStride);
2538                 } else if (floatData != null) {
2539                     decodeRaw(floatData, dstOffset,
2540                               pixelBitStride, scanlineStride);
2541                 } else if (doubleData != null) {
2542                     decodeRaw(doubleData, dstOffset,
2543                               pixelBitStride, scanlineStride);
2544                 } else {
2545                     if (shortData != null) {
2546                         if(areSampleSizesEqual(sm) &&
2547                            sm.getSampleSize(0) == 16) {
2548                             // Decode directly into short data.
2549                             decodeRaw(shortData, dstOffset,
2550                                       pixelBitStride, scanlineStride);
2551                         } else {
2552                             // Decode into bytes and reformat into shorts.
2553                             int bpp = getBitsPerPixel(sm);


2562                         if(areSampleSizesEqual(sm) &&
2563                            sm.getSampleSize(0) == 32) {
2564                             // Decode directly into int data.
2565                             decodeRaw(intData, dstOffset,
2566                                       pixelBitStride, scanlineStride);
2567                         } else {
2568                             // Decode into bytes and reformat into ints.
2569                             int bpp = getBitsPerPixel(sm);
2570                             int bytesPerRow = (bpp*srcWidth + 7)/8;
2571                             byte[] buf = new byte[bytesPerRow*srcHeight];
2572                             decodeRaw(buf, 0, bpp, bytesPerRow);
2573                             reformatData(buf, bytesPerRow, srcHeight,
2574                                          null, intData,
2575                                          dstOffset, scanlineStride);
2576                         }
2577                     }
2578                 }
2579             } else {
2580                 // Read discontiguous data into bytes and set the samples
2581                 // into the Raster.
2582                 int bpp;
2583                 if (planar) {
2584                     bpp = bitsPerSample[planarBand];
2585                 } else {
2586                     bpp = 0;
2587                     for (int bps : bitsPerSample) {
2588                         bpp += bps;
2589                     }
2590                 }
2591                 int bytesPerRow = (bpp*srcWidth + 7)/8;
2592                 byte[] buf = new byte[bytesPerRow*srcHeight];
2593                 decodeRaw(buf, 0, bpp, bytesPerRow);
2594                 reformatDiscontiguousData(buf, bitsPerSample, bytesPerRow,
2595                                           srcWidth, srcHeight,
2596                                           ras);
2597             }
2598         }
2599 
2600         if (colorConverter != null) {
2601             float[] rgb = new float[3];
2602 
2603             if(byteData != null) {
2604                 for (int j = 0; j < dstHeight; j++) {
2605                     int idx = dstOffset;
2606                     for (int i = 0; i < dstWidth; i++) {
2607                         float x0 = (float)(byteData[idx] & 0xff);
2608                         float x1 = (float)(byteData[idx + 1] & 0xff);
2609                         float x2 = (float)(byteData[idx + 2] & 0xff);
2610 
2611                         colorConverter.toRGB(x0, x1, x2, rgb);
2612 
2613                         byteData[idx] = (byte)(rgb[0]);
2614                         byteData[idx + 1] = (byte)(rgb[1]);


< prev index next >