< 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                                 {
1321                                     temp[3] = 0;
1322                                 } else {
1323                                     temp[3] = opaque;
1324                                 }
1325                             } else {
1326                                 // when tRNS_colorType is PNG_COLOR_GRAY
1327                                 temp[0] = ps[0];
1328                                 if (ps[0] == metadata.tRNS_gray)
1329                                 {
1330                                     temp[1] = 0;
1331                                 } else {
1332                                     temp[1] = opaque;
1333                                 }
1334                             }
1335                             imRas.setPixel(dstX, dstY, temp);
1336                         } else {
1337                             imRas.setPixel(dstX, dstY, ps);
1338                         }
1339                         newSrcX += srcXStep;
1340                     }
1341                 }
1342 
1343                 processImageUpdate(theImage,
1344                                    updateMinX, dstY,
1345                                    updateWidth, 1,
1346                                    updateXStep, updateYStep,
1347                                    destinationBands);
1348             }
1349         }
1350 
1351         processPassComplete(theImage);
1352     }
1353 
1354     private void decodeImage()
1355         throws IOException, IIOException  {
1356         int width = metadata.IHDR_width;
1357         int height = metadata.IHDR_height;
1358 


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


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


< prev index next >