< prev index next >

src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java

Print this page




 681         stream.readFully(b);
 682         metadata.zTXt_text.add(new String(inflate(b), "ISO-8859-1"));
 683 
 684         // Check if the text chunk contains image creation time
 685         if (keyword.equals(PNGMetadata.tEXt_creationTimeKey)) {
 686             // Update Standard/Document/ImageCreationTime from text chunk
 687             int index = metadata.zTXt_text.size() - 1;
 688             metadata.decodeImageCreationTimeFromTextChunk(
 689                     metadata.zTXt_text.listIterator(index));
 690         }
 691     }
 692 
 693     private void readMetadata() throws IIOException {
 694         if (gotMetadata) {
 695             return;
 696         }
 697 
 698         readHeader();
 699 
 700         /*
 701          * Optimization: We can skip the remaining metadata if the
 702          * ignoreMetadata flag is set, and only if this is not a palette
 703          * image (in that case, we need to read the metadata to get the
 704          * tRNS chunk, which is needed for the getImageTypes() method).


 705          */
 706         int colorType = metadata.IHDR_colorType;
 707         if (ignoreMetadata && colorType != PNG_COLOR_PALETTE) {
 708             try {
 709                 while (true) {
 710                     int chunkLength = stream.readInt();
 711 
 712                     // verify the chunk length first
 713                     if (chunkLength < 0 || chunkLength + 4 < 0) {
 714                         throw new IIOException("Invalid chunk length " + chunkLength);
 715                     }
 716 
 717                     int chunkType = stream.readInt();
 718 
 719                     if (chunkType == IDAT_TYPE) {
 720                         // We've reached the image data
 721                         stream.skipBytes(-8);
 722                         imageStartPosition = stream.getStreamPosition();





 723                         break;




 724                     } else {
 725                         // Skip the chunk plus the 4 CRC bytes that follow
 726                         stream.skipBytes(chunkLength + 4);
 727                     }
 728                 }
 729             } catch (IOException e) {
 730                 throw new IIOException("Error skipping PNG metadata", e);
 731             }
 732 
 733             gotMetadata = true;
 734             return;
 735         }
 736 
 737         try {
 738             loop: while (true) {
 739                 int chunkLength = stream.readInt();
 740                 int chunkType = stream.readInt();
 741                 int chunkCRC;
 742 
 743                 // verify the chunk length


1057                                           sourceXSubsampling,
1058                                           sourceYSubsampling,
1059                                           xStart, yStart,
1060                                           passWidth, passHeight,
1061                                           xStep, yStep);
1062         int updateMinX = vals[0];
1063         int updateMinY = vals[1];
1064         int updateWidth = vals[2];
1065         int updateXStep = vals[4];
1066         int updateYStep = vals[5];
1067 
1068         int bitDepth = metadata.IHDR_bitDepth;
1069         int inputBands = inputBandsForColorType[metadata.IHDR_colorType];
1070         int bytesPerPixel = (bitDepth == 16) ? 2 : 1;
1071         bytesPerPixel *= inputBands;
1072 
1073         int bitsPerRow = Math.multiplyExact((inputBands * bitDepth), passWidth);
1074         int bytesPerRow = (bitsPerRow + 7) / 8;
1075         int eltsPerRow = (bitDepth == 16) ? bytesPerRow/2 : bytesPerRow;
1076 


























1077         // If no pixels need updating, just skip the input data
1078         if (updateWidth == 0) {
1079             for (int srcY = 0; srcY < passHeight; srcY++) {
1080                 // Update count of pixels read
1081                 updateImageProgress(passWidth);
1082                 /*
1083                  * If read has been aborted, just return
1084                  * processReadAborted will be called later
1085                  */
1086                 if (abortRequested()) {
1087                     return;
1088                 }
1089                 // Skip filter byte and the remaining row bytes
1090                 pixelStream.skipBytes(1 + bytesPerRow);
1091             }
1092             return;
1093         }
1094 
1095         // Backwards map from destination pixels
1096         // (dstX = updateMinX + k*updateXStep)
1097         // to source pixels (sourceX), and then
1098         // to offset and skip in passRow (srcX and srcXStep)
1099         int sourceX =
1100             (updateMinX - destinationOffset.x)*sourceXSubsampling +
1101             sourceRegion.x;
1102         int srcX = (sourceX - xStart)/xStep;
1103 
1104         // Compute the step factor in the source
1105         int srcXStep = updateXStep*sourceXSubsampling/xStep;
1106 
1107         byte[] byteData = null;
1108         short[] shortData = null;
1109         byte[] curr = new byte[bytesPerRow];
1110         byte[] prior = new byte[bytesPerRow];
1111 
1112         // Create a 1-row tall Raster to hold the data
1113         WritableRaster passRow = createRaster(passWidth, 1, inputBands,
1114                                               eltsPerRow,
1115                                               bitDepth);
1116 
1117         // Create an array suitable for holding one pixel
1118         int[] ps = passRow.getPixel(0, 0, (int[])null);
1119 
1120         DataBuffer dataBuffer = passRow.getDataBuffer();
1121         int type = dataBuffer.getDataType();
1122         if (type == DataBuffer.TYPE_BYTE) {
1123             byteData = ((DataBufferByte)dataBuffer).getData();
1124         } else {
1125             shortData = ((DataBufferUShort)dataBuffer).getData();
1126         }
1127 
1128         processPassStarted(theImage,
1129                            passNum,
1130                            sourceMinProgressivePass,
1131                            sourceMaxProgressivePass,
1132                            updateMinX, updateMinY,
1133                            updateXStep, updateYStep,
1134                            destinationBands);
1135 
1136         // Handle source and destination bands


1221                 break;
1222             case PNG_FILTER_SUB:
1223                 decodeSubFilter(curr, 0, bytesPerRow, bytesPerPixel);
1224                 break;
1225             case PNG_FILTER_UP:
1226                 decodeUpFilter(curr, 0, prior, 0, bytesPerRow);
1227                 break;
1228             case PNG_FILTER_AVERAGE:
1229                 decodeAverageFilter(curr, 0, prior, 0, bytesPerRow,
1230                                     bytesPerPixel);
1231                 break;
1232             case PNG_FILTER_PAETH:
1233                 decodePaethFilter(curr, 0, prior, 0, bytesPerRow,
1234                                   bytesPerPixel);
1235                 break;
1236             default:
1237                 throw new IIOException("Unknown row filter type (= " +
1238                                        filter + ")!");
1239             }
1240 
1241             // Copy data into passRow byte by byte
























































1242             if (bitDepth < 16) {
1243                 System.arraycopy(curr, 0, byteData, 0, bytesPerRow);
1244             } else {
1245                 int idx = 0;
1246                 for (int j = 0; j < eltsPerRow; j++) {
1247                     shortData[j] =
1248                         (short)((curr[idx] << 8) | (curr[idx + 1] & 0xff));
1249                     idx += 2;
1250                 }
1251             }

1252 
1253             // True Y position in source
1254             int sourceY = srcY*yStep + yStart;
1255             if ((sourceY >= sourceRegion.y) &&
1256                 (sourceY < sourceRegion.y + sourceRegion.height) &&
1257                 (((sourceY - sourceRegion.y) %
1258                   sourceYSubsampling) == 0)) {
1259 
1260                 int dstY = destinationOffset.y +
1261                     (sourceY - sourceRegion.y)/sourceYSubsampling;
1262                 if (dstY < dstMinY) {
1263                     continue;
1264                 }
1265                 if (dstY > dstMaxY) {
1266                     break;
1267                 }
1268 
1269                 if (useSetRect) {
1270                     imRas.setRect(updateMinX, dstY, passRow);
1271                 } else {


1405              * the level of application, so we will not try to estimate
1406              * the required amount of the memory and/or handle OOM in
1407              * any way.
1408              */
1409             theImage = getDestination(param,
1410                                       getImageTypes(0),
1411                                       width,
1412                                       height);
1413 
1414             Rectangle destRegion = new Rectangle(0, 0, 0, 0);
1415             sourceRegion = new Rectangle(0, 0, 0, 0);
1416             computeRegions(param, width, height,
1417                            theImage,
1418                            sourceRegion, destRegion);
1419             destinationOffset.setLocation(destRegion.getLocation());
1420 
1421             // At this point the header has been read and we know
1422             // how many bands are in the image, so perform checking
1423             // of the read param.
1424             int colorType = metadata.IHDR_colorType;






1425             checkReadParamBandSettings(param,
1426                                        inputBandsForColorType[colorType],
1427                                       theImage.getSampleModel().getNumBands());

1428 
1429             clearAbortRequest();
1430             processImageStarted(0);
1431             if (abortRequested()) {
1432                 processReadAborted();
1433             } else {
1434                 decodeImage();
1435                 if (abortRequested()) {
1436                     processReadAborted();
1437                 } else {
1438                     processImageComplete();
1439                 }
1440             }
1441 
1442         } catch (IOException e) {
1443             throw new IIOException("Error reading PNG image data", e);
1444         } finally {
1445             if (inf != null) {
1446                 inf.end();
1447             }
1448         }
1449     }
1450 

















1451     public int getNumImages(boolean allowSearch) throws IIOException {
1452         if (stream == null) {
1453             throw new IllegalStateException("No input source set!");
1454         }
1455         if (seekForwardOnly && allowSearch) {
1456             throw new IllegalStateException
1457                 ("seekForwardOnly and allowSearch can't both be true!");
1458         }
1459         return 1;
1460     }
1461 
1462     public int getWidth(int imageIndex) throws IIOException {
1463         if (imageIndex != 0) {
1464             throw new IndexOutOfBoundsException("imageIndex != 0!");
1465         }
1466 
1467         readHeader();
1468 
1469         return metadata.IHDR_width;
1470     }


1497 
1498         int bitDepth = metadata.IHDR_bitDepth;
1499         int colorType = metadata.IHDR_colorType;
1500 
1501         int dataType;
1502         if (bitDepth <= 8) {
1503             dataType = DataBuffer.TYPE_BYTE;
1504         } else {
1505             dataType = DataBuffer.TYPE_USHORT;
1506         }
1507 
1508         switch (colorType) {
1509         case PNG_COLOR_GRAY:
1510             // Packed grayscale
1511             l.add(ImageTypeSpecifier.createGrayscale(bitDepth,
1512                                                      dataType,
1513                                                      false));
1514             break;
1515 
1516         case PNG_COLOR_RGB:







1517             if (bitDepth == 8) {




1518                 // some standard types of buffered images
1519                 // which can be used as destination
1520                 l.add(ImageTypeSpecifier.createFromBufferedImageType(
1521                           BufferedImage.TYPE_3BYTE_BGR));
1522 
1523                 l.add(ImageTypeSpecifier.createFromBufferedImageType(
1524                           BufferedImage.TYPE_INT_RGB));
1525 
1526                 l.add(ImageTypeSpecifier.createFromBufferedImageType(
1527                           BufferedImage.TYPE_INT_BGR));
1528 












1529             }
1530             // Component R, G, B
1531             rgb = ColorSpace.getInstance(ColorSpace.CS_sRGB);
1532             bandOffsets = new int[3];
1533             bandOffsets[0] = 0;
1534             bandOffsets[1] = 1;
1535             bandOffsets[2] = 2;
1536             l.add(ImageTypeSpecifier.createInterleaved(rgb,
1537                                                        bandOffsets,
1538                                                        dataType,
1539                                                        false,
1540                                                        false));
1541             break;
1542 
1543         case PNG_COLOR_PALETTE:
1544             readMetadata(); // Need tRNS chunk
1545 
1546             /*
1547              * The PLTE chunk spec says:
1548              *




 681         stream.readFully(b);
 682         metadata.zTXt_text.add(new String(inflate(b), "ISO-8859-1"));
 683 
 684         // Check if the text chunk contains image creation time
 685         if (keyword.equals(PNGMetadata.tEXt_creationTimeKey)) {
 686             // Update Standard/Document/ImageCreationTime from text chunk
 687             int index = metadata.zTXt_text.size() - 1;
 688             metadata.decodeImageCreationTimeFromTextChunk(
 689                     metadata.zTXt_text.listIterator(index));
 690         }
 691     }
 692 
 693     private void readMetadata() throws IIOException {
 694         if (gotMetadata) {
 695             return;
 696         }
 697 
 698         readHeader();
 699 
 700         /*
 701          * Optimization: We can skip reading metadata if ignoreMetadata
 702          * flag is set and colorType is not PNG_COLOR_PALETTE. But we need
 703          * to parse only the tRNS chunk even in the case where IHDR colortype
 704          * is not PNG_COLOR_PALETTE, because we need tRNS chunk transparent
 705          * pixel information for PNG_COLOR_RGB while storing the pixel data
 706          * in decodePass().
 707          */
 708         int colorType = metadata.IHDR_colorType;
 709         if (ignoreMetadata && colorType != PNG_COLOR_PALETTE) {
 710             try {
 711                 while (true) {
 712                     int chunkLength = stream.readInt();
 713 
 714                     // verify the chunk length first
 715                     if (chunkLength < 0 || chunkLength + 4 < 0) {
 716                         throw new IIOException("Invalid chunk length " + chunkLength);
 717                     }
 718 
 719                     int chunkType = stream.readInt();
 720 
 721                     if (chunkType == IDAT_TYPE) {
 722                         // We've reached the first IDAT chunk position
 723                         stream.skipBytes(-8);
 724                         imageStartPosition = stream.getStreamPosition();
 725                         /*
 726                          * According to PNG specification tRNS chunk must
 727                          * precede the first IDAT chunk. So we can stop
 728                          * reading metadata.
 729                          */
 730                         break;
 731                     } else if (chunkType == tRNS_TYPE) {
 732                         parse_tRNS_chunk(chunkLength);
 733                         // After parsing tRNS chunk we will skip 4 CRC bytes
 734                         stream.skipBytes(4);
 735                     } else {
 736                         // Skip the chunk plus the 4 CRC bytes that follow
 737                         stream.skipBytes(chunkLength + 4);
 738                     }
 739                 }
 740             } catch (IOException e) {
 741                 throw new IIOException("Error skipping PNG metadata", e);
 742             }
 743 
 744             gotMetadata = true;
 745             return;
 746         }
 747 
 748         try {
 749             loop: while (true) {
 750                 int chunkLength = stream.readInt();
 751                 int chunkType = stream.readInt();
 752                 int chunkCRC;
 753 
 754                 // verify the chunk length


1068                                           sourceXSubsampling,
1069                                           sourceYSubsampling,
1070                                           xStart, yStart,
1071                                           passWidth, passHeight,
1072                                           xStep, yStep);
1073         int updateMinX = vals[0];
1074         int updateMinY = vals[1];
1075         int updateWidth = vals[2];
1076         int updateXStep = vals[4];
1077         int updateYStep = vals[5];
1078 
1079         int bitDepth = metadata.IHDR_bitDepth;
1080         int inputBands = inputBandsForColorType[metadata.IHDR_colorType];
1081         int bytesPerPixel = (bitDepth == 16) ? 2 : 1;
1082         bytesPerPixel *= inputBands;
1083 
1084         int bitsPerRow = Math.multiplyExact((inputBands * bitDepth), passWidth);
1085         int bytesPerRow = (bitsPerRow + 7) / 8;
1086         int eltsPerRow = (bitDepth == 16) ? bytesPerRow/2 : bytesPerRow;
1087 
1088         WritableRaster passRow;
1089         if (considerTransparentPixel()) {
1090             /*
1091              * When we have tRNS chunk for image type PNG_COLOR_RGB, we need
1092              * extra alpha channel to represent transparency. In getImageTypes()
1093              * we create a 4 channel destination image, so we need to calculate
1094              * destEltsPerRow and create appropriate Raster.
1095              */
1096             int destBands = 4;
1097             int destBytesPerPixel = (bitDepth == 16) ? 2 : 1;
1098             destBytesPerPixel *= destBands;
1099             int destBitsPerRow =
1100                 Math.multiplyExact((destBands * bitDepth), passWidth);
1101             int destBytesPerRow = (destBitsPerRow + 7) / 8;
1102             int destEltsPerRow =
1103                 (bitDepth == 16) ? destBytesPerRow/2 : destBytesPerRow;
1104 
1105             // Create a 1-row tall Raster to hold the data
1106             passRow = createRaster(passWidth, 1, destBands,
1107                                    destEltsPerRow, bitDepth);
1108         } else {
1109             // Create a 1-row tall Raster to hold the data
1110             passRow = createRaster(passWidth, 1, inputBands,
1111                                    eltsPerRow, bitDepth);
1112         }
1113 
1114         // If no pixels need updating, just skip the input data
1115         if (updateWidth == 0) {
1116             for (int srcY = 0; srcY < passHeight; srcY++) {
1117                 // Update count of pixels read
1118                 updateImageProgress(passWidth);
1119                 /*
1120                  * If read has been aborted, just return
1121                  * processReadAborted will be called later
1122                  */
1123                 if (abortRequested()) {
1124                     return;
1125                 }
1126                 // Skip filter byte and the remaining row bytes
1127                 pixelStream.skipBytes(1 + bytesPerRow);
1128             }
1129             return;
1130         }
1131 
1132         // Backwards map from destination pixels
1133         // (dstX = updateMinX + k*updateXStep)
1134         // to source pixels (sourceX), and then
1135         // to offset and skip in passRow (srcX and srcXStep)
1136         int sourceX =
1137             (updateMinX - destinationOffset.x)*sourceXSubsampling +
1138             sourceRegion.x;
1139         int srcX = (sourceX - xStart)/xStep;
1140 
1141         // Compute the step factor in the source
1142         int srcXStep = updateXStep*sourceXSubsampling/xStep;
1143 
1144         byte[] byteData = null;
1145         short[] shortData = null;
1146         byte[] curr = new byte[bytesPerRow];
1147         byte[] prior = new byte[bytesPerRow];
1148 





1149         // Create an array suitable for holding one pixel
1150         int[] ps = passRow.getPixel(0, 0, (int[])null);
1151 
1152         DataBuffer dataBuffer = passRow.getDataBuffer();
1153         int type = dataBuffer.getDataType();
1154         if (type == DataBuffer.TYPE_BYTE) {
1155             byteData = ((DataBufferByte)dataBuffer).getData();
1156         } else {
1157             shortData = ((DataBufferUShort)dataBuffer).getData();
1158         }
1159 
1160         processPassStarted(theImage,
1161                            passNum,
1162                            sourceMinProgressivePass,
1163                            sourceMaxProgressivePass,
1164                            updateMinX, updateMinY,
1165                            updateXStep, updateYStep,
1166                            destinationBands);
1167 
1168         // Handle source and destination bands


1253                 break;
1254             case PNG_FILTER_SUB:
1255                 decodeSubFilter(curr, 0, bytesPerRow, bytesPerPixel);
1256                 break;
1257             case PNG_FILTER_UP:
1258                 decodeUpFilter(curr, 0, prior, 0, bytesPerRow);
1259                 break;
1260             case PNG_FILTER_AVERAGE:
1261                 decodeAverageFilter(curr, 0, prior, 0, bytesPerRow,
1262                                     bytesPerPixel);
1263                 break;
1264             case PNG_FILTER_PAETH:
1265                 decodePaethFilter(curr, 0, prior, 0, bytesPerRow,
1266                                   bytesPerPixel);
1267                 break;
1268             default:
1269                 throw new IIOException("Unknown row filter type (= " +
1270                                        filter + ")!");
1271             }
1272 
1273             /*
1274              * Copy data into passRow byte by byte. In case of colortype
1275              * PNG_COLOR_RGB if we have transparent pixel information from
1276              * tRNS chunk we need to consider that and store proper information
1277              * in alpha channel.
1278              */
1279             if (considerTransparentPixel()) {
1280                 if (bitDepth < 16) {
1281                     int srcidx = 0;
1282                     int destidx = 0;
1283                     for (int i = 0; i < passWidth; i++) {
1284                         if (curr[srcidx] == (byte)metadata.tRNS_red &&
1285                             curr[srcidx + 1] == (byte)metadata.tRNS_green &&
1286                             curr[srcidx + 2] == (byte)metadata.tRNS_blue)
1287                         {
1288                             byteData[destidx] = curr[srcidx];
1289                             byteData[destidx + 1] = curr[srcidx + 1];
1290                             byteData[destidx + 2] = curr[srcidx + 2];
1291                             byteData[destidx + 3] = (byte)0;
1292                         } else {
1293                             byteData[destidx] = curr[srcidx];
1294                             byteData[destidx + 1] = curr[srcidx + 1];
1295                             byteData[destidx + 2] = curr[srcidx + 2];
1296                             byteData[destidx + 3] = (byte)255;
1297                         }
1298                         srcidx += 3;
1299                         destidx += 4;
1300                     }
1301                 } else {
1302                     int srcidx = 0;
1303                     int destidx = 0;
1304                     for (int i = 0; i < passWidth; i++) {
1305                         short red = (short)
1306                             ((curr[srcidx] << 8) | (curr[srcidx + 1] & 0xff));
1307                         short green = (short)
1308                             ((curr[srcidx + 2] << 8) | (curr[srcidx + 3] & 0xff));
1309                         short blue = (short)
1310                             ((curr[srcidx + 4] << 8) | (curr[srcidx + 5] & 0xff));
1311                         if (red == (short)metadata.tRNS_red &&
1312                             green == (short)metadata.tRNS_green &&
1313                             blue == (short)metadata.tRNS_blue)
1314                         {
1315                             shortData[destidx] = red;
1316                             shortData[destidx + 1] = green;
1317                             shortData[destidx + 2] = blue;
1318                             shortData[destidx + 3] = (short)0;
1319                         } else {
1320                             shortData[destidx] = red;
1321                             shortData[destidx + 1] = green;
1322                             shortData[destidx + 2] = blue;
1323                             shortData[destidx + 3] = (short)65535;
1324                         }
1325                         srcidx += 6;
1326                         destidx += 4;
1327                     }
1328                 }
1329             } else {
1330                 if (bitDepth < 16) {
1331                     System.arraycopy(curr, 0, byteData, 0, bytesPerRow);
1332                 } else {
1333                     int idx = 0;
1334                     for (int j = 0; j < eltsPerRow; j++) {
1335                         shortData[j] =
1336                         (short)((curr[idx] << 8) | (curr[idx + 1] & 0xff));
1337                         idx += 2;
1338                     }
1339                 }
1340             }
1341 
1342             // True Y position in source
1343             int sourceY = srcY*yStep + yStart;
1344             if ((sourceY >= sourceRegion.y) &&
1345                 (sourceY < sourceRegion.y + sourceRegion.height) &&
1346                 (((sourceY - sourceRegion.y) %
1347                   sourceYSubsampling) == 0)) {
1348 
1349                 int dstY = destinationOffset.y +
1350                     (sourceY - sourceRegion.y)/sourceYSubsampling;
1351                 if (dstY < dstMinY) {
1352                     continue;
1353                 }
1354                 if (dstY > dstMaxY) {
1355                     break;
1356                 }
1357 
1358                 if (useSetRect) {
1359                     imRas.setRect(updateMinX, dstY, passRow);
1360                 } else {


1494              * the level of application, so we will not try to estimate
1495              * the required amount of the memory and/or handle OOM in
1496              * any way.
1497              */
1498             theImage = getDestination(param,
1499                                       getImageTypes(0),
1500                                       width,
1501                                       height);
1502 
1503             Rectangle destRegion = new Rectangle(0, 0, 0, 0);
1504             sourceRegion = new Rectangle(0, 0, 0, 0);
1505             computeRegions(param, width, height,
1506                            theImage,
1507                            sourceRegion, destRegion);
1508             destinationOffset.setLocation(destRegion.getLocation());
1509 
1510             // At this point the header has been read and we know
1511             // how many bands are in the image, so perform checking
1512             // of the read param.
1513             int colorType = metadata.IHDR_colorType;
1514             if (considerTransparentPixel()) {
1515                 checkReadParamBandSettings(param,
1516                     4,
1517                     theImage.getSampleModel().getNumBands());
1518 
1519             } else {
1520                 checkReadParamBandSettings(param,
1521                     inputBandsForColorType[colorType],
1522                     theImage.getSampleModel().getNumBands());
1523             }
1524 
1525             clearAbortRequest();
1526             processImageStarted(0);
1527             if (abortRequested()) {
1528                 processReadAborted();
1529             } else {
1530                 decodeImage();
1531                 if (abortRequested()) {
1532                     processReadAborted();
1533                 } else {
1534                     processImageComplete();
1535                 }
1536             }
1537 
1538         } catch (IOException e) {
1539             throw new IIOException("Error reading PNG image data", e);
1540         } finally {
1541             if (inf != null) {
1542                 inf.end();
1543             }
1544         }
1545     }
1546 
1547     private boolean considerTransparentPixel(){
1548         /*
1549          * In case of non-indexed PNG_COLOR_RGB images if we have tRNS chunk,
1550          * we need to consider transparent pixel values and store alpha channel
1551          * also. If user explicitly provides ImageReadParam with
1552          * destinationBands as 3 when we have tRNS chunk, only then we will
1553          * ignore tRNS chunk values.
1554          */
1555         if ((destinationBands == null ||
1556              destinationBands.length == 4) &&
1557             metadata.tRNS_colorType == PNG_COLOR_RGB)
1558         {
1559             return true;
1560         }
1561         return false;
1562     }
1563 
1564     public int getNumImages(boolean allowSearch) throws IIOException {
1565         if (stream == null) {
1566             throw new IllegalStateException("No input source set!");
1567         }
1568         if (seekForwardOnly && allowSearch) {
1569             throw new IllegalStateException
1570                 ("seekForwardOnly and allowSearch can't both be true!");
1571         }
1572         return 1;
1573     }
1574 
1575     public int getWidth(int imageIndex) throws IIOException {
1576         if (imageIndex != 0) {
1577             throw new IndexOutOfBoundsException("imageIndex != 0!");
1578         }
1579 
1580         readHeader();
1581 
1582         return metadata.IHDR_width;
1583     }


1610 
1611         int bitDepth = metadata.IHDR_bitDepth;
1612         int colorType = metadata.IHDR_colorType;
1613 
1614         int dataType;
1615         if (bitDepth <= 8) {
1616             dataType = DataBuffer.TYPE_BYTE;
1617         } else {
1618             dataType = DataBuffer.TYPE_USHORT;
1619         }
1620 
1621         switch (colorType) {
1622         case PNG_COLOR_GRAY:
1623             // Packed grayscale
1624             l.add(ImageTypeSpecifier.createGrayscale(bitDepth,
1625                                                      dataType,
1626                                                      false));
1627             break;
1628 
1629         case PNG_COLOR_RGB:
1630             readMetadata(); // Need tRNS chunk
1631 
1632             /*
1633              * In case of PNG_COLOR_RGB colortype if we have transparent
1634              * pixel information in tRNS chunk we create destination
1635              * image with 4 channels.
1636              */
1637             if (bitDepth == 8) {
1638                 if (considerTransparentPixel()) {
1639                     l.add(ImageTypeSpecifier.createFromBufferedImageType(
1640                             BufferedImage.TYPE_4BYTE_ABGR));
1641                 }
1642                 // some standard types of buffered images
1643                 // which can be used as destination
1644                 l.add(ImageTypeSpecifier.createFromBufferedImageType(
1645                           BufferedImage.TYPE_3BYTE_BGR));
1646 
1647                 l.add(ImageTypeSpecifier.createFromBufferedImageType(
1648                           BufferedImage.TYPE_INT_RGB));
1649 
1650                 l.add(ImageTypeSpecifier.createFromBufferedImageType(
1651                           BufferedImage.TYPE_INT_BGR));
1652 
1653             }
1654             if (considerTransparentPixel()) {
1655                 rgb = ColorSpace.getInstance(ColorSpace.CS_sRGB);
1656                 bandOffsets = new int[4];
1657                 bandOffsets[0] = 0;
1658                 bandOffsets[1] = 1;
1659                 bandOffsets[2] = 2;
1660                 bandOffsets[3] = 3;
1661 
1662                 l.add(ImageTypeSpecifier.
1663                     createInterleaved(rgb, bandOffsets,
1664                                       dataType, true, false));
1665             }
1666             // Component R, G, B
1667             rgb = ColorSpace.getInstance(ColorSpace.CS_sRGB);
1668             bandOffsets = new int[3];
1669             bandOffsets[0] = 0;
1670             bandOffsets[1] = 1;
1671             bandOffsets[2] = 2;
1672             l.add(ImageTypeSpecifier.createInterleaved(rgb,
1673                                                        bandOffsets,
1674                                                        dataType,
1675                                                        false,
1676                                                        false));
1677             break;
1678 
1679         case PNG_COLOR_PALETTE:
1680             readMetadata(); // Need tRNS chunk
1681 
1682             /*
1683              * The PLTE chunk spec says:
1684              *


< prev index next >