diff options
author | Alan Newberger <alann@google.com> | 2014-12-03 10:47:03 -0800 |
---|---|---|
committer | Alan Newberger <alann@google.com> | 2014-12-03 10:47:03 -0800 |
commit | 617200ae32e6671631846ae0f840115c4463c8d4 (patch) | |
tree | 17fb77eadd24974e99a5b1a44df32f5ea81f1665 /third_party/gif_decoder | |
parent | 9dbd132bec874fdb47231ffe45d4df2b1ae05764 (diff) | |
parent | a311d4835cdede5757e203d52a1bb5e707cfd989 (diff) | |
download | glide-617200ae32e6671631846ae0f840115c4463c8d4.tar.gz |
Merge tag 'v3.4.0' of https://github.com/bumptech/glide into ub-camera-haleakala
Change-Id: Ic290a947323184bfd15576a781bceb88258a5dd1
Diffstat (limited to 'third_party/gif_decoder')
3 files changed, 61 insertions, 67 deletions
diff --git a/third_party/gif_decoder/build.gradle b/third_party/gif_decoder/build.gradle deleted file mode 100644 index 8834279f..00000000 --- a/third_party/gif_decoder/build.gradle +++ /dev/null @@ -1,22 +0,0 @@ -apply plugin: 'com.android.library' -apply plugin: 'robolectric' - -dependencies { - androidTestCompile 'com.android.support:support-v4:19.1.0' - androidTestCompile 'org.hamcrest:hamcrest-core:1.3' - androidTestCompile 'org.hamcrest:hamcrest-library:1.3' - androidTestCompile 'junit:junit:4.11' - androidTestCompile 'org.mockito:mockito-all:1.9.5' - androidTestCompile 'org.robolectric:robolectric:2.4-SNAPSHOT' -} - -android { - compileSdkVersion 19 - buildToolsVersion '19.1.0' - - defaultConfig { - applicationId 'com.bumptech.glide.gifdecoder' - minSdkVersion 10 - targetSdkVersion 19 - } -} diff --git a/third_party/gif_decoder/src/main/java/com/bumptech/glide/gifdecoder/GifDecoder.java b/third_party/gif_decoder/src/main/java/com/bumptech/glide/gifdecoder/GifDecoder.java index 92dc3bfc..c4b4281d 100644 --- a/third_party/gif_decoder/src/main/java/com/bumptech/glide/gifdecoder/GifDecoder.java +++ b/third_party/gif_decoder/src/main/java/com/bumptech/glide/gifdecoder/GifDecoder.java @@ -98,6 +98,11 @@ public class GifDecoder { private static final int INITIAL_FRAME_POINTER = -1; + // We can't tell if a gif has transparency to decode a partial frame on top of a previous frame, or if the final + // frame will actually have transparent pixels, so we must always use a format that supports transparency. We can't + // use ARGB_4444 because of framework issues drawing onto ARGB_4444 Bitmaps using Canvas. + private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888; + // Global File Header values and parsing flags. // Active color table. private int[] act; @@ -123,7 +128,6 @@ public class GifDecoder { private BitmapProvider bitmapProvider; private Bitmap previousImage; private boolean savePrevious; - private Bitmap.Config config; private int status; /** @@ -135,8 +139,8 @@ public class GifDecoder { * Returns an {@link Bitmap} with exactly the given dimensions and config, or null if no such {@link Bitmap} * could be obtained. * - * @param width The width of the desired {@link android.graphics.Bitmap}. - * @param height The height of the desired {@link android.graphics.Bitmap}. + * @param width The width in pixels of the desired {@link android.graphics.Bitmap}. + * @param height The height in pixels of the desired {@link android.graphics.Bitmap}. * @param config The {@link android.graphics.Bitmap.Config} of the desired {@link android.graphics.Bitmap}. */ public Bitmap obtain(int width, int height, Bitmap.Config config); @@ -164,10 +168,6 @@ public class GifDecoder { return data; } - public void setPreferredConfig(Bitmap.Config config) { - this.config = config; - } - /** * Returns the current status of the decoder. * @@ -202,7 +202,7 @@ public class GifDecoder { } /** - * Gets display duration for the upcoming frame. + * Gets display duration for the upcoming frame in ms. */ public int getNextDelay() { if (header.frameCount <= 0 || framePointer < 0) { @@ -248,46 +248,59 @@ public class GifDecoder { * * @return Bitmap representation of frame. */ - public Bitmap getNextFrame() { + public synchronized Bitmap getNextFrame() { if (header.frameCount <= 0 || framePointer < 0) { + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "unable to decode frame, frameCount=" + header.frameCount + " framePointer=" + framePointer); + } status = STATUS_FORMAT_ERROR; } if (status == STATUS_FORMAT_ERROR || status == STATUS_OPEN_ERROR) { + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "Unable to decode frame, status=" + status); + } return null; } status = STATUS_OK; - GifFrame frame = header.frames.get(framePointer); + GifFrame currentFrame = header.frames.get(framePointer); + GifFrame previousFrame = null; + int previousIndex = framePointer - 1; + if (previousIndex >= 0) { + previousFrame = header.frames.get(previousIndex); + } // Set the appropriate color table. - if (frame.lct == null) { + if (currentFrame.lct == null) { act = header.gct; } else { - act = frame.lct; - if (header.bgIndex == frame.transIndex) { + act = currentFrame.lct; + if (header.bgIndex == currentFrame.transIndex) { header.bgColor = 0; } } int save = 0; - if (frame.transparency) { - save = act[frame.transIndex]; + if (currentFrame.transparency) { + save = act[currentFrame.transIndex]; // Set transparent color if specified. - act[frame.transIndex] = 0; + act[currentFrame.transIndex] = 0; } if (act == null) { - Log.w(TAG, "No Valid Color Table"); + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "No Valid Color Table"); + } // No color table defined. status = STATUS_FORMAT_ERROR; return null; } // Transfer pixel data to image. - Bitmap result = setPixels(framePointer); + Bitmap result = setPixels(currentFrame, previousFrame); // Reset the transparent pixel in the color table - if (frame.transparency) { - act[frame.transIndex] = save; + if (currentFrame.transparency) { + act[currentFrame.transIndex] = save; } return result; @@ -408,13 +421,8 @@ public class GifDecoder { /** * Creates new frame image from current data (and previous frames as specified by their disposition codes). */ - private Bitmap setPixels(int frameIndex) { - GifFrame currentFrame = header.frames.get(frameIndex); - GifFrame previousFrame = null; - int previousIndex = frameIndex - 1; - if (previousIndex >= 0) { - previousFrame = header.frames.get(previousIndex); - } + private Bitmap setPixels(GifFrame currentFrame, GifFrame previousFrame) { + int width = header.width; int height = header.height; @@ -676,21 +684,10 @@ public class GifDecoder { return n; } - private Bitmap.Config getPreferredConfig() { - // We can't tell if a gif has transparency to decode a partial frame on top of a previous frame, or if the final - // frame will actually have transparent pixels, so we must always use a format that supports transparency. - if (config == Bitmap.Config.RGB_565 || config == Bitmap.Config.ARGB_4444) { - return Bitmap.Config.ARGB_4444; - } else { - return Bitmap.Config.ARGB_8888; - } - } - private Bitmap getNextBitmap() { - Bitmap.Config targetConfig = getPreferredConfig(); - Bitmap result = bitmapProvider.obtain(header.width, header.height, targetConfig); + Bitmap result = bitmapProvider.obtain(header.width, header.height, BITMAP_CONFIG); if (result == null) { - result = Bitmap.createBitmap(header.width, header.height, targetConfig); + result = Bitmap.createBitmap(header.width, header.height, BITMAP_CONFIG); } setAlpha(result); return result; diff --git a/third_party/gif_decoder/src/main/java/com/bumptech/glide/gifdecoder/GifHeaderParser.java b/third_party/gif_decoder/src/main/java/com/bumptech/glide/gifdecoder/GifHeaderParser.java index 286a5602..cf61531c 100644 --- a/third_party/gif_decoder/src/main/java/com/bumptech/glide/gifdecoder/GifHeaderParser.java +++ b/third_party/gif_decoder/src/main/java/com/bumptech/glide/gifdecoder/GifHeaderParser.java @@ -1,5 +1,7 @@ package com.bumptech.glide.gifdecoder; +import static com.bumptech.glide.gifdecoder.GifDecoder.STATUS_FORMAT_ERROR; + import android.util.Log; import java.nio.BufferUnderflowException; @@ -7,8 +9,6 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.Arrays; -import static com.bumptech.glide.gifdecoder.GifDecoder.STATUS_FORMAT_ERROR; - /** * A class responsible for creating {@link com.bumptech.glide.gifdecoder.GifHeader}s from data representing animated * gifs. @@ -16,6 +16,11 @@ import static com.bumptech.glide.gifdecoder.GifDecoder.STATUS_FORMAT_ERROR; public class GifHeaderParser { public static final String TAG = "GifHeaderParser"; + // The minimum frame delay in hundredths of a second. + static final int MIN_FRAME_DELAY = 3; + // The default frame delay in hundredths of a second for GIFs with frame delays less than the minimum. + static final int DEFAULT_FRAME_DELAY = 10; + private static final int MAX_BLOCK_SIZE = 256; // Raw data read working array. private final byte[] block = new byte[MAX_BLOCK_SIZE]; @@ -37,6 +42,11 @@ public class GifHeaderParser { return this; } + public void clear() { + rawData = null; + header = null; + } + private void reset() { rawData = null; Arrays.fill(block, (byte) 0); @@ -147,7 +157,12 @@ public class GifHeaderParser { } header.currentFrame.transparency = (packed & 1) != 0; // Delay in milliseconds. - header.currentFrame.delay = readShort() * 10; + int delayInHundredthsOfASecond = readShort(); + // TODO: consider allowing -1 to indicate show forever. + if (delayInHundredthsOfASecond < MIN_FRAME_DELAY) { + delayInHundredthsOfASecond = DEFAULT_FRAME_DELAY; + } + header.currentFrame.delay = delayInHundredthsOfASecond * 10; // Transparent color index header.currentFrame.transIndex = read(); // Block terminator @@ -275,7 +290,9 @@ public class GifHeaderParser { tab[i++] = 0xff000000 | (r << 16) | (g << 8) | b; } } catch (BufferUnderflowException e) { - Log.w(TAG, "Format Error Reading Color Table", e); + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "Format Error Reading Color Table", e); + } header.status = STATUS_FORMAT_ERROR; } @@ -321,7 +338,9 @@ public class GifHeaderParser { n += count; } } catch (Exception e) { - Log.w(TAG, "Error Reading Block n: " + n + " count: " + count + " blockSize: " + blockSize, e); + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "Error Reading Block n: " + n + " count: " + count + " blockSize: " + blockSize, e); + } header.status = STATUS_FORMAT_ERROR; } } |