Skip to content

Commit d704c89

Browse files
vigneshvgglide-copybara-robot
authored andcommittedFeb 14, 2023
Rename AnimatedWebpDecoder to AnimatedImageDecoder
This sets up the class to be used in a generic manner for other animated image formats (like AVIF) that are supported by the android platform's ImageDecoder. PiperOrigin-RevId: 509657824
1 parent 895e2f7 commit d704c89

File tree

3 files changed

+171
-6
lines changed

3 files changed

+171
-6
lines changed
 

‎library/src/main/java/com/bumptech/glide/RegistryFactory.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
import com.bumptech.glide.load.resource.bitmap.UnitBitmapDecoder;
5959
import com.bumptech.glide.load.resource.bitmap.VideoDecoder;
6060
import com.bumptech.glide.load.resource.bytes.ByteBufferRewinder;
61-
import com.bumptech.glide.load.resource.drawable.AnimatedWebpDecoder;
61+
import com.bumptech.glide.load.resource.drawable.AnimatedImageDecoder;
6262
import com.bumptech.glide.load.resource.drawable.ResourceDrawableDecoder;
6363
import com.bumptech.glide.load.resource.drawable.UnitDrawableDecoder;
6464
import com.bumptech.glide.load.resource.file.FileDecoder;
@@ -174,12 +174,12 @@ private static void initializeDefaults(
174174
Registry.BUCKET_ANIMATION,
175175
InputStream.class,
176176
Drawable.class,
177-
AnimatedWebpDecoder.streamDecoder(imageHeaderParsers, arrayPool));
177+
AnimatedImageDecoder.streamDecoder(imageHeaderParsers, arrayPool));
178178
registry.append(
179179
Registry.BUCKET_ANIMATION,
180180
ByteBuffer.class,
181181
Drawable.class,
182-
AnimatedWebpDecoder.byteBufferDecoder(imageHeaderParsers, arrayPool));
182+
AnimatedImageDecoder.byteBufferDecoder(imageHeaderParsers, arrayPool));
183183
}
184184

