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) { |