< 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


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 {
1272                     int newSrcX = srcX;
1273 
1274                     for (int dstX = updateMinX;
1275                          dstX < updateMinX + updateWidth;
1276                          dstX += updateXStep) {
1277 
1278                         passRow.getPixel(newSrcX, 0, ps);
1279                         if (adjustBitDepths) {
1280                             for (int b = 0; b < numBands; b++) {
1281                                 ps[b] = scale[b][ps[b]];
1282                             }
1283                         }







































1284                         imRas.setPixel(dstX, dstY, ps);

1285                         newSrcX += srcXStep;
1286                     }
1287                 }
1288 
1289                 processImageUpdate(theImage,
1290                                    updateMinX, dstY,
1291                                    updateWidth, 1,
1292                                    updateXStep, updateYStep,
1293                                    destinationBands);
1294             }
1295         }
1296 
1297         processPassComplete(theImage);
1298     }
1299 
1300     private void decodeImage()
1301         throws IOException, IIOException  {
1302         int width = metadata.IHDR_width;
1303         int height = metadata.IHDR_height;
1304 


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             }


1489         readHeader();
1490 
1491         ArrayList<ImageTypeSpecifier> l =
1492             new ArrayList<ImageTypeSpecifier>(1);
1493 
1494         ColorSpace rgb;
1495         ColorSpace gray;
1496         int[] bandOffsets;
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. However,
 703          * we parse tRNS chunk to retrieve the transparent color from the
 704          * metadata. Doing so, helps PNGImageReader to appropriately
 705          * identify and set transparent pixels in the decoded image for
 706          * colorType PNG_COLOR_RGB and PNG_COLOR_GRAY.
 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


