in src/main/java/org/apache/commons/imaging/formats/bmp/BmpImageParser.java [466:643]
private BmpImageContents readImageContents(final InputStream is,
final FormatCompliance formatCompliance)
throws ImagingException, IOException {
final BmpHeaderInfo bhi = readBmpHeaderInfo(is, formatCompliance);
int colorTableSize = bhi.colorsUsed;
if (colorTableSize == 0) {
colorTableSize = (1 << bhi.bitsPerPixel);
}
if (LOGGER.isLoggable(Level.FINE)) {
debugNumber("ColorsUsed", bhi.colorsUsed, 4);
debugNumber("BitsPerPixel", bhi.bitsPerPixel, 4);
debugNumber("ColorTableSize", colorTableSize, 4);
debugNumber("bhi.colorsUsed", bhi.colorsUsed, 4);
debugNumber("Compression", bhi.compression, 4);
}
// A palette is always valid, even for images that don't need it
// (like 32 bpp), it specifies the "optimal color palette" for
// when the image is displayed on a <= 256 color graphics card.
int paletteLength;
int rleSamplesPerByte = 0;
boolean rle = false;
switch (bhi.compression) {
case BI_RGB:
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine("Compression: BI_RGB");
}
if (bhi.bitsPerPixel <= 8) {
paletteLength = 4 * colorTableSize;
} else {
paletteLength = 0;
}
// BytesPerPaletteEntry = 0;
// System.out.println("Compression: BI_RGBx2: " + bhi.BitsPerPixel);
// System.out.println("Compression: BI_RGBx2: " + (bhi.BitsPerPixel
// <= 16));
break;
case BI_RLE4:
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine("Compression: BI_RLE4");
}
paletteLength = 4 * colorTableSize;
rleSamplesPerByte = 2;
// ExtraBitsPerPixel = 4;
rle = true;
// // BytesPerPixel = 2;
// // BytesPerPaletteEntry = 0;
break;
//
case BI_RLE8:
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine("Compression: BI_RLE8");
}
paletteLength = 4 * colorTableSize;
rleSamplesPerByte = 1;
// ExtraBitsPerPixel = 8;
rle = true;
// BytesPerPixel = 2;
// BytesPerPaletteEntry = 0;
break;
//
case BI_BITFIELDS:
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine("Compression: BI_BITFIELDS");
}
if (bhi.bitsPerPixel <= 8) {
paletteLength = 4 * colorTableSize;
} else {
paletteLength = 0;
}
// BytesPerPixel = 2;
// BytesPerPaletteEntry = 4;
break;
default:
throw new ImagingException("BMP: Unknown Compression: "
+ bhi.compression);
}
if (paletteLength < 0) {
throw new ImagingException("BMP: Invalid negative palette length: " + paletteLength);
}
byte[] colorTable = null;
if (paletteLength > 0) {
colorTable = readBytes("ColorTable", is, paletteLength,
"Not a Valid BMP File");
}
if (LOGGER.isLoggable(Level.FINE)) {
debugNumber("paletteLength", paletteLength, 4);
LOGGER.fine("ColorTable: "
+ ((colorTable == null) ? "null" : Integer.toString(colorTable.length)));
}
int imageLineLength = (((bhi.bitsPerPixel) * bhi.width) + 7) / 8;
if (LOGGER.isLoggable(Level.FINE)) {
final int pixelCount = bhi.width * bhi.height;
// this.debugNumber("Total BitsPerPixel",
// (ExtraBitsPerPixel + bhi.BitsPerPixel), 4);
// this.debugNumber("Total Bit Per Line",
// ((ExtraBitsPerPixel + bhi.BitsPerPixel) * bhi.Width), 4);
// this.debugNumber("ExtraBitsPerPixel", ExtraBitsPerPixel, 4);
debugNumber("bhi.Width", bhi.width, 4);
debugNumber("bhi.Height", bhi.height, 4);
debugNumber("ImageLineLength", imageLineLength, 4);
// this.debugNumber("imageDataSize", imageDataSize, 4);
debugNumber("PixelCount", pixelCount, 4);
}
// int ImageLineLength = BytesPerPixel * bhi.Width;
while ((imageLineLength % 4) != 0) {
imageLineLength++;
}
final int headerSize = BITMAP_FILE_HEADER_SIZE
+ bhi.bitmapHeaderSize
+ (bhi.bitmapHeaderSize == 40
&& bhi.compression == BI_BITFIELDS ? 3 * 4 : 0);
final int expectedDataOffset = headerSize + paletteLength;
if (LOGGER.isLoggable(Level.FINE)) {
debugNumber("bhi.BitmapDataOffset", bhi.bitmapDataOffset, 4);
debugNumber("expectedDataOffset", expectedDataOffset, 4);
}
final int extraBytes = bhi.bitmapDataOffset - expectedDataOffset;
if (extraBytes < 0) {
throw new ImagingException("BMP has invalid image data offset: "
+ bhi.bitmapDataOffset + " (expected: "
+ expectedDataOffset + ", paletteLength: " + paletteLength
+ ", headerSize: " + headerSize + ")");
}
if (extraBytes > 0) {
readBytes("BitmapDataOffset", is, extraBytes, "Not a Valid BMP File");
}
final int imageDataSize = bhi.height * imageLineLength;
if (LOGGER.isLoggable(Level.FINE)) {
debugNumber("imageDataSize", imageDataSize, 4);
}
byte[] imageData;
if (rle) {
imageData = getRleBytes(is, rleSamplesPerByte);
} else {
imageData = readBytes("ImageData", is, imageDataSize,
"Not a Valid BMP File");
}
if (LOGGER.isLoggable(Level.FINE)) {
debugNumber("ImageData.length", imageData.length, 4);
}
PixelParser pixelParser;
switch (bhi.compression) {
case BI_RLE4:
case BI_RLE8:
pixelParser = new PixelParserRle(bhi, colorTable, imageData);
break;
case BI_RGB:
pixelParser = new PixelParserRgb(bhi, colorTable, imageData);
break;
case BI_BITFIELDS:
pixelParser = new PixelParserBitFields(bhi, colorTable, imageData);
break;
default:
throw new ImagingException("BMP: Unknown Compression: "
+ bhi.compression);
}
return new BmpImageContents(bhi, colorTable, imageData, pixelParser);
}