< 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                     for (int dstX = updateMinX;
1296                          dstX < updateMinX + updateWidth;
1297                          dstX += updateXStep) {
1298 
1299                         passRow.getPixel(newSrcX, 0, ps);
1300                         if (adjustBitDepths) {
1301                             for (int b = 0; b < numBands; b++) {
1302                                 ps[b] = scale[b][ps[b]];
1303                             }
1304                         }
1305                         if (tRNSTransparentPixelPresent) {
1306                             /*
1307                              * Create intermediate array to fill the extra
1308                              * alpha channel for each pixel.
1309                              */
1310                             int[] temp = new int[inputBands + 1];
1311 
1312                             int opaque = (bitDepth < 16) ? 255 : 65535;
1313                             if (metadata.tRNS_colorType == PNG_COLOR_RGB) {
1314                                 temp[0] = ps[0];
1315                                 temp[1] = ps[1];
1316                                 temp[2] = ps[2];
1317                                 if (ps[0] == metadata.tRNS_red &&
1318                                     ps[1] == metadata.tRNS_green &&
1319                                     ps[2] == metadata.tRNS_blue) {
1320                                     temp[3] = 0;
1321                                 } else {
1322                                     temp[3] = opaque;
1323                                 }
1324                             } else {
1325                                 // when tRNS_colorType is PNG_COLOR_GRAY
1326                                 temp[0] = ps[0];
1327                                 if (ps[0] == metadata.tRNS_gray) {
1328                                     temp[1] = 0;
1329                                 } else {
1330                                     temp[1] = opaque;
1331                                 }
1332                             }
1333                             imRas.setPixel(dstX, dstY, temp);
1334                         } else {
1335                             imRas.setPixel(dstX, dstY, ps);
1336                         }
1337                         newSrcX += srcXStep;
1338                     }
1339                 }
1340 
1341                 processImageUpdate(theImage,
1342                                    updateMinX, dstY,
1343                                    updateWidth, 1,
1344                                    updateXStep, updateYStep,
1345                                    destinationBands);
1346             }
1347         }
1348 
1349         processPassComplete(theImage);
1350     }
1351 
1352     private void decodeImage()
1353         throws IOException, IIOException  {
1354         int width = metadata.IHDR_width;
1355         int height = metadata.IHDR_height;
1356 


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


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


< prev index next >