Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
沉迷打码的小凳子
glide
提交
4185efc3
G
glide
项目概览
沉迷打码的小凳子
/
glide
与 Fork 源项目一致
从无法访问的项目Fork
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
G
glide
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
4185efc3
编写于
9月 26, 2014
作者:
S
Sam Judd
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Decode first gif frame before returning resource.
Fixes #159.
上级
e08fca67
变更
11
隐藏空白更改
内联
并排
Showing
11 changed file
with
293 addition
and
110 deletion
+293
-110
library/src/androidTest/java/com/bumptech/glide/GlideTest.java
...ry/src/androidTest/java/com/bumptech/glide/GlideTest.java
+13
-1
library/src/androidTest/java/com/bumptech/glide/load/resource/gif/GifDrawableResourceTest.java
...tech/glide/load/resource/gif/GifDrawableResourceTest.java
+6
-3
library/src/androidTest/java/com/bumptech/glide/load/resource/gif/GifDrawableTest.java
...com/bumptech/glide/load/resource/gif/GifDrawableTest.java
+37
-5
library/src/androidTest/java/com/bumptech/glide/load/resource/gif/GifDrawableTransformationTest.java
...lide/load/resource/gif/GifDrawableTransformationTest.java
+4
-1
library/src/androidTest/java/com/bumptech/glide/load/resource/gif/GifResourceDecoderTest.java
...ptech/glide/load/resource/gif/GifResourceDecoderTest.java
+75
-14
library/src/main/java/com/bumptech/glide/load/resource/gif/GifDrawable.java
...ava/com/bumptech/glide/load/resource/gif/GifDrawable.java
+31
-28
library/src/main/java/com/bumptech/glide/load/resource/gif/GifDrawableResource.java
...bumptech/glide/load/resource/gif/GifDrawableResource.java
+2
-1
library/src/main/java/com/bumptech/glide/load/resource/gif/GifDrawableTransformation.java
...ch/glide/load/resource/gif/GifDrawableTransformation.java
+6
-20
library/src/main/java/com/bumptech/glide/load/resource/gif/GifResourceDecoder.java
.../bumptech/glide/load/resource/gif/GifResourceDecoder.java
+52
-30
samples/giphy/src/main/java/com/bumptech/glide/samples/giphy/MainActivity.java
...n/java/com/bumptech/glide/samples/giphy/MainActivity.java
+59
-7
third_party/gif_decoder/src/main/java/com/bumptech/glide/gifdecoder/GifDecoder.java
...c/main/java/com/bumptech/glide/gifdecoder/GifDecoder.java
+8
-0
未找到文件。
library/src/androidTest/java/com/bumptech/glide/GlideTest.java
浏览文件 @
4185efc3
...
...
@@ -49,6 +49,7 @@ import org.robolectric.RobolectricTestRunner;
import
org.robolectric.annotation.Config
;
import
org.robolectric.annotation.Implementation
;
import
org.robolectric.annotation.Implements
;
import
org.robolectric.shadows.ShadowBitmap
;
import
java.io.ByteArrayInputStream
;
import
java.io.File
;
...
...
@@ -79,7 +80,7 @@ import static org.mockito.Mockito.when;
*/
@RunWith
(
RobolectricTestRunner
.
class
)
@Config
(
shadows
=
{
GlideTest
.
ShadowFileDescriptorContentResolver
.
class
,
GlideTest
.
ShadowMediaMetadataRetriever
.
class
,
GlideShadowLooper
.
class
})
GlideShadowLooper
.
class
,
GlideTest
.
MutableShadowBitmap
.
class
})
public
class
GlideTest
{
private
Target
target
=
null
;
private
ImageView
imageView
;
...
...
@@ -808,6 +809,17 @@ public class GlideTest {
}
}
@Implements
(
Bitmap
.
class
)
public
static
class
MutableShadowBitmap
extends
ShadowBitmap
{
@Implementation
public
static
Bitmap
createBitmap
(
int
width
,
int
height
,
Bitmap
.
Config
config
)
{
Bitmap
bitmap
=
ShadowBitmap
.
createBitmap
(
width
,
height
,
config
);
Robolectric
.
shadowOf
(
bitmap
).
setMutable
(
true
);
return
bitmap
;
}
}
@Implements
(
MediaMetadataRetriever
.
class
)
public
static
class
ShadowMediaMetadataRetriever
{
...
...
library/src/androidTest/java/com/bumptech/glide/load/resource/gif/GifDrawableResourceTest.java
浏览文件 @
4185efc3
package
com.bumptech.glide.load.resource.gif
;
import
android.graphics.Bitmap
;
import
android.graphics.drawable.Drawable
;
import
com.bumptech.glide.util.Util
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
...
...
@@ -41,11 +42,13 @@ public class GifDrawableResourceTest {
}
@Test
public
void
testReturnsDrawableSize
()
{
public
void
testReturnsDrawableSize
PlusFirstFrameSize
()
{
final
int
size
=
2134
;
Bitmap
firstFrame
=
Bitmap
.
createBitmap
(
100
,
100
,
Bitmap
.
Config
.
ARGB_8888
);
when
(
drawable
.
getFirstFrame
()).
thenReturn
(
firstFrame
);
when
(
drawable
.
getData
()).
thenReturn
(
new
byte
[
size
]);
assertEquals
(
size
,
resource
.
getSize
());
assertEquals
(
size
+
Util
.
getBitmapByteSize
(
firstFrame
)
,
resource
.
getSize
());
}
@Test
...
...
library/src/androidTest/java/com/bumptech/glide/load/resource/gif/GifDrawableTest.java
浏览文件 @
4185efc3
...
...
@@ -9,6 +9,7 @@ import android.graphics.drawable.Drawable;
import
com.bumptech.glide.gifdecoder.GifDecoder
;
import
com.bumptech.glide.gifdecoder.GifHeader
;
import
com.bumptech.glide.load.Transformation
;
import
com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool
;
import
com.bumptech.glide.load.resource.drawable.GlideDrawable
;
import
com.bumptech.glide.tests.GlideShadowLooper
;
...
...
@@ -42,24 +43,47 @@ public class GifDrawableTest {
private
Drawable
.
Callback
cb
=
mock
(
Drawable
.
Callback
.
class
);
private
int
frameHeight
;
private
int
frameWidth
;
private
Bitmap
firstFrame
;
private
BitmapPool
bitmapPool
;
@Before
public
void
setUp
()
{
frameWidth
=
120
;
frameHeight
=
450
;
gifDecoder
=
mock
(
GifDecoder
.
class
);
drawable
=
new
GifDrawable
(
gifDecoder
,
frameManager
,
frameWidth
,
frameHeight
);
firstFrame
=
Bitmap
.
createBitmap
(
frameWidth
,
frameHeight
,
Bitmap
.
Config
.
RGB_565
);
bitmapPool
=
mock
(
BitmapPool
.
class
);
drawable
=
new
GifDrawable
(
gifDecoder
,
frameManager
,
firstFrame
,
bitmapPool
);
drawable
.
setCallback
(
cb
);
}
@Test
public
void
testShould
NotDrawNullBitmap
()
{
public
void
testShould
DrawFirstFrameBeforeAnyFrameRead
()
{
Canvas
canvas
=
mock
(
Canvas
.
class
);
drawable
.
draw
(
canvas
);
verify
(
canvas
).
drawBitmap
(
eq
(
firstFrame
),
anyInt
(),
anyInt
(),
any
(
Paint
.
class
));
}
@Test
public
void
testShouldNotDrawNullBitmapFrame
()
{
Canvas
canvas
=
mock
(
Canvas
.
class
);
drawable
=
new
GifDrawable
(
gifDecoder
,
frameManager
,
firstFrame
,
bitmapPool
);
drawable
.
onFrameRead
(
null
,
0
);
drawable
.
draw
(
canvas
);
verify
(
canvas
).
drawBitmap
(
eq
(
firstFrame
),
anyInt
(),
anyInt
(),
any
(
Paint
.
class
));
verify
(
canvas
,
never
()).
drawBitmap
((
Bitmap
)
isNull
(),
anyInt
(),
anyInt
(),
any
(
Paint
.
class
));
}
@Test
public
void
testDoesNotDrawNullFirstFrame
()
{
drawable
=
new
GifDrawable
(
gifDecoder
,
frameManager
,
null
,
bitmapPool
);
Canvas
canvas
=
mock
(
Canvas
.
class
);
verify
(
canvas
,
never
()).
drawBitmap
(
any
(
Bitmap
.
class
),
anyInt
(),
anyInt
(),
any
(
Paint
.
class
));
}
@Test
public
void
testRequestsNextFrameOnStart
()
{
drawable
.
setVisible
(
true
,
true
);
...
...
@@ -80,7 +104,7 @@ public class GifDrawableTest {
drawable
.
setVisible
(
false
,
false
);
drawable
.
start
();
verify
(
frameManager
,
never
()).
getNextFrame
(
eq
(
drawable
));
verify
(
frameManager
,
never
()).
getNextFrame
(
any
(
GifFrameManager
.
FrameCallback
.
class
));
}
@Test
...
...
@@ -226,6 +250,13 @@ public class GifDrawableTest {
verify
(
frameManager
).
clear
();
}
@Test
public
void
testRecycleReturnsFirstFrameToPool
()
{
drawable
.
recycle
();
verify
(
bitmapPool
).
put
(
eq
(
firstFrame
));
}
@Test
public
void
testIsNotRecycledIfNotRecycled
()
{
assertFalse
(
drawable
.
isRecycled
());
...
...
@@ -248,8 +279,9 @@ public class GifDrawableTest {
GifHeader
gifHeader
=
new
GifHeader
();
Transformation
<
Bitmap
>
transformation
=
mock
(
Transformation
.
class
);
GifDecoder
.
BitmapProvider
provider
=
mock
(
GifDecoder
.
BitmapProvider
.
class
);
drawable
=
new
GifDrawable
(
Robolectric
.
application
,
provider
,
transformation
,
100
,
100
,
"fakeId"
,
gifHeader
,
new
byte
[
0
],
100
,
100
);
Bitmap
firstFrame
=
Bitmap
.
createBitmap
(
100
,
100
,
Bitmap
.
Config
.
ARGB_8888
);
drawable
=
new
GifDrawable
(
Robolectric
.
application
,
provider
,
bitmapPool
,
transformation
,
100
,
100
,
"fakeId"
,
gifHeader
,
new
byte
[
0
],
firstFrame
);
assertNotNull
(
drawable
.
getConstantState
().
newDrawable
());
assertNotNull
(
drawable
.
getConstantState
().
newDrawable
(
Robolectric
.
application
.
getResources
()));
...
...
library/src/androidTest/java/com/bumptech/glide/load/resource/gif/GifDrawableTransformationTest.java
浏览文件 @
4185efc3
...
...
@@ -51,6 +51,9 @@ public class GifDrawableTransformationTest {
when
(
gifDrawable
.
getIntrinsicHeight
()).
thenReturn
(
500
);
when
(
resource
.
get
()).
thenReturn
(
gifDrawable
);
Bitmap
firstFrame
=
Bitmap
.
createBitmap
(
100
,
100
,
Bitmap
.
Config
.
ARGB_8888
);
when
(
gifDrawable
.
getFirstFrame
()).
thenReturn
(
firstFrame
);
final
int
width
=
123
;
final
int
height
=
456
;
Bitmap
expectedBitmap
=
Bitmap
.
createBitmap
(
width
,
height
,
Bitmap
.
Config
.
ARGB_8888
);
...
...
@@ -60,6 +63,6 @@ public class GifDrawableTransformationTest {
transformation
.
transform
(
resource
,
width
,
height
);
verify
(
gifDrawable
).
setFrameTransformation
(
any
(
Transformation
.
class
),
eq
(
width
),
eq
(
height
));
verify
(
gifDrawable
).
setFrameTransformation
(
any
(
Transformation
.
class
),
eq
(
expectedBitmap
));
}
}
library/src/androidTest/java/com/bumptech/glide/load/resource/gif/GifResourceDecoderTest.java
浏览文件 @
4185efc3
package
com.bumptech.glide.load.resource.gif
;
import
android.graphics.Bitmap
;
import
com.bumptech.glide.gifdecoder.GifDecoder
;
import
com.bumptech.glide.gifdecoder.GifHeader
;
import
com.bumptech.glide.gifdecoder.GifHeaderParser
;
...
...
@@ -9,6 +10,8 @@ import com.bumptech.glide.tests.GlideShadowLooper;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.mockito.InOrder
;
import
org.mockito.Mockito
;
import
org.robolectric.Robolectric
;
import
org.robolectric.RobolectricTestRunner
;
import
org.robolectric.annotation.Config
;
...
...
@@ -17,10 +20,12 @@ import java.io.ByteArrayInputStream;
import
java.io.IOException
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertNotNull
;
import
static
org
.
junit
.
Assert
.
assertNull
;
import
static
org
.
junit
.
Assert
.
fail
;
import
static
org
.
mockito
.
Matchers
.
any
;
import
static
org
.
mockito
.
Matchers
.
eq
;
import
static
org
.
mockito
.
Mockito
.
inOrder
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
mockito
.
Mockito
.
verify
;
import
static
org
.
mockito
.
Mockito
.
when
;
...
...
@@ -31,48 +36,50 @@ public class GifResourceDecoderTest {
private
GifResourceDecoder
decoder
;
private
GifHeaderParser
parser
;
private
GifResourceDecoder
.
GifHeaderParserPool
parserPool
;
private
GifResourceDecoder
.
GifDecoderPool
decoderPool
;
private
GifDecoder
gifDecoder
;
private
GifHeader
gifHeader
;
@Before
public
void
setUp
()
{
BitmapPool
bitmapPool
=
mock
(
BitmapPool
.
class
);
gifHeader
=
Mockito
.
spy
(
new
GifHeader
());
parser
=
mock
(
GifHeaderParser
.
class
);
when
(
parser
.
parseHeader
()).
thenReturn
(
gifHeader
);
parserPool
=
mock
(
GifResourceDecoder
.
GifHeaderParserPool
.
class
);
when
(
parserPool
.
obtain
(
any
(
byte
[].
class
))).
thenReturn
(
parser
);
decoder
=
new
GifResourceDecoder
(
Robolectric
.
application
,
bitmapPool
,
parserPool
);
gifDecoder
=
mock
(
GifDecoder
.
class
);
decoderPool
=
mock
(
GifResourceDecoder
.
GifDecoderPool
.
class
);
when
(
decoderPool
.
obtain
(
any
(
GifDecoder
.
BitmapProvider
.
class
))).
thenReturn
(
gifDecoder
);
decoder
=
new
GifResourceDecoder
(
Robolectric
.
application
,
bitmapPool
,
parserPool
,
decoderPool
);
}
@Test
public
void
testReturnsNullIfParsedHeaderHasZeroFrames
()
throws
IOException
{
GifHeader
header
=
mock
(
GifHeader
.
class
);
when
(
parser
.
parseHeader
()).
thenReturn
(
header
);
when
(
header
.
getNumFrames
()).
thenReturn
(
0
);
when
(
gifHeader
.
getNumFrames
()).
thenReturn
(
0
);
assertNull
(
decoder
.
decode
(
new
ByteArrayInputStream
(
new
byte
[
0
]),
100
,
100
));
}
@Test
public
void
testReturnsNullIfParsedHeaderHasFormatError
()
{
GifHeader
header
=
mock
(
GifHeader
.
class
);
when
(
parser
.
parseHeader
()).
thenReturn
(
header
);
when
(
header
.
getStatus
()).
thenReturn
(
GifDecoder
.
STATUS_FORMAT_ERROR
);
when
(
gifHeader
.
getStatus
()).
thenReturn
(
GifDecoder
.
STATUS_FORMAT_ERROR
);
assertNull
(
decoder
.
decode
(
new
ByteArrayInputStream
(
new
byte
[
0
]),
100
,
100
));
}
@Test
public
void
testReturnsNullIfParsedHeaderHasOpenError
()
{
GifHeader
header
=
mock
(
GifHeader
.
class
);
when
(
parser
.
parseHeader
()).
thenReturn
(
header
);
when
(
header
.
getStatus
()).
thenReturn
(
GifDecoder
.
STATUS_OPEN_ERROR
);
when
(
gifHeader
.
getStatus
()).
thenReturn
(
GifDecoder
.
STATUS_OPEN_ERROR
);
assertNull
(
decoder
.
decode
(
new
ByteArrayInputStream
(
new
byte
[
0
]),
100
,
100
));
}
@Test
public
void
testReturnsParserToPool
()
throws
IOException
{
when
(
parserPool
.
obtain
(
any
(
byte
[].
class
))).
thenReturn
(
parser
);
when
(
parser
.
parseHeader
()).
thenReturn
(
mock
(
GifHeader
.
class
));
decoder
.
decode
(
new
ByteArrayInputStream
(
new
byte
[
0
]),
100
,
100
);
verify
(
parserPool
).
release
(
eq
(
parser
));
}
...
...
@@ -82,7 +89,7 @@ public class GifResourceDecoderTest {
when
(
parser
.
parseHeader
()).
thenThrow
(
new
RuntimeException
(
"Test"
));
try
{
decoder
.
decode
(
new
ByteArrayInputStream
(
new
byte
[
0
]),
100
,
100
);
fail
(
"
Expected exception is not thrown.
"
);
fail
(
"
Failed to receive expected exception
"
);
}
catch
(
RuntimeException
e
)
{
// Expected.
}
...
...
@@ -90,6 +97,60 @@ public class GifResourceDecoderTest {
verify
(
parserPool
).
release
(
eq
(
parser
));
}
@Test
public
void
testDecodesFirstFrameAndReturnsGifDecoderToPool
()
{
when
(
gifHeader
.
getNumFrames
()).
thenReturn
(
1
);
when
(
gifHeader
.
getStatus
()).
thenReturn
(
GifDecoder
.
STATUS_OK
);
when
(
gifDecoder
.
getNextFrame
()).
thenReturn
(
Bitmap
.
createBitmap
(
100
,
100
,
Bitmap
.
Config
.
ARGB_8888
));
byte
[]
data
=
new
byte
[
100
];
decoder
.
decode
(
new
ByteArrayInputStream
(
data
),
100
,
100
);
InOrder
order
=
inOrder
(
decoderPool
,
gifDecoder
);
order
.
verify
(
decoderPool
).
obtain
(
any
(
GifDecoder
.
BitmapProvider
.
class
));
order
.
verify
(
gifDecoder
).
setData
(
any
(
String
.
class
),
eq
(
gifHeader
),
eq
(
data
));
order
.
verify
(
gifDecoder
).
advance
();
order
.
verify
(
gifDecoder
).
getNextFrame
();
order
.
verify
(
decoderPool
).
release
(
eq
(
gifDecoder
));
}
@Test
public
void
testReturnsGifDecoderToPoolWhenDecoderThrows
()
{
when
(
gifHeader
.
getNumFrames
()).
thenReturn
(
1
);
when
(
gifHeader
.
getStatus
()).
thenReturn
(
GifDecoder
.
STATUS_OK
);
when
(
gifDecoder
.
getNextFrame
()).
thenThrow
(
new
RuntimeException
(
"test"
));
try
{
decoder
.
decode
(
new
ByteArrayInputStream
(
new
byte
[
0
]),
100
,
100
);
fail
(
"Failed to receive expected exception"
);
}
catch
(
RuntimeException
e
)
{
// Expected.
}
verify
(
decoderPool
).
release
(
eq
(
gifDecoder
));
}
@Test
public
void
testCanObtainNonNullDecoderFromPool
()
{
GifDecoder
.
BitmapProvider
provider
=
mock
(
GifDecoder
.
BitmapProvider
.
class
);
GifResourceDecoder
.
GifDecoderPool
pool
=
new
GifResourceDecoder
.
GifDecoderPool
();
assertNotNull
(
pool
.
obtain
(
provider
));
}
@Test
public
void
testCanPutAndObtainDecoderFromPool
()
{
GifResourceDecoder
.
GifDecoderPool
pool
=
new
GifResourceDecoder
.
GifDecoderPool
();
pool
.
release
(
gifDecoder
);
GifDecoder
fromPool
=
pool
.
obtain
(
mock
(
GifDecoder
.
BitmapProvider
.
class
));
assertEquals
(
gifDecoder
,
fromPool
);
}
@Test
public
void
testDecoderPoolClearsDecoders
()
{
GifResourceDecoder
.
GifDecoderPool
pool
=
new
GifResourceDecoder
.
GifDecoderPool
();
pool
.
release
(
gifDecoder
);
verify
(
gifDecoder
).
clear
();
}
@Test
public
void
testHasValidId
()
{
assertEquals
(
""
,
decoder
.
getId
());
...
...
library/src/main/java/com/bumptech/glide/load/resource/gif/GifDrawable.java
浏览文件 @
4185efc3
...
...
@@ -14,6 +14,7 @@ import android.os.Build;
import
com.bumptech.glide.gifdecoder.GifDecoder
;
import
com.bumptech.glide.gifdecoder.GifHeader
;
import
com.bumptech.glide.load.Transformation
;
import
com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool
;
import
com.bumptech.glide.load.resource.drawable.GlideDrawable
;
/**
...
...
@@ -47,11 +48,13 @@ public class GifDrawable extends GlideDrawable implements GifFrameManager.FrameC
/**
* Constructor for GifDrawable.
*
* @see #setFrameTransformation(com.bumptech.glide.load.Transformation,
int, int
)
* @see #setFrameTransformation(com.bumptech.glide.load.Transformation,
android.graphics.Bitmap
)
*
* @param context A context.
* @param bitmapProvider An {@link com.bumptech.glide.gifdecoder.GifDecoder.BitmapProvider} that can be used to
* retrieve re-usable {@link android.graphics.Bitmap}s.
* @param bitmapPool A {@link com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool} that can be used to return
* the first frame when this drawable is recycled.
* @param frameTransformation An {@link com.bumptech.glide.load.Transformation} that can be applied to each frame.
* @param targetFrameWidth The desired width of the frames displayed by this drawable (the width of the view or
* {@link com.bumptech.glide.request.target.Target} this drawable is being loaded into).
...
...
@@ -60,15 +63,13 @@ public class GifDrawable extends GlideDrawable implements GifFrameManager.FrameC
* @param id An id that uniquely identifies this particular gif.
* @param gifHeader The header data for this gif.
* @param data The full bytes of the gif.
* @param finalFrameWidth The final width of the frames displayed by this drawable after they have been transformed.
* @param finalFrameHeight The final height of the frames displayed by this drwaable after they have been
* transformed.
* @param firstFrame The decoded and transformed first frame of this gif.
*/
public
GifDrawable
(
Context
context
,
GifDecoder
.
BitmapProvider
bitmapProvider
,
public
GifDrawable
(
Context
context
,
GifDecoder
.
BitmapProvider
bitmapProvider
,
BitmapPool
bitmapPool
,
Transformation
<
Bitmap
>
frameTransformation
,
int
targetFrameWidth
,
int
targetFrameHeight
,
String
id
,
GifHeader
gifHeader
,
byte
[]
data
,
int
finalFrameWidth
,
int
finalFrameHeight
)
{
GifHeader
gifHeader
,
byte
[]
data
,
Bitmap
firstFrame
)
{
this
(
new
GifState
(
id
,
gifHeader
,
data
,
context
,
frameTransformation
,
targetFrameWidth
,
targetFrameHeight
,
bitmapProvider
,
finalFrameWidth
,
finalFrameHeight
));
bitmapProvider
,
bitmapPool
,
firstFrame
));
}
private
GifDrawable
(
GifState
state
)
{
...
...
@@ -76,23 +77,25 @@ public class GifDrawable extends GlideDrawable implements GifFrameManager.FrameC
this
.
decoder
=
new
GifDecoder
(
state
.
bitmapProvider
);
decoder
.
setData
(
state
.
id
,
state
.
gifHeader
,
state
.
data
);
frameManager
=
new
GifFrameManager
(
state
.
context
,
decoder
,
state
.
frameTransformation
,
state
.
targetWidth
,
state
.
targetHeight
,
state
.
fi
nalFrameWidth
,
state
.
finalFrameHeight
);
state
.
targetHeight
,
state
.
fi
rstFrame
.
getWidth
(),
state
.
firstFrame
.
getHeight
()
);
}
//
F
or testing.
GifDrawable
(
GifDecoder
decoder
,
GifFrameManager
frameManager
,
int
finalFrameWidth
,
int
finalFrameHeight
)
{
//
Visible f
or testing.
GifDrawable
(
GifDecoder
decoder
,
GifFrameManager
frameManager
,
Bitmap
firstFrame
,
BitmapPool
bitmapPool
)
{
this
.
decoder
=
decoder
;
this
.
frameManager
=
frameManager
;
this
.
state
=
new
GifState
(
null
);
state
.
finalFrameWidth
=
finalFrameWidth
;
state
.
finalFrameHeight
=
finalFrameHeight
;
state
.
bitmapPool
=
bitmapPool
;
state
.
firstFrame
=
firstFrame
;
}
public
Bitmap
getFirstFrame
()
{
return
state
.
firstFrame
;
}
public
void
setFrameTransformation
(
Transformation
<
Bitmap
>
frameTransformation
,
int
finalFrameWidth
,
int
finalFrameHeight
)
{
public
void
setFrameTransformation
(
Transformation
<
Bitmap
>
frameTransformation
,
Bitmap
firstFrame
)
{
state
.
frameTransformation
=
frameTransformation
;
state
.
finalFrameWidth
=
finalFrameWidth
;
state
.
finalFrameHeight
=
finalFrameHeight
;
state
.
firstFrame
=
firstFrame
;
}
public
Transformation
<
Bitmap
>
getFrameTransformation
()
{
...
...
@@ -147,12 +150,12 @@ public class GifDrawable extends GlideDrawable implements GifFrameManager.FrameC
@Override
public
int
getIntrinsicWidth
()
{
return
state
.
fi
nalFrameWidth
;
return
state
.
fi
rstFrame
.
getWidth
()
;
}
@Override
public
int
getIntrinsicHeight
()
{
return
state
.
fi
nalFrameHeight
;
return
state
.
fi
rstFrame
.
getHeight
()
;
}
@Override
...
...
@@ -167,9 +170,8 @@ public class GifDrawable extends GlideDrawable implements GifFrameManager.FrameC
@Override
public
void
draw
(
Canvas
canvas
)
{
if
(
currentFrame
!=
null
)
{
canvas
.
drawBitmap
(
currentFrame
,
0
,
0
,
paint
);
}
Bitmap
toDraw
=
currentFrame
!=
null
?
currentFrame
:
state
.
firstFrame
;
canvas
.
drawBitmap
(
toDraw
,
0
,
0
,
paint
);
}
@Override
...
...
@@ -224,6 +226,7 @@ public class GifDrawable extends GlideDrawable implements GifFrameManager.FrameC
*/
public
void
recycle
()
{
isRecycled
=
true
;
state
.
bitmapPool
.
put
(
state
.
firstFrame
);
frameManager
.
clear
();
}
...
...
@@ -255,22 +258,22 @@ public class GifDrawable extends GlideDrawable implements GifFrameManager.FrameC
String
id
;
GifHeader
gifHeader
;
byte
[]
data
;
int
finalFrameWidth
;
int
finalFrameHeight
;
Context
context
;
Transformation
<
Bitmap
>
frameTransformation
;
int
targetWidth
;
int
targetHeight
;
GifDecoder
.
BitmapProvider
bitmapProvider
;
BitmapPool
bitmapPool
;
Bitmap
firstFrame
;
public
GifState
(
String
id
,
GifHeader
header
,
byte
[]
data
,
Context
context
,
Transformation
<
Bitmap
>
frameTransformation
,
int
targetWidth
,
int
targetHeight
,
GifDecoder
.
BitmapProvider
provider
,
int
finalFrameWidth
,
int
finalFrameHeight
)
{
GifDecoder
.
BitmapProvider
provider
,
BitmapPool
bitmapPool
,
Bitmap
firstFrame
)
{
this
.
id
=
id
;
gifHeader
=
header
;
this
.
data
=
data
;
this
.
finalFrameWidth
=
finalFrameWidth
;
this
.
fi
nalFrameHeight
=
finalFrameHeight
;
this
.
bitmapPool
=
bitmapPool
;
this
.
fi
rstFrame
=
firstFrame
;
this
.
context
=
context
.
getApplicationContext
();
this
.
frameTransformation
=
frameTransformation
;
this
.
targetWidth
=
targetWidth
;
...
...
@@ -288,8 +291,8 @@ public class GifDrawable extends GlideDrawable implements GifFrameManager.FrameC
targetWidth
=
original
.
targetWidth
;
targetHeight
=
original
.
targetHeight
;
bitmapProvider
=
original
.
bitmapProvider
;
finalFrameWidth
=
original
.
finalFrameWidth
;
fi
nalFrameHeight
=
original
.
finalFrameHeight
;
bitmapPool
=
original
.
bitmapPool
;
fi
rstFrame
=
original
.
firstFrame
;
}
}
...
...
library/src/main/java/com/bumptech/glide/load/resource/gif/GifDrawableResource.java
浏览文件 @
4185efc3
package
com.bumptech.glide.load.resource.gif
;
import
com.bumptech.glide.load.resource.drawable.DrawableResource
;
import
com.bumptech.glide.util.Util
;
/**
* A resource wrapping an {@link com.bumptech.glide.load.resource.gif.GifDrawable}.
...
...
@@ -12,7 +13,7 @@ public class GifDrawableResource extends DrawableResource<GifDrawable> {
@Override
public
int
getSize
()
{
return
drawable
.
getData
().
length
;
return
drawable
.
getData
().
length
+
Util
.
getBitmapByteSize
(
drawable
.
getFirstFrame
())
;
}
@Override
...
...
library/src/main/java/com/bumptech/glide/load/resource/gif/GifDrawableTransformation.java
浏览文件 @
4185efc3
package
com.bumptech.glide.load.resource.gif
;
import
android.graphics.Bitmap
;
import
com.bumptech.glide.load.MultiTransformation
;
import
com.bumptech.glide.load.Transformation
;
import
com.bumptech.glide.load.engine.Resource
;
import
com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool
;
...
...
@@ -24,32 +22,20 @@ public class GifDrawableTransformation implements Transformation<GifDrawable> {
@Override
public
Resource
<
GifDrawable
>
transform
(
Resource
<
GifDrawable
>
resource
,
int
outWidth
,
int
outHeight
)
{
GifDrawable
drawable
=
resource
.
get
();
@SuppressWarnings
(
"unchecked"
)
Transformation
<
Bitmap
>
newTransformation
=
new
MultiTransformation
<
Bitmap
>(
drawable
.
getFrameTransformation
(),
wrapped
);
// The drawable needs to be initialized with the correct width and height in order for a view displaying it
// to end up with the right dimensions. Since our transformations may arbitrarily modify the dimensions of
// our gif, here we create a stand in for a frame and pass it to the transformation to see what the final
// transformed dimensions will be so that our drawable can report the correct intrinsict width and height.
Bitmap
toTest
=
bitmapPool
.
get
(
drawable
.
getIntrinsicWidth
(),
drawable
.
getIntrinsicHeight
(),
Bitmap
.
Config
.
RGB_565
);
if
(
toTest
==
null
)
{
toTest
=
Bitmap
.
createBitmap
(
drawable
.
getIntrinsicWidth
(),
drawable
.
getIntrinsicHeight
(),
Bitmap
.
Config
.
RGB_565
);
}
Resource
<
Bitmap
>
bitmapResource
=
new
BitmapResource
(
toTest
,
bitmapPool
);
Resource
<
Bitmap
>
transformed
=
newTransformation
.
transform
(
bitmapResource
,
outWidth
,
outHeight
);
// transformed dimensions will be so that our drawable can report the correct intrinsic width and height.
Bitmap
firstFrame
=
resource
.
get
().
getFirstFrame
();
Resource
<
Bitmap
>
bitmapResource
=
new
BitmapResource
(
firstFrame
,
bitmapPool
);
Resource
<
Bitmap
>
transformed
=
wrapped
.
transform
(
bitmapResource
,
outWidth
,
outHeight
);
if
(
bitmapResource
!=
transformed
)
{
bitmapResource
.
recycle
();
}
Bitmap
bitmap
=
transformed
.
get
();
final
int
transformedWidth
=
bitmap
.
getWidth
();
final
int
transformedHeight
=
bitmap
.
getHeight
();
transformed
.
recycle
();
Bitmap
transformedFrame
=
transformed
.
get
();
drawable
.
setFrameTransformation
(
newTransformation
,
transformedWidth
,
transformedHeight
);
drawable
.
setFrameTransformation
(
wrapped
,
transformedFrame
);
return
resource
;
}
...
...
library/src/main/java/com/bumptech/glide/load/resource/gif/GifResourceDecoder.java
浏览文件 @
4185efc3
...
...
@@ -3,7 +3,6 @@ package com.bumptech.glide.load.resource.gif;
import
android.content.Context
;
import
android.graphics.Bitmap
;
import
android.util.Log
;
import
com.bumptech.glide.Glide
;
import
com.bumptech.glide.gifdecoder.GifDecoder
;
import
com.bumptech.glide.gifdecoder.GifHeader
;
...
...
@@ -28,22 +27,30 @@ import java.util.UUID;
*/
public
class
GifResourceDecoder
implements
ResourceDecoder
<
InputStream
,
GifDrawable
>
{
private
static
final
String
TAG
=
"GifResourceDecoder"
;
private
static
final
GifHeaderParserPool
PARSER_POOL
=
new
DefaultGifHeaderParserPool
();
private
static
final
GifHeaderParserPool
PARSER_POOL
=
new
GifHeaderParserPool
();
private
static
final
GifDecoderPool
DECODER_POOL
=
new
GifDecoderPool
();
private
final
Context
context
;
private
final
BitmapPool
bitmapPool
;
private
final
GifHeaderParserPool
parserPool
;
private
BitmapPool
bitmapPool
;
private
final
GifDecoderPool
decoderPool
;
private
final
GifBitmapProvider
provider
;
public
GifResourceDecoder
(
Context
context
)
{
this
(
context
,
Glide
.
get
(
context
).
getBitmapPool
());
}
public
GifResourceDecoder
(
Context
context
,
BitmapPool
bitmapPool
)
{
this
(
context
,
bitmapPool
,
PARSER_POOL
);
this
(
context
,
bitmapPool
,
PARSER_POOL
,
DECODER_POOL
);
}
GifResourceDecoder
(
Context
context
,
BitmapPool
bitmapPool
,
GifHeaderParserPool
parserPool
)
{
// Visible for testing.
GifResourceDecoder
(
Context
context
,
BitmapPool
bitmapPool
,
GifHeaderParserPool
parserPool
,
GifDecoderPool
decoderPool
)
{
this
.
context
=
context
;
this
.
bitmapPool
=
bitmapPool
;
this
.
decoderPool
=
decoderPool
;
this
.
provider
=
new
GifBitmapProvider
(
bitmapPool
);
this
.
parserPool
=
parserPool
;
}
...
...
@@ -51,14 +58,16 @@ public class GifResourceDecoder implements ResourceDecoder<InputStream, GifDrawa
public
GifDrawableResource
decode
(
InputStream
source
,
int
width
,
int
height
)
{
byte
[]
data
=
inputStreamToBytes
(
source
);
final
GifHeaderParser
parser
=
parserPool
.
obtain
(
data
);
final
GifDecoder
decoder
=
decoderPool
.
obtain
(
provider
);
try
{
return
decode
(
data
,
width
,
height
,
parser
);
return
decode
(
data
,
width
,
height
,
parser
,
decoder
);
}
finally
{
parserPool
.
release
(
parser
);
decoderPool
.
release
(
decoder
);
}
}
private
GifDrawableResource
decode
(
byte
[]
data
,
int
width
,
int
height
,
GifHeaderParser
parser
)
{
private
GifDrawableResource
decode
(
byte
[]
data
,
int
width
,
int
height
,
GifHeaderParser
parser
,
GifDecoder
decoder
)
{
final
GifHeader
header
=
parser
.
parseHeader
();
if
(
header
.
getNumFrames
()
<=
0
||
header
.
getStatus
()
!=
GifDecoder
.
STATUS_OK
)
{
// If we couldn't decode the GIF, we will end up with a frame count of 0.
...
...
@@ -66,14 +75,21 @@ public class GifResourceDecoder implements ResourceDecoder<InputStream, GifDrawa
}
String
id
=
getGifId
(
data
);
Bitmap
firstFrame
=
decodeFirstFrame
(
decoder
,
id
,
header
,
data
);
Transformation
<
Bitmap
>
unitTransformation
=
UnitTransformation
.
get
();
Transformation
<
Bitmap
>
transformation
=
UnitTransformation
.
get
();
GifDrawable
gifDrawable
=
new
GifDrawable
(
context
,
new
GifBitmapProvider
(
bitmapPool
),
transformation
,
width
,
height
,
id
,
header
,
data
,
header
.
getWidth
(),
header
.
getHeight
());
GifDrawable
gifDrawable
=
new
GifDrawable
(
context
,
provider
,
bitmapPool
,
unitTransformation
,
width
,
height
,
id
,
header
,
data
,
firstFrame
);
return
new
GifDrawableResource
(
gifDrawable
);
}
private
Bitmap
decodeFirstFrame
(
GifDecoder
decoder
,
String
id
,
GifHeader
header
,
byte
[]
data
)
{
decoder
.
setData
(
id
,
header
,
data
);
decoder
.
advance
();
return
decoder
.
getNextFrame
();
}
@Override
public
String
getId
()
{
return
""
;
...
...
@@ -94,12 +110,12 @@ public class GifResourceDecoder implements ResourceDecoder<InputStream, GifDrawa
}
private
static
byte
[]
inputStreamToBytes
(
InputStream
is
)
{
final
int
bufferSize
=
16384
,
initialCapacity
=
bufferSize
;
ByteArrayOutputStream
buffer
=
new
ByteArrayOutputStream
(
initialCapacity
);
final
int
bufferSize
=
16384
;
ByteArrayOutputStream
buffer
=
new
ByteArrayOutputStream
(
bufferSize
);
try
{
int
nRead
;
byte
[]
data
=
new
byte
[
bufferSize
];
while
((
nRead
=
is
.
read
(
data
,
0
,
data
.
length
))
!=
-
1
)
{
while
((
nRead
=
is
.
read
(
data
))
!=
-
1
)
{
buffer
.
write
(
data
,
0
,
nRead
);
}
buffer
.
flush
();
...
...
@@ -110,32 +126,38 @@ public class GifResourceDecoder implements ResourceDecoder<InputStream, GifDrawa
return
buffer
.
toByteArray
();
}
interface
GifHeaderParserPool
{
public
GifHeaderParser
obtain
(
byte
[]
data
);
public
void
release
(
GifHeaderParser
parser
);
// Visible for testing.
static
class
GifDecoderPool
{
private
final
Queue
<
GifDecoder
>
pool
=
Util
.
createQueue
(
0
);
public
synchronized
GifDecoder
obtain
(
GifDecoder
.
BitmapProvider
bitmapProvider
)
{
GifDecoder
result
=
pool
.
poll
();
if
(
result
==
null
)
{
result
=
new
GifDecoder
(
bitmapProvider
);
}
return
result
;
}
public
synchronized
void
release
(
GifDecoder
decoder
)
{
decoder
.
clear
();
pool
.
offer
(
decoder
);
}
}
private
static
class
DefaultGifHeaderParserPool
implements
GifHeaderParserPool
{
private
static
final
Queue
<
GifHeaderParser
>
POOL
=
Util
.
createQueue
(
0
);
// Visible for testing.
static
class
GifHeaderParserPool
{
private
final
Queue
<
GifHeaderParser
>
pool
=
Util
.
createQueue
(
0
);
@Override
public
GifHeaderParser
obtain
(
byte
[]
data
)
{
GifHeaderParser
result
;
synchronized
(
POOL
)
{
result
=
POOL
.
poll
();
}
public
synchronized
GifHeaderParser
obtain
(
byte
[]
data
)
{
GifHeaderParser
result
=
pool
.
poll
();
if
(
result
==
null
)
{
result
=
new
GifHeaderParser
();
}
return
result
.
setData
(
data
);
}
@Override
public
void
release
(
GifHeaderParser
parser
)
{
synchronized
(
POOL
)
{
POOL
.
offer
(
parser
);
}
public
synchronized
void
release
(
GifHeaderParser
parser
)
{
pool
.
offer
(
parser
);
}
}
...
...
samples/giphy/src/main/java/com/bumptech/glide/samples/giphy/MainActivity.java
浏览文件 @
4185efc3
...
...
@@ -8,10 +8,13 @@ import android.view.ViewGroup;
import
android.widget.BaseAdapter
;
import
android.widget.ImageView
;
import
android.widget.ListView
;
import
com.bumptech.glide.GenericRequestBuilder
;
import
com.bumptech.glide.Glide
;
import
com.bumptech.glide.ListPreloader
;
import
java.io.InputStream
;
import
java.util.ArrayList
;
import
java.util.List
;
/**
...
...
@@ -37,8 +40,11 @@ public class MainActivity extends Activity implements Api.Monitor {
.
into
(
giphyLogoView
);
ListView
gifList
=
(
ListView
)
findViewById
(
R
.
id
.
gif_list
);
adapter
=
new
GifAdapter
(
this
);
GiphyPreloader
preloader
=
new
GiphyPreloader
(
2
);
adapter
=
new
GifAdapter
(
this
,
preloader
);
gifList
.
setAdapter
(
adapter
);
gifList
.
setOnScrollListener
(
preloader
);
}
@Override
...
...
@@ -58,14 +64,47 @@ public class MainActivity extends Activity implements Api.Monitor {
adapter
.
setResults
(
result
.
data
);
}
private
class
GiphyPreloader
extends
ListPreloader
<
Api
.
GifResult
>
{
private
int
[]
dimensions
;
public
GiphyPreloader
(
int
maxPreload
)
{
super
(
maxPreload
);
}
@Override
protected
int
[]
getDimensions
(
Api
.
GifResult
item
)
{
return
dimensions
;
}
@Override
protected
List
<
Api
.
GifResult
>
getItems
(
int
start
,
int
end
)
{
List
<
Api
.
GifResult
>
items
=
new
ArrayList
<
Api
.
GifResult
>(
end
-
start
);
for
(
int
i
=
start
;
i
<
end
;
i
++)
{
items
.
add
(
adapter
.
getItem
(
i
));
}
return
items
;
}
@Override
protected
GenericRequestBuilder
getRequestBuilder
(
Api
.
GifResult
item
)
{
return
Glide
.
with
(
MainActivity
.
this
)
.
load
(
item
)
.
fitCenter
();
}
}
private
static
class
GifAdapter
extends
BaseAdapter
{
private
static
final
Api
.
GifResult
[]
EMPTY_RESULTS
=
new
Api
.
GifResult
[
0
];
private
final
Activity
activity
;
private
final
GiphyPreloader
preloader
;
private
Api
.
GifResult
[]
results
=
EMPTY_RESULTS
;
private
Activity
activity
;
public
GifAdapter
(
Activity
activity
)
{
public
GifAdapter
(
Activity
activity
,
GiphyPreloader
preloader
)
{
this
.
activity
=
activity
;
this
.
preloader
=
preloader
;
}
public
void
setResults
(
Api
.
GifResult
[]
results
)
{
...
...
@@ -83,8 +122,8 @@ public class MainActivity extends Activity implements Api.Monitor {
}
@Override
public
Objec
t
getItem
(
int
i
)
{
return
null
;
public
Api
.
GifResul
t
getItem
(
int
i
)
{
return
results
[
i
]
;
}
@Override
...
...
@@ -102,13 +141,26 @@ public class MainActivity extends Activity implements Api.Monitor {
if
(
Log
.
isLoggable
(
TAG
,
Log
.
DEBUG
))
{
Log
.
d
(
TAG
,
"load result: "
+
result
);
}
ImageView
gifView
=
(
ImageView
)
convertView
.
findViewById
(
R
.
id
.
gif_view
);
final
ImageView
gifView
=
(
ImageView
)
convertView
.
findViewById
(
R
.
id
.
gif_view
);
Glide
.
with
(
activity
)
.
load
(
result
)
.
fitCenter
()
.
into
(
gifView
);
if
(
preloader
.
dimensions
==
null
)
{
gifView
.
post
(
new
Runnable
()
{
@Override
public
void
run
()
{
if
(
gifView
.
getWidth
()
>
0
&&
gifView
.
getHeight
()
>
0
)
{
preloader
.
dimensions
=
new
int
[
2
];
preloader
.
dimensions
[
0
]
=
gifView
.
getWidth
();
preloader
.
dimensions
[
1
]
=
gifView
.
getHeight
();
}
}
});
}
return
convertView
;
}
}
...
...
third_party/gif_decoder/src/main/java/com/bumptech/glide/gifdecoder/GifDecoder.java
浏览文件 @
4185efc3
...
...
@@ -297,6 +297,14 @@ public class GifDecoder {
return
header
.
status
;
}
public
void
clear
()
{
id
=
null
;
header
=
null
;
data
=
null
;
mainPixels
=
null
;
mainScratch
=
null
;
}
public
void
setData
(
String
id
,
GifHeader
header
,
byte
[]
data
)
{
this
.
id
=
id
;
this
.
header
=
header
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录