1260                     idx += 2;
1261                 }
1262             }
1263 
1264             // True Y position in source
1265             int sourceY = srcY*yStep + yStart;
1266             if ((sourceY >= sourceRegion.y) &&
1267                 (sourceY < sourceRegion.y + sourceRegion.height) &&
1268                 (((sourceY - sourceRegion.y) %
1269                   sourceYSubsampling) == 0)) {
1270 
1271                 int dstY = destinationOffset.y +
1272                     (sourceY - sourceRegion.y)/sourceYSubsampling;
1273                 if (dstY < dstMinY) {
1274                     continue;
1275                 }
1276                 if (dstY > dstMaxY) {
1277                     break;
1278                 }
1279 
1280                /*
1281                 * In case of colortype PNG_COLOR_RGB or PNG_COLOR_GRAY
1282                 * if we have transparent pixel information from tRNS chunk
1283                 * we need to consider that also and store proper information
1284                 * in alpha channel.
1285                 *
1286                 * Also we create destination image with extra alpha channel
1287                 * in getImageTypes() when we have tRNS chunk for colorType
1288                 * PNG_COLOR_RGB or PNG_COLOR_GRAY.
1289                 */
1290                 boolean tRNSTransparentPixelPresent =
1291                     theImage.getSampleModel().getNumBands() == inputBands + 1 &&
1292                     metadata.tRNS_present &&
1293                     (metadata.tRNS_colorType == PNG_COLOR_RGB ||
1294                      metadata.tRNS_colorType == PNG_COLOR_GRAY);
1295                 if (useSetRect &&
1296                     !tRNSTransparentPixelPresent)
1297                 {
1298                     imRas.setRect(updateMinX, dstY, passRow);
1299                 } else {
1300                     int newSrcX = srcX;
1301 
1302                     for (int dstX = updateMinX;
1303                          dstX < updateMinX + updateWidth;
1304                          dstX += updateXStep) {
1305 
1306                         passRow.getPixel(newSrcX, 0, ps);
1307                         if (adjustBitDepths) {
1308                             for (int b = 0; b < numBands; b++) {
1309                                 ps[b] = scale[b][ps[b]];
1310                             }
1311                         }
1312                         if (tRNSTransparentPixelPresent)
1313                         {
1314                             /*
1315                              * Create intermediate array to fill the extra
1316                              * alpha channel for each pixel.
1317                              */
1318                             int[] temp = new int[inputBands + 1];
1319                             if (metadata.tRNS_colorType == PNG_COLOR_RGB) {
1320                                 temp[0] = ps[0];
1321                                 temp[1] = ps[1];
1322                                 temp[2] = ps[2];
1323                                 if (ps[0] == metadata.tRNS_red &&
1324                                     ps[1] == metadata.tRNS_green &&
1325                                     ps[2] == metadata.tRNS_blue)
1326                                 {
1327                                     temp[3] = 0;
1328                                 } else {
1329                                     if (bitDepth < 16) {
1330                                         temp[3] = 255;
1331                                     } else {
1332                                         temp[3] = 65535;
1333                                     }
1334                                 }
1335                             } else {
1336                                 // when tRNS_colorType is PNG_COLOR_GRAY
1337                                 temp[0] = ps[0];
1338                                 if (ps[0] == metadata.tRNS_gray)
1339                                 {
1340                                     temp[1] = 0;
1341                                 } else {
1342                                     if (bitDepth < 16) {
1343                                         temp[1] = 255;
1344                                     } else {
1345                                         temp[1] = 65535;
1346                                     }
1347                                 }
1348                             }
1349                             imRas.setPixel(dstX, dstY, temp);
1350                         } else {
1351                             imRas.setPixel(dstX, dstY, ps);
1352                         }
1353                         newSrcX += srcXStep;
1354                     }
1355                 }
1356 
1357                 processImageUpdate(theImage,
1358                                    updateMinX, dstY,
1359                                    updateWidth, 1,
1360                                    updateXStep, updateYStep,
1361                                    destinationBands);
1362             }
1363         }
1364 
1365         processPassComplete(theImage);
1366     }
1367 
1368     private void decodeImage()
1369         throws IOException, IIOException  {
1370         int width = metadata.IHDR_width;
1371         int height = metadata.IHDR_height;
1372 


1473              * the level of application, so we will not try to estimate
1474              * the required amount of the memory and/or handle OOM in
1475              * any way.
1476              */
1477             theImage = getDestination(param,
1478                                       getImageTypes(0),
1479                                       width,
1480                                       height);
1481 
1482             Rectangle destRegion = new Rectangle(0, 0, 0, 0);
1483             sourceRegion = new Rectangle(0, 0, 0, 0);
1484             computeRegions(param, width, height,
1485                            theImage,
1486                            sourceRegion, destRegion);
1487             destinationOffset.setLocation(destRegion.getLocation());
1488 
1489             // At this point the header has been read and we know
1490             // how many bands are in the image, so perform checking
1491             // of the read param.
1492             int colorType = metadata.IHDR_colorType;
1493             if (theImage.getSampleModel().getNumBands() ==
1494                     inputBandsForColorType[colorType] + 1 &&
1495                 metadata.tRNS_present &&
1496                 (metadata.tRNS_colorType == PNG_COLOR_RGB ||
1497                  metadata.tRNS_colorType == PNG_COLOR_GRAY))
1498             {
1499                 checkReadParamBandSettings(param,
1500                     inputBandsForColorType[colorType] + 1,
1501                     theImage.getSampleModel().getNumBands());
1502             } else {
1503                 checkReadParamBandSettings(param,
1504                     inputBandsForColorType[colorType],
1505                     theImage.getSampleModel().getNumBands());
1506             }
1507 
1508             clearAbortRequest();
1509             processImageStarted(0);
1510             if (abortRequested()) {
1511                 processReadAborted();
1512             } else {
1513                 decodeImage();
1514                 if (abortRequested()) {
1515                     processReadAborted();
1516                 } else {
1517                     processImageComplete();
1518                 }
1519             }
1520 
1521         } catch (IOException e) {
1522             throw new IIOException("Error reading PNG image data", e);
1523         } finally {
1524             if (inf != null) {
1525                 inf.end();
1526             }


1568         readHeader();
1569 
1570         ArrayList<ImageTypeSpecifier> l =
1571             new ArrayList<ImageTypeSpecifier>(1);
1572 
1573         ColorSpace rgb;
1574         ColorSpace gray;
1575         int[] bandOffsets;
1576 
1577         int bitDepth = metadata.IHDR_bitDepth;
1578         int colorType = metadata.IHDR_colorType;
1579 
1580         int dataType;
1581         if (bitDepth <= 8) {
1582             dataType = DataBuffer.TYPE_BYTE;
1583         } else {
1584             dataType = DataBuffer.TYPE_USHORT;
1585         }
1586 
1587         switch (colorType) {
1588         /*
1589          * In case of PNG_COLOR_RGB or PNG_COLOR_GRAY, if we
1590          * have transparent pixel information in tRNS chunk
1591          * we create destination image having alpha channel.
1592          */
1593         case PNG_COLOR_GRAY:
1594             readMetadata(); // Need tRNS chunk
1595 
1596             if (metadata.tRNS_present &&
1597                 metadata.tRNS_colorType == PNG_COLOR_GRAY)
1598             {
1599                 gray = ColorSpace.getInstance(ColorSpace.CS_GRAY);
1600                 bandOffsets = new int[2];
1601                 bandOffsets[0] = 0;
1602                 bandOffsets[1] = 1;
1603                 l.add(ImageTypeSpecifier.createInterleaved(gray,
1604                                                            bandOffsets,
1605                                                            dataType,
1606                                                            true,
1607                                                            false));
1608             }
1609             // Packed grayscale
1610             l.add(ImageTypeSpecifier.createGrayscale(bitDepth,
1611                                                      dataType,
1612                                                      false));
1613             break;
1614 
1615         case PNG_COLOR_RGB:
1616             readMetadata(); // Need tRNS chunk
1617 
1618             if (bitDepth == 8) {
1619                 if (metadata.tRNS_present &&
1620                     metadata.tRNS_colorType == PNG_COLOR_RGB)
1621                 {
1622                     l.add(ImageTypeSpecifier.createFromBufferedImageType(
1623                             BufferedImage.TYPE_4BYTE_ABGR));
1624                 }
1625                 // some standard types of buffered images
1626                 // which can be used as destination
1627                 l.add(ImageTypeSpecifier.createFromBufferedImageType(
1628                           BufferedImage.TYPE_3BYTE_BGR));
1629 
1630                 l.add(ImageTypeSpecifier.createFromBufferedImageType(
1631                           BufferedImage.TYPE_INT_RGB));
1632 
1633                 l.add(ImageTypeSpecifier.createFromBufferedImageType(
1634                           BufferedImage.TYPE_INT_BGR));
1635 
1636             }
1637             if (metadata.tRNS_present &&
1638                 metadata.tRNS_colorType == PNG_COLOR_RGB)
1639             {
1640                 rgb = ColorSpace.getInstance(ColorSpace.CS_sRGB);
1641                 bandOffsets = new int[4];
1642                 bandOffsets[0] = 0;
1643                 bandOffsets[1] = 1;
1644                 bandOffsets[2] = 2;
1645                 bandOffsets[3] = 3;
1646 
1647                 l.add(ImageTypeSpecifier.
1648                     createInterleaved(rgb, bandOffsets,
1649                                       dataType, true, false));
1650             }
1651             // Component R, G, B
1652             rgb = ColorSpace.getInstance(ColorSpace.CS_sRGB);
1653             bandOffsets = new int[3];
1654             bandOffsets[0] = 0;
1655             bandOffsets[1] = 1;
1656             bandOffsets[2] = 2;
1657             l.add(ImageTypeSpecifier.createInterleaved(rgb,
1658                                                        bandOffsets,
1659                                                        dataType,
1660                                                        false,
1661                                                        false));
1662             break;
1663 
1664         case PNG_COLOR_PALETTE:
1665             readMetadata(); // Need tRNS chunk
1666 
1667             /*
1668              * The PLTE chunk spec says:
1669              *


< prev index next >