jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java
changeset 43517 31e01190e3c5
parent 41010 9824689edeb1
child 43835 bb3935761c12
equal deleted inserted replaced
43516:f23912ce3308 43517:31e01190e3c5
     1 /*
     1 /*
     2  * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
  1557 
  1557 
  1558         // Decompress the RLE4 compressed data.
  1558         // Decompress the RLE4 compressed data.
  1559         decodeRLE4(imSize, padding, values, bdata);
  1559         decodeRLE4(imSize, padding, values, bdata);
  1560     }
  1560     }
  1561 
  1561 
       
  1562     private boolean copyRLE4ScanlineToDst(int lineNo,
       
  1563                                           byte[] val,
       
  1564                                           byte[] bdata) throws IOException {
       
  1565         // Return value
       
  1566         boolean isSuccess = false;
       
  1567 
       
  1568         // Reusing the code to copy 1 row of pixels or scanline to required
       
  1569         // destination buffer.
       
  1570         if (lineNo >= sourceRegion.y &&
       
  1571             lineNo < sourceRegion.y + sourceRegion.height) {
       
  1572             if (noTransform) {
       
  1573                 int pos = lineNo * (width + 1 >> 1);
       
  1574                 for(int i = 0, j = 0; i < width >> 1; i++)
       
  1575                     bdata[pos++] =
       
  1576                         (byte)((val[j++] << 4) | val[j++]);
       
  1577                 if ((width & 1) == 1)
       
  1578                     bdata[pos] |= val[width - 1] << 4;
       
  1579 
       
  1580                 processImageUpdate(bi, 0, lineNo,
       
  1581                                    destinationRegion.width, 1, 1, 1,
       
  1582                                    new int[]{0});
       
  1583                 isSuccess = true;
       
  1584             } else if ((lineNo - sourceRegion.y) % scaleY == 0) {
       
  1585                 int lineStride =
       
  1586                     ((MultiPixelPackedSampleModel)sampleModel).getScanlineStride();
       
  1587                 int currentLine = (lineNo - sourceRegion.y) / scaleY +
       
  1588                     destinationRegion.y;
       
  1589                 int pos = currentLine * lineStride;
       
  1590                 pos += destinationRegion.x >> 1;
       
  1591                 int shift = (1 - (destinationRegion.x & 1)) << 2;
       
  1592                 for (int i = sourceRegion.x;
       
  1593                      i < sourceRegion.x + sourceRegion.width;
       
  1594                      i += scaleX) {
       
  1595                     bdata[pos] |= val[i] << shift;
       
  1596                     shift += 4;
       
  1597                     if (shift == 4) {
       
  1598                         pos++;
       
  1599                     }
       
  1600                     shift &= 7;
       
  1601                 }
       
  1602                 processImageUpdate(bi, 0, currentLine,
       
  1603                                    destinationRegion.width, 1, 1, 1,
       
  1604                                    new int[]{0});
       
  1605                 isSuccess = true;
       
  1606             }
       
  1607             // Ensure to reset the scanline buffer once the copy is complete.
       
  1608             for(int scIndex = 0; scIndex < width; scIndex++) {
       
  1609                 val[scIndex] = 0;
       
  1610             }
       
  1611         }
       
  1612         return isSuccess;
       
  1613     }
       
  1614 
  1562     private void decodeRLE4(int imSize,
  1615     private void decodeRLE4(int imSize,
  1563                             int padding,
  1616                             int padding,
  1564                             byte[] values,
  1617                             byte[] values,
  1565                             byte[] bdata) throws IOException {
  1618                             byte[] bdata) throws IOException {
  1566         byte[] val = new byte[width];
  1619         byte[] val = new byte[width];
  1567         int count = 0, l = 0;
  1620         int count = 0, l = 0;
  1568         int value;
  1621         int value;
  1569         boolean flag = false;
  1622         boolean flag = false;
  1570         int lineNo = isBottomUp ? height - 1 : 0;
  1623         int lineNo = isBottomUp ? height - 1 : 0;
  1571         int lineStride =
       
  1572             ((MultiPixelPackedSampleModel)sampleModel).getScanlineStride();
       
  1573         int finished = 0;
  1624         int finished = 0;
  1574 
  1625 
  1575         while (count != imSize) {
  1626         // Ensure the image has sufficient data before proceeding to decode
       
  1627         while ((count + 1) < imSize) {
  1576 
  1628 
  1577             value = values[count++] & 0xFF;
  1629             value = values[count++] & 0xFF;
  1578             if (value == 0) {
  1630             if (value == 0) {
  1579 
  1631 
  1580 
       
  1581                 // Absolute mode
  1632                 // Absolute mode
  1582                 switch(values[count++] & 0xFF) {
  1633                 switch(values[count++] & 0xFF) {
  1583 
  1634 
  1584                 case 0:
  1635                 case 0:
  1585                     // End-of-scanline marker
  1636                     // End-of-scanline marker
  1586                     // End-of-scanline marker
  1637                     // Copy the decoded scanline to destination
  1587                     if (lineNo >= sourceRegion.y &&
  1638                     if (copyRLE4ScanlineToDst(lineNo, val, bdata)) {
  1588                         lineNo < sourceRegion.y + sourceRegion.height) {
  1639                         finished++;
  1589                         if (noTransform) {
       
  1590                             int pos = lineNo * (width + 1 >> 1);
       
  1591                             for(int i = 0, j = 0; i < width >> 1; i++)
       
  1592                                 bdata[pos++] =
       
  1593                                     (byte)((val[j++] << 4) | val[j++]);
       
  1594                             if ((width & 1) == 1)
       
  1595                                 bdata[pos] |= val[width - 1] << 4;
       
  1596 
       
  1597                             processImageUpdate(bi, 0, lineNo,
       
  1598                                                destinationRegion.width, 1, 1, 1,
       
  1599                                                new int[]{0});
       
  1600                             finished++;
       
  1601                         } else if ((lineNo - sourceRegion.y) % scaleY == 0) {
       
  1602                             int currentLine = (lineNo - sourceRegion.y) / scaleY +
       
  1603                                 destinationRegion.y;
       
  1604                             int pos = currentLine * lineStride;
       
  1605                             pos += destinationRegion.x >> 1;
       
  1606                             int shift = (1 - (destinationRegion.x & 1)) << 2;
       
  1607                             for (int i = sourceRegion.x;
       
  1608                                  i < sourceRegion.x + sourceRegion.width;
       
  1609                                  i += scaleX) {
       
  1610                                 bdata[pos] |= val[i] << shift;
       
  1611                                 shift += 4;
       
  1612                                 if (shift == 4) {
       
  1613                                     pos++;
       
  1614                                 }
       
  1615                                 shift &= 7;
       
  1616                             }
       
  1617                             processImageUpdate(bi, 0, currentLine,
       
  1618                                                destinationRegion.width, 1, 1, 1,
       
  1619                                                new int[]{0});
       
  1620                             finished++;
       
  1621                         }
       
  1622                     }
  1640                     }
  1623                     processImageProgress(100.0F * finished / destinationRegion.height);
  1641                     processImageProgress(100.0F * finished / destinationRegion.height);
  1624                     lineNo += isBottomUp ? -1 : 1;
  1642                     lineNo += isBottomUp ? -1 : 1;
  1625                     l = 0;
  1643                     l = 0;
  1626 
  1644 
  1631                     break;
  1649                     break;
  1632 
  1650 
  1633                 case 1:
  1651                 case 1:
  1634                     // End-of-RLE marker
  1652                     // End-of-RLE marker
  1635                     flag = true;
  1653                     flag = true;
       
  1654 
       
  1655                     // Check if the last decoded scanline was copied to
       
  1656                     // destination bitmap
       
  1657                     if (l != 0) {
       
  1658                         // Copy the decoded scanline to destination
       
  1659                         if (copyRLE4ScanlineToDst(lineNo, val, bdata)) {
       
  1660                             finished++;
       
  1661                         }
       
  1662                         processImageProgress(100.0F * finished / destinationRegion.height);
       
  1663                         lineNo += isBottomUp ? -1 : 1;
       
  1664                         l = 0;
       
  1665                     }
  1636                     break;
  1666                     break;
  1637 
  1667 
  1638                 case 2:
  1668                 case 2:
  1639                     // delta or vector marker
  1669                     // delta or vector marker
  1640                     int xoff = values[count++] & 0xFF;
  1670                     if ((count + 1) < imSize) {
  1641                     int yoff = values[count] & 0xFF;
  1671                         int xoff = values[count++] & 0xFF;
  1642                     // Move to the position xoff, yoff down
  1672                         int yoff = values[count++] & 0xFF;
  1643                     l += xoff + yoff*width;
  1673 
       
  1674                         // Check if the yOffset shifts the decoding to another
       
  1675                         // row. In such cases, the decoded pixels in scanline
       
  1676                         // buffer-val must be copied to the destination image.
       
  1677                         if (yoff != 0) {
       
  1678                             // Copy the decoded scanline to destination
       
  1679                             if (copyRLE4ScanlineToDst(lineNo, val, bdata)) {
       
  1680                                 finished++;
       
  1681                             }
       
  1682                             processImageProgress(100.0F * finished
       
  1683                                                  / destinationRegion.height);
       
  1684                             lineNo += isBottomUp ? -yoff : yoff;
       
  1685                         }
       
  1686 
       
  1687                         // Move to the position (xoff, yoff). Since l-is used
       
  1688                         // to index into the scanline buffer, the accumulated
       
  1689                         // offset is limited to the width of the scanline
       
  1690                         l += xoff + yoff*width;
       
  1691                         l %= width;
       
  1692                     }
  1644                     break;
  1693                     break;
  1645 
  1694 
  1646                 default:
  1695                 default:
  1647                     int end = values[count-1] & 0xFF;
  1696                     int end = values[count-1] & 0xFF;
  1648                     for (int i=0; i<end; i++) {
  1697                     byte readByte = 0;
  1649                         val[l++] = (byte)(((i & 1) == 0) ? (values[count] & 0xf0) >> 4
  1698                     // Ensure to check if the source index-count, does not
  1650                                           : (values[count++] & 0x0f));
  1699                     // exceed the source image size
       
  1700                     for (int i = 0; (i < end) && (count < imSize); i++) {
       
  1701                         readByte = (byte)(((i & 1) == 0) ?
       
  1702                                         (values[count] & 0xf0) >> 4 :
       
  1703                                         (values[count++] & 0x0f));
       
  1704                         // Ensure to check if scanline index-l, does not
       
  1705                         // exceed the scanline buffer size (width of image)
       
  1706                         if (l < width) {
       
  1707                             val[l++] = readByte;
       
  1708                         }
  1651                     }
  1709                     }
  1652 
  1710 
  1653                     // When end is odd, the above for loop does not
  1711                     // When end is odd, the above for loop does not
  1654                     // increment count, so do it now.
  1712                     // increment count, so do it now.
  1655                     if ((end & 1) == 1) {
  1713                     if ((end & 1) == 1) {
  1663                     }
  1721                     }
  1664                     break;
  1722                     break;
  1665                 }
  1723                 }
  1666             } else {
  1724             } else {
  1667                 // Encoded mode
  1725                 // Encoded mode
  1668                 int alternate[] = { (values[count] & 0xf0) >> 4,
  1726                 // Ensure to check if the source index-count, does not
  1669                                     values[count] & 0x0f };
  1727                 // exceed the source image size
  1670                 for (int i=0; (i < value) && (l < width); i++) {
  1728                 if (count < imSize) {
  1671                     val[l++] = (byte)alternate[i & 1];
  1729                     int alternate[] = { (values[count] & 0xf0) >> 4,
       
  1730                                         values[count] & 0x0f };
       
  1731                     for (int i=0; (i < value) && (l < width); i++) {
       
  1732                         val[l++] = (byte)alternate[i & 1];
       
  1733                     }
  1672                 }
  1734                 }
  1673 
  1735 
  1674                 count++;
  1736                 count++;
  1675             }
  1737             }
  1676 
  1738