From 990a0d3e7d59029a96d720aac578945d14d55baa Mon Sep 17 00:00:00 2001 From: Sam Judd Date: Sat, 18 Oct 2014 10:52:58 -0700 Subject: Add tests for local color tables in gif parser. --- .../glide/gifdecoder/GifHeaderParserTest.java | 81 +++++++++++++++++++++- .../glide/gifdecoder/test/GifBytesTestUtil.java | 39 ++++++++++- .../gifdecoder/test/GifBytesTestUtilTest.java | 70 ++++++++++++++++++- 3 files changed, 181 insertions(+), 9 deletions(-) (limited to 'third_party/gif_decoder/src/androidTest') diff --git a/third_party/gif_decoder/src/androidTest/java/com/bumptech/glide/gifdecoder/GifHeaderParserTest.java b/third_party/gif_decoder/src/androidTest/java/com/bumptech/glide/gifdecoder/GifHeaderParserTest.java index ca9879f2..3433153e 100644 --- a/third_party/gif_decoder/src/androidTest/java/com/bumptech/glide/gifdecoder/GifHeaderParserTest.java +++ b/third_party/gif_decoder/src/androidTest/java/com/bumptech/glide/gifdecoder/GifHeaderParserTest.java @@ -13,6 +13,7 @@ import java.nio.ByteOrder; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; /** * Tests for {@link com.bumptech.glide.gifdecoder.GifHeaderParser}. @@ -62,10 +63,58 @@ public class GifHeaderParserTest { @Test public void testCanReadImageDescriptorWithoutGraphicalExtension() { - ByteBuffer buffer = ByteBuffer.allocate(GifBytesTestUtil.HEADER_LENGTH - + GifBytesTestUtil.IMAGE_DESCRIPTOR_LENGTH + 4).order(ByteOrder.LITTLE_ENDIAN); + final int lzwMinCodeSize = 2; + ByteBuffer buffer = ByteBuffer.allocate( + GifBytesTestUtil.HEADER_LENGTH + + GifBytesTestUtil.IMAGE_DESCRIPTOR_LENGTH + + GifBytesTestUtil.getImageDataSize(lzwMinCodeSize) + ).order(ByteOrder.LITTLE_ENDIAN); GifBytesTestUtil.writeHeaderAndLsd(buffer, 1, 1, false, 0); - GifBytesTestUtil.writeImageDescriptor(buffer, 0, 0, 1, 1); + GifBytesTestUtil.writeImageDescriptor(buffer, 0, 0, 1, 1, false /*hasLct*/, 0); + GifBytesTestUtil.writeFakeImageData(buffer, lzwMinCodeSize); + + parser.setData(buffer.array()); + GifHeader header = parser.parseHeader(); + assertEquals(1, header.width); + assertEquals(1, header.height); + assertEquals(1, header.frameCount); + assertNotNull(header.frames.get(0)); + } + + @Test + public void testSetsFrameLocalColorTableToNullIfNoColorTable() { + final int lzwMinCodeSize = 2; + ByteBuffer buffer = ByteBuffer.allocate( + GifBytesTestUtil.HEADER_LENGTH + + GifBytesTestUtil.IMAGE_DESCRIPTOR_LENGTH + + GifBytesTestUtil.getImageDataSize(lzwMinCodeSize) + ).order(ByteOrder.LITTLE_ENDIAN); + GifBytesTestUtil.writeHeaderAndLsd(buffer, 1, 1, false, 0); + GifBytesTestUtil.writeImageDescriptor(buffer, 0, 0, 1, 1, false /*hasLct*/, 0); + GifBytesTestUtil.writeFakeImageData(buffer, lzwMinCodeSize); + + parser.setData(buffer.array()); + GifHeader header = parser.parseHeader(); + assertEquals(1, header.width); + assertEquals(1, header.height); + assertEquals(1, header.frameCount); + assertNotNull(header.frames.get(0)); + assertNull(header.frames.get(0).lct); + } + + @Test + public void testSetsFrameLocalColorTableIfHasColorTable() { + final int lzwMinCodeSize = 2; + final int numColors = 4; + ByteBuffer buffer = ByteBuffer.allocate( + GifBytesTestUtil.HEADER_LENGTH + + GifBytesTestUtil.IMAGE_DESCRIPTOR_LENGTH + + GifBytesTestUtil.getImageDataSize(lzwMinCodeSize) + + GifBytesTestUtil.getColorTableLength(numColors) + ).order(ByteOrder.LITTLE_ENDIAN); + GifBytesTestUtil.writeHeaderAndLsd(buffer, 1, 1, false, 0); + GifBytesTestUtil.writeImageDescriptor(buffer, 0, 0, 1, 1, true /*hasLct*/, numColors); + GifBytesTestUtil.writeColorTable(buffer, numColors); GifBytesTestUtil.writeFakeImageData(buffer, 2); parser.setData(buffer.array()); @@ -74,6 +123,32 @@ public class GifHeaderParserTest { assertEquals(1, header.height); assertEquals(1, header.frameCount); assertNotNull(header.frames.get(0)); + + GifFrame frame = header.frames.get(0); + assertNotNull(frame.lct); + } + + @Test + public void testCanParseMultipleFrames() { + final int lzwMinCodeSize = 2; + final int expectedFrames = 3; + + final int frameSize = GifBytesTestUtil.IMAGE_DESCRIPTOR_LENGTH + + GifBytesTestUtil.getImageDataSize(lzwMinCodeSize); + ByteBuffer buffer = ByteBuffer.allocate( + GifBytesTestUtil.HEADER_LENGTH + expectedFrames * frameSize + ).order(ByteOrder.LITTLE_ENDIAN); + + GifBytesTestUtil.writeHeaderAndLsd(buffer, 1, 1, false, 0); + for (int i = 0; i < expectedFrames; i++) { + GifBytesTestUtil.writeImageDescriptor(buffer, 0, 0, 1, 1, false /*hasLct*/, 0 /*numColors*/); + GifBytesTestUtil.writeFakeImageData(buffer, 2); + } + + parser.setData(buffer.array()); + GifHeader header = parser.parseHeader(); + assertEquals(expectedFrames, header.frameCount); + assertEquals(expectedFrames, header.frames.size()); } private InputStream openResource(String imageName) throws IOException { diff --git a/third_party/gif_decoder/src/androidTest/java/com/bumptech/glide/gifdecoder/test/GifBytesTestUtil.java b/third_party/gif_decoder/src/androidTest/java/com/bumptech/glide/gifdecoder/test/GifBytesTestUtil.java index 97c3d4fa..e389deed 100644 --- a/third_party/gif_decoder/src/androidTest/java/com/bumptech/glide/gifdecoder/test/GifBytesTestUtil.java +++ b/third_party/gif_decoder/src/androidTest/java/com/bumptech/glide/gifdecoder/test/GifBytesTestUtil.java @@ -11,6 +11,15 @@ public class GifBytesTestUtil { // Length in bytes. public static final int IMAGE_DESCRIPTOR_LENGTH = 10; + public static int getColorTableLength(int numColors) { + return 3 * numColors; + } + + public static int getImageDataSize(int lzwMinCodeSize) { + // TODO: fill this out. + return 4; + } + public static void writeFakeImageData(ByteBuffer out, int lzwMinCodeSize) { // 1 for lzwMinCodeSize, 1 for length, 1 for min content, 1 for block terminator. verifyRemaining(out, 4); @@ -25,16 +34,40 @@ public class GifBytesTestUtil { out.put((byte) 0x00); } + public static void writeColorTable(ByteBuffer out, int numColors) { + verifyRemaining(out, getColorTableLength(numColors)); + for (int i = 0; i < numColors; i++) { + out.put((byte) (0xFF0000 & i)); + out.put((byte) (0x00FF00 & i)); + out.put((byte) (0x0000FF & i)); + } + } + public static void writeImageDescriptor(ByteBuffer out, int imageLeft, int imageTop, int imageWidth, - int imageHeight) { + int imageHeight, boolean hasLct, int numColors) { verifyRemaining(out, IMAGE_DESCRIPTOR_LENGTH); verifyShortValues(imageLeft, imageTop, imageWidth, imageHeight); + final byte packed; + if (hasLct) { + int size = log2(numColors) - 1; + packed = (byte) (0x80 | size); + } else { + packed = 0x00; + } + // Image separator out.put((byte) 0x2C); + out + .putShort((short) imageLeft) + .putShort((short) imageTop) + .putShort((short) imageWidth) + .putShort((short) imageHeight) + .put(packed); + } - out.putShort((short) imageLeft).putShort((short) imageTop).putShort((short) imageWidth) - .putShort((short) imageHeight); + private static int log2(int num) { + return (int) Math.round(Math.log(num) / Math.log(2)); } public static void writeHeaderAndLsd(ByteBuffer out, int width, int height, boolean hasGct, int gctSize) { diff --git a/third_party/gif_decoder/src/androidTest/java/com/bumptech/glide/gifdecoder/test/GifBytesTestUtilTest.java b/third_party/gif_decoder/src/androidTest/java/com/bumptech/glide/gifdecoder/test/GifBytesTestUtilTest.java index 7b25c96b..88106ea6 100644 --- a/third_party/gif_decoder/src/androidTest/java/com/bumptech/glide/gifdecoder/test/GifBytesTestUtilTest.java +++ b/third_party/gif_decoder/src/androidTest/java/com/bumptech/glide/gifdecoder/test/GifBytesTestUtilTest.java @@ -3,6 +3,7 @@ package com.bumptech.glide.gifdecoder.test; import org.junit.Test; import java.nio.ByteBuffer; +import java.util.Arrays; import static org.junit.Assert.assertArrayEquals; @@ -33,15 +34,78 @@ public class GifBytesTestUtilTest { } @Test - public void testWriteImageDescriptor() { + public void testWriteImageDescriptorWithoutColorTable() { ByteBuffer buffer = ByteBuffer.allocate(GifBytesTestUtil.IMAGE_DESCRIPTOR_LENGTH); - GifBytesTestUtil.writeImageDescriptor(buffer, 10, 9, 8, 7); + GifBytesTestUtil.writeImageDescriptor(buffer, 10, 9, 8, 7, false, 0); + + byte[] expected = new byte[] { + // Image separator. + 0x2C, + // Image left. + 0x00, 0x0A, + // Image right. + 0x00, 0X09, + // Image width. + 0x00, 0x08, + // Image height. + 0x00, 0x07, + // Packed field. + 0x00 + }; - byte[] expected = new byte[] { 0x2C, 0x00, 0x0A, 0x00, 0X09, 0x00, 0x08, 0x000, 0x07, 0x00 }; + assertArrayEquals(expected, buffer.array()); + } + + @Test + public void testWriteImageDescriptorWithColorTable() { + ByteBuffer buffer = ByteBuffer.allocate(GifBytesTestUtil.IMAGE_DESCRIPTOR_LENGTH); + GifBytesTestUtil.writeImageDescriptor(buffer, 10, 9, 8, 7, true, 4); + + byte packedField = + // Set LCT flag + (byte) 0x80 + // Size of color table (2^(N + 1) == 4) + | 0x01; + + byte[] expected = new byte[] { + // Image separator. + 0x2C, + // Image left. + 0x00, 0x0A, + // Image right. + 0x00, 0X09, + // Image width. + 0x00, 0x08, + // Image height. + 0x00, 0x07, + packedField + }; assertArrayEquals(expected, buffer.array()); } + @Test + public void testWriteColorTable() { + final int numColors = 4; + ByteBuffer buffer = ByteBuffer.allocate(GifBytesTestUtil.getColorTableLength(numColors)); + GifBytesTestUtil.writeColorTable(buffer, numColors); + + byte[] expected = new byte[] { + // First color. + 0x00, 0x00, 0x00, + // Second color. + 0x00, 0x00, 0x01, + // Third color. + 0x00, 0x00, 0x02, + // Fourth color. + 0x00, 0x00, 0x03, + }; + + + assertArrayEquals("expected=" + Arrays.toString(expected) + " received=" + Arrays.toString(buffer.array()), + expected, buffer.array()); + } + @Test public void testWriteFakeImageData() { ByteBuffer buffer = ByteBuffer.allocate(4); -- cgit v1.2.3