Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
沉迷打码的小凳子
glide
提交
ea01ddd7
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,发现更多精彩内容 >>
提交
ea01ddd7
编写于
6月 06, 2014
作者:
S
Sam Judd
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add GifDecoder and GifResource*
上级
b38d03ba
变更
26
隐藏空白更改
内联
并排
Showing
26 changed file
with
2220 addition
and
0 deletion
+2220
-0
library/src/main/java/com/bumptech/glide/load/resource/drawable/DrawableResource.java
...mptech/glide/load/resource/drawable/DrawableResource.java
+29
-0
library/src/main/java/com/bumptech/glide/load/resource/drawable/GifBitmap.java
.../com/bumptech/glide/load/resource/drawable/GifBitmap.java
+43
-0
library/src/main/java/com/bumptech/glide/load/resource/drawable/GifBitmapResource.java
...ptech/glide/load/resource/drawable/GifBitmapResource.java
+25
-0
library/src/main/java/com/bumptech/glide/load/resource/drawable/GifBitmapResourceDecoder.java
...lide/load/resource/drawable/GifBitmapResourceDecoder.java
+58
-0
library/src/main/java/com/bumptech/glide/load/resource/drawable/GifBitmapResourceEncoder.java
...lide/load/resource/drawable/GifBitmapResourceEncoder.java
+35
-0
library/src/main/java/com/bumptech/glide/load/resource/drawable/GifBitmapStreamResourceDecoder.java
...oad/resource/drawable/GifBitmapStreamResourceDecoder.java
+26
-0
library/src/main/java/com/bumptech/glide/load/resource/gif/GifDecoder.java
...java/com/bumptech/glide/load/resource/gif/GifDecoder.java
+854
-0
library/src/main/java/com/bumptech/glide/load/resource/gif/GifDrawable.java
...ava/com/bumptech/glide/load/resource/gif/GifDrawable.java
+113
-0
library/src/main/java/com/bumptech/glide/load/resource/gif/GifFrameLoader.java
.../com/bumptech/glide/load/resource/gif/GifFrameLoader.java
+43
-0
library/src/main/java/com/bumptech/glide/load/resource/gif/GifFrameManager.java
...com/bumptech/glide/load/resource/gif/GifFrameManager.java
+99
-0
library/src/main/java/com/bumptech/glide/load/resource/gif/GifFrameResourceDecoder.java
...tech/glide/load/resource/gif/GifFrameResourceDecoder.java
+20
-0
library/src/main/java/com/bumptech/glide/load/resource/gif/GifResource.java
...ava/com/bumptech/glide/load/resource/gif/GifResource.java
+34
-0
library/src/main/java/com/bumptech/glide/load/resource/gif/GifResourceDecoder.java
.../bumptech/glide/load/resource/gif/GifResourceDecoder.java
+36
-0
library/src/main/java/com/bumptech/glide/load/resource/gif/GifResourceEncoder.java
.../bumptech/glide/load/resource/gif/GifResourceEncoder.java
+30
-0
library/src/main/java/com/bumptech/glide/load/resource/transcode/GifBitmapDrawableTranscoder.java
.../load/resource/transcode/GifBitmapDrawableTranscoder.java
+40
-0
library/src/test/java/com/bumptech/glide/load/resource/drawable/DrawableResourceTest.java
...ch/glide/load/resource/drawable/DrawableResourceTest.java
+47
-0
library/src/test/java/com/bumptech/glide/load/resource/drawable/GifBitmapResourceDecoderTest.java
.../load/resource/drawable/GifBitmapResourceDecoderTest.java
+87
-0
library/src/test/java/com/bumptech/glide/load/resource/drawable/GifBitmapResourceEncoderTest.java
.../load/resource/drawable/GifBitmapResourceEncoderTest.java
+93
-0
library/src/test/java/com/bumptech/glide/load/resource/drawable/GifBitmapStreamResourceDecoderTest.java
...resource/drawable/GifBitmapStreamResourceDecoderTest.java
+63
-0
library/src/test/java/com/bumptech/glide/load/resource/gif/GifDrawableTest.java
...com/bumptech/glide/load/resource/gif/GifDrawableTest.java
+166
-0
library/src/test/java/com/bumptech/glide/load/resource/gif/GifFrameResourceDecoderTest.java
.../glide/load/resource/gif/GifFrameResourceDecoderTest.java
+40
-0
library/src/test/java/com/bumptech/glide/load/resource/gif/GifResourceEncoderTest.java
...ptech/glide/load/resource/gif/GifResourceEncoderTest.java
+64
-0
library/src/test/java/com/bumptech/glide/load/resource/gif/GifResourceTest.java
...com/bumptech/glide/load/resource/gif/GifResourceTest.java
+53
-0
library/src/test/java/com/bumptech/glide/load/resource/transcode/GifBitmapDrawableTranscoderTest.java
...d/resource/transcode/GifBitmapDrawableTranscoderTest.java
+104
-0
samples/flickr/res/layout/flickr_search_activity.xml
samples/flickr/res/layout/flickr_search_activity.xml
+5
-0
samples/flickr/src/main/java/com/bumptech/glide/samples/flickr/FlickrSearchActivity.java
...m/bumptech/glide/samples/flickr/FlickrSearchActivity.java
+13
-0
未找到文件。
library/src/main/java/com/bumptech/glide/load/resource/drawable/DrawableResource.java
0 → 100644
浏览文件 @
ea01ddd7
package
com.bumptech.glide.load.resource.drawable
;
import
android.graphics.drawable.Drawable
;
import
com.bumptech.glide.Resource
;
public
class
DrawableResource
extends
Resource
<
Drawable
>
{
private
final
Drawable
drawable
;
private
final
Resource
wrapped
;
public
DrawableResource
(
Drawable
drawable
,
Resource
wrapped
)
{
this
.
drawable
=
drawable
;
this
.
wrapped
=
wrapped
;
}
@Override
public
Drawable
get
()
{
return
drawable
;
}
@Override
public
int
getSize
()
{
return
wrapped
.
getSize
();
}
@Override
protected
void
recycleInternal
()
{
wrapped
.
recycle
();
}
}
library/src/main/java/com/bumptech/glide/load/resource/drawable/GifBitmap.java
0 → 100644
浏览文件 @
ea01ddd7
package
com.bumptech.glide.load.resource.drawable
;
import
android.content.res.Resources
;
import
android.graphics.Bitmap
;
import
android.graphics.drawable.BitmapDrawable
;
import
android.graphics.drawable.Drawable
;
import
com.bumptech.glide.Resource
;
import
com.bumptech.glide.load.resource.gif.GifDrawable
;
public
class
GifBitmap
{
private
Resource
<
GifDrawable
>
gifResource
;
private
Resource
<
Bitmap
>
bitmapResource
;
private
Resources
resources
;
public
GifBitmap
(
Resources
resources
,
Resource
<
Bitmap
>
bitmapResource
)
{
this
.
resources
=
resources
;
this
.
bitmapResource
=
bitmapResource
;
}
public
GifBitmap
(
Resource
<
GifDrawable
>
gifResource
)
{
this
.
gifResource
=
gifResource
;
}
public
int
getSize
()
{
return
0
;
}
public
Resource
<
Bitmap
>
getBitmapResource
()
{
return
bitmapResource
;
}
public
Resource
<
GifDrawable
>
getGifResource
()
{
return
gifResource
;
}
public
Drawable
getDrawable
()
{
if
(
gifResource
!=
null
)
{
return
gifResource
.
get
();
}
else
{
return
new
BitmapDrawable
(
resources
,
bitmapResource
.
get
());
}
}
}
library/src/main/java/com/bumptech/glide/load/resource/drawable/GifBitmapResource.java
0 → 100644
浏览文件 @
ea01ddd7
package
com.bumptech.glide.load.resource.drawable
;
import
com.bumptech.glide.Resource
;
public
class
GifBitmapResource
extends
Resource
<
GifBitmap
>
{
private
GifBitmap
data
;
public
GifBitmapResource
(
GifBitmap
data
)
{
this
.
data
=
data
;
}
@Override
public
GifBitmap
get
()
{
return
data
;
}
@Override
public
int
getSize
()
{
return
data
.
getSize
();
}
@Override
protected
void
recycleInternal
()
{
}
}
library/src/main/java/com/bumptech/glide/load/resource/drawable/GifBitmapResourceDecoder.java
0 → 100644
浏览文件 @
ea01ddd7
package
com.bumptech.glide.load.resource.drawable
;
import
android.content.Context
;
import
android.graphics.Bitmap
;
import
com.bumptech.glide.Resource
;
import
com.bumptech.glide.load.ResourceDecoder
;
import
com.bumptech.glide.load.model.ImageVideoWrapper
;
import
com.bumptech.glide.load.resource.bitmap.ImageHeaderParser
;
import
com.bumptech.glide.load.resource.bitmap.RecyclableBufferedInputStream
;
import
com.bumptech.glide.load.resource.gif.GifDrawable
;
import
com.bumptech.glide.util.ByteArrayPool
;
import
java.io.IOException
;
import
java.io.InputStream
;
public
class
GifBitmapResourceDecoder
implements
ResourceDecoder
<
ImageVideoWrapper
,
GifBitmap
>
{
private
Context
context
;
private
final
ResourceDecoder
<
ImageVideoWrapper
,
Bitmap
>
bitmapDecoder
;
private
final
ResourceDecoder
<
InputStream
,
GifDrawable
>
gifDecoder
;
public
GifBitmapResourceDecoder
(
Context
context
,
ResourceDecoder
<
ImageVideoWrapper
,
Bitmap
>
bitmapDecoder
,
ResourceDecoder
<
InputStream
,
GifDrawable
>
gifDecoder
)
{
this
.
context
=
context
;
this
.
bitmapDecoder
=
bitmapDecoder
;
this
.
gifDecoder
=
gifDecoder
;
}
@Override
public
Resource
<
GifBitmap
>
decode
(
ImageVideoWrapper
source
,
int
width
,
int
height
)
throws
IOException
{
ByteArrayPool
pool
=
ByteArrayPool
.
get
();
InputStream
is
=
source
.
getStream
();
GifBitmap
result
=
null
;
if
(
is
!=
null
)
{
byte
[]
tempBytes
=
pool
.
getBytes
();
RecyclableBufferedInputStream
bis
=
new
RecyclableBufferedInputStream
(
is
,
tempBytes
);
bis
.
mark
(
1024
);
ImageHeaderParser
.
ImageType
type
=
new
ImageHeaderParser
(
bis
).
getType
();
bis
.
reset
();
if
(
type
==
ImageHeaderParser
.
ImageType
.
GIF
)
{
Resource
<
GifDrawable
>
gifResource
=
gifDecoder
.
decode
(
is
,
width
,
height
);
result
=
new
GifBitmap
(
gifResource
);
}
pool
.
releaseBytes
(
tempBytes
);
}
if
(
result
==
null
)
{
Resource
<
Bitmap
>
bitmapResource
=
bitmapDecoder
.
decode
(
source
,
width
,
height
);
result
=
new
GifBitmap
(
context
.
getResources
(),
bitmapResource
);
}
return
new
GifBitmapResource
(
result
);
}
@Override
public
String
getId
()
{
return
"GifBitmapResourceDecoder.com.bumptech.glide.load.resource.drawable"
;
}
}
library/src/main/java/com/bumptech/glide/load/resource/drawable/GifBitmapResourceEncoder.java
0 → 100644
浏览文件 @
ea01ddd7
package
com.bumptech.glide.load.resource.drawable
;
import
android.graphics.Bitmap
;
import
com.bumptech.glide.Resource
;
import
com.bumptech.glide.load.ResourceEncoder
;
import
com.bumptech.glide.load.resource.gif.GifDrawable
;
import
java.io.OutputStream
;
public
class
GifBitmapResourceEncoder
implements
ResourceEncoder
<
GifBitmap
>
{
private
final
ResourceEncoder
<
Bitmap
>
bitmapEncoder
;
private
final
ResourceEncoder
<
GifDrawable
>
gifEncoder
;
public
GifBitmapResourceEncoder
(
ResourceEncoder
<
Bitmap
>
bitmapEncoder
,
ResourceEncoder
<
GifDrawable
>
gifEncoder
)
{
this
.
bitmapEncoder
=
bitmapEncoder
;
this
.
gifEncoder
=
gifEncoder
;
}
@Override
public
boolean
encode
(
Resource
<
GifBitmap
>
resource
,
OutputStream
os
)
{
final
GifBitmap
gifBitmap
=
resource
.
get
();
final
Resource
<
Bitmap
>
bitmapResource
=
gifBitmap
.
getBitmapResource
();
if
(
bitmapResource
!=
null
)
{
return
bitmapEncoder
.
encode
(
bitmapResource
,
os
);
}
else
{
return
gifEncoder
.
encode
(
gifBitmap
.
getGifResource
(),
os
);
}
}
@Override
public
String
getId
()
{
return
"GifBitmapResourceEncoder.com.bumptech.glide.load.resource.drawable"
;
}
}
library/src/main/java/com/bumptech/glide/load/resource/drawable/GifBitmapStreamResourceDecoder.java
0 → 100644
浏览文件 @
ea01ddd7
package
com.bumptech.glide.load.resource.drawable
;
import
com.bumptech.glide.Resource
;
import
com.bumptech.glide.load.ResourceDecoder
;
import
com.bumptech.glide.load.model.ImageVideoWrapper
;
import
java.io.IOException
;
import
java.io.InputStream
;
public
class
GifBitmapStreamResourceDecoder
implements
ResourceDecoder
<
InputStream
,
GifBitmap
>{
private
ResourceDecoder
<
ImageVideoWrapper
,
GifBitmap
>
gifBitmapDecoder
;
public
GifBitmapStreamResourceDecoder
(
ResourceDecoder
<
ImageVideoWrapper
,
GifBitmap
>
gifBitmapDecoder
)
{
this
.
gifBitmapDecoder
=
gifBitmapDecoder
;
}
@Override
public
Resource
<
GifBitmap
>
decode
(
InputStream
source
,
int
width
,
int
height
)
throws
IOException
{
return
gifBitmapDecoder
.
decode
(
new
ImageVideoWrapper
(
source
,
null
),
width
,
height
);
}
@Override
public
String
getId
()
{
return
"GifBitmapStreamResourceDecoder.com.bumptech.glide.resource.drawable"
;
}
}
library/src/main/java/com/bumptech/glide/load/resource/gif/GifDecoder.java
0 → 100644
浏览文件 @
ea01ddd7
package
com.bumptech.glide.load.resource.gif
;
/**
* Copyright (c) 2013 Xcellent Creations, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import
android.graphics.Bitmap
;
import
android.os.SystemClock
;
import
android.util.Log
;
import
com.bumptech.glide.Resource
;
import
com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool
;
import
com.bumptech.glide.load.resource.bitmap.BitmapResource
;
import
java.io.ByteArrayOutputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.nio.BufferUnderflowException
;
import
java.nio.ByteBuffer
;
import
java.nio.ByteOrder
;
import
java.util.ArrayList
;
/**
* Reads frame data from a GIF image source and decodes it into individual frames
* for animation purposes. Image data can be read from either and InputStream source
* or a byte[].
*
* This class is optimized for running animations with the frames, there
* are no methods to get individual frame images, only to decode the next frame in the
* animation sequence. Instead, it lowers its memory footprint by only housing the minimum
* data necessary to decode the next frame in the animation sequence.
*
* The animation must be manually moved forward using {@link #advance()} before requesting the next
* frame. This method must also be called before you request the first frame or an error will
* occur.
*
* Implementation adapted from sample code published in Lyons. (2004). <em>Java for Programmers</em>,
* republished under the MIT Open Source License
*/
public
class
GifDecoder
{
private
static
final
String
TAG
=
GifDecoder
.
class
.
getSimpleName
();
/**
* File read status: No errors.
*/
public
static
final
int
STATUS_OK
=
0
;
/**
* File read status: Error decoding file (may be partially decoded)
*/
public
static
final
int
STATUS_FORMAT_ERROR
=
1
;
/**
* File read status: Unable to open source.
*/
public
static
final
int
STATUS_OPEN_ERROR
=
2
;
/**
* max decoder pixel stack size
*/
protected
static
final
int
MAX_STACK_SIZE
=
4096
;
/**
* GIF Disposal Method meaning take no action
*/
private
static
final
int
DISPOSAL_UNSPECIFIED
=
0
;
/**
* GIF Disposal Method meaning leave canvas from previous frame
*/
private
static
final
int
DISPOSAL_NONE
=
1
;
/**
* GIF Disposal Method meaning clear canvas to background color
*/
private
static
final
int
DISPOSAL_BACKGROUND
=
2
;
/**
* GIF Disposal Method meaning clear canvas to frame before last
*/
private
static
final
int
DISPOSAL_PREVIOUS
=
3
;
/**
* Global status code of GIF data parsing
*/
protected
int
status
;
//Global File Header values and parsing flags
protected
int
width
;
// full image width
protected
int
height
;
// full image height
protected
boolean
gctFlag
;
// global color table used
protected
int
gctSize
;
// size of global color table
protected
int
loopCount
=
1
;
// iterations; 0 = repeat forever
protected
int
[]
gct
;
// global color table
protected
int
[]
act
;
// active color table
protected
int
bgIndex
;
// background color index
protected
int
bgColor
;
// background color
protected
int
pixelAspect
;
// pixel aspect ratio
protected
boolean
lctFlag
;
// local color table flag
protected
int
lctSize
;
// local color table size
private
boolean
isTransparent
;
// Raw GIF data from input source
protected
ByteBuffer
rawData
;
// Raw data read working array
protected
byte
[]
block
=
new
byte
[
256
];
// current data block
protected
int
blockSize
=
0
;
// block size last graphic control extension info
// LZW decoder working arrays
protected
short
[]
prefix
;
protected
byte
[]
suffix
;
protected
byte
[]
pixelStack
;
protected
byte
[]
mainPixels
;
protected
int
[]
mainScratch
;
protected
ArrayList
<
GifFrame
>
frames
;
// frames read from current file
protected
GifFrame
currentFrame
;
protected
int
framePointer
;
protected
int
frameCount
;
private
BitmapPool
bitmapPool
;
private
Bitmap
currentImage
;
private
byte
[]
data
;
/**
* Inner model class housing metadata for each frame
*/
private
static
class
GifFrame
{
public
int
ix
,
iy
,
iw
,
ih
;
/* Control Flags */
public
boolean
interlace
;
public
boolean
transparency
;
/* Disposal Method */
public
int
dispose
;
/* Transparency Index */
public
int
transIndex
;
/* Delay, in ms, to next frame */
public
int
delay
;
/* Index in the raw buffer where we need to start reading to decode */
public
int
bufferFrameStart
;
/* Local Color Table */
public
int
[]
lct
;
}
public
GifDecoder
(
BitmapPool
bitmapPool
)
{
this
.
bitmapPool
=
bitmapPool
;
}
public
int
getWidth
()
{
return
width
;
}
public
int
getHeight
()
{
return
height
;
}
public
boolean
isTransparent
()
{
return
isTransparent
;
}
public
int
getGifByteSize
()
{
return
data
.
length
;
}
public
byte
[]
getData
()
{
return
data
;
}
public
int
getDecodedFrameByteSize
()
{
// 4 == ARGB_8888, 2 == RGB_565
return
frameCount
*
width
*
height
*
(
isTransparent
?
4
:
2
);
}
/**
* Move the animation frame counter forward
*/
public
void
advance
()
{
framePointer
=
(
framePointer
+
1
)
%
frameCount
;
}
/**
* Gets display duration for specified frame.
*
* @param n int index of frame
* @return delay in milliseconds
*/
public
int
getDelay
(
int
n
)
{
int
delay
=
-
1
;
if
((
n
>=
0
)
&&
(
n
<
frameCount
))
{
delay
=
frames
.
get
(
n
).
delay
;
}
return
delay
;
}
/**
* Gets display duration for the upcoming frame
*/
public
int
getNextDelay
()
{
if
(
frameCount
<=
0
||
framePointer
<
0
)
{
return
-
1
;
}
return
getDelay
(
framePointer
);
}
/**
* Gets the number of frames read from file.
*
* @return frame count
*/
public
int
getFrameCount
()
{
return
frameCount
;
}
/**
* Gets the current index of the animation frame, or -1 if animation hasn't not yet started
*
* @return frame index
*/
public
int
getCurrentFrameIndex
()
{
return
framePointer
;
}
/**
* Gets the "Netscape" iteration count, if any. A count of 0 means repeat indefinitiely.
*
* @return iteration count if one was specified, else 1.
*/
public
int
getLoopCount
()
{
return
loopCount
;
}
/**
* Get the next frame in the animation sequence.
*
* @return Bitmap representation of frame
*/
public
Resource
<
Bitmap
>
getNextFrame
()
{
if
(
frameCount
<=
0
||
framePointer
<
0
)
{
return
null
;
}
long
startTime
=
SystemClock
.
currentThreadTimeMillis
();
GifFrame
frame
=
frames
.
get
(
framePointer
);
//Set the appropriate color table
if
(
frame
.
lct
==
null
)
{
act
=
gct
;
}
else
{
act
=
frame
.
lct
;
if
(
bgIndex
==
frame
.
transIndex
)
{
bgColor
=
0
;
}
}
int
save
=
0
;
if
(
frame
.
transparency
)
{
save
=
act
[
frame
.
transIndex
];
act
[
frame
.
transIndex
]
=
0
;
// set transparent color if specified
}
if
(
act
==
null
)
{
Log
.
w
(
TAG
,
"No Valid Color Table"
);
status
=
STATUS_FORMAT_ERROR
;
// no color table defined
return
null
;
}
Bitmap
result
=
setPixels
(
framePointer
);
// transfer pixel data to image
currentImage
=
result
;
// Reset the transparent pixel in the color table
if
(
frame
.
transparency
)
{
act
[
frame
.
transIndex
]
=
save
;
}
return
new
BitmapResource
(
result
,
bitmapPool
);
}
/**
* Reads GIF image from stream
*
* @param is containing GIF file.
* @return read status code (0 = no errors)
*/
public
int
read
(
InputStream
is
,
int
contentLength
)
{
if
(
is
!=
null
)
{
try
{
int
capacity
=
(
contentLength
>
0
)
?
(
contentLength
+
4096
)
:
16384
;
ByteArrayOutputStream
buffer
=
new
ByteArrayOutputStream
(
capacity
);
int
nRead
;
byte
[]
data
=
new
byte
[
16384
];
while
((
nRead
=
is
.
read
(
data
,
0
,
data
.
length
))
!=
-
1
)
{
buffer
.
write
(
data
,
0
,
nRead
);
}
buffer
.
flush
();
read
(
buffer
.
toByteArray
());
}
catch
(
IOException
e
)
{
Log
.
w
(
TAG
,
"Error reading data from stream"
,
e
);
}
}
else
{
status
=
STATUS_OPEN_ERROR
;
}
try
{
is
.
close
();
}
catch
(
Exception
e
)
{
Log
.
w
(
TAG
,
"Error closing stream"
,
e
);
}
return
status
;
}
/**
* Reads GIF image from byte array
*
* @param data containing GIF file.
* @return read status code (0 = no errors)
*/
public
int
read
(
byte
[]
data
)
{
this
.
data
=
data
;
init
();
if
(
data
!=
null
)
{
//Initialize the raw data buffer
rawData
=
ByteBuffer
.
wrap
(
data
);
rawData
.
rewind
();
rawData
.
order
(
ByteOrder
.
LITTLE_ENDIAN
);
readHeader
();
if
(!
err
())
{
readContents
();
if
(
frameCount
<
0
)
{
status
=
STATUS_FORMAT_ERROR
;
}
}
}
else
{
status
=
STATUS_OPEN_ERROR
;
}
return
status
;
}
/**
* Creates new frame image from current data (and previous frames as specified by their disposition codes).
*/
protected
Bitmap
setPixels
(
int
frameIndex
)
{
GifFrame
currentFrame
=
frames
.
get
(
frameIndex
);
GifFrame
previousFrame
=
null
;
int
previousIndex
=
frameIndex
-
1
;
if
(
previousIndex
>=
0
)
{
previousFrame
=
frames
.
get
(
previousIndex
);
}
// final location of blended pixels
final
int
[]
dest
=
mainScratch
;
// fill in starting image contents based on last image's dispose code
long
disposeStartTime
=
System
.
currentTimeMillis
();
if
(
previousFrame
!=
null
&&
previousFrame
.
dispose
>
DISPOSAL_UNSPECIFIED
)
{
if
(
previousFrame
.
dispose
==
DISPOSAL_NONE
&&
currentImage
!=
null
)
{
// Start with the current image
currentImage
.
getPixels
(
dest
,
0
,
width
,
0
,
0
,
width
,
height
);
}
if
(
previousFrame
.
dispose
==
DISPOSAL_BACKGROUND
)
{
// Start with a canvas filled with the background color
int
c
=
0
;
if
(!
currentFrame
.
transparency
)
{
c
=
bgColor
;
}
for
(
int
i
=
0
;
i
<
previousFrame
.
ih
;
i
++)
{
int
n1
=
(
previousFrame
.
iy
+
i
)
*
width
+
previousFrame
.
ix
;
int
n2
=
n1
+
previousFrame
.
iw
;
for
(
int
k
=
n1
;
k
<
n2
;
k
++)
{
dest
[
k
]
=
c
;
}
}
}
}
else
{
int
c
=
0
;
if
(!
currentFrame
.
transparency
)
{
c
=
bgColor
;
}
for
(
int
i
=
0
;
i
<
dest
.
length
;
i
++)
{
dest
[
i
]
=
c
;
}
}
//Decode pixels for this frame into the global pixels[] scratch
long
start
=
System
.
currentTimeMillis
();
decodeBitmapData
(
currentFrame
,
mainPixels
);
// decode pixel data
// copy each source line to the appropriate place in the destination
long
startTime
=
System
.
currentTimeMillis
();
int
pass
=
1
;
int
inc
=
8
;
int
iline
=
0
;
for
(
int
i
=
0
;
i
<
currentFrame
.
ih
;
i
++)
{
int
line
=
i
;
if
(
currentFrame
.
interlace
)
{
if
(
iline
>=
currentFrame
.
ih
)
{
pass
++;
switch
(
pass
)
{
case
2
:
iline
=
4
;
break
;
case
3
:
iline
=
2
;
inc
=
4
;
break
;
case
4
:
iline
=
1
;
inc
=
2
;
break
;
default
:
break
;
}
}
line
=
iline
;
iline
+=
inc
;
}
line
+=
currentFrame
.
iy
;
if
(
line
<
height
)
{
int
k
=
line
*
width
;
int
dx
=
k
+
currentFrame
.
ix
;
// start of line in dest
int
dlim
=
dx
+
currentFrame
.
iw
;
// end of dest line
if
((
k
+
width
)
<
dlim
)
{
dlim
=
k
+
width
;
// past dest edge
}
int
sx
=
i
*
currentFrame
.
iw
;
// start of line in source
while
(
dx
<
dlim
)
{
// map color and insert in destination
int
index
=
((
int
)
mainPixels
[
sx
++])
&
0xff
;
int
c
=
act
[
index
];
if
(
c
!=
0
)
{
dest
[
dx
]
=
c
;
}
dx
++;
}
}
}
//Set pixels for current image
long
startSetPixelBitmap
=
System
.
currentTimeMillis
();
Bitmap
result
=
getNextBitmap
();
result
.
setPixels
(
dest
,
0
,
width
,
0
,
0
,
width
,
height
);
return
result
;
}
/**
* Decodes LZW image data into pixel array. Adapted from John Cristy's BitmapMagick.
*/
protected
void
decodeBitmapData
(
GifFrame
frame
,
byte
[]
dstPixels
)
{
if
(
frame
!=
null
)
{
//Jump to the frame start position
rawData
.
position
(
frame
.
bufferFrameStart
);
}
int
nullCode
=
-
1
;
int
npix
=
(
frame
==
null
)
?
width
*
height
:
frame
.
iw
*
frame
.
ih
;
int
available
,
clear
,
code_mask
,
code_size
,
end_of_information
,
in_code
,
old_code
,
bits
,
code
,
count
,
i
,
datum
,
data_size
,
first
,
top
,
bi
,
pi
;
if
(
dstPixels
==
null
||
dstPixels
.
length
<
npix
)
{
dstPixels
=
new
byte
[
npix
];
// allocate new pixel array
}
if
(
prefix
==
null
)
{
prefix
=
new
short
[
MAX_STACK_SIZE
];
}
if
(
suffix
==
null
)
{
suffix
=
new
byte
[
MAX_STACK_SIZE
];
}
if
(
pixelStack
==
null
)
{
pixelStack
=
new
byte
[
MAX_STACK_SIZE
+
1
];
}
// Initialize GIF data stream decoder.
data_size
=
read
();
clear
=
1
<<
data_size
;
end_of_information
=
clear
+
1
;
available
=
clear
+
2
;
old_code
=
nullCode
;
code_size
=
data_size
+
1
;
code_mask
=
(
1
<<
code_size
)
-
1
;
long
start
=
System
.
currentTimeMillis
();
for
(
code
=
0
;
code
<
clear
;
code
++)
{
prefix
[
code
]
=
0
;
// XXX ArrayIndexOutOfBoundsException
suffix
[
code
]
=
(
byte
)
code
;
}
start
=
System
.
currentTimeMillis
();
// Decode GIF pixel stream.
datum
=
bits
=
count
=
first
=
top
=
pi
=
bi
=
0
;
int
iterations
=
0
;
for
(
i
=
0
;
i
<
npix
;
)
{
iterations
++;
if
(
top
==
0
)
{
if
(
bits
<
code_size
)
{
// Load bytes until there are enough bits for a code.
if
(
count
==
0
)
{
// Read a new data block.
count
=
readBlock
();
if
(
count
<=
0
)
{
break
;
}
bi
=
0
;
}
datum
+=
(((
int
)
block
[
bi
])
&
0xff
)
<<
bits
;
bits
+=
8
;
bi
++;
count
--;
continue
;
}
// Get the next code.
code
=
datum
&
code_mask
;
datum
>>=
code_size
;
bits
-=
code_size
;
// Interpret the code
if
((
code
>
available
)
||
(
code
==
end_of_information
))
{
break
;
}
if
(
code
==
clear
)
{
// Reset decoder.
code_size
=
data_size
+
1
;
code_mask
=
(
1
<<
code_size
)
-
1
;
available
=
clear
+
2
;
old_code
=
nullCode
;
continue
;
}
if
(
old_code
==
nullCode
)
{
pixelStack
[
top
++]
=
suffix
[
code
];
old_code
=
code
;
first
=
code
;
continue
;
}
in_code
=
code
;
if
(
code
==
available
)
{
pixelStack
[
top
++]
=
(
byte
)
first
;
code
=
old_code
;
}
while
(
code
>
clear
)
{
pixelStack
[
top
++]
=
suffix
[
code
];
code
=
prefix
[
code
];
}
first
=
((
int
)
suffix
[
code
])
&
0xff
;
// Add a new string to the string table,
if
(
available
>=
MAX_STACK_SIZE
)
{
break
;
}
pixelStack
[
top
++]
=
(
byte
)
first
;
prefix
[
available
]
=
(
short
)
old_code
;
suffix
[
available
]
=
(
byte
)
first
;
available
++;
if
(((
available
&
code_mask
)
==
0
)
&&
(
available
<
MAX_STACK_SIZE
))
{
code_size
++;
code_mask
+=
available
;
}
old_code
=
in_code
;
}
// Pop a pixel off the pixel stack.
top
--;
dstPixels
[
pi
++]
=
pixelStack
[
top
];
i
++;
}
start
=
System
.
currentTimeMillis
();
for
(
i
=
pi
;
i
<
npix
;
i
++)
{
dstPixels
[
i
]
=
0
;
// clear missing pixels
}
}
/**
* Returns true if an error was encountered during reading/decoding
*/
protected
boolean
err
()
{
return
status
!=
STATUS_OK
;
}
/**
* Initializes or re-initializes reader
*/
protected
void
init
()
{
status
=
STATUS_OK
;
frameCount
=
0
;
framePointer
=
-
1
;
frames
=
new
ArrayList
<
GifFrame
>();
gct
=
null
;
}
/**
* Reads a single byte from the input stream.
*/
protected
int
read
()
{
int
curByte
=
0
;
try
{
curByte
=
(
rawData
.
get
()
&
0xFF
);
}
catch
(
Exception
e
)
{
status
=
STATUS_FORMAT_ERROR
;
}
return
curByte
;
}
/**
* Reads next variable length block from input.
*
* @return number of bytes stored in "buffer"
*/
protected
int
readBlock
()
{
blockSize
=
read
();
int
n
=
0
;
if
(
blockSize
>
0
)
{
try
{
int
count
;
while
(
n
<
blockSize
)
{
count
=
blockSize
-
n
;
rawData
.
get
(
block
,
n
,
count
);
n
+=
count
;
}
}
catch
(
Exception
e
)
{
Log
.
w
(
TAG
,
"Error Reading Block"
,
e
);
status
=
STATUS_FORMAT_ERROR
;
}
}
return
n
;
}
/**
* Reads color table as 256 RGB integer values
*
* @param ncolors int number of colors to read
* @return int array containing 256 colors (packed ARGB with full alpha)
*/
protected
int
[]
readColorTable
(
int
ncolors
)
{
int
nbytes
=
3
*
ncolors
;
int
[]
tab
=
null
;
byte
[]
c
=
new
byte
[
nbytes
];
try
{
rawData
.
get
(
c
);
tab
=
new
int
[
256
];
// max size to avoid bounds checks
int
i
=
0
;
int
j
=
0
;
while
(
i
<
ncolors
)
{
int
r
=
((
int
)
c
[
j
++])
&
0xff
;
int
g
=
((
int
)
c
[
j
++])
&
0xff
;
int
b
=
((
int
)
c
[
j
++])
&
0xff
;
tab
[
i
++]
=
0xff000000
|
(
r
<<
16
)
|
(
g
<<
8
)
|
b
;
}
}
catch
(
BufferUnderflowException
e
)
{
Log
.
w
(
TAG
,
"Format Error Reading Color Table"
,
e
);
status
=
STATUS_FORMAT_ERROR
;
}
return
tab
;
}
/**
* Main file parser. Reads GIF content blocks.
*/
protected
void
readContents
()
{
// read GIF file content blocks
boolean
done
=
false
;
while
(!(
done
||
err
()))
{
int
code
=
read
();
switch
(
code
)
{
case
0x2C
:
// image separator
readBitmap
();
break
;
case
0x21
:
// extension
code
=
read
();
switch
(
code
)
{
case
0xf9
:
// graphics control extension
//Start a new frame
currentFrame
=
new
GifFrame
();
readGraphicControlExt
();
break
;
case
0xff
:
// application extension
readBlock
();
String
app
=
""
;
for
(
int
i
=
0
;
i
<
11
;
i
++)
{
app
+=
(
char
)
block
[
i
];
}
if
(
app
.
equals
(
"NETSCAPE2.0"
))
{
readNetscapeExt
();
}
else
{
skip
();
// don't care
}
break
;
case
0xfe
:
// comment extension
skip
();
break
;
case
0x01
:
// plain text extension
skip
();
break
;
default
:
// uninteresting extension
skip
();
}
break
;
case
0x3b
:
// terminator
done
=
true
;
break
;
case
0x00
:
// bad byte, but keep going and see what happens break;
default
:
status
=
STATUS_FORMAT_ERROR
;
}
}
}
/**
* Reads GIF file header information.
*/
protected
void
readHeader
()
{
String
id
=
""
;
for
(
int
i
=
0
;
i
<
6
;
i
++)
{
id
+=
(
char
)
read
();
}
if
(!
id
.
startsWith
(
"GIF"
))
{
status
=
STATUS_FORMAT_ERROR
;
return
;
}
readLSD
();
if
(
gctFlag
&&
!
err
())
{
gct
=
readColorTable
(
gctSize
);
bgColor
=
gct
[
bgIndex
];
}
}
/**
* Reads Graphics Control Extension values
*/
protected
void
readGraphicControlExt
()
{
read
();
// block size
int
packed
=
read
();
// packed fields
currentFrame
.
dispose
=
(
packed
&
0x1c
)
>>
2
;
// disposal method
if
(
currentFrame
.
dispose
==
0
)
{
currentFrame
.
dispose
=
1
;
// elect to keep old image if discretionary
}
currentFrame
.
transparency
=
(
packed
&
1
)
!=
0
;
isTransparent
|=
currentFrame
.
transparency
;
currentFrame
.
delay
=
readShort
()
*
10
;
// delay in milliseconds
currentFrame
.
transIndex
=
read
();
// transparent color index
read
();
// block terminator
}
/**
* Reads next frame image
*/
protected
void
readBitmap
()
{
currentFrame
.
ix
=
readShort
();
// (sub)image position & size
currentFrame
.
iy
=
readShort
();
currentFrame
.
iw
=
readShort
();
currentFrame
.
ih
=
readShort
();
int
packed
=
read
();
lctFlag
=
(
packed
&
0x80
)
!=
0
;
// 1 - local color table flag interlace
lctSize
=
(
int
)
Math
.
pow
(
2
,
(
packed
&
0x07
)
+
1
);
// 3 - sort flag
// 4-5 - reserved lctSize = 2 << (packed & 7); // 6-8 - local color
// table size
currentFrame
.
interlace
=
(
packed
&
0x40
)
!=
0
;
if
(
lctFlag
)
{
currentFrame
.
lct
=
readColorTable
(
lctSize
);
// read table
}
else
{
currentFrame
.
lct
=
null
;
//No local color table
}
currentFrame
.
bufferFrameStart
=
rawData
.
position
();
//Save this as the decoding position pointer
decodeBitmapData
(
null
,
mainPixels
);
// false decode pixel data to advance buffer
skip
();
if
(
err
())
{
return
;
}
frameCount
++;
frames
.
add
(
currentFrame
);
// add image to frame
}
/**
* Reads Logical Screen Descriptor
*/
protected
void
readLSD
()
{
// logical screen size
width
=
readShort
();
height
=
readShort
();
// packed fields
int
packed
=
read
();
gctFlag
=
(
packed
&
0x80
)
!=
0
;
// 1 : global color table flag
// 2-4 : color resolution
// 5 : gct sort flag
gctSize
=
2
<<
(
packed
&
7
);
// 6-8 : gct size
bgIndex
=
read
();
// background color index
pixelAspect
=
read
();
// pixel aspect ratio
//Now that we know the size, init scratch arrays
mainPixels
=
new
byte
[
width
*
height
];
mainScratch
=
new
int
[
width
*
height
];
}
private
Bitmap
getNextBitmap
()
{
Bitmap
.
Config
targetConfig
=
isTransparent
?
Bitmap
.
Config
.
ARGB_8888
:
Bitmap
.
Config
.
RGB_565
;
Bitmap
result
=
bitmapPool
.
get
(
width
,
height
,
targetConfig
);
if
(
result
==
null
)
{
result
=
Bitmap
.
createBitmap
(
width
,
height
,
targetConfig
);
}
return
result
;
}
/**
* Reads Netscape extenstion to obtain iteration count
*/
protected
void
readNetscapeExt
()
{
do
{
readBlock
();
if
(
block
[
0
]
==
1
)
{
// loop count sub-block
int
b1
=
((
int
)
block
[
1
])
&
0xff
;
int
b2
=
((
int
)
block
[
2
])
&
0xff
;
loopCount
=
(
b2
<<
8
)
|
b1
;
}
}
while
((
blockSize
>
0
)
&&
!
err
());
}
/**
* Reads next 16-bit value, LSB first
*/
protected
int
readShort
()
{
// read 16-bit value
return
rawData
.
getShort
();
}
/**
* Skips variable length blocks up to and including next zero length block.
*/
protected
void
skip
()
{
do
{
readBlock
();
}
while
((
blockSize
>
0
)
&&
!
err
());
}
}
library/src/main/java/com/bumptech/glide/load/resource/gif/GifDrawable.java
0 → 100644
浏览文件 @
ea01ddd7
package
com.bumptech.glide.load.resource.gif
;
import
android.graphics.Bitmap
;
import
android.graphics.Canvas
;
import
android.graphics.ColorFilter
;
import
android.graphics.Paint
;
import
android.graphics.PixelFormat
;
import
android.graphics.drawable.Animatable
;
import
android.graphics.drawable.Drawable
;
public
class
GifDrawable
extends
Drawable
implements
Animatable
,
GifFrameManager
.
FrameCallback
{
private
final
Paint
paint
;
private
final
GifFrameManager
frameManager
;
private
GifDecoder
decoder
;
private
boolean
isRunning
;
private
Bitmap
currentFrame
;
public
GifDrawable
(
GifDecoder
decoder
,
GifFrameManager
frameManager
)
{
this
.
decoder
=
decoder
;
this
.
frameManager
=
frameManager
;
paint
=
new
Paint
();
}
GifDecoder
getDecoder
()
{
return
decoder
;
}
@Override
public
void
start
()
{
if
(!
isRunning
)
{
isRunning
=
true
;
frameManager
.
getNextFrame
(
decoder
,
this
);
invalidateSelf
();
}
}
@Override
public
boolean
setVisible
(
boolean
visible
,
boolean
restart
)
{
if
(!
visible
)
{
stop
();
}
else
{
start
();
}
return
super
.
setVisible
(
visible
,
restart
);
}
@Override
public
int
getIntrinsicWidth
()
{
return
decoder
.
getWidth
();
}
@Override
public
int
getIntrinsicHeight
()
{
return
decoder
.
getHeight
();
}
@Override
public
void
stop
()
{
isRunning
=
false
;
}
@Override
public
boolean
isRunning
()
{
return
isRunning
;
}
// For testing.
void
setIsRunning
(
boolean
isRunning
)
{
this
.
isRunning
=
isRunning
;
}
@Override
public
void
draw
(
Canvas
canvas
)
{
if
(
currentFrame
!=
null
)
{
canvas
.
drawBitmap
(
currentFrame
,
0
,
0
,
paint
);
}
}
@Override
public
void
setAlpha
(
int
i
)
{
paint
.
setAlpha
(
i
);
}
@Override
public
void
setColorFilter
(
ColorFilter
colorFilter
)
{
paint
.
setColorFilter
(
colorFilter
);
}
@Override
public
int
getOpacity
()
{
return
decoder
.
isTransparent
()
?
PixelFormat
.
TRANSPARENT
:
PixelFormat
.
OPAQUE
;
}
@Override
public
void
onFrameRead
(
Bitmap
frame
)
{
if
(!
isRunning
)
{
return
;
}
if
(
frame
!=
null
)
{
currentFrame
=
frame
;
invalidateSelf
();
}
frameManager
.
getNextFrame
(
decoder
,
this
);
}
public
void
recycle
()
{
frameManager
.
clear
();
}
}
library/src/main/java/com/bumptech/glide/load/resource/gif/GifFrameLoader.java
0 → 100644
浏览文件 @
ea01ddd7
package
com.bumptech.glide.load.resource.gif
;
import
com.bumptech.glide.Priority
;
import
com.bumptech.glide.load.data.DataFetcher
;
import
com.bumptech.glide.load.model.ModelLoader
;
public
class
GifFrameLoader
implements
ModelLoader
<
GifDecoder
,
GifDecoder
>
{
private
String
gifId
;
//TODO: this should be in the model.
public
GifFrameLoader
(
String
gifId
)
{
this
.
gifId
=
gifId
;
}
@Override
public
DataFetcher
<
GifDecoder
>
getResourceFetcher
(
GifDecoder
model
,
int
width
,
int
height
)
{
return
new
GifFrameDataFetcher
(
model
);
}
@Override
public
String
getId
(
GifDecoder
model
)
{
return
gifId
+
model
.
getCurrentFrameIndex
();
}
private
static
class
GifFrameDataFetcher
implements
DataFetcher
<
GifDecoder
>
{
private
GifDecoder
decoder
;
public
GifFrameDataFetcher
(
GifDecoder
decoder
)
{
this
.
decoder
=
decoder
;
}
@Override
public
GifDecoder
loadData
(
Priority
priority
)
throws
Exception
{
return
decoder
;
}
@Override
public
void
cleanup
()
{
}
@Override
public
void
cancel
()
{
}
}
}
library/src/main/java/com/bumptech/glide/load/resource/gif/GifFrameManager.java
0 → 100644
浏览文件 @
ea01ddd7
package
com.bumptech.glide.load.resource.gif
;
import
android.content.Context
;
import
android.graphics.Bitmap
;
import
android.os.Handler
;
import
android.os.Looper
;
import
android.os.SystemClock
;
import
com.bumptech.glide.Glide
;
import
com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool
;
import
com.bumptech.glide.load.engine.cache.MemorySizeCalculator
;
import
com.bumptech.glide.load.resource.bitmap.StreamBitmapDecoder
;
import
com.bumptech.glide.request.target.SimpleTarget
;
import
java.util.UUID
;
class
GifFrameManager
{
static
final
long
MIN_FRAME_DELAY
=
16
;
private
final
String
id
;
private
final
MemorySizeCalculator
calculator
;
private
BitmapPool
bitmapPool
;
private
final
Handler
mainHandler
;
private
Context
context
;
private
DelayTarget
current
;
private
DelayTarget
next
;
public
interface
FrameCallback
{
public
void
onFrameRead
(
Bitmap
frame
);
}
public
GifFrameManager
(
Context
context
,
BitmapPool
bitmapPool
)
{
this
(
context
,
UUID
.
randomUUID
().
toString
(),
bitmapPool
,
new
Handler
(
Looper
.
getMainLooper
()));
}
public
GifFrameManager
(
Context
context
,
String
id
,
BitmapPool
bitmapPool
,
Handler
mainHandler
)
{
this
.
context
=
context
;
this
.
id
=
id
;
this
.
bitmapPool
=
bitmapPool
;
this
.
mainHandler
=
mainHandler
;
calculator
=
new
MemorySizeCalculator
(
context
);
}
public
void
getNextFrame
(
final
GifDecoder
decoder
,
FrameCallback
cb
)
{
decoder
.
advance
();
boolean
skipCache
=
decoder
.
getDecodedFrameByteSize
()
>
calculator
.
getMemoryCacheSize
()
/
2
;
long
targetTime
=
SystemClock
.
uptimeMillis
()
+
(
Math
.
min
(
MIN_FRAME_DELAY
,
decoder
.
getNextDelay
()));
next
=
new
DelayTarget
(
decoder
,
cb
,
targetTime
,
mainHandler
);
Glide
.
with
(
context
)
.
using
(
new
GifFrameLoader
(
id
),
GifDecoder
.
class
)
.
load
(
decoder
)
.
as
(
Bitmap
.
class
)
.
decoder
(
new
GifFrameResourceDecoder
())
.
cacheDecoder
(
new
StreamBitmapDecoder
(
bitmapPool
))
.
skipMemoryCache
(
skipCache
)
.
skipDiskCache
(
true
)
.
into
(
next
);
}
public
void
clear
()
{
if
(
current
!=
null
)
{
Glide
.
clear
(
current
);
mainHandler
.
removeCallbacks
(
current
);
}
if
(
next
!=
null
)
{
Glide
.
clear
(
next
);
mainHandler
.
removeCallbacks
(
next
);
}
}
class
DelayTarget
extends
SimpleTarget
<
Bitmap
>
implements
Runnable
{
private
FrameCallback
cb
;
private
long
targetTime
;
private
Handler
mainHandler
;
private
Bitmap
resource
;
public
DelayTarget
(
GifDecoder
decoder
,
FrameCallback
cb
,
long
targetTime
,
Handler
mainHandler
)
{
super
(
decoder
.
getWidth
(),
decoder
.
getHeight
());
this
.
cb
=
cb
;
this
.
targetTime
=
targetTime
;
this
.
mainHandler
=
mainHandler
;
}
@Override
public
void
onResourceReady
(
final
Bitmap
resource
)
{
this
.
resource
=
resource
;
mainHandler
.
postAtTime
(
this
,
targetTime
);
if
(
current
!=
null
)
{
Glide
.
clear
(
current
);
}
current
=
next
;
next
=
null
;
}
@Override
public
void
run
()
{
cb
.
onFrameRead
(
resource
);
}
}
}
library/src/main/java/com/bumptech/glide/load/resource/gif/GifFrameResourceDecoder.java
0 → 100644
浏览文件 @
ea01ddd7
package
com.bumptech.glide.load.resource.gif
;
import
android.graphics.Bitmap
;
import
com.bumptech.glide.Resource
;
import
com.bumptech.glide.load.ResourceDecoder
;
import
java.io.IOException
;
class
GifFrameResourceDecoder
implements
ResourceDecoder
<
GifDecoder
,
Bitmap
>
{
@Override
public
Resource
<
Bitmap
>
decode
(
GifDecoder
source
,
int
width
,
int
height
)
throws
IOException
{
return
source
.
getNextFrame
();
}
@Override
public
String
getId
()
{
return
"GifFrameResourceDecoder.com.bumptech.glide.load.resource.gif"
;
}
}
library/src/main/java/com/bumptech/glide/load/resource/gif/GifResource.java
0 → 100644
浏览文件 @
ea01ddd7
package
com.bumptech.glide.load.resource.gif
;
import
com.bumptech.glide.Resource
;
//TODO: make this safe for multiple consumers.
public
class
GifResource
extends
Resource
<
GifDrawable
>
{
private
final
GifDrawable
drawable
;
private
final
GifDecoder
decoder
;
public
GifResource
(
GifDecoder
decoder
,
GifFrameManager
frameManager
)
{
this
(
decoder
,
new
GifDrawable
(
decoder
,
frameManager
));
}
GifResource
(
GifDecoder
gifDecoder
,
GifDrawable
gifDrawable
)
{
decoder
=
gifDecoder
;
drawable
=
gifDrawable
;
}
@Override
public
GifDrawable
get
()
{
return
drawable
;
}
@Override
public
int
getSize
()
{
return
decoder
.
getGifByteSize
();
}
@Override
protected
void
recycleInternal
()
{
drawable
.
stop
();
drawable
.
recycle
();
}
}
library/src/main/java/com/bumptech/glide/load/resource/gif/GifResourceDecoder.java
0 → 100644
浏览文件 @
ea01ddd7
package
com.bumptech.glide.load.resource.gif
;
import
android.content.Context
;
import
com.bumptech.glide.Glide
;
import
com.bumptech.glide.load.ResourceDecoder
;
import
com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool
;
import
java.io.IOException
;
import
java.io.InputStream
;
public
class
GifResourceDecoder
implements
ResourceDecoder
<
InputStream
,
GifDrawable
>
{
private
Context
context
;
private
BitmapPool
bitmapPool
;
public
GifResourceDecoder
(
Context
context
)
{
this
(
context
,
Glide
.
get
(
context
).
getBitmapPool
());
}
public
GifResourceDecoder
(
Context
context
,
BitmapPool
bitmapPool
)
{
this
.
context
=
context
;
this
.
bitmapPool
=
bitmapPool
;
}
@Override
public
GifResource
decode
(
InputStream
source
,
int
width
,
int
height
)
throws
IOException
{
GifDecoder
gifDecoder
=
new
GifDecoder
(
bitmapPool
);
gifDecoder
.
read
(
source
,
0
);
GifFrameManager
frameManager
=
new
GifFrameManager
(
context
,
bitmapPool
);
return
new
GifResource
(
gifDecoder
,
frameManager
);
}
@Override
public
String
getId
()
{
return
"GifResourceDecoder.com.bumptech.glide.load.gif"
;
}
}
library/src/main/java/com/bumptech/glide/load/resource/gif/GifResourceEncoder.java
0 → 100644
浏览文件 @
ea01ddd7
package
com.bumptech.glide.load.resource.gif
;
import
android.util.Log
;
import
com.bumptech.glide.Resource
;
import
com.bumptech.glide.load.ResourceEncoder
;
import
java.io.IOException
;
import
java.io.OutputStream
;
public
class
GifResourceEncoder
implements
ResourceEncoder
<
GifDrawable
>
{
private
static
final
String
TAG
=
"GifEncoder"
;
@Override
public
boolean
encode
(
Resource
<
GifDrawable
>
resource
,
OutputStream
os
)
{
boolean
result
=
true
;
try
{
os
.
write
(
resource
.
get
().
getDecoder
().
getData
());
}
catch
(
IOException
e
)
{
if
(
Log
.
isLoggable
(
TAG
,
Log
.
DEBUG
))
{
Log
.
d
(
TAG
,
"Failed to encode gif"
,
e
);
}
result
=
false
;
}
return
result
;
}
@Override
public
String
getId
()
{
return
"GifEncoder.com.bumptech.glide.load.resource.gif"
;
}
}
library/src/main/java/com/bumptech/glide/load/resource/transcode/GifBitmapDrawableTranscoder.java
0 → 100644
浏览文件 @
ea01ddd7
package
com.bumptech.glide.load.resource.transcode
;
import
android.content.Context
;
import
android.content.res.Resources
;
import
android.graphics.Bitmap
;
import
android.graphics.drawable.BitmapDrawable
;
import
android.graphics.drawable.Drawable
;
import
com.bumptech.glide.Resource
;
import
com.bumptech.glide.load.resource.drawable.DrawableResource
;
import
com.bumptech.glide.load.resource.drawable.GifBitmap
;
public
class
GifBitmapDrawableTranscoder
implements
ResourceTranscoder
<
GifBitmap
,
Drawable
>
{
private
final
Resources
resources
;
public
GifBitmapDrawableTranscoder
(
Context
context
)
{
resources
=
context
.
getResources
();
}
@Override
public
Resource
<
Drawable
>
transcode
(
Resource
<
GifBitmap
>
toTranscode
)
{
GifBitmap
gifBitmap
=
toTranscode
.
get
();
Resource
<
Bitmap
>
bitmapResource
=
gifBitmap
.
getBitmapResource
();
final
Resource
resource
;
final
Drawable
drawable
;
if
(
bitmapResource
!=
null
)
{
resource
=
bitmapResource
;
drawable
=
new
BitmapDrawable
(
resources
,
bitmapResource
.
get
());
}
else
{
resource
=
gifBitmap
.
getGifResource
();
drawable
=
gifBitmap
.
getGifResource
().
get
();
}
return
new
DrawableResource
(
drawable
,
resource
);
}
@Override
public
String
getId
()
{
return
"GifBitmapDrawableTranscoder.com.bumptech.glide.load.resource.transcode"
;
}
}
library/src/test/java/com/bumptech/glide/load/resource/drawable/DrawableResourceTest.java
0 → 100644
浏览文件 @
ea01ddd7
package
com.bumptech.glide.load.resource.drawable
;
import
android.graphics.Color
;
import
android.graphics.drawable.ColorDrawable
;
import
com.bumptech.glide.Resource
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.robolectric.RobolectricTestRunner
;
import
static
junit
.
framework
.
Assert
.
assertEquals
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
mockito
.
Mockito
.
verify
;
import
static
org
.
mockito
.
Mockito
.
when
;
@RunWith
(
RobolectricTestRunner
.
class
)
public
class
DrawableResourceTest
{
private
ColorDrawable
drawable
;
private
DrawableResource
resource
;
private
Resource
wrapped
;
@Before
public
void
setUp
()
{
drawable
=
new
ColorDrawable
(
Color
.
RED
);
wrapped
=
mock
(
Resource
.
class
);
resource
=
new
DrawableResource
(
drawable
,
wrapped
);
}
@Test
public
void
testReturnsGivenSize
()
{
final
int
size
=
100
;
when
(
wrapped
.
getSize
()).
thenReturn
(
size
);
assertEquals
(
size
,
resource
.
getSize
());
}
@Test
public
void
testGetReturnsGivenDrawable
()
{
assertEquals
(
drawable
,
resource
.
get
());
}
@Test
public
void
testRecyclesWrappedWhenRecycled
()
{
resource
.
recycleInternal
();
verify
(
wrapped
).
recycle
();
}
}
library/src/test/java/com/bumptech/glide/load/resource/drawable/GifBitmapResourceDecoderTest.java
0 → 100644
浏览文件 @
ea01ddd7
package
com.bumptech.glide.load.resource.drawable
;
import
android.graphics.Bitmap
;
import
android.graphics.drawable.BitmapDrawable
;
import
android.os.ParcelFileDescriptor
;
import
com.bumptech.glide.Resource
;
import
com.bumptech.glide.load.ResourceDecoder
;
import
com.bumptech.glide.load.model.ImageVideoWrapper
;
import
com.bumptech.glide.load.resource.gif.GifDrawable
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.robolectric.Robolectric
;
import
org.robolectric.RobolectricTestRunner
;
import
java.io.ByteArrayInputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
static
junit
.
framework
.
Assert
.
assertEquals
;
import
static
org
.
mockito
.
Matchers
.
any
;
import
static
org
.
mockito
.
Matchers
.
anyInt
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
mockito
.
Mockito
.
when
;
@RunWith
(
RobolectricTestRunner
.
class
)
public
class
GifBitmapResourceDecoderTest
{
private
ResourceDecoder
<
ImageVideoWrapper
,
Bitmap
>
bitmapDecoder
;
private
ResourceDecoder
<
InputStream
,
GifDrawable
>
gifDecoder
;
private
GifBitmapResourceDecoder
decoder
;
@SuppressWarnings
(
"unchecked"
)
@Before
public
void
setUp
()
{
bitmapDecoder
=
mock
(
ResourceDecoder
.
class
);
gifDecoder
=
mock
(
ResourceDecoder
.
class
);
decoder
=
new
GifBitmapResourceDecoder
(
Robolectric
.
application
,
bitmapDecoder
,
gifDecoder
);
}
@Test
public
void
testDecoderUsesGifDecoderResultIfGif
()
throws
IOException
{
GifDrawable
expected
=
mock
(
GifDrawable
.
class
);
Resource
<
GifDrawable
>
gifDrawableResource
=
mock
(
Resource
.
class
);
when
(
gifDrawableResource
.
get
()).
thenReturn
(
expected
);
when
(
gifDecoder
.
decode
(
any
(
InputStream
.
class
),
anyInt
(),
anyInt
())).
thenReturn
(
gifDrawableResource
);
byte
[]
data
=
new
byte
[]
{
'G'
,
'I'
,
'F'
};
ImageVideoWrapper
wrapper
=
new
ImageVideoWrapper
(
new
ByteArrayInputStream
(
data
),
null
);
Resource
<
GifBitmap
>
result
=
decoder
.
decode
(
wrapper
,
100
,
100
);
assertEquals
(
expected
,
result
.
get
().
getDrawable
());
}
@Test
public
void
testDecoderUsesBitmapDecoderIfStreamIsNotGif
()
throws
IOException
{
Bitmap
expected
=
Bitmap
.
createBitmap
(
100
,
100
,
Bitmap
.
Config
.
ARGB_8888
);
Resource
<
Bitmap
>
bitmapResource
=
mock
(
Resource
.
class
);
when
(
bitmapResource
.
get
()).
thenReturn
(
expected
);
when
(
bitmapDecoder
.
decode
(
any
(
ImageVideoWrapper
.
class
),
anyInt
(),
anyInt
())).
thenReturn
(
bitmapResource
);
byte
[]
data
=
new
byte
[]
{
'A'
,
'I'
,
'F'
};
ImageVideoWrapper
wrapper
=
new
ImageVideoWrapper
(
new
ByteArrayInputStream
(
data
),
null
);
Resource
<
GifBitmap
>
result
=
decoder
.
decode
(
wrapper
,
100
,
100
);
BitmapDrawable
bitmapDrawable
=
(
BitmapDrawable
)
result
.
get
().
getDrawable
();
assertEquals
(
expected
,
bitmapDrawable
.
getBitmap
());
}
@Test
public
void
testDecoderUsesBitmapDecoderIfIsFileDescriptor
()
throws
IOException
{
Bitmap
expected
=
Bitmap
.
createBitmap
(
100
,
100
,
Bitmap
.
Config
.
ARGB_8888
);
Resource
<
Bitmap
>
bitmapResource
=
mock
(
Resource
.
class
);
when
(
bitmapResource
.
get
()).
thenReturn
(
expected
);
when
(
bitmapDecoder
.
decode
(
any
(
ImageVideoWrapper
.
class
),
anyInt
(),
anyInt
())).
thenReturn
(
bitmapResource
);
ImageVideoWrapper
wrapper
=
new
ImageVideoWrapper
(
null
,
mock
(
ParcelFileDescriptor
.
class
));
Resource
<
GifBitmap
>
result
=
decoder
.
decode
(
wrapper
,
100
,
100
);
BitmapDrawable
bitmapDrawable
=
(
BitmapDrawable
)
result
.
get
().
getDrawable
();
assertEquals
(
expected
,
bitmapDrawable
.
getBitmap
());
}
}
library/src/test/java/com/bumptech/glide/load/resource/drawable/GifBitmapResourceEncoderTest.java
0 → 100644
浏览文件 @
ea01ddd7
package
com.bumptech.glide.load.resource.drawable
;
import
android.graphics.Bitmap
;
import
com.bumptech.glide.Resource
;
import
com.bumptech.glide.load.ResourceEncoder
;
import
com.bumptech.glide.load.resource.gif.GifDrawable
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.robolectric.RobolectricTestRunner
;
import
java.io.ByteArrayOutputStream
;
import
java.io.OutputStream
;
import
static
junit
.
framework
.
Assert
.
assertFalse
;
import
static
junit
.
framework
.
Assert
.
assertNotNull
;
import
static
junit
.
framework
.
Assert
.
assertTrue
;
import
static
org
.
mockito
.
Matchers
.
any
;
import
static
org
.
mockito
.
Matchers
.
eq
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
mockito
.
Mockito
.
verify
;
import
static
org
.
mockito
.
Mockito
.
when
;
@RunWith
(
RobolectricTestRunner
.
class
)
public
class
GifBitmapResourceEncoderTest
{
private
ResourceEncoder
<
Bitmap
>
bitmapEncoder
;
private
ResourceEncoder
<
GifDrawable
>
gifEncoder
;
private
GifBitmapResourceEncoder
encoder
;
private
Resource
<
GifBitmap
>
resource
;
private
GifBitmap
gifBitmap
;
@SuppressWarnings
(
"unchecked"
)
@Before
public
void
setUp
()
{
bitmapEncoder
=
mock
(
ResourceEncoder
.
class
);
gifEncoder
=
mock
(
ResourceEncoder
.
class
);
encoder
=
new
GifBitmapResourceEncoder
(
bitmapEncoder
,
gifEncoder
);
resource
=
mock
(
Resource
.
class
);
gifBitmap
=
mock
(
GifBitmap
.
class
);
when
(
resource
.
get
()).
thenReturn
(
gifBitmap
);
}
@Test
public
void
testEncodesWithBitmapEncoderIfHasBitmapResource
()
{
Resource
<
Bitmap
>
bitmapResource
=
mock
(
Resource
.
class
);
when
(
gifBitmap
.
getBitmapResource
()).
thenReturn
(
bitmapResource
);
ByteArrayOutputStream
os
=
new
ByteArrayOutputStream
();
encoder
.
encode
(
resource
,
os
);
verify
(
bitmapEncoder
).
encode
(
eq
(
bitmapResource
),
eq
(
os
));
}
@Test
public
void
testReturnsBitmapEncoderResultIfHasBitmapResource
()
{
Resource
<
Bitmap
>
bitmapResource
=
mock
(
Resource
.
class
);
when
(
gifBitmap
.
getBitmapResource
()).
thenReturn
(
bitmapResource
);
when
(
bitmapEncoder
.
encode
(
any
(
Resource
.
class
),
any
(
OutputStream
.
class
))).
thenReturn
(
true
);
assertTrue
(
encoder
.
encode
(
resource
,
new
ByteArrayOutputStream
()));
when
(
bitmapEncoder
.
encode
(
any
(
Resource
.
class
),
any
(
OutputStream
.
class
))).
thenReturn
(
false
);
assertFalse
(
encoder
.
encode
(
resource
,
new
ByteArrayOutputStream
()));
}
@Test
public
void
testEncodesWithGifEncoderIfHasGif
()
{
Resource
<
GifDrawable
>
gifResource
=
mock
(
Resource
.
class
);
when
(
gifBitmap
.
getGifResource
()).
thenReturn
(
gifResource
);
ByteArrayOutputStream
os
=
new
ByteArrayOutputStream
();
encoder
.
encode
(
resource
,
os
);
verify
(
gifEncoder
).
encode
(
eq
(
gifResource
),
eq
(
os
));
}
@Test
public
void
testReturnsGifEncoderResultIfHasGifResource
()
{
Resource
<
GifDrawable
>
gifResource
=
mock
(
Resource
.
class
);
when
(
gifBitmap
.
getGifResource
()).
thenReturn
(
gifResource
);
when
(
gifEncoder
.
encode
(
any
(
Resource
.
class
),
any
(
OutputStream
.
class
))).
thenReturn
(
true
);
assertTrue
(
encoder
.
encode
(
resource
,
new
ByteArrayOutputStream
()));
when
(
gifEncoder
.
encode
(
any
(
Resource
.
class
),
any
(
OutputStream
.
class
))).
thenReturn
(
false
);
assertFalse
(
encoder
.
encode
(
resource
,
new
ByteArrayOutputStream
()));
}
@Test
public
void
testReturnsNonNullId
()
{
assertNotNull
(
encoder
.
getId
());
}
}
library/src/test/java/com/bumptech/glide/load/resource/drawable/GifBitmapStreamResourceDecoderTest.java
0 → 100644
浏览文件 @
ea01ddd7
package
com.bumptech.glide.load.resource.drawable
;
import
com.bumptech.glide.Resource
;
import
com.bumptech.glide.load.ResourceDecoder
;
import
com.bumptech.glide.load.model.ImageVideoWrapper
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.mockito.invocation.InvocationOnMock
;
import
org.mockito.stubbing.Answer
;
import
java.io.ByteArrayInputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
static
junit
.
framework
.
Assert
.
assertEquals
;
import
static
junit
.
framework
.
Assert
.
assertNotNull
;
import
static
org
.
mockito
.
Matchers
.
any
;
import
static
org
.
mockito
.
Matchers
.
anyInt
;
import
static
org
.
mockito
.
Matchers
.
eq
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
mockito
.
Mockito
.
when
;
public
class
GifBitmapStreamResourceDecoderTest
{
ResourceDecoder
<
ImageVideoWrapper
,
GifBitmap
>
gifBitmapDecoder
;
private
GifBitmapStreamResourceDecoder
decoder
;
@SuppressWarnings
(
"unchecked"
)
@Before
public
void
setUp
()
{
gifBitmapDecoder
=
mock
(
ResourceDecoder
.
class
);
decoder
=
new
GifBitmapStreamResourceDecoder
(
gifBitmapDecoder
);
}
@Test
public
void
testReturnsWrappedDecoderResult
()
throws
IOException
{
int
width
=
100
;
int
height
=
110
;
Resource
<
GifBitmap
>
expected
=
mock
(
Resource
.
class
);
when
(
gifBitmapDecoder
.
decode
(
any
(
ImageVideoWrapper
.
class
),
eq
(
width
),
eq
(
height
))).
thenReturn
(
expected
);
assertEquals
(
expected
,
decoder
.
decode
(
new
ByteArrayInputStream
(
new
byte
[
0
]),
width
,
height
));
}
@Test
public
void
testPassesGivenInputStreamWrappedAsImageVideoWrapper
()
throws
IOException
{
final
InputStream
expected
=
new
ByteArrayInputStream
(
new
byte
[
0
]);
when
(
gifBitmapDecoder
.
decode
(
any
(
ImageVideoWrapper
.
class
),
anyInt
(),
anyInt
())).
thenAnswer
(
new
Answer
<
Object
>()
{
@Override
public
Object
answer
(
InvocationOnMock
invocation
)
throws
Throwable
{
ImageVideoWrapper
wrapper
=
(
ImageVideoWrapper
)
invocation
.
getArguments
()[
0
];
assertEquals
(
expected
,
wrapper
.
getStream
());
return
null
;
}
});
decoder
.
decode
(
expected
,
1
,
2
);
}
@Test
public
void
testReturnsNonNullId
()
{
assertNotNull
(
decoder
.
getId
());
}
}
library/src/test/java/com/bumptech/glide/load/resource/gif/GifDrawableTest.java
0 → 100644
浏览文件 @
ea01ddd7
package
com.bumptech.glide.load.resource.gif
;
import
android.graphics.Bitmap
;
import
android.graphics.Canvas
;
import
android.graphics.Paint
;
import
android.graphics.PixelFormat
;
import
android.graphics.drawable.Drawable
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.robolectric.RobolectricTestRunner
;
import
static
junit
.
framework
.
Assert
.
assertEquals
;
import
static
junit
.
framework
.
Assert
.
assertFalse
;
import
static
junit
.
framework
.
Assert
.
assertTrue
;
import
static
org
.
mockito
.
Matchers
.
any
;
import
static
org
.
mockito
.
Matchers
.
anyInt
;
import
static
org
.
mockito
.
Matchers
.
eq
;
import
static
org
.
mockito
.
Matchers
.
isNull
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
mockito
.
Mockito
.
never
;
import
static
org
.
mockito
.
Mockito
.
times
;
import
static
org
.
mockito
.
Mockito
.
verify
;
import
static
org
.
mockito
.
Mockito
.
when
;
@RunWith
(
RobolectricTestRunner
.
class
)
public
class
GifDrawableTest
{
private
GifDecoder
gifDecoder
;
private
GifDrawable
drawable
;
private
GifFrameManager
frameManager
=
mock
(
GifFrameManager
.
class
);
private
Drawable
.
Callback
cb
=
mock
(
Drawable
.
Callback
.
class
);
@Before
public
void
setUp
()
{
gifDecoder
=
mock
(
GifDecoder
.
class
);
drawable
=
new
GifDrawable
(
gifDecoder
,
frameManager
);
drawable
.
setCallback
(
cb
);
}
@Test
public
void
testReturnsDecoderWidth
()
{
int
width
=
123
;
when
(
gifDecoder
.
getWidth
()).
thenReturn
(
width
);
assertEquals
(
width
,
drawable
.
getIntrinsicWidth
());
}
@Test
public
void
testReturnsDecoderHeight
()
{
int
height
=
321
;
when
(
gifDecoder
.
getHeight
()).
thenReturn
(
height
);
assertEquals
(
height
,
drawable
.
getIntrinsicHeight
());
}
@Test
public
void
testShouldNotDrawNullBitmap
()
{
Canvas
canvas
=
mock
(
Canvas
.
class
);
drawable
.
draw
(
canvas
);
verify
(
canvas
,
never
()).
drawBitmap
((
Bitmap
)
isNull
(),
anyInt
(),
anyInt
(),
any
(
Paint
.
class
));
}
@Test
public
void
testRequestsNextFrameOnStart
()
{
drawable
.
start
();
verify
(
frameManager
).
getNextFrame
(
eq
(
gifDecoder
),
eq
(
drawable
));
}
@Test
public
void
testShouldInvalidateSelfOnRun
()
{
drawable
.
start
();
verify
(
cb
).
invalidateDrawable
(
eq
(
drawable
));
}
@Test
public
void
testShouldNotScheduleItselfIfAlreadyRunning
()
{
drawable
.
start
();
drawable
.
start
();
verify
(
frameManager
,
times
(
1
)).
getNextFrame
(
eq
(
gifDecoder
),
eq
(
drawable
));
}
@Test
public
void
testReturnsFalseFromIsRunningWhenNotRunning
()
{
assertFalse
(
drawable
.
isRunning
());
}
@Test
public
void
testReturnsTrueFromIsRunningWhenRunning
()
{
drawable
.
start
();
assertTrue
(
drawable
.
isRunning
());
}
@Test
public
void
testStartsLoadingNextFrameWhenCurrentFinishes
()
{
drawable
.
setIsRunning
(
true
);
drawable
.
onFrameRead
(
Bitmap
.
createBitmap
(
100
,
100
,
Bitmap
.
Config
.
ARGB_8888
));
verify
(
frameManager
).
getNextFrame
(
eq
(
gifDecoder
),
eq
(
drawable
));
}
@Test
public
void
testInvalidatesSelfWhenFrameReady
()
{
drawable
.
setIsRunning
(
true
);
drawable
.
onFrameRead
(
Bitmap
.
createBitmap
(
100
,
100
,
Bitmap
.
Config
.
RGB_565
));
verify
(
cb
).
invalidateDrawable
(
eq
(
drawable
));
}
@Test
public
void
testDoesNotStartLoadingNextFrameWhenCurrentFinishesIfNotRunn
()
{
drawable
.
setIsRunning
(
false
);
drawable
.
onFrameRead
(
Bitmap
.
createBitmap
(
10
,
100
,
Bitmap
.
Config
.
ARGB_8888
));
verify
(
frameManager
,
never
()).
getNextFrame
(
eq
(
gifDecoder
),
eq
(
drawable
));
}
@Test
public
void
testSetsIsRunningFalseOnStop
()
{
drawable
.
start
();
drawable
.
stop
();
assertFalse
(
drawable
.
isRunning
());
}
@Test
public
void
testStopsOnSetVisibleFalse
()
{
drawable
.
start
();
drawable
.
setVisible
(
false
,
true
);
assertFalse
(
drawable
.
isRunning
());
}
@Test
public
void
testStartsOnSetVisibleTrue
()
{
drawable
.
setVisible
(
true
,
true
);
assertTrue
(
drawable
.
isRunning
());
}
@Test
public
void
testGetOpacityReturnsTransparentfDecoderHasTransparency
()
{
when
(
gifDecoder
.
isTransparent
()).
thenReturn
(
true
);
assertEquals
(
PixelFormat
.
TRANSPARENT
,
drawable
.
getOpacity
());
}
@Test
public
void
testGetOpacityReturnsOpaqueIfDecoderDoesNotHaveTransparency
()
{
when
(
gifDecoder
.
isTransparent
()).
thenReturn
(
false
);
assertEquals
(
PixelFormat
.
OPAQUE
,
drawable
.
getOpacity
());
}
@Test
public
void
testRecycleCallsClearOnFrameManager
()
{
drawable
.
recycle
();
verify
(
frameManager
).
clear
();
}
}
library/src/test/java/com/bumptech/glide/load/resource/gif/GifFrameResourceDecoderTest.java
0 → 100644
浏览文件 @
ea01ddd7
package
com.bumptech.glide.load.resource.gif
;
import
android.graphics.Bitmap
;
import
com.bumptech.glide.Resource
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.robolectric.RobolectricTestRunner
;
import
java.io.IOException
;
import
static
junit
.
framework
.
Assert
.
assertEquals
;
import
static
junit
.
framework
.
Assert
.
assertNotNull
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
mockito
.
Mockito
.
when
;
@RunWith
(
RobolectricTestRunner
.
class
)
public
class
GifFrameResourceDecoderTest
{
private
GifDecoder
gifDecoder
;
private
GifFrameResourceDecoder
resourceDecoder
;
@Before
public
void
setUp
()
{
gifDecoder
=
mock
(
GifDecoder
.
class
);
resourceDecoder
=
new
GifFrameResourceDecoder
();
}
@Test
public
void
testReturnsNonNullId
()
{
assertNotNull
(
resourceDecoder
.
getId
());
}
@Test
public
void
testReturnsFrameFromGifDecoder
()
throws
IOException
{
Resource
<
Bitmap
>
resource
=
mock
(
Resource
.
class
);
when
(
gifDecoder
.
getNextFrame
()).
thenReturn
(
resource
);
assertEquals
(
resource
,
resourceDecoder
.
decode
(
gifDecoder
,
100
,
100
));
}
}
library/src/test/java/com/bumptech/glide/load/resource/gif/GifResourceEncoderTest.java
0 → 100644
浏览文件 @
ea01ddd7
package
com.bumptech.glide.load.resource.gif
;
import
com.bumptech.glide.Resource
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.robolectric.RobolectricTestRunner
;
import
java.io.ByteArrayOutputStream
;
import
java.io.IOException
;
import
java.io.OutputStream
;
import
java.util.Arrays
;
import
static
junit
.
framework
.
Assert
.
assertTrue
;
import
static
junit
.
framework
.
TestCase
.
assertFalse
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
mockito
.
Mockito
.
when
;
@RunWith
(
RobolectricTestRunner
.
class
)
public
class
GifResourceEncoderTest
{
private
Resource
<
GifDrawable
>
resource
;
private
byte
[]
data
;
private
GifResourceEncoder
encoder
;
@SuppressWarnings
(
"unchecked"
)
@Before
public
void
setUp
()
{
resource
=
mock
(
Resource
.
class
);
data
=
new
byte
[]{
2
,
3
,
5
,
8
};
GifDecoder
decoder
=
mock
(
GifDecoder
.
class
);
GifDrawable
drawable
=
mock
(
GifDrawable
.
class
);
when
(
drawable
.
getDecoder
()).
thenReturn
(
decoder
);
when
(
resource
.
get
()).
thenReturn
(
drawable
);
when
(
decoder
.
getData
()).
thenReturn
(
data
);
encoder
=
new
GifResourceEncoder
();
}
@Test
public
void
testWritesDataToOutputStream
()
{
ByteArrayOutputStream
os
=
new
ByteArrayOutputStream
();
encoder
.
encode
(
resource
,
os
);
assertTrue
(
Arrays
.
equals
(
data
,
os
.
toByteArray
()));
}
@Test
public
void
testReturnsTrueIfWriteCompletes
()
{
assertTrue
(
encoder
.
encode
(
resource
,
new
ByteArrayOutputStream
()));
}
@Test
public
void
testReturnsFalseIfWriteFails
()
{
OutputStream
os
=
new
ByteArrayOutputStream
()
{
@Override
public
void
write
(
byte
[]
buffer
)
throws
IOException
{
super
.
write
(
buffer
);
//To change body of overridden methods use File | Settings | File Templates.
throw
new
IOException
(
"Test"
);
}
};
assertFalse
(
encoder
.
encode
(
resource
,
os
));
}
}
library/src/test/java/com/bumptech/glide/load/resource/gif/GifResourceTest.java
0 → 100644
浏览文件 @
ea01ddd7
package
com.bumptech.glide.load.resource.gif
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.robolectric.RobolectricTestRunner
;
import
static
junit
.
framework
.
Assert
.
assertEquals
;
import
static
junit
.
framework
.
Assert
.
assertNotNull
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
mockito
.
Mockito
.
verify
;
import
static
org
.
mockito
.
Mockito
.
when
;
@RunWith
(
RobolectricTestRunner
.
class
)
public
class
GifResourceTest
{
private
GifDecoder
decoder
;
private
GifDrawable
gifDrawable
;
private
GifResource
resource
;
@Before
public
void
setUp
()
{
decoder
=
mock
(
GifDecoder
.
class
);
gifDrawable
=
mock
(
GifDrawable
.
class
);
resource
=
new
GifResource
(
decoder
,
gifDrawable
);
}
@Test
public
void
testSizeReturnsGifDecoderGifByteSize
()
{
int
size
=
1234
;
when
(
decoder
.
getGifByteSize
()).
thenReturn
(
size
);
assertEquals
(
size
,
resource
.
getSize
());
}
@Test
public
void
testReturnsNonNullDrawable
()
{
assertNotNull
(
resource
.
get
());
}
@Test
public
void
testStopsGifDrawableOnRecycle
()
{
resource
.
recycle
();
verify
(
gifDrawable
).
stop
();
}
@Test
public
void
testRecyclesGifDrawableOnRecycle
()
{
resource
.
recycle
();
verify
(
gifDrawable
).
recycle
();
}
}
library/src/test/java/com/bumptech/glide/load/resource/transcode/GifBitmapDrawableTranscoderTest.java
0 → 100644
浏览文件 @
ea01ddd7
package
com.bumptech.glide.load.resource.transcode
;
import
android.graphics.Bitmap
;
import
android.graphics.drawable.BitmapDrawable
;
import
android.graphics.drawable.Drawable
;
import
com.bumptech.glide.Resource
;
import
com.bumptech.glide.load.resource.drawable.GifBitmap
;
import
com.bumptech.glide.load.resource.gif.GifDrawable
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.robolectric.Robolectric
;
import
org.robolectric.RobolectricTestRunner
;
import
static
junit
.
framework
.
Assert
.
assertEquals
;
import
static
junit
.
framework
.
Assert
.
assertNotNull
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
mockito
.
Mockito
.
when
;
@RunWith
(
RobolectricTestRunner
.
class
)
public
class
GifBitmapDrawableTranscoderTest
{
private
GifBitmapDrawableTranscoder
transcoder
;
@Before
public
void
setUp
()
{
transcoder
=
new
GifBitmapDrawableTranscoder
(
Robolectric
.
application
);
}
@Test
public
void
testReturnsBitmapDrawableIfGifBitmapHasBitmap
()
{
GifBitmapWithBitmapHarness
harness
=
new
GifBitmapWithBitmapHarness
();
BitmapDrawable
transcoded
=
(
BitmapDrawable
)
transcoder
.
transcode
(
harness
.
gifBitmapResource
).
get
();
assertEquals
(
harness
.
expected
,
transcoded
.
getBitmap
());
}
@Test
public
void
testReturnedResourceHasBitmapSizeIfGifBitmapHasBitmap
()
{
final
int
size
=
100
;
GifBitmapWithBitmapHarness
harness
=
new
GifBitmapWithBitmapHarness
();
when
(
harness
.
bitmapResource
.
getSize
()).
thenReturn
(
size
);
Resource
<
Drawable
>
transcoded
=
transcoder
.
transcode
(
harness
.
gifBitmapResource
);
assertEquals
(
size
,
transcoded
.
getSize
());
}
@Test
public
void
testReturnsGifDrawableIfGifBitmapHasGif
()
{
GifBitmapWithGifHarness
harness
=
new
GifBitmapWithGifHarness
();
Drawable
transcoded
=
transcoder
.
transcode
(
harness
.
gifBitmapResource
).
get
();
assertEquals
(
harness
.
expected
,
transcoded
);
}
@Test
public
void
testReturnedResourceHasGifDrawableSizeIfGifBitmapHasGif
()
{
final
int
size
=
200
;
GifBitmapWithGifHarness
harness
=
new
GifBitmapWithGifHarness
();
when
(
harness
.
gifResource
.
getSize
()).
thenReturn
(
size
);
Resource
<
Drawable
>
transcoded
=
transcoder
.
transcode
(
harness
.
gifBitmapResource
);
assertEquals
(
size
,
transcoded
.
getSize
());
}
@Test
public
void
testHasNonNullId
()
{
assertNotNull
(
transcoder
.
getId
());
}
private
static
class
TranscoderHarness
{
Resource
<
GifBitmap
>
gifBitmapResource
=
mock
(
Resource
.
class
);
GifBitmap
gifBitmap
=
mock
(
GifBitmap
.
class
);
public
TranscoderHarness
()
{
when
(
gifBitmapResource
.
get
()).
thenReturn
(
gifBitmap
);
}
}
private
static
class
GifBitmapWithBitmapHarness
extends
TranscoderHarness
{
Bitmap
expected
=
Bitmap
.
createBitmap
(
100
,
200
,
Bitmap
.
Config
.
ARGB_8888
);
Resource
<
Bitmap
>
bitmapResource
=
mock
(
Resource
.
class
);
public
GifBitmapWithBitmapHarness
()
{
super
();
when
(
bitmapResource
.
get
()).
thenReturn
(
expected
);
when
(
gifBitmap
.
getBitmapResource
()).
thenReturn
(
bitmapResource
);
}
}
private
static
class
GifBitmapWithGifHarness
extends
TranscoderHarness
{
GifDrawable
expected
=
mock
(
GifDrawable
.
class
);
Resource
<
GifDrawable
>
gifResource
=
mock
(
Resource
.
class
);
public
GifBitmapWithGifHarness
()
{
super
();
when
(
gifResource
.
get
()).
thenReturn
(
expected
);
when
(
gifBitmap
.
getGifResource
()).
thenReturn
(
gifResource
);
}
}
}
samples/flickr/res/layout/flickr_search_activity.xml
浏览文件 @
ea01ddd7
...
...
@@ -4,6 +4,11 @@
android:orientation=
"vertical"
android:layout_width=
"fill_parent"
android:layout_height=
"fill_parent"
>
<ImageView
android:id=
"@+id/test"
android:background=
"@android:color/holo_red_light"
android:layout_width=
"fill_parent"
android:layout_height=
"fill_parent"
/>
<LinearLayout
android:layout_width=
"fill_parent"
android:layout_height=
"wrap_content"
...
...
samples/flickr/src/main/java/com/bumptech/glide/samples/flickr/FlickrSearchActivity.java
浏览文件 @
ea01ddd7
...
...
@@ -13,10 +13,13 @@ import android.view.View;
import
android.view.inputmethod.EditorInfo
;
import
android.widget.Button
;
import
android.widget.EditText
;
import
android.widget.ImageView
;
import
android.widget.TextView
;
import
com.actionbarsherlock.app.ActionBar
;
import
com.actionbarsherlock.app.SherlockFragmentActivity
;
import
com.bumptech.glide.Glide
;
import
com.bumptech.glide.load.resource.gif.GifDecoder
;
import
com.bumptech.glide.load.resource.gif.GifDrawable
;
import
com.bumptech.glide.samples.flickr.api.Api
;
import
com.bumptech.glide.samples.flickr.api.Photo
;
...
...
@@ -75,6 +78,16 @@ public class FlickrSearchActivity extends SherlockFragmentActivity {
.
penaltyLog
()
.
build
());
InputStream
inputStream
=
getResources
().
openRawResource
(
R
.
raw
.
test_animated
);
GifDecoder
gifDecoder
=
new
GifDecoder
();
gifDecoder
.
read
(
inputStream
,
0
);
GifDrawable
drawable
=
new
GifDrawable
(
gifDecoder
);
ImageView
testView
=
(
ImageView
)
findViewById
(
R
.
id
.
test
);
drawable
.
setCallback
(
testView
);
testView
.
setImageDrawable
(
drawable
);
drawable
.
start
();
Glide
.
get
(
this
).
register
(
Photo
.
class
,
InputStream
.
class
,
new
FlickrModelLoader
.
Factory
());
searching
=
findViewById
(
R
.
id
.
searching
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录