185185
ResourceDrawableDecoder resourceDrawableDecoder = new ResourceDrawableDecoder(context);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
package com.bumptech.glide.load.resource.drawable;
2+
3+
import android.graphics.Bitmap;
4+
import android.graphics.ImageDecoder;
5+
import android.graphics.ImageDecoder.Source;
6+
import android.graphics.drawable.AnimatedImageDrawable;
7+
import android.graphics.drawable.Drawable;
8+
import android.os.Build;
9+
import androidx.annotation.NonNull;
10+
import androidx.annotation.RequiresApi;
11+
import com.bumptech.glide.load.ImageHeaderParser;
12+
import com.bumptech.glide.load.ImageHeaderParser.ImageType;
13+
import com.bumptech.glide.load.ImageHeaderParserUtils;
14+
import com.bumptech.glide.load.Options;
15+
import com.bumptech.glide.load.ResourceDecoder;
16+
import com.bumptech.glide.load.engine.Resource;
17+
import com.bumptech.glide.load.engine.bitmap_recycle.ArrayPool;
18+
import com.bumptech.glide.load.resource.DefaultOnHeaderDecodedListener;
19+
import com.bumptech.glide.util.ByteBufferUtil;
20+
import com.bumptech.glide.util.Synthetic;
21+
import com.bumptech.glide.util.Util;
22+
import java.io.IOException;
23+
import java.io.InputStream;
24+
import java.nio.ByteBuffer;
25+
import java.util.List;
26+
27+
/**
28+
* Allows decoding animated images using {@link ImageDecoder}.
29+
*
30+
* <p>Supported formats: WebP on Android P+.
31+
*/
32+
@RequiresApi(Build.VERSION_CODES.P)
33+
public final class AnimatedImageDecoder {
34+
private final List<ImageHeaderParser> imageHeaderParsers;
35+
private final ArrayPool arrayPool;
36+
37+
public static ResourceDecoder<InputStream, Drawable> streamDecoder(
38+
List<ImageHeaderParser> imageHeaderParsers, ArrayPool arrayPool) {
39+
return new StreamAnimatedImageDecoder(new AnimatedImageDecoder(imageHeaderParsers, arrayPool));
40+
}
41+
42+
public static ResourceDecoder<ByteBuffer, Drawable> byteBufferDecoder(
43+
List<ImageHeaderParser> imageHeaderParsers, ArrayPool arrayPool) {
44+
return new ByteBufferAnimatedImageDecoder(
45+
new AnimatedImageDecoder(imageHeaderParsers, arrayPool));
46+
}
47+
48+
private AnimatedImageDecoder(List<ImageHeaderParser> imageHeaderParsers, ArrayPool arrayPool) {
49+
this.imageHeaderParsers = imageHeaderParsers;
50+
this.arrayPool = arrayPool;
51+
}
52+
53+
@Synthetic
54+
boolean handles(ByteBuffer byteBuffer) throws IOException {
55+
return isHandled(ImageHeaderParserUtils.getType(imageHeaderParsers, byteBuffer));
56+
}
57+
58+
@Synthetic
59+
boolean handles(InputStream is) throws IOException {
60+
return isHandled(ImageHeaderParserUtils.getType(imageHeaderParsers, is, arrayPool));
61+
}
62+
63+
private boolean isHandled(ImageType imageType) {
64+
return imageType == ImageType.ANIMATED_WEBP;
65+
}
66+
67+
@Synthetic
68+
Resource<Drawable> decode(@NonNull Source source, int width, int height, @NonNull Options options)
69+
throws IOException {
70+
Drawable decoded =
71+
ImageDecoder.decodeDrawable(
72+
source, new DefaultOnHeaderDecodedListener(width, height, options));
73+
if (!(decoded instanceof AnimatedImageDrawable)) {
74+
throw new IOException(
75+
"Received unexpected drawable type for animated webp, failing: " + decoded);
76+
}
77+
return new AnimatedImageDrawableResource((AnimatedImageDrawable) decoded);
78+
}
79+
80+
private static final class AnimatedImageDrawableResource implements Resource<Drawable> {
81+
/** A totally made up number of the number of frames we think are held in memory at once... */
82+
private static final int ESTIMATED_NUMBER_OF_FRAMES = 2;
83+
84+
private final AnimatedImageDrawable imageDrawable;
85+
86+
AnimatedImageDrawableResource(AnimatedImageDrawable imageDrawable) {
87+
this.imageDrawable = imageDrawable;
88+
}
89+
90+
@NonNull
91+
@Override
92+
public Class<Drawable> getResourceClass() {
93+
return Drawable.class;
94+
}
95+
96+
@NonNull
97+
@Override
98+
public AnimatedImageDrawable get() {
99+
return imageDrawable;
100+
}
101+
102+
@Override
103+
public int getSize() {
104+
return imageDrawable.getIntrinsicWidth()
105+
* imageDrawable.getIntrinsicHeight()
106+
* Util.getBytesPerPixel(Bitmap.Config.ARGB_8888)
107+
* ESTIMATED_NUMBER_OF_FRAMES;
108+
}
109+
110+
@Override
111+
public void recycle() {
112+
imageDrawable.stop();
113+
imageDrawable.clearAnimationCallbacks();
114+
}
115+
}
116+
117+
private static final class StreamAnimatedImageDecoder
118+
implements ResourceDecoder<InputStream, Drawable> {
119+
120+
private final AnimatedImageDecoder delegate;
121+
122+
StreamAnimatedImageDecoder(AnimatedImageDecoder delegate) {
123+
this.delegate = delegate;
124+
}
125+
126+
@Override
127+
public boolean handles(@NonNull InputStream source, @NonNull Options options)
128+
throws IOException {
129+
return delegate.handles(source);
130+
}
131+
132+
@Override
133+
public Resource<Drawable> decode(
134+
@NonNull InputStream is, int width, int height, @NonNull Options options)
135+
throws IOException {
136+
Source source = ImageDecoder.createSource(ByteBufferUtil.fromStream(is));
137+
return delegate.decode(source, width, height, options);
138+
}
139+
}
140+
141+
private static final class ByteBufferAnimatedImageDecoder
142+
implements ResourceDecoder<ByteBuffer, Drawable> {
143+
144+
private final AnimatedImageDecoder delegate;
145+
146+
ByteBufferAnimatedImageDecoder(AnimatedImageDecoder delegate) {
147+
this.delegate = delegate;
148+
}
149+
150+
@Override
151+
public boolean handles(@NonNull ByteBuffer source, @NonNull Options options)
152+
throws IOException {
153+
return delegate.handles(source);
154+
}
155+
156+
@Override
157+
public Resource<Drawable> decode(
158+
@NonNull ByteBuffer byteBuffer, int width, int height, @NonNull Options options)
159+
throws IOException {
160+
Source source = ImageDecoder.createSource(byteBuffer);
161+
return delegate.decode(source, width, height, options);
162+
}
163+
}
164+
}

‎library/src/main/java/com/bumptech/glide/load/resource/drawable/AnimatedWebpDecoder.java

+4-3
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,11 @@
2525
import java.util.List;
2626

2727
/**
28-
* Allows decoding animated webp images using {@link ImageDecoder} on Android P+.
29-
*
30-
* <p>This class is experimental and may be removed at any time.
28+
* Allows decoding animated webp images using {@link ImageDecoder} on Android P+. @Deprecated This
29+
* class has been replaced by {@link AnimatedImageDecoder} and is not used in Glide by default. It
30+
* will be removed in a future version.
3131
*/
32+
@Deprecated
3233
@RequiresApi(Build.VERSION_CODES.P)
3334
public final class AnimatedWebpDecoder {
3435
private final List<ImageHeaderParser> imageHeaderParsers;

0 commit comments

Comments
 (0)
Please sign in to comment.