< 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                 * For PNG images of color type PNG_COLOR_RGB or PNG_COLOR_GRAY
1282                 * that contain a specific transparent color (given by tRNS
1283                 * chunk), we compare the decoded pixel color with the color
1284                 * given by tRNS chunk to set the alpha on the destination.
1285                 */
1286                 boolean tRNSTransparentPixelPresent =
1287                     theImage.getSampleModel().getNumBands() == inputBands + 1 &&
1288                     metadata.hasTransparentColor();
1289                 if (useSetRect &&
1290                     !tRNSTransparentPixelPresent) {
1291                     imRas.setRect(updateMinX, dstY, passRow);
1292                 } else {
1293                     int newSrcX = srcX;
1294 
1295                     /*
1296                      * Create intermediate array to fill the extra alpha
1297                      * channel when tRNSTransparentPixelPresent is true.
1298                      */
1299                     final int[] temp = new int[inputBands + 1];
1300                     final int opaque = (bitDepth < 16) ? 255 : 65535;
1301                     for (int dstX = updateMinX;
1302                          dstX < updateMinX + updateWidth;
1303                          dstX += updateXStep) {
1304 
1305                         passRow.getPixel(newSrcX, 0, ps);
1306                         if (adjustBitDepths) {
1307                             for (int b = 0; b < numBands; b++) {
1308                                 ps[b] = scale[b][ps[b]];
1309                             }
1310                         }
1311                         if (tRNSTransparentPixelPresent) {
1312                             if (metadata.tRNS_colorType == PNG_COLOR_RGB) {
1313                                 temp[0] = ps[0];
1314                                 temp[1] = ps[1];
1315                                 temp[2] = ps[2];
1316                                 if (ps[0] == metadata.tRNS_red &&
1317                                     ps[1] == metadata.tRNS_green &&
1318                                     ps[2] == metadata.tRNS_blue) {
1319                                     temp[3] = 0;
1320                                 } else {
1321                                     temp[3] = opaque;
1322                                 }
1323                             } else {
1324                                 // when tRNS_colorType is PNG_COLOR_GRAY
1325                                 temp[0] = ps[0];
1326                                 if (ps[0] == metadata.tRNS_gray) {
1327                                     temp[1] = 0;
1328                                 } else {
1329                                     temp[1] = opaque;
1330                                 }
1331                             }
1332                             imRas.setPixel(dstX, dstY, temp);
1333                         } else {
1334                             imRas.setPixel(dstX, dstY, ps);
1335                         }
1336                         newSrcX += srcXStep;
1337                     }
1338                 }
1339 
1340                 processImageUpdate(theImage,
1341                                    updateMinX, dstY,
1342                                    updateWidth, 1,
1343                                    updateXStep, updateYStep,
1344                                    destinationBands);
1345             }
1346         }
1347 
1348         processPassComplete(theImage);
1349     }
1350 
1351     private void decodeImage()
1352         throws IOException, IIOException  {
1353         int width = metadata.IHDR_width;
1354         int height = metadata.IHDR_height;
1355 


1456              * the level of application, so we will not try to estimate
1457              * the required amount of the memory and/or handle OOM in
1458              * any way.
1459              */
1460             theImage = getDestination(param,
1461                                       getImageTypes(0),
1462                                       width,
1463                                       height);
1464 
1465             Rectangle destRegion = new Rectangle(0, 0, 0, 0);
1466             sourceRegion = new Rectangle(0, 0, 0, 0);
1467             computeRegions(param, width, height,
1468                            theImage,
1469                            sourceRegion, destRegion);
1470             destinationOffset.setLocation(destRegion.getLocation());
1471 
1472             // At this point the header has been read and we know
1473             // how many bands are in the image, so perform checking
1474             // of the read param.
1475             int colorType = metadata.IHDR_colorType;
1476             if (theImage.getSampleModel().getNumBands()
1477                 == inputBandsForColorType[colorType] + 1
1478                 && metadata.hasTransparentColor()) {
1479                 checkReadParamBandSettings(param,
1480                     inputBandsForColorType[colorType] + 1,
1481                     theImage.getSampleModel().getNumBands());
1482             } else {
1483                 checkReadParamBandSettings(param,
1484                     inputBandsForColorType[colorType],
1485                     theImage.getSampleModel().getNumBands());
1486             }
1487 
1488             clearAbortRequest();
1489             processImageStarted(0);
1490             if (abortRequested()) {
1491                 processReadAborted();
1492             } else {
1493                 decodeImage();
1494                 if (abortRequested()) {
1495                     processReadAborted();
1496                 } else {
1497                     processImageComplete();
1498                 }
1499             }
1500 
1501         } catch (IOException e) {
1502             throw new IIOException("Error reading PNG image data", e);
1503         } finally {
1504             if (inf != null) {
1505                 inf.end();
1506             }


1548         readHeader();
1549 
1550         ArrayList<ImageTypeSpecifier> l =
1551             new ArrayList<ImageTypeSpecifier>(1);
1552 
1553         ColorSpace rgb;
1554         ColorSpace gray;
1555         int[] bandOffsets;
1556 
1557         int bitDepth = metadata.IHDR_bitDepth;
1558         int colorType = metadata.IHDR_colorType;
1559 
1560         int dataType;
1561         if (bitDepth <= 8) {
1562             dataType = DataBuffer.TYPE_BYTE;
1563         } else {
1564             dataType = DataBuffer.TYPE_USHORT;
1565         }
1566 
1567         switch (colorType) {
1568         /*
1569          * For PNG images of color type PNG_COLOR_RGB or PNG_COLOR_GRAY that
1570          * contain a specific transparent color (given by tRNS chunk), we add
1571          * ImageTypeSpecifier(s) that support transparency to the list of
1572          * supported image types.
1573          */
1574         case PNG_COLOR_GRAY:
1575             readMetadata(); // Need tRNS chunk
1576 
1577             if (metadata.hasTransparentColor()) {
1578                 gray = ColorSpace.getInstance(ColorSpace.CS_GRAY);
1579                 bandOffsets = new int[2];
1580                 bandOffsets[0] = 0;
1581                 bandOffsets[1] = 1;
1582                 l.add(ImageTypeSpecifier.createInterleaved(gray,
1583                                                            bandOffsets,
1584                                                            dataType,
1585                                                            true,
1586                                                            false));
1587             }
1588             // Packed grayscale
1589             l.add(ImageTypeSpecifier.createGrayscale(bitDepth,
1590                                                      dataType,
1591                                                      false));
1592             break;
1593 
1594         case PNG_COLOR_RGB:
1595             readMetadata(); // Need tRNS chunk
1596 
1597             if (bitDepth == 8) {
1598                 if (metadata.hasTransparentColor()) {
1599                     l.add(ImageTypeSpecifier.createFromBufferedImageType(
1600                             BufferedImage.TYPE_4BYTE_ABGR));
1601                 }
1602                 // some standard types of buffered images
1603                 // which can be used as destination
1604                 l.add(ImageTypeSpecifier.createFromBufferedImageType(
1605                           BufferedImage.TYPE_3BYTE_BGR));
1606 
1607                 l.add(ImageTypeSpecifier.createFromBufferedImageType(
1608                           BufferedImage.TYPE_INT_RGB));
1609 
1610                 l.add(ImageTypeSpecifier.createFromBufferedImageType(
1611                           BufferedImage.TYPE_INT_BGR));
1612 
1613             }
1614 
1615             if (metadata.hasTransparentColor()) {
1616                 rgb = ColorSpace.getInstance(ColorSpace.CS_sRGB);
1617                 bandOffsets = new int[4];
1618                 bandOffsets[0] = 0;
1619                 bandOffsets[1] = 1;
1620                 bandOffsets[2] = 2;
1621                 bandOffsets[3] = 3;
1622 
1623                 l.add(ImageTypeSpecifier.
1624                     createInterleaved(rgb, bandOffsets,
1625                                       dataType, true, false));
1626             }
1627             // Component R, G, B
1628             rgb = ColorSpace.getInstance(ColorSpace.CS_sRGB);
1629             bandOffsets = new int[3];
1630             bandOffsets[0] = 0;
1631             bandOffsets[1] = 1;
1632             bandOffsets[2] = 2;
1633             l.add(ImageTypeSpecifier.createInterleaved(rgb,
1634                                                        bandOffsets,
1635                                                        dataType,
1636                                                        false,
1637                                                        false));
1638             break;
1639 
1640         case PNG_COLOR_PALETTE:
1641             readMetadata(); // Need tRNS chunk
1642 
1643             /*
1644              * The PLTE chunk spec says:
1645              *


< prev index next >