Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
沉迷打码的小凳子
glide
提交
2c259f53
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,发现更多精彩内容 >>
提交
2c259f53
编写于
10月 18, 2014
作者:
S
Sam Judd
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Set transIndex for GIFs with transparent pixels.
Fixes #201.
上级
3640e349
变更
8
显示空白变更内容
内联
并排
Showing
8 changed file
with
63 addition
and
93 deletion
+63
-93
library/src/androidTest/java/com/bumptech/glide/load/resource/gif/GifDrawableTest.java
...com/bumptech/glide/load/resource/gif/GifDrawableTest.java
+1
-10
library/src/main/java/com/bumptech/glide/load/resource/gif/GifBitmapProvider.java
...m/bumptech/glide/load/resource/gif/GifBitmapProvider.java
+1
-1
library/src/main/java/com/bumptech/glide/load/resource/gif/GifDrawable.java
...ava/com/bumptech/glide/load/resource/gif/GifDrawable.java
+2
-1
library/src/main/java/com/bumptech/glide/load/resource/gif/GifFrameManager.java
...com/bumptech/glide/load/resource/gif/GifFrameManager.java
+3
-36
third_party/gif_decoder/src/main/java/com/bumptech/glide/gifdecoder/GifDecoder.java
...c/main/java/com/bumptech/glide/gifdecoder/GifDecoder.java
+16
-11
third_party/gif_decoder/src/main/java/com/bumptech/glide/gifdecoder/GifHeader.java
...rc/main/java/com/bumptech/glide/gifdecoder/GifHeader.java
+0
-1
third_party/gif_decoder/src/main/java/com/bumptech/glide/gifdecoder/GifHeaderParser.java
...n/java/com/bumptech/glide/gifdecoder/GifHeaderParser.java
+0
-1
third_party/gif_encoder/src/main/java/com/bumptech/glide/gifencoder/AnimatedGifEncoder.java
...ava/com/bumptech/glide/gifencoder/AnimatedGifEncoder.java
+40
-32
未找到文件。
library/src/androidTest/java/com/bumptech/glide/load/resource/gif/GifDrawableTest.java
浏览文件 @
2c259f53
...
...
@@ -246,19 +246,10 @@ public class GifDrawableTest {
}
@Test
public
void
testGetOpacityReturnsTransparentIfDecoderHasTransparency
()
{
when
(
gifDecoder
.
isTransparent
()).
thenReturn
(
true
);
public
void
testGetOpacityReturnsTransparent
()
{
assertEquals
(
PixelFormat
.
TRANSPARENT
,
drawable
.
getOpacity
());
}
@Test
public
void
testGetOpacityReturnsOpaqueIfDecoderDoesNotHaveTransparency
()
{
when
(
gifDecoder
.
isTransparent
()).
thenReturn
(
false
);
assertEquals
(
PixelFormat
.
OPAQUE
,
drawable
.
getOpacity
());
}
@Test
public
void
testReturnsFrameCountFromDecoder
()
{
int
expected
=
4
;
...
...
library/src/main/java/com/bumptech/glide/load/resource/gif/GifBitmapProvider.java
浏览文件 @
2c259f53
...
...
@@ -14,6 +14,6 @@ class GifBitmapProvider implements GifDecoder.BitmapProvider {
@Override
public
Bitmap
obtain
(
int
width
,
int
height
,
Bitmap
.
Config
config
)
{
return
bitmapPool
.
get
(
width
,
height
,
config
);
return
bitmapPool
.
get
Dirty
(
width
,
height
,
config
);
}
}
library/src/main/java/com/bumptech/glide/load/resource/gif/GifDrawable.java
浏览文件 @
2c259f53
...
...
@@ -197,7 +197,8 @@ public class GifDrawable extends GlideDrawable implements GifFrameManager.FrameC
@Override
public
int
getOpacity
()
{
return
decoder
.
isTransparent
()
?
PixelFormat
.
TRANSPARENT
:
PixelFormat
.
OPAQUE
;
// We can't tell, so default to transparent to be safe.
return
PixelFormat
.
TRANSPARENT
;
}
@TargetApi
(
Build
.
VERSION_CODES
.
HONEYCOMB
)
...
...
library/src/main/java/com/bumptech/glide/load/resource/gif/GifFrameManager.java
浏览文件 @
2c259f53
...
...
@@ -5,26 +5,17 @@ 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.gifdecoder.GifDecoder
;
import
com.bumptech.glide.load.Encoder
;
import
com.bumptech.glide.load.ResourceDecoder
;
import
com.bumptech.glide.load.ResourceEncoder
;
import
com.bumptech.glide.load.Transformation
;
import
com.bumptech.glide.load.engine.DiskCacheStrategy
;
import
com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool
;
import
com.bumptech.glide.load.engine.cache.MemorySizeCalculator
;
import
com.bumptech.glide.load.resource.NullDecoder
;
import
com.bumptech.glide.load.resource.NullEncoder
;
import
com.bumptech.glide.load.resource.NullResourceEncoder
;
import
com.bumptech.glide.load.resource.bitmap.BitmapEncoder
;
import
com.bumptech.glide.load.resource.bitmap.StreamBitmapDecoder
;
import
com.bumptech.glide.load.resource.file.FileToStreamDecoder
;
import
com.bumptech.glide.request.animation.GlideAnimation
;
import
com.bumptech.glide.request.target.SimpleTarget
;
import
java.io.File
;
import
com.bumptech.glide.util.Util
;
class
GifFrameManager
{
/** 60fps is {@value #MIN_FRAME_DELAY}ms per frame. */
...
...
@@ -32,10 +23,8 @@ class GifFrameManager {
private
final
MemorySizeCalculator
calculator
;
private
final
GifFrameModelLoader
frameLoader
;
private
final
GifFrameResourceDecoder
frameResourceDecoder
;
private
final
ResourceDecoder
<
File
,
Bitmap
>
cacheDecoder
;
private
final
GifDecoder
decoder
;
private
final
Handler
mainHandler
;
private
final
ResourceEncoder
<
Bitmap
>
encoder
;
private
final
Context
context
;
private
final
Encoder
<
GifDecoder
>
sourceEncoder
;
private
final
Transformation
<
Bitmap
>[]
transformation
;
...
...
@@ -69,23 +58,11 @@ class GifFrameManager {
this
.
transformation
=
new
Transformation
[]
{
transformation
};
this
.
targetWidth
=
targetWidth
;
this
.
targetHeight
=
targetHeight
;
this
.
totalFrameSize
=
frameWidth
*
frameHeight
*
(
decoder
.
isTransparent
()
?
4
:
2
);
this
.
totalFrameSize
=
Util
.
getBitmapByteSize
(
frameWidth
,
frameHeight
,
Bitmap
.
Config
.
ARGB_8888
);
this
.
calculator
=
new
MemorySizeCalculator
(
context
);
this
.
frameLoader
=
new
GifFrameModelLoader
();
this
.
sourceEncoder
=
NullEncoder
.
get
();
if
(!
decoder
.
isTransparent
())
{
// For non transparent gifs, we can beat the performance of our gif decoder for each frame by decoding jpegs
// from disk.
this
.
cacheDecoder
=
new
FileToStreamDecoder
<
Bitmap
>(
new
StreamBitmapDecoder
(
context
));
this
.
encoder
=
new
BitmapEncoder
();
}
else
{
// For transparent gifs, we would have to encode as pngs which is actually slower than our gif decoder so we
// avoid writing frames to the disk cache entirely.
this
.
cacheDecoder
=
NullDecoder
.
get
();
this
.
encoder
=
NullResourceEncoder
.
get
();
}
}
Transformation
<
Bitmap
>
getTransformation
()
{
...
...
@@ -95,17 +72,9 @@ class GifFrameManager {
public
void
getNextFrame
(
FrameCallback
cb
)
{
decoder
.
advance
();
/**
* Note - Using the disk cache can potentially cause frames to be decoded incorrectly because the decoder is
* sequential. If earlier frames are evicted for some reason, later ones may then not be decoded correctly.
*/
// We don't want to blow out the entire memory cache with frames of gifs, so try to set some
// maximum size beyond which we will always just decode one frame at a time.
boolean
skipCache
=
totalFrameSize
>
calculator
.
getMemoryCacheSize
()
/
2
;
// We can decode non transparent (cached as jpegs) frames more quickly from cache, but transparent
// (cached as png) frames more quickly from the gif data.
boolean
skipDiskCache
=
decoder
.
isTransparent
();
long
targetTime
=
SystemClock
.
uptimeMillis
()
+
Math
.
max
(
MIN_FRAME_DELAY
,
decoder
.
getNextDelay
());
next
=
new
DelayTarget
(
cb
,
targetTime
);
...
...
@@ -117,11 +86,9 @@ class GifFrameManager {
.
as
(
Bitmap
.
class
)
.
sourceEncoder
(
sourceEncoder
)
.
decoder
(
frameResourceDecoder
)
.
cacheDecoder
(
cacheDecoder
)
.
encoder
(
encoder
)
.
transform
(
transformation
)
.
skipMemoryCache
(
skipCache
)
.
diskCacheStrategy
(
skipDiskCache
?
DiskCacheStrategy
.
NONE
:
DiskCacheStrategy
.
RESULT
)
.
diskCacheStrategy
(
DiskCacheStrategy
.
NONE
)
.
into
(
next
);
}
...
...
third_party/gif_decoder/src/main/java/com/bumptech/glide/gifdecoder/GifDecoder.java
浏览文件 @
2c259f53
...
...
@@ -24,8 +24,9 @@ package com.bumptech.glide.gifdecoder;
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import
android.annotation.TargetApi
;
import
android.graphics.Bitmap
;
import
android.
graphics.Color
;
import
android.
os.Build
;
import
android.util.Log
;
import
java.io.ByteArrayOutputStream
;
...
...
@@ -144,10 +145,6 @@ public class GifDecoder {
return
header
.
height
;
}
public
boolean
isTransparent
()
{
return
header
.
isTransparent
;
}
public
byte
[]
getData
()
{
return
data
;
}
...
...
@@ -323,6 +320,7 @@ public class GifDecoder {
rawData
.
rewind
();
rawData
.
order
(
ByteOrder
.
LITTLE_ENDIAN
);
// No point in specially saving an old frame if we're never going to use it.
savePrevious
=
false
;
for
(
GifFrame
frame
:
header
.
frames
)
{
...
...
@@ -458,7 +456,7 @@ public class GifDecoder {
}
}
//Copy pixels into previous image
//
Copy pixels into previous image
if
(
savePrevious
&&
currentFrame
.
dispose
==
DISPOSAL_UNSPECIFIED
||
currentFrame
.
dispose
==
DISPOSAL_NONE
)
{
if
(
previousImage
==
null
)
{
previousImage
=
getNextBitmap
();
...
...
@@ -631,8 +629,10 @@ public class GifDecoder {
}
private
Bitmap
.
Config
getPreferredConfig
()
{
if
(
config
==
Bitmap
.
Config
.
RGB_565
&&
!
header
.
isTransparent
)
{
return
Bitmap
.
Config
.
RGB_565
;
// We can't tell if a gif has transparency to decode a partial frame on top of a previous frame, or if the final
// frame will actually have transparent pixels, so we must always use a format that supports transparency.
if
(
config
==
Bitmap
.
Config
.
RGB_565
||
config
==
Bitmap
.
Config
.
ARGB_4444
)
{
return
Bitmap
.
Config
.
ARGB_4444
;
}
else
{
return
Bitmap
.
Config
.
ARGB_8888
;
}
...
...
@@ -643,10 +643,15 @@ public class GifDecoder {
Bitmap
result
=
bitmapProvider
.
obtain
(
header
.
width
,
header
.
height
,
targetConfig
);
if
(
result
==
null
)
{
result
=
Bitmap
.
createBitmap
(
header
.
width
,
header
.
height
,
targetConfig
);
}
else
{
// If we're reusing a bitmap it may have other things drawn in it which we need to remove.
result
.
eraseColor
(
Color
.
TRANSPARENT
);
}
setAlpha
(
result
);
return
result
;
}
@TargetApi
(
12
)
private
static
void
setAlpha
(
Bitmap
bitmap
)
{
if
(
Build
.
VERSION
.
SDK_INT
>=
12
)
{
bitmap
.
setHasAlpha
(
true
);
}
}
}
third_party/gif_decoder/src/main/java/com/bumptech/glide/gifdecoder/GifHeader.java
浏览文件 @
2c259f53
...
...
@@ -34,7 +34,6 @@ public class GifHeader {
int
pixelAspect
;
//TODO: this is set both during reading the header and while decoding frames...
int
bgColor
;
boolean
isTransparent
;
int
loopCount
;
public
int
getHeight
()
{
...
...
third_party/gif_decoder/src/main/java/com/bumptech/glide/gifdecoder/GifHeaderParser.java
浏览文件 @
2c259f53
...
...
@@ -143,7 +143,6 @@ public class GifHeaderParser {
header
.
currentFrame
.
dispose
=
1
;
}
header
.
currentFrame
.
transparency
=
(
packed
&
1
)
!=
0
;
header
.
isTransparent
|=
header
.
currentFrame
.
transparency
;
// Delay in milliseconds.
header
.
currentFrame
.
delay
=
readShort
()
*
10
;
// Transparent color index
...
...
third_party/gif_encoder/src/main/java/com/bumptech/glide/gifencoder/AnimatedGifEncoder.java
浏览文件 @
2c259f53
...
...
@@ -36,45 +36,47 @@ import java.io.OutputStream;
public
class
AnimatedGifEncoder
{
pr
otected
int
width
;
// image size
pr
ivate
int
width
;
// image size
pr
otected
int
height
;
pr
ivate
int
height
;
pr
otected
Integer
transparent
=
null
;
// transparent color if given
pr
ivate
Integer
transparent
=
null
;
// transparent color if given
pr
otected
int
transIndex
;
// transparent index in color table
pr
ivate
int
transIndex
;
// transparent index in color table
pr
otected
int
repeat
=
-
1
;
// no repeat
pr
ivate
int
repeat
=
-
1
;
// no repeat
pr
otected
int
delay
=
0
;
// frame delay (hundredths)
pr
ivate
int
delay
=
0
;
// frame delay (hundredths)
pr
otected
boolean
started
=
false
;
// ready to output frames
pr
ivate
boolean
started
=
false
;
// ready to output frames
pr
otected
OutputStream
out
;
pr
ivate
OutputStream
out
;
pr
otected
Bitmap
image
;
// current frame
pr
ivate
Bitmap
image
;
// current frame
pr
otected
byte
[]
pixels
;
// BGR byte array from frame
pr
ivate
byte
[]
pixels
;
// BGR byte array from frame
pr
otected
byte
[]
indexedPixels
;
// converted frame indexed to palette
pr
ivate
byte
[]
indexedPixels
;
// converted frame indexed to palette
pr
otected
int
colorDepth
;
// number of bit planes
pr
ivate
int
colorDepth
;
// number of bit planes
pr
otected
byte
[]
colorTab
;
// RGB palette
pr
ivate
byte
[]
colorTab
;
// RGB palette
pr
otected
boolean
[]
usedEntry
=
new
boolean
[
256
];
// active palette entries
pr
ivate
boolean
[]
usedEntry
=
new
boolean
[
256
];
// active palette entries
pr
otected
int
palSize
=
7
;
// color table size (bits-1)
pr
ivate
int
palSize
=
7
;
// color table size (bits-1)
pr
otected
int
dispose
=
-
1
;
// disposal code (-1 = use default)
pr
ivate
int
dispose
=
-
1
;
// disposal code (-1 = use default)
pr
otected
boolean
closeStream
=
false
;
// close stream when finished
pr
ivate
boolean
closeStream
=
false
;
// close stream when finished
pr
otected
boolean
firstFrame
=
true
;
pr
ivate
boolean
firstFrame
=
true
;
pr
otected
boolean
sizeSet
=
false
;
// if false, get size from first frame
pr
ivate
boolean
sizeSet
=
false
;
// if false, get size from first frame
protected
int
sample
=
10
;
// default sample interval for quantizer
private
int
sample
=
10
;
// default sample interval for quantizer
private
boolean
hasTransparentPixels
;
/**
* Sets the delay time between each frame, or changes it for subsequent frames
...
...
@@ -300,7 +302,7 @@ public class AnimatedGifEncoder {
/**
* Analyzes image colors and creates color map.
*/
pr
otected
void
analyzePixels
()
{
pr
ivate
void
analyzePixels
()
{
int
len
=
pixels
.
length
;
int
nPix
=
len
/
3
;
indexedPixels
=
new
byte
[
nPix
];
...
...
@@ -327,6 +329,8 @@ public class AnimatedGifEncoder {
// get closest match to transparent color if specified
if
(
transparent
!=
null
)
{
transIndex
=
findClosest
(
transparent
);
}
else
if
(
hasTransparentPixels
)
{
transIndex
=
findClosest
(
Color
.
TRANSPARENT
);
}
}
...
...
@@ -334,7 +338,7 @@ public class AnimatedGifEncoder {
* Returns index of palette color closest to c
*
*/
pr
otected
int
findClosest
(
int
color
)
{
pr
ivate
int
findClosest
(
int
color
)
{
if
(
colorTab
==
null
)
return
-
1
;
int
r
=
Color
.
red
(
color
);
...
...
@@ -361,7 +365,7 @@ public class AnimatedGifEncoder {
/**
* Extracts image pixels into byte array "pixels"
*/
pr
otected
void
getImagePixels
()
{
pr
ivate
void
getImagePixels
()
{
int
w
=
image
.
getWidth
();
int
h
=
image
.
getHeight
();
...
...
@@ -379,7 +383,11 @@ public class AnimatedGifEncoder {
pixels
=
new
byte
[
pixelsInt
.
length
*
3
];
int
pixelsIndex
=
0
;
hasTransparentPixels
=
false
;
for
(
final
int
pixel
:
pixelsInt
)
{
if
(
pixel
==
Color
.
TRANSPARENT
)
{
hasTransparentPixels
=
true
;
}
pixels
[
pixelsIndex
++]
=
(
byte
)
(
pixel
&
0xFF
);
pixels
[
pixelsIndex
++]
=
(
byte
)
((
pixel
>>
8
)
&
0xFF
);
pixels
[
pixelsIndex
++]
=
(
byte
)
((
pixel
>>
16
)
&
0xFF
);
...
...
@@ -389,12 +397,12 @@ public class AnimatedGifEncoder {
/**
* Writes Graphic Control Extension
*/
pr
otected
void
writeGraphicCtrlExt
()
throws
IOException
{
pr
ivate
void
writeGraphicCtrlExt
()
throws
IOException
{
out
.
write
(
0x21
);
// extension introducer
out
.
write
(
0xf9
);
// GCE label
out
.
write
(
4
);
// data block size
int
transp
,
disp
;
if
(
transparent
==
null
)
{
if
(
transparent
==
null
&&
!
hasTransparentPixels
)
{
transp
=
0
;
disp
=
0
;
// dispose = no action
}
else
{
...
...
@@ -420,7 +428,7 @@ public class AnimatedGifEncoder {
/**
* Writes Image Descriptor
*/
pr
otected
void
writeImageDesc
()
throws
IOException
{
pr
ivate
void
writeImageDesc
()
throws
IOException
{
out
.
write
(
0x2c
);
// image separator
writeShort
(
0
);
// image position x,y = 0,0
writeShort
(
0
);
...
...
@@ -443,7 +451,7 @@ public class AnimatedGifEncoder {
/**
* Writes Logical Screen Descriptor
*/
pr
otected
void
writeLSD
()
throws
IOException
{
pr
ivate
void
writeLSD
()
throws
IOException
{
// logical screen size
writeShort
(
width
);
writeShort
(
height
);
...
...
@@ -460,7 +468,7 @@ public class AnimatedGifEncoder {
/**
* Writes Netscape application extension to define repeat count.
*/
pr
otected
void
writeNetscapeExt
()
throws
IOException
{
pr
ivate
void
writeNetscapeExt
()
throws
IOException
{
out
.
write
(
0x21
);
// extension introducer
out
.
write
(
0xff
);
// app extension label
out
.
write
(
11
);
// block size
...
...
@@ -474,7 +482,7 @@ public class AnimatedGifEncoder {
/**
* Writes color table
*/
pr
otected
void
writePalette
()
throws
IOException
{
pr
ivate
void
writePalette
()
throws
IOException
{
out
.
write
(
colorTab
,
0
,
colorTab
.
length
);
int
n
=
(
3
*
256
)
-
colorTab
.
length
;
for
(
int
i
=
0
;
i
<
n
;
i
++)
{
...
...
@@ -485,7 +493,7 @@ public class AnimatedGifEncoder {
/**
* Encodes and writes pixel data
*/
pr
otected
void
writePixels
()
throws
IOException
{
pr
ivate
void
writePixels
()
throws
IOException
{
LZWEncoder
encoder
=
new
LZWEncoder
(
width
,
height
,
indexedPixels
,
colorDepth
);
encoder
.
encode
(
out
);
}
...
...
@@ -493,7 +501,7 @@ public class AnimatedGifEncoder {
/**
* Write 16-bit value to output stream, LSB first
*/
pr
otected
void
writeShort
(
int
value
)
throws
IOException
{
pr
ivate
void
writeShort
(
int
value
)
throws
IOException
{
out
.
write
(
value
&
0xff
);
out
.
write
((
value
>>
8
)
&
0xff
);
}
...
...
@@ -501,7 +509,7 @@ public class AnimatedGifEncoder {
/**
* Writes string to output stream
*/
pr
otected
void
writeString
(
String
s
)
throws
IOException
{
pr
ivate
void
writeString
(
String
s
)
throws
IOException
{
for
(
int
i
=
0
;
i
<
s
.
length
();
i
++)
{
out
.
write
((
byte
)
s
.
charAt
(
i
));
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录