diff --git a/pom.xml b/pom.xml index 9d73b1e..8491a8e 100644 --- a/pom.xml +++ b/pom.xml @@ -14,12 +14,28 @@ 2006 - 6 - 6 + 8 + 8 + + + junit + junit + 4.12 + test + + + ${basedir}/src + ${basedir}/test + + + + ${basedir}/test-resources + + diff --git a/src/net/sf/image4j/codec/bmp/BMPDecoder.java b/src/net/sf/image4j/codec/bmp/BMPDecoder.java index db0f206..d9bcab4 100644 --- a/src/net/sf/image4j/codec/bmp/BMPDecoder.java +++ b/src/net/sf/image4j/codec/bmp/BMPDecoder.java @@ -47,7 +47,7 @@ public BMPDecoder(java.io.InputStream in) throws IOException { //DataOffset [4] file offset to raster data int dataOffset = lis.readIntLE(); - /* info header [40] */ + /* info header */ infoHeader = readInfoHeader(lis); @@ -264,7 +264,7 @@ public static BufferedImage read1(InfoHeader infoHeader, int padBits = bitsPerLine - dataBitsPerLine; int padBytes = padBits / 8; - int bytesPerLine = (int) (bitsPerLine / 8); + int bytesPerLine = (infoHeader.iWidth + 31)/32 * 4; int[] line = new int[bytesPerLine]; for (int y = infoHeader.iHeight - 1; y >= 0; y--) { diff --git a/src/net/sf/image4j/codec/bmp/InfoHeader.java b/src/net/sf/image4j/codec/bmp/InfoHeader.java index d77fffb..019731b 100644 --- a/src/net/sf/image4j/codec/bmp/InfoHeader.java +++ b/src/net/sf/image4j/codec/bmp/InfoHeader.java @@ -99,11 +99,14 @@ public InfoHeader(net.sf.image4j.io.LittleEndianInputStream in, int infoSize) th protected void init(net.sf.image4j.io.LittleEndianInputStream in, int infoSize) throws IOException { this.iSize = infoSize; + // Only 40-byte header is read. If actual header is longer, just skip the rest + int ntHeaderSize = 40; + //Width iWidth = in.readIntLE(); //Height iHeight = in.readIntLE(); - //Planes (=1) + //Planes sPlanes = in.readShortLE(); //Bit count sBitCount = in.readShortLE(); @@ -123,13 +126,18 @@ protected void init(net.sf.image4j.io.LittleEndianInputStream in, int infoSize) iColorsUsed = in.readIntLE(); //Colors important - number of important colors 0 = all iColorsImportant = in.readIntLE(); + + if(iSize > ntHeaderSize){ + in.skipBytes(infoSize - ntHeaderSize); + } + } /** * Creates an InfoHeader with default values. */ public InfoHeader() { - //Size of InfoHeader structure = 40 + //Size of InfoHeader structure = 40 for Windows NT BITMAPINFOHEADER, see Wikipedia iSize = 40; //Width iWidth = 0; diff --git a/test-resources/monochrome.bmp b/test-resources/monochrome.bmp new file mode 100644 index 0000000..222e819 Binary files /dev/null and b/test-resources/monochrome.bmp differ diff --git a/test/net/sf/image4j/codec/bmp/BMPDecoderTest.java b/test/net/sf/image4j/codec/bmp/BMPDecoderTest.java new file mode 100644 index 0000000..c608585 --- /dev/null +++ b/test/net/sf/image4j/codec/bmp/BMPDecoderTest.java @@ -0,0 +1,57 @@ +package net.sf.image4j.codec.bmp; + +import static org.junit.Assert.*; + +import java.awt.image.BufferedImage; +import java.awt.image.Raster; +import java.io.InputStream; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.BlockJUnit4ClassRunner; + +@RunWith(BlockJUnit4ClassRunner.class) +public class BMPDecoderTest { + + InputStream is; + + String filename = "/monochrome.bmp"; + + @Before + public void setUp() throws Exception { + is = getClass().getResourceAsStream(filename); + } + + @After + public void tearDown() throws Exception { + if (is != null) { + is.close(); + } + } + + @Test + public void testMonochromeImage() throws Exception { + assertNotNull("Test file missing", + getClass().getResource(filename)); + BufferedImage image = BMPDecoder.read(is); + + assertEquals("Wrong width", 4, image.getWidth()); + assertEquals("Wrong height", 8, image.getHeight()); + assertEquals("Wrong image type", BufferedImage.TYPE_BYTE_BINARY, image.getType()); + + Raster raster = image.getRaster(); + assertEquals("Wrong number of bands", 1, raster.getNumBands()); + for (int x = 0; x < image.getWidth(); ++x) { + for (int y = 0; y < image.getHeight(); ++y) { + if (x == y) { + assertEquals("Wrong pixel on the main diagonal", 1, raster.getSample(x, y, 0)); + } else { + assertEquals("Wrong pixel outside the main diagonal", 0, raster.getSample(x, y, 0)); + } + } + } + } + +}