src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageReader.java
changeset 49995 6f595ec05539
parent 48728 fb62f481671e
child 52742 b9f3606b2f83
equal deleted inserted replaced
49994:0e9be7add10a 49995:6f595ec05539
   696         }
   696         }
   697 
   697 
   698         readHeader();
   698         readHeader();
   699 
   699 
   700         /*
   700         /*
   701          * Optimization: We can skip the remaining metadata if the
   701          * Optimization: We can skip reading metadata if ignoreMetadata
   702          * ignoreMetadata flag is set, and only if this is not a palette
   702          * flag is set and colorType is not PNG_COLOR_PALETTE. However,
   703          * image (in that case, we need to read the metadata to get the
   703          * we parse tRNS chunk to retrieve the transparent color from the
   704          * tRNS chunk, which is needed for the getImageTypes() method).
   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.
   705          */
   707          */
   706         int colorType = metadata.IHDR_colorType;
   708         int colorType = metadata.IHDR_colorType;
   707         if (ignoreMetadata && colorType != PNG_COLOR_PALETTE) {
   709         if (ignoreMetadata && colorType != PNG_COLOR_PALETTE) {
   708             try {
   710             try {
   709                 while (true) {
   711                 while (true) {
   715                     }
   717                     }
   716 
   718 
   717                     int chunkType = stream.readInt();
   719                     int chunkType = stream.readInt();
   718 
   720 
   719                     if (chunkType == IDAT_TYPE) {
   721                     if (chunkType == IDAT_TYPE) {
   720                         // We've reached the image data
   722                         // We've reached the first IDAT chunk position
   721                         stream.skipBytes(-8);
   723                         stream.skipBytes(-8);
   722                         imageStartPosition = stream.getStreamPosition();
   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                          */
   723                         break;
   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);
   724                     } else {
   735                     } else {
   725                         // Skip the chunk plus the 4 CRC bytes that follow
   736                         // Skip the chunk plus the 4 CRC bytes that follow
   726                         stream.skipBytes(chunkLength + 4);
   737                         stream.skipBytes(chunkLength + 4);
   727                     }
   738                     }
   728                 }
   739                 }
  1264                 }
  1275                 }
  1265                 if (dstY > dstMaxY) {
  1276                 if (dstY > dstMaxY) {
  1266                     break;
  1277                     break;
  1267                 }
  1278                 }
  1268 
  1279 
  1269                 if (useSetRect) {
  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) {
  1270                     imRas.setRect(updateMinX, dstY, passRow);
  1291                     imRas.setRect(updateMinX, dstY, passRow);
  1271                 } else {
  1292                 } else {
  1272                     int newSrcX = srcX;
  1293                     int newSrcX = srcX;
  1273 
  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;
  1274                     for (int dstX = updateMinX;
  1301                     for (int dstX = updateMinX;
  1275                          dstX < updateMinX + updateWidth;
  1302                          dstX < updateMinX + updateWidth;
  1276                          dstX += updateXStep) {
  1303                          dstX += updateXStep) {
  1277 
  1304 
  1278                         passRow.getPixel(newSrcX, 0, ps);
  1305                         passRow.getPixel(newSrcX, 0, ps);
  1279                         if (adjustBitDepths) {
  1306                         if (adjustBitDepths) {
  1280                             for (int b = 0; b < numBands; b++) {
  1307                             for (int b = 0; b < numBands; b++) {
  1281                                 ps[b] = scale[b][ps[b]];
  1308                                 ps[b] = scale[b][ps[b]];
  1282                             }
  1309                             }
  1283                         }
  1310                         }
  1284                         imRas.setPixel(dstX, dstY, ps);
  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                         }
  1285                         newSrcX += srcXStep;
  1336                         newSrcX += srcXStep;
  1286                     }
  1337                     }
  1287                 }
  1338                 }
  1288 
  1339 
  1289                 processImageUpdate(theImage,
  1340                 processImageUpdate(theImage,
  1420 
  1471 
  1421             // At this point the header has been read and we know
  1472             // At this point the header has been read and we know
  1422             // how many bands are in the image, so perform checking
  1473             // how many bands are in the image, so perform checking
  1423             // of the read param.
  1474             // of the read param.
  1424             int colorType = metadata.IHDR_colorType;
  1475             int colorType = metadata.IHDR_colorType;
  1425             checkReadParamBandSettings(param,
  1476             if (theImage.getSampleModel().getNumBands()
  1426                                        inputBandsForColorType[colorType],
  1477                 == inputBandsForColorType[colorType] + 1
  1427                                       theImage.getSampleModel().getNumBands());
  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             }
  1428 
  1487 
  1429             clearAbortRequest();
  1488             clearAbortRequest();
  1430             processImageStarted(0);
  1489             processImageStarted(0);
  1431             if (abortRequested()) {
  1490             if (abortRequested()) {
  1432                 processReadAborted();
  1491                 processReadAborted();
  1504         } else {
  1563         } else {
  1505             dataType = DataBuffer.TYPE_USHORT;
  1564             dataType = DataBuffer.TYPE_USHORT;
  1506         }
  1565         }
  1507 
  1566 
  1508         switch (colorType) {
  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          */
  1509         case PNG_COLOR_GRAY:
  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             }
  1510             // Packed grayscale
  1588             // Packed grayscale
  1511             l.add(ImageTypeSpecifier.createGrayscale(bitDepth,
  1589             l.add(ImageTypeSpecifier.createGrayscale(bitDepth,
  1512                                                      dataType,
  1590                                                      dataType,
  1513                                                      false));
  1591                                                      false));
  1514             break;
  1592             break;
  1515 
  1593 
  1516         case PNG_COLOR_RGB:
  1594         case PNG_COLOR_RGB:
       
  1595             readMetadata(); // Need tRNS chunk
       
  1596 
  1517             if (bitDepth == 8) {
  1597             if (bitDepth == 8) {
       
  1598                 if (metadata.hasTransparentColor()) {
       
  1599                     l.add(ImageTypeSpecifier.createFromBufferedImageType(
       
  1600                             BufferedImage.TYPE_4BYTE_ABGR));
       
  1601                 }
  1518                 // some standard types of buffered images
  1602                 // some standard types of buffered images
  1519                 // which can be used as destination
  1603                 // which can be used as destination
  1520                 l.add(ImageTypeSpecifier.createFromBufferedImageType(
  1604                 l.add(ImageTypeSpecifier.createFromBufferedImageType(
  1521                           BufferedImage.TYPE_3BYTE_BGR));
  1605                           BufferedImage.TYPE_3BYTE_BGR));
  1522 
  1606 
  1524                           BufferedImage.TYPE_INT_RGB));
  1608                           BufferedImage.TYPE_INT_RGB));
  1525 
  1609 
  1526                 l.add(ImageTypeSpecifier.createFromBufferedImageType(
  1610                 l.add(ImageTypeSpecifier.createFromBufferedImageType(
  1527                           BufferedImage.TYPE_INT_BGR));
  1611                           BufferedImage.TYPE_INT_BGR));
  1528 
  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));
  1529             }
  1626             }
  1530             // Component R, G, B
  1627             // Component R, G, B
  1531             rgb = ColorSpace.getInstance(ColorSpace.CS_sRGB);
  1628             rgb = ColorSpace.getInstance(ColorSpace.CS_sRGB);
  1532             bandOffsets = new int[3];
  1629             bandOffsets = new int[3];
  1533             bandOffsets[0] = 0;
  1630             bandOffsets[0] = 0;