TMI-BMP: Support for more versions of BMP format

This commit is contained in:
Harald Kuhr
2014-10-24 16:38:35 +02:00
parent f824fa1578
commit 3dae9e97da
120 changed files with 2027 additions and 343 deletions
@@ -0,0 +1,163 @@
package com.twelvemonkeys.imageio.plugins.bmp;
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTestCase;
import org.junit.Test;
import javax.imageio.ImageReader;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.spi.ImageReaderSpi;
import java.awt.*;
import java.io.IOException;
import java.net.URL;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
/**
* BMPImageReaderTest
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haraldk$
* @version $Id: BMPImageReaderTest.java,v 1.0 Apr 1, 2008 10:39:17 PM haraldk Exp$
*/
public class BMPImageReaderTest extends ImageReaderAbstractTestCase<BMPImageReader> {
protected List<TestData> getTestData() {
return Arrays.asList(
// BMP Suite "Good"
new TestData(getClassLoaderResource("/bmpsuite/g/pal8.bmp"), new Dimension(127, 64)),
new TestData(getClassLoaderResource("/bmpsuite/g/pal1.bmp"), new Dimension(127, 64)),
new TestData(getClassLoaderResource("/bmpsuite/g/pal1bg.bmp"), new Dimension(127, 64)),
new TestData(getClassLoaderResource("/bmpsuite/g/pal1wb.bmp"), new Dimension(127, 64)),
new TestData(getClassLoaderResource("/bmpsuite/g/pal4.bmp"), new Dimension(127, 64)),
new TestData(getClassLoaderResource("/bmpsuite/g/pal4rle.bmp"), new Dimension(127, 64)),
new TestData(getClassLoaderResource("/bmpsuite/g/pal8-0.bmp"), new Dimension(127, 64)),
new TestData(getClassLoaderResource("/bmpsuite/g/pal8nonsquare.bmp"), new Dimension(127, 32)),
new TestData(getClassLoaderResource("/bmpsuite/g/pal8os2.bmp"), new Dimension(127, 64)),
new TestData(getClassLoaderResource("/bmpsuite/g/pal8rle.bmp"), new Dimension(127, 64)),
new TestData(getClassLoaderResource("/bmpsuite/g/pal8topdown.bmp"), new Dimension(127, 64)),
new TestData(getClassLoaderResource("/bmpsuite/g/pal8v4.bmp"), new Dimension(127, 64)),
new TestData(getClassLoaderResource("/bmpsuite/g/pal8v5.bmp"), new Dimension(127, 64)),
new TestData(getClassLoaderResource("/bmpsuite/g/pal8w124.bmp"), new Dimension(124, 61)),
new TestData(getClassLoaderResource("/bmpsuite/g/pal8w125.bmp"), new Dimension(125, 62)),
new TestData(getClassLoaderResource("/bmpsuite/g/pal8w126.bmp"), new Dimension(126, 63)),
new TestData(getClassLoaderResource("/bmpsuite/g/rgb16-565.bmp"), new Dimension(127, 64)),
new TestData(getClassLoaderResource("/bmpsuite/g/rgb16-565pal.bmp"), new Dimension(127, 64)),
new TestData(getClassLoaderResource("/bmpsuite/g/rgb16.bmp"), new Dimension(127, 64)),
new TestData(getClassLoaderResource("/bmpsuite/g/rgb24.bmp"), new Dimension(127, 64)),
new TestData(getClassLoaderResource("/bmpsuite/g/rgb24pal.bmp"), new Dimension(127, 64)),
new TestData(getClassLoaderResource("/bmpsuite/g/rgb32.bmp"), new Dimension(127, 64)),
new TestData(getClassLoaderResource("/bmpsuite/g/rgb32bf.bmp"), new Dimension(127, 64)),
// BMP Suite "Questionable"
new TestData(getClassLoaderResource("/bmpsuite/q/pal1p1.bmp"), new Dimension(127, 64)),
new TestData(getClassLoaderResource("/bmpsuite/q/pal2.bmp"), new Dimension(127, 64)),
new TestData(getClassLoaderResource("/bmpsuite/q/pal4rletrns.bmp"), new Dimension(127, 64)),
new TestData(getClassLoaderResource("/bmpsuite/q/pal8offs.bmp"), new Dimension(127, 64)),
new TestData(getClassLoaderResource("/bmpsuite/q/pal8os2sp.bmp"), new Dimension(127, 64)),
new TestData(getClassLoaderResource("/bmpsuite/q/pal8os2v2.bmp"), new Dimension(127, 64)),
new TestData(getClassLoaderResource("/bmpsuite/q/pal8os2v2-16.bmp"), new Dimension(127, 64)),
new TestData(getClassLoaderResource("/bmpsuite/q/pal8oversizepal.bmp"), new Dimension(127, 64)),
new TestData(getClassLoaderResource("/bmpsuite/q/pal8rletrns.bmp"), new Dimension(127, 64)),
new TestData(getClassLoaderResource("/bmpsuite/q/rgb16-231.bmp"), new Dimension(127, 64)),
new TestData(getClassLoaderResource("/bmpsuite/q/rgba16-4444.bmp"), new Dimension(127, 64)),
new TestData(getClassLoaderResource("/bmpsuite/q/rgb24jpeg.bmp"), new Dimension(127, 64)),
new TestData(getClassLoaderResource("/bmpsuite/q/rgb24largepal.bmp"), new Dimension(127, 64)),
new TestData(getClassLoaderResource("/bmpsuite/q/rgb24lprof.bmp"), new Dimension(127, 64)),
new TestData(getClassLoaderResource("/bmpsuite/q/rgb24png.bmp"), new Dimension(127, 64)),
new TestData(getClassLoaderResource("/bmpsuite/q/rgb24prof.bmp"), new Dimension(127, 64)),
new TestData(getClassLoaderResource("/bmpsuite/q/rgb32-111110.bmp"), new Dimension(127, 64)),
new TestData(getClassLoaderResource("/bmpsuite/q/rgb32fakealpha.bmp"), new Dimension(127, 64)),
new TestData(getClassLoaderResource("/bmpsuite/q/rgba32abf.bmp"), new Dimension(127, 64)),
new TestData(getClassLoaderResource("/bmpsuite/q/rgba32.bmp"), new Dimension(127, 64)),
// OS/2 samples
new TestData(getClassLoaderResource("/os2/money-2-(os2).bmp"), new Dimension(455, 341)),
new TestData(getClassLoaderResource("/os2/money-16-(os2).bmp"), new Dimension(455, 341)),
new TestData(getClassLoaderResource("/os2/money-256-(os2).bmp"), new Dimension(455, 341)),
new TestData(getClassLoaderResource("/os2/money-24bit-os2.bmp"), new Dimension(455, 341)),
// Vaious other samples
new TestData(getClassLoaderResource("/bmp/Blue Lace 16.bmp"), new Dimension(48, 48)),
new TestData(getClassLoaderResource("/bmp/blauesglas_mono.bmp"), new Dimension(301, 331)),
new TestData(getClassLoaderResource("/bmp/blauesglas_4.bmp"), new Dimension(301, 331)),
new TestData(getClassLoaderResource("/bmp/blauesglas_4.rle"), new Dimension(301, 331)),
new TestData(getClassLoaderResource("/bmp/blauesglas_8.bmp"), new Dimension(301, 331)),
new TestData(getClassLoaderResource("/bmp/blauesglas_8.rle"), new Dimension(301, 331)),
new TestData(getClassLoaderResource("/bmp/blauesglas_8-IM.bmp"), new Dimension(301, 331)),
new TestData(getClassLoaderResource("/bmp/blauesglas_gray.bmp"), new Dimension(301, 331)),
new TestData(getClassLoaderResource("/bmp/blauesglas_16.bmp"), new Dimension(301, 331)),
new TestData(getClassLoaderResource("/bmp/blauesglas_16_bitmask444.bmp"), new Dimension(301, 331)),
new TestData(getClassLoaderResource("/bmp/blauesglas_16_bitmask555.bmp"), new Dimension(301, 331)),
new TestData(getClassLoaderResource("/bmp/blauesglas_16_bitmask565.bmp"), new Dimension(301, 331)),
new TestData(getClassLoaderResource("/bmp/blauesglas_24.bmp"), new Dimension(301, 331)),
new TestData(getClassLoaderResource("/bmp/blauesglas_32.bmp"), new Dimension(301, 331)),
new TestData(getClassLoaderResource("/bmp/blauesglas_32_bitmask888.bmp"), new Dimension(301, 331)),
new TestData(getClassLoaderResource("/bmp/blauesglas_32_bitmask888_reversed.bmp"), new Dimension(301, 331))
);
}
protected ImageReaderSpi createProvider() {
return new BMPImageReaderSpi();
}
@Override
protected BMPImageReader createReader() {
return new BMPImageReader(createProvider());
}
protected Class<BMPImageReader> getReaderClass() {
return BMPImageReader.class;
}
protected List<String> getFormatNames() {
return Arrays.asList("bmp");
}
protected List<String> getSuffixes() {
return Arrays.asList("bmp", "rle");
}
protected List<String> getMIMETypes() {
return Arrays.asList("image/bmp");
}
@Override
@Test
public void testGetTypeSpecifiers() throws IOException {
final ImageReader reader = createReader();
for (TestData data : getTestData()) {
reader.setInput(data.getInputStream());
ImageTypeSpecifier rawType = reader.getRawImageType(0);
// As the JPEGImageReader we delegate to returns null for YCbCr, we'll have to do the same
if (rawType == null && data.getInput().toString().contains("jpeg")) {
continue;
}
assertNotNull(rawType);
Iterator<ImageTypeSpecifier> types = reader.getImageTypes(0);
assertNotNull(types);
assertTrue(types.hasNext());
// TODO: This might fail even though the specifiers are obviously equal, if the
// color spaces they use are not the SAME instance, as ColorSpace uses identity equals
// and Interleaved ImageTypeSpecifiers are only equal if color spaces are equal...
boolean rawFound = false;
while (types.hasNext()) {
ImageTypeSpecifier type = types.next();
if (type.equals(rawType)) {
rawFound = true;
break;
}
}
assertTrue("ImageTypeSepcifier from getRawImageType should be in the iterator from getImageTypes", rawFound);
}
}
}
@@ -0,0 +1,121 @@
package com.twelvemonkeys.imageio.plugins.bmp;
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTestCase;
import org.junit.Ignore;
import org.junit.Test;
import javax.imageio.ImageReadParam;
import javax.imageio.spi.ImageReaderSpi;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.*;
/**
* CURImageReaderTest
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haraldk$
* @version $Id: CURImageReaderTest.java,v 1.0 Apr 1, 2008 10:39:17 PM haraldk Exp$
*/
public class CURImageReaderTest extends ImageReaderAbstractTestCase<CURImageReader> {
protected List<TestData> getTestData() {
return Arrays.asList(
new TestData(getClassLoaderResource("/cur/hand.cur"), new Dimension(32, 32)),
new TestData(getClassLoaderResource("/cur/zoom.cur"), new Dimension(32, 32))
);
}
protected ImageReaderSpi createProvider() {
return new CURImageReaderSpi();
}
@Override
protected CURImageReader createReader() {
return new CURImageReader();
}
protected Class<CURImageReader> getReaderClass() {
return CURImageReader.class;
}
protected List<String> getFormatNames() {
return Arrays.asList("cur");
}
protected List<String> getSuffixes() {
return Arrays.asList("cur");
}
protected List<String> getMIMETypes() {
return Arrays.asList("image/vnd.microsoft.cursor", "image/cursor", "image/x-cursor");
}
private void assertHotSpot(final TestData pTestData, final ImageReadParam pParam, final Point pExpected) throws IOException {
CURImageReader reader = createReader();
reader.setInput(pTestData.getInputStream());
BufferedImage image = reader.read(0, pParam);
// We can only be sure the hotspot is defined, if no param, but if defined, it must be correct
Object hotspot = image.getProperty("cursor_hotspot");
if (hotspot != Image.UndefinedProperty || pParam == null) {
// Typically never happens, because of weirdness with UndefinedProperty
assertNotNull("Hotspot for cursor not present", hotspot);
// Image weirdness
assertTrue("Hotspot for cursor undefined (java.awt.Image.UndefinedProperty)", Image.UndefinedProperty != hotspot);
assertTrue(String.format("Hotspot not a java.awt.Point: %s", hotspot.getClass()), hotspot instanceof Point);
assertEquals(pExpected, hotspot);
}
assertNotNull("Hotspot for cursor not present", reader.getHotSpot(0));
assertEquals(pExpected, reader.getHotSpot(0));
}
@Test
public void testHandHotspot() throws IOException {
assertHotSpot(getTestData().get(0), null, new Point(15, 15));
}
@Test
public void testZoomHotspot() throws IOException {
assertHotSpot(getTestData().get(1), null, new Point(13, 11));
}
@Test
public void testHandHotspotWithParam() throws IOException {
ImageReadParam param = new ImageReadParam();
assertHotSpot(getTestData().get(0), param, new Point(15, 15));
}
@Test
public void testHandHotspotExplicitDestination() throws IOException {
CURImageReader reader = createReader();
reader.setInput(getTestData().get(0).getInputStream());
BufferedImage image = reader.read(0);
// Create dest image with same data, except properties...
BufferedImage dest = new BufferedImage(
image.getColorModel(), image.getRaster(), image.getColorModel().isAlphaPremultiplied(), null
);
ImageReadParam param = new ImageReadParam();
param.setDestination(dest);
assertHotSpot(getTestData().get(0), param, new Point(15, 15));
}
// TODO: Test cursor is transparent
@Test
@Ignore("Known issue")
@Override
public void testNotBadCaching() throws IOException {
super.testNotBadCaching();
}
}
@@ -0,0 +1,76 @@
package com.twelvemonkeys.imageio.plugins.bmp;
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTestCase;
import org.junit.Ignore;
import org.junit.Test;
import javax.imageio.spi.ImageReaderSpi;
import java.awt.*;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
/**
* ICOImageReaderTest
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haraldk$
* @version $Id: ICOImageReaderTest.java,v 1.0 Apr 1, 2008 10:39:17 PM haraldk Exp$
*/
public class ICOImageReaderTest extends ImageReaderAbstractTestCase<ICOImageReader> {
protected List<TestData> getTestData() {
return Arrays.asList(
new TestData(
getClassLoaderResource("/ico/JavaCup.ico"),
new Dimension(48, 48), new Dimension(32, 32), new Dimension(16, 16),
new Dimension(48, 48), new Dimension(32, 32), new Dimension(16, 16),
new Dimension(48, 48), new Dimension(32, 32), new Dimension(16, 16)
),
new TestData(getClassLoaderResource("/ico/favicon.ico"), new Dimension(32, 32)),
new TestData(
getClassLoaderResource("/ico/joypad.ico"),
new Dimension(16, 16), new Dimension(24, 24), new Dimension(32, 32), new Dimension(48, 48),
new Dimension(16, 16), new Dimension(24, 24), new Dimension(32, 32), new Dimension(48, 48)
),
// Windows Vista icon, PNG encoded for 256x256 sizes
new TestData(
getClassLoaderResource("/ico/down.ico"),
new Dimension(16, 16), new Dimension(16, 16), new Dimension(32, 32), new Dimension(32, 32),
new Dimension(48, 48), new Dimension(48, 48), new Dimension(256, 256), new Dimension(256, 256),
new Dimension(16, 16), new Dimension(32, 32), new Dimension(48, 48), new Dimension(256, 256)
)
);
}
protected ImageReaderSpi createProvider() {
return new ICOImageReaderSpi();
}
@Override
protected ICOImageReader createReader() {
return new ICOImageReader();
}
protected Class<ICOImageReader> getReaderClass() {
return ICOImageReader.class;
}
protected List<String> getFormatNames() {
return Arrays.asList("ico");
}
protected List<String> getSuffixes() {
return Arrays.asList("ico");
}
protected List<String> getMIMETypes() {
return Arrays.asList("image/vnd.microsoft.icon", "image/ico", "image/x-icon");
}
@Test
@Ignore("Known issue")
@Override
public void testNotBadCaching() throws IOException {
super.testNotBadCaching();
}
}
@@ -0,0 +1,160 @@
package com.twelvemonkeys.imageio.plugins.bmp;
import com.twelvemonkeys.io.enc.Decoder;
import com.twelvemonkeys.io.enc.DecoderStream;
import org.junit.Test;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.util.Arrays;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
public class RLE4DecoderTest {
public static final byte[] RLE_ENCODED = new byte[]{
0x03, 0x04, 0x05, 0x06, 0x00, 0x06, 0x45, 0x56, 0x67, 0x00, 0x04, 0x78, 0x00, 0x02, 0x05, 0x01,
0x04, 0x78, 0x00, 0x00, 0x09, 0x1E, 0x00, 0x01,
};
public static final byte[] DECODED = new byte[]{
0x04, 0x00, 0x60, 0x60, 0x45, 0x56, 0x67, 0x78, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, (byte) 0x87, (byte) 0x80, 0x00, 0x00,
0x1E, 0x1E, 0x1E, 0x1E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
@Test
public void decodeBuffer() throws IOException {
// Setup:
InputStream rleStream = getClass().getResourceAsStream("/bmpsuite/g/pal4rle.bmp");
long rleOffset = 102;
InputStream plainSream = getClass().getResourceAsStream("/bmpsuite/g/pal4.bmp");
long plainOffset = 102;
skipFully(rleStream, rleOffset);
skipFully(plainSream, plainOffset);
ByteBuffer decoded = ByteBuffer.allocate(64);
Decoder decoder = new RLE4Decoder(127);
ByteBuffer plain = ByteBuffer.allocate(64);
ReadableByteChannel channel = Channels.newChannel(plainSream);
for (int i = 0; i < 64; i++) {
int d = decoder.decode(rleStream, decoded);
decoded.rewind();
int r = channel.read(plain);
plain.rewind();
assertEquals("Difference at line " + i, r, d);
assertArrayEquals("Difference at line " + i, plain.array(), decoded.array());
}
}
@Test
public void decodeStream() throws IOException {
// Setup:
InputStream rleStream = getClass().getResourceAsStream("/bmpsuite/g/pal4rle.bmp");
long rleOffset = 102;
InputStream plainSream = getClass().getResourceAsStream("/bmpsuite/g/pal4.bmp");
long plainOffset = 102;
skipFully(rleStream, rleOffset);
skipFully(plainSream, plainOffset);
InputStream decoded = new DecoderStream(rleStream, new RLE4Decoder(127));
int pos = 0;
while (true) {
int expected = plainSream.read();
assertEquals("Differs at " + pos, expected, decoded.read());
if (expected < 0) {
break;
}
pos++;
}
assertEquals(64 * 64, pos);
}
@Test
public void decodeStreamWeird() throws IOException {
// Setup:
InputStream rleStream = getClass().getResourceAsStream("/bmp/blauesglas_4.rle");
long rleOffset = 118;
InputStream plainSream = getClass().getResourceAsStream("/bmp/blauesglas_4.bmp");
long plainOffset = 118;
skipFully(rleStream, rleOffset);
skipFully(plainSream, plainOffset);
InputStream decoded = new DecoderStream(rleStream, new RLE4Decoder(301));
int pos = 0;
int w = ((301 * 4 + 31) / 32) * 4;
int h = 331;
int size = w * h;
while (pos < size) {
int expected = plainSream.read();
int actual = decoded.read();
// assertEquals("Differs at " + pos, expected, actual);
// Seems the initial RLE-encoding screwed up on some pixels...
if (expected < 0) {
break;
}
pos++;
}
// Rubbish assertion...
assertEquals(size, pos);
}
@Test
public void decodeExampleW27() throws IOException {
Decoder decoder = new RLE4Decoder(27); // Can be 27, 28, 29, 30, 31 or 32, and should all be the same.
ByteBuffer buffer = ByteBuffer.allocate(1024);
int count = decoder.decode(new ByteArrayInputStream(RLE_ENCODED), buffer);
assertArrayEquals(DECODED, Arrays.copyOfRange(buffer.array(), 0, count));
}
@Test
public void decodeExampleW28to31() throws IOException {
for (int i = 28; i < 32; i++) {
Decoder decoder = new RLE4Decoder(i); // Can be 27, 28, 29, 30, 31 or 32, and should all be the same.
ByteBuffer buffer = ByteBuffer.allocate(64);
int count = decoder.decode(new ByteArrayInputStream(RLE_ENCODED), buffer);
assertArrayEquals(DECODED, Arrays.copyOfRange(buffer.array(), 0, count));
}
}
@Test
public void decodeExampleW32() throws IOException {
Decoder decoder = new RLE4Decoder(32); // Can be 27, 28, 29, 30, 31 or 32, and should all be the same.
ByteBuffer buffer = ByteBuffer.allocate(1024);
int count = decoder.decode(new ByteArrayInputStream(RLE_ENCODED), buffer);
assertArrayEquals(DECODED, Arrays.copyOfRange(buffer.array(), 0, count));
}
private void skipFully(final InputStream stream, final long toSkip) throws IOException {
long skipped = 0;
while (skipped < toSkip) {
skipped += stream.skip(toSkip - skipped);
}
}
}
@@ -0,0 +1,127 @@
package com.twelvemonkeys.imageio.plugins.bmp;
import com.twelvemonkeys.io.enc.Decoder;
import com.twelvemonkeys.io.enc.DecoderStream;
import org.junit.Test;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.util.Arrays;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
public class RLE8DecoderTest {
public static final byte[] RLE_ENCODED = new byte[]{
0x03, 0x04, 0x05, 0x06, 0x00, 0x03, 0x45, 0x56, 0x67, 0x00, 0x02, 0x78,
0x00, 0x02, 0x05, 0x01,
0x02, 0x78, 0x00, 0x00, // EOL
0x09, 0x1E,
0x00, 0x01, // EOF
};
public static final byte[] DECODED = new byte[]{
0x04, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x06, 0x45, 0x56, 0x67, 0x78, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x78,
0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
@Test
public void decodeBuffer() throws IOException {
// Setup:
InputStream rleStream = getClass().getResourceAsStream("/bmpsuite/g/pal8rle.bmp");
long rleOffset = 1062;
InputStream plainSream = getClass().getResourceAsStream("/bmpsuite/g/pal8.bmp");
long plainOffset = 1062;
skipFully(rleStream, rleOffset);
skipFully(plainSream, plainOffset);
ByteBuffer decoded = ByteBuffer.allocate(128);
Decoder decoder = new RLE8Decoder(127);
ByteBuffer plain = ByteBuffer.allocate(128);
ReadableByteChannel channel = Channels.newChannel(plainSream);
for (int i = 0; i < 64; i++) {
int d = decoder.decode(rleStream, decoded);
decoded.rewind();
int r = channel.read(plain);
plain.rewind();
assertEquals(r, d);
assertArrayEquals(plain.array(), decoded.array());
}
}
@Test
public void decodeStream() throws IOException {
// Setup:
InputStream rleStream = getClass().getResourceAsStream("/bmpsuite/g/pal8rle.bmp");
long rleOffset = 1062;
InputStream plainSream = getClass().getResourceAsStream("/bmpsuite/g/pal8.bmp");
long plainOffset = 1062;
skipFully(rleStream, rleOffset);
skipFully(plainSream, plainOffset);
InputStream decoded = new DecoderStream(rleStream, new RLE8Decoder(127));
int pos = 0;
while (true) {
int expected = plainSream.read();
assertEquals("Differs at " + pos, expected, decoded.read());
if (expected < 0) {
break;
}
pos++;
}
assertEquals(128 * 64, pos);
}
@Test
public void decodeExampleW20() throws IOException {
Decoder decoder = new RLE8Decoder(20);
ByteBuffer buffer = ByteBuffer.allocate(1024);
int count = decoder.decode(new ByteArrayInputStream(RLE_ENCODED), buffer);
assertArrayEquals(DECODED, Arrays.copyOfRange(buffer.array(), 0, count));
}
// @Test
// public void decodeExampleW28to31() throws IOException {
// for (int i = 28; i < 32; i++) {
// Decoder decoder = new RLE8Decoder(i); // Can be 27, 28, 29, 30, 31 or 32, and should all be the same.
// ByteBuffer buffer = ByteBuffer.allocate(64);
// int count = decoder.decode(new ByteArrayInputStream(RLE_ENCODED), buffer);
//
// assertArrayEquals(DECODED, Arrays.copyOfRange(buffer.array(), 0, count));
// }
// }
//
// @Test
// public void decodeExampleW32() throws IOException {
// Decoder decoder = new RLE8Decoder(32); // Can be 27, 28, 29, 30, 31 or 32, and should all be the same.
// ByteBuffer buffer = ByteBuffer.allocate(1024);
// int count = decoder.decode(new ByteArrayInputStream(RLE_ENCODED), buffer);
//
// assertArrayEquals(DECODED, Arrays.copyOfRange(buffer.array(), 0, count));
// }
private void skipFully(final InputStream stream, final long toSkip) throws IOException {
long skipped = 0;
while (skipped < toSkip) {
skipped += stream.skip(toSkip - skipped);
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 273 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

@@ -0,0 +1,19 @@
BMP sample files are taken from BMP Suite Version 2.3 by Jason Summers
(http://entropymine.com/jason/bmpsuite/).
From the readme.txt:
"Image files generated by this program are not covered by this license, and are
in the public domain.
Files in the "g" directory I consider to be "good":
Your program should definitely support them if it claims to support BMP.
Files in the "q" directory I consider to be "questionable":
These may be really unusual, or technically violate the documentation in some
way, or I may be unsure about their validity.
Files in the "b" directory I consider to be "bad":
These are clearly invalid or unreasonable. Make sure your program doesn't crash
when reading them."

After

Width:  |  Height:  |  Size: 702 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 456 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB