TMI-BMP: Support for more versions of BMP format
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 195 KiB |
|
After Width: | Height: | Size: 195 KiB |
|
After Width: | Height: | Size: 195 KiB |
|
After Width: | Height: | Size: 195 KiB |
|
After Width: | Height: | Size: 292 KiB |
|
After Width: | Height: | Size: 389 KiB |
|
After Width: | Height: | Size: 389 KiB |
|
After Width: | Height: | Size: 389 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 49 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 63 KiB |
|
After Width: | Height: | Size: 99 KiB |
|
After Width: | Height: | Size: 74 KiB |
|
After Width: | Height: | Size: 99 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 257 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 8.4 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 8.6 KiB |
|
After Width: | Height: | Size: 273 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 4.1 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 9.1 KiB |
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 5.0 KiB |
|
After Width: | Height: | Size: 8.8 KiB |
|
After Width: | Height: | Size: 8.6 KiB |
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 9.1 KiB |
|
After Width: | Height: | Size: 9.1 KiB |
|
After Width: | Height: | Size: 8.4 KiB |
|
After Width: | Height: | Size: 8.8 KiB |
|
After Width: | Height: | Size: 8.9 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 9.1 KiB |
|
After Width: | Height: | Size: 8.8 KiB |
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 9.1 KiB |
|
After Width: | Height: | Size: 9.2 KiB |
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
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 |
|
After Width: | Height: | Size: 326 B |
|
After Width: | Height: | Size: 326 B |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 113 KiB |
|
After Width: | Height: | Size: 149 KiB |
|
After Width: | Height: | Size: 766 B |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 456 KiB |
|
After Width: | Height: | Size: 153 KiB |