--- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java Fri Jan 27 15:37:47 2017 +0530
+++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java Mon Jan 30 16:32:46 2017 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1559,6 +1559,59 @@
decodeRLE4(imSize, padding, values, bdata);
}
+ private boolean copyRLE4ScanlineToDst(int lineNo,
+ byte[] val,
+ byte[] bdata) throws IOException {
+ // Return value
+ boolean isSuccess = false;
+
+ // Reusing the code to copy 1 row of pixels or scanline to required
+ // destination buffer.
+ if (lineNo >= sourceRegion.y &&
+ lineNo < sourceRegion.y + sourceRegion.height) {
+ if (noTransform) {
+ int pos = lineNo * (width + 1 >> 1);
+ for(int i = 0, j = 0; i < width >> 1; i++)
+ bdata[pos++] =
+ (byte)((val[j++] << 4) | val[j++]);
+ if ((width & 1) == 1)
+ bdata[pos] |= val[width - 1] << 4;
+
+ processImageUpdate(bi, 0, lineNo,
+ destinationRegion.width, 1, 1, 1,
+ new int[]{0});
+ isSuccess = true;
+ } else if ((lineNo - sourceRegion.y) % scaleY == 0) {
+ int lineStride =
+ ((MultiPixelPackedSampleModel)sampleModel).getScanlineStride();
+ int currentLine = (lineNo - sourceRegion.y) / scaleY +
+ destinationRegion.y;
+ int pos = currentLine * lineStride;
+ pos += destinationRegion.x >> 1;
+ int shift = (1 - (destinationRegion.x & 1)) << 2;
+ for (int i = sourceRegion.x;
+ i < sourceRegion.x + sourceRegion.width;
+ i += scaleX) {
+ bdata[pos] |= val[i] << shift;
+ shift += 4;
+ if (shift == 4) {
+ pos++;
+ }
+ shift &= 7;
+ }
+ processImageUpdate(bi, 0, currentLine,
+ destinationRegion.width, 1, 1, 1,
+ new int[]{0});
+ isSuccess = true;
+ }
+ // Ensure to reset the scanline buffer once the copy is complete.
+ for(int scIndex = 0; scIndex < width; scIndex++) {
+ val[scIndex] = 0;
+ }
+ }
+ return isSuccess;
+ }
+
private void decodeRLE4(int imSize,
int padding,
byte[] values,
@@ -1568,57 +1621,22 @@
int value;
boolean flag = false;
int lineNo = isBottomUp ? height - 1 : 0;
- int lineStride =
- ((MultiPixelPackedSampleModel)sampleModel).getScanlineStride();
int finished = 0;
- while (count != imSize) {
+ // Ensure the image has sufficient data before proceeding to decode
+ while ((count + 1) < imSize) {
value = values[count++] & 0xFF;
if (value == 0) {
-
// Absolute mode
switch(values[count++] & 0xFF) {
case 0:
// End-of-scanline marker
- // End-of-scanline marker
- if (lineNo >= sourceRegion.y &&
- lineNo < sourceRegion.y + sourceRegion.height) {
- if (noTransform) {
- int pos = lineNo * (width + 1 >> 1);
- for(int i = 0, j = 0; i < width >> 1; i++)
- bdata[pos++] =
- (byte)((val[j++] << 4) | val[j++]);
- if ((width & 1) == 1)
- bdata[pos] |= val[width - 1] << 4;
-
- processImageUpdate(bi, 0, lineNo,
- destinationRegion.width, 1, 1, 1,
- new int[]{0});
- finished++;
- } else if ((lineNo - sourceRegion.y) % scaleY == 0) {
- int currentLine = (lineNo - sourceRegion.y) / scaleY +
- destinationRegion.y;
- int pos = currentLine * lineStride;
- pos += destinationRegion.x >> 1;
- int shift = (1 - (destinationRegion.x & 1)) << 2;
- for (int i = sourceRegion.x;
- i < sourceRegion.x + sourceRegion.width;
- i += scaleX) {
- bdata[pos] |= val[i] << shift;
- shift += 4;
- if (shift == 4) {
- pos++;
- }
- shift &= 7;
- }
- processImageUpdate(bi, 0, currentLine,
- destinationRegion.width, 1, 1, 1,
- new int[]{0});
- finished++;
- }
+ // Copy the decoded scanline to destination
+ if (copyRLE4ScanlineToDst(lineNo, val, bdata)) {
+ finished++;
}
processImageProgress(100.0F * finished / destinationRegion.height);
lineNo += isBottomUp ? -1 : 1;
@@ -1633,21 +1651,61 @@
case 1:
// End-of-RLE marker
flag = true;
+
+ // Check if the last decoded scanline was copied to
+ // destination bitmap
+ if (l != 0) {
+ // Copy the decoded scanline to destination
+ if (copyRLE4ScanlineToDst(lineNo, val, bdata)) {
+ finished++;
+ }
+ processImageProgress(100.0F * finished / destinationRegion.height);
+ lineNo += isBottomUp ? -1 : 1;
+ l = 0;
+ }
break;
case 2:
// delta or vector marker
- int xoff = values[count++] & 0xFF;
- int yoff = values[count] & 0xFF;
- // Move to the position xoff, yoff down
- l += xoff + yoff*width;
+ if ((count + 1) < imSize) {
+ int xoff = values[count++] & 0xFF;
+ int yoff = values[count++] & 0xFF;
+
+ // Check if the yOffset shifts the decoding to another
+ // row. In such cases, the decoded pixels in scanline
+ // buffer-val must be copied to the destination image.
+ if (yoff != 0) {
+ // Copy the decoded scanline to destination
+ if (copyRLE4ScanlineToDst(lineNo, val, bdata)) {
+ finished++;
+ }
+ processImageProgress(100.0F * finished
+ / destinationRegion.height);
+ lineNo += isBottomUp ? -yoff : yoff;
+ }
+
+ // Move to the position (xoff, yoff). Since l-is used
+ // to index into the scanline buffer, the accumulated
+ // offset is limited to the width of the scanline
+ l += xoff + yoff*width;
+ l %= width;
+ }
break;
default:
int end = values[count-1] & 0xFF;
- for (int i=0; i<end; i++) {
- val[l++] = (byte)(((i & 1) == 0) ? (values[count] & 0xf0) >> 4
- : (values[count++] & 0x0f));
+ byte readByte = 0;
+ // Ensure to check if the source index-count, does not
+ // exceed the source image size
+ for (int i = 0; (i < end) && (count < imSize); i++) {
+ readByte = (byte)(((i & 1) == 0) ?
+ (values[count] & 0xf0) >> 4 :
+ (values[count++] & 0x0f));
+ // Ensure to check if scanline index-l, does not
+ // exceed the scanline buffer size (width of image)
+ if (l < width) {
+ val[l++] = readByte;
+ }
}
// When end is odd, the above for loop does not
@@ -1665,10 +1723,14 @@
}
} else {
// Encoded mode
- int alternate[] = { (values[count] & 0xf0) >> 4,
- values[count] & 0x0f };
- for (int i=0; (i < value) && (l < width); i++) {
- val[l++] = (byte)alternate[i & 1];
+ // Ensure to check if the source index-count, does not
+ // exceed the source image size
+ if (count < imSize) {
+ int alternate[] = { (values[count] & 0xf0) >> 4,
+ values[count] & 0x0f };
+ for (int i=0; (i < value) && (l < width); i++) {
+ val[l++] = (byte)alternate[i & 1];
+ }
}
count++;