private BmpImageContents readImageContents()

in src/main/java/org/apache/commons/imaging/formats/bmp/BmpImageParser.java [453:617]


    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.
        final 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 || extraBytes > bhi.fileSize) {
            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);
        }

        final 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);
        }

        final AbstractPixelParser abstractPixelParser;
        switch (bhi.compression) {
        case BI_RLE4:
        case BI_RLE8:
            abstractPixelParser = new PixelParserRle(bhi, colorTable, imageData);
            break;
        case BI_RGB:
            abstractPixelParser = new PixelParserRgb(bhi, colorTable, imageData);
            break;
        case BI_BITFIELDS:
            abstractPixelParser = new PixelParserBitFields(bhi, colorTable, imageData);
            break;
        default:
            throw new ImagingException("BMP: Unknown Compression: " + bhi.compression);
        }

        return new BmpImageContents(bhi, colorTable, imageData, abstractPixelParser);
    }