aboutsummaryrefslogtreecommitdiff
path: root/library/src/main/java/com/bumptech/glide/load/resource/gif/GifData.java
blob: 5d9494f44fbce309f5b54a0f850db8d17dd1762d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package com.bumptech.glide.load.resource.gif;

import android.content.Context;
import android.graphics.Bitmap;
import com.bumptech.glide.gifdecoder.GifDecoder;
import com.bumptech.glide.gifdecoder.GifHeader;
import com.bumptech.glide.load.Transformation;
import com.bumptech.glide.load.resource.UnitTransformation;
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;

import java.util.ArrayList;
import java.util.List;

/**
 * A container for data related to a particular GIF image that includes a partially decoded header and the bytes of
 * the compressed image that can be used together to decode individual frames of the GIF.
 */
public class GifData {
    private final Context context;
    private final GifHeader header;
    private final byte[] data;
    private final GifDecoderBitmapProvider bitmapProvider;
    private final String gifId;
    private final int targetWidth;
    private final int targetHeight;
    private final List<GifDrawable> drawables = new ArrayList<GifDrawable>();
    private Transformation<Bitmap> frameTransformation;

    public GifData(Context context, BitmapPool bitmapPool, String gifId, GifHeader header, byte[] data,
            int targetWidth, int targetHeight) {
        this.context = context;
        this.header = header;
        this.data = data;
        this.gifId = gifId;
        this.targetWidth = targetWidth;
        this.targetHeight = targetHeight;
        bitmapProvider = new GifDecoderBitmapProvider(bitmapPool);
    }

    /**
     * Returns the current non null frame {@link com.bumptech.glide.load.Transformation}.
     */
    @SuppressWarnings("unchecked")
    public Transformation<Bitmap> getFrameTransformation() {
        if (frameTransformation != null) {
            return frameTransformation;
        } else {
            return UnitTransformation.get();
        }
    }

    /**
     * Sets a {@link com.bumptech.glide.load.Transformation} that will be applied to each frame in the animation
     * individually.
     *
     * <p>
     *     Note - The frame transformations are not permanent in that they do not modify the underlying data,
     *     but only each frame as they are decoded. As a result these frame transformations cannot be cached and must
     *     be applied to the GifData whenever one is decoded, regardless of whether it came from the cache or not.
     * </p>
     *
     * @param transformation The transformation to apply.
     */
    public void setFrameTransformation(Transformation<Bitmap> transformation) {
        this.frameTransformation = transformation;
    }

    /**
     * Returns the size in bytes of the original compressed GIF image.
     */
    public int getByteSize() {
        return data.length;
    }

    /**
     * Returns the bytes of the original compressed GIF image.
     */
    public byte[] getData() {
        return data;
    }

    /**
     * Returns a new {@link com.bumptech.glide.load.resource.gif.GifDrawable} that can animate between the frames of
     * the wrapped GIF.
     */
    public GifDrawable getDrawable() {
        GifDecoder gifDecoder = new GifDecoder(bitmapProvider);
        gifDecoder.setData(gifId, header, data);
        GifFrameManager frameManager = new GifFrameManager(context, gifDecoder, getFrameTransformation(),
                targetWidth, targetHeight);

        GifDrawable result = new GifDrawable(gifDecoder, frameManager);
        drawables.add(result);
        return result;
    }

    /**
     * Recycles the resources used by any {@link com.bumptech.glide.load.resource.gif.GifDrawable}s returned from
     * {@link #getDrawable()}.
     */
    public void recycle() {
        for (GifDrawable drawable : drawables) {
            drawable.stop();
            drawable.recycle();
        }
    }

    private static class GifDecoderBitmapProvider implements GifDecoder.BitmapProvider {
        private BitmapPool bitmapPool;

        public GifDecoderBitmapProvider(BitmapPool bitmapPool) {
            this.bitmapPool = bitmapPool;
        }

        @Override
        public Bitmap obtain(int width, int height, Bitmap.Config config) {
            return bitmapPool.get(width, height, config);
        }
    }
}