Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
沉迷打码的小凳子
glide
提交
52985d7c
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,体验更适合开发者的 AI 搜索 >>
提交
52985d7c
编写于
4月 04, 2015
作者:
S
Sam Judd
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Handle partial reads/skips in ImageHeaderParser.
Fixes #387
上级
02901005
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
130 addition
and
12 deletion
+130
-12
library/src/androidTest/java/com/bumptech/glide/load/resource/bitmap/ImageHeaderParserTest.java
...ech/glide/load/resource/bitmap/ImageHeaderParserTest.java
+78
-2
library/src/androidTest/java/com/bumptech/glide/resize/load/ExifTest.java
...oidTest/java/com/bumptech/glide/resize/load/ExifTest.java
+7
-0
library/src/androidTest/resources/issue387_rotated_jpeg.jpg
library/src/androidTest/resources/issue387_rotated_jpeg.jpg
+0
-0
library/src/main/java/com/bumptech/glide/load/resource/bitmap/ImageHeaderParser.java
...umptech/glide/load/resource/bitmap/ImageHeaderParser.java
+45
-10
未找到文件。
library/src/androidTest/java/com/bumptech/glide/load/resource/bitmap/ImageHeaderParserTest.java
浏览文件 @
52985d7c
package
com.bumptech.glide.load.resource.bitmap
;
import
static
com
.
google
.
common
.
truth
.
Truth
.
assertThat
;
import
static
com
.
bumptech
.
glide
.
load
.
resource
.
bitmap
.
ImageHeaderParser
.
ImageType
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
...
...
@@ -7,13 +8,16 @@ import com.bumptech.glide.testutil.TestResourceUtil;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.junit.runners.JUnit4
;
import
org.robolectric.RobolectricTestRunner
;
import
org.robolectric.annotation.Config
;
import
java.io.ByteArrayInputStream
;
import
java.io.FilterInputStream
;
import
java.io.IOException
;
import
java.io.InputStream
;
@RunWith
(
JUnit4
.
class
)
@RunWith
(
RobolectricTestRunner
.
class
)
@Config
(
manifest
=
Config
.
NONE
,
emulateSdk
=
18
)
public
class
ImageHeaderParserTest
{
private
static
final
byte
[]
PNG_HEADER_WITH_IHDR_CHUNK
=
new
byte
[]
{(
byte
)
0x89
,
0x50
,
0x4e
,
0x47
,
0xd
,
0xa
,
0x1a
,
...
...
@@ -84,10 +88,82 @@ public class ImageHeaderParserTest {
assertEquals
(-
1
,
parser
.
getOrientation
());
}
// Test for #387.
@Test
public
void
testHandlesPartialReads
()
throws
IOException
{
InputStream
is
=
TestResourceUtil
.
openResource
(
getClass
(),
"issue387_rotated_jpeg.jpg"
);
ImageHeaderParser
parser
=
new
ImageHeaderParser
(
new
PartialReadInputStream
(
is
));
assertThat
(
parser
.
getOrientation
()).
isEqualTo
(
6
);
}
// Test for #387.
@Test
public
void
testHandlesPartialSkips
()
throws
IOException
{
InputStream
is
=
TestResourceUtil
.
openResource
(
getClass
(),
"issue387_rotated_jpeg.jpg"
);
ImageHeaderParser
parser
=
new
ImageHeaderParser
(
new
PartialSkipInputStream
(
is
));
assertThat
(
parser
.
getOrientation
()).
isEqualTo
(
6
);
}
@Test
public
void
testHandlesSometimesZeroSkips
()
throws
IOException
{
InputStream
is
=
new
ByteArrayInputStream
(
new
byte
[]
{
(
byte
)
0x89
,
0x50
,
0x4e
,
0x47
,
0x0d
,
0x0a
,
0x1a
,
0x0a
});
ImageHeaderParser
parser
=
new
ImageHeaderParser
(
new
SometimesZeroSkipInputStream
(
is
));
assertEquals
(
ImageType
.
PNG
,
parser
.
getType
());
}
private
static
byte
[]
generatePngHeaderWithIhdr
(
int
bitDepth
)
{
byte
[]
result
=
new
byte
[
PNG_HEADER_WITH_IHDR_CHUNK
.
length
];
System
.
arraycopy
(
PNG_HEADER_WITH_IHDR_CHUNK
,
0
,
result
,
0
,
PNG_HEADER_WITH_IHDR_CHUNK
.
length
);
result
[
result
.
length
-
1
]
=
(
byte
)
bitDepth
;
return
result
;
}
private
static
class
SometimesZeroSkipInputStream
extends
FilterInputStream
{
boolean
returnZeroFlag
=
true
;
protected
SometimesZeroSkipInputStream
(
InputStream
in
)
{
super
(
in
);
}
@Override
public
long
skip
(
long
byteCount
)
throws
IOException
{
if
(
returnZeroFlag
)
{
return
0
;
}
returnZeroFlag
=
!
returnZeroFlag
;
return
super
.
skip
(
byteCount
);
}
}
private
static
class
PartialSkipInputStream
extends
FilterInputStream
{
protected
PartialSkipInputStream
(
InputStream
in
)
{
super
(
in
);
}
@Override
public
long
skip
(
long
byteCount
)
throws
IOException
{
long
toActuallySkip
=
byteCount
/
2
;
if
(
byteCount
==
1
)
{
toActuallySkip
=
1
;
}
return
super
.
skip
(
toActuallySkip
);
}
}
private
static
class
PartialReadInputStream
extends
FilterInputStream
{
protected
PartialReadInputStream
(
InputStream
in
)
{
super
(
in
);
}
@Override
public
int
read
(
byte
[]
buffer
,
int
byteOffset
,
int
byteCount
)
throws
IOException
{
int
toActuallyRead
=
byteCount
/
2
;
if
(
byteCount
==
1
)
{
toActuallyRead
=
1
;
}
return
super
.
read
(
buffer
,
byteOffset
,
toActuallyRead
);
}
}
}
\ No newline at end of file
library/src/androidTest/java/com/bumptech/glide/resize/load/ExifTest.java
浏览文件 @
52985d7c
package
com.bumptech.glide.resize.load
;
import
static
com
.
google
.
common
.
truth
.
Truth
.
assertThat
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertNull
;
...
...
@@ -41,6 +42,12 @@ public class ExifTest {
}
}
@Test
public
void
testIssue387
()
throws
IOException
{
InputStream
is
=
TestResourceUtil
.
openResource
(
getClass
(),
"issue387_rotated_jpeg.jpg"
);
assertThat
(
new
ImageHeaderParser
(
is
).
getOrientation
()).
isEqualTo
(
6
);
}
@Test
public
void
testLandscape
()
throws
IOException
{
for
(
int
i
=
1
;
i
<=
8
;
i
++)
{
...
...
library/src/androidTest/resources/issue387_rotated_jpeg.jpg
0 → 100644
浏览文件 @
52985d7c
2.5 MB
library/src/main/java/com/bumptech/glide/load/resource/bitmap/ImageHeaderParser.java
浏览文件 @
52985d7c
...
...
@@ -23,7 +23,7 @@ public class ImageHeaderParser {
/**
* The format of the image data including whether or not the image may include transparent pixels.
*/
public
static
enum
ImageType
{
public
enum
ImageType
{
/** GIF type. */
GIF
(
true
),
/** JPG type. */
...
...
@@ -171,18 +171,25 @@ public class ImageHeaderParser {
segmentLength
=
streamReader
.
getUInt16
()
-
2
;
if
(
segmentType
!=
EXIF_SEGMENT_TYPE
)
{
if
(
segmentLength
!=
streamReader
.
skip
(
segmentLength
))
{
long
skipped
=
streamReader
.
skip
(
segmentLength
);
if
(
skipped
!=
segmentLength
)
{
if
(
Log
.
isLoggable
(
TAG
,
Log
.
DEBUG
))
{
Log
.
d
(
TAG
,
"Unable to skip enough data for type="
+
segmentType
);
Log
.
d
(
TAG
,
"Unable to skip enough data"
+
", type: "
+
segmentType
+
", wanted to skip: "
+
segmentLength
+
", but actually skipped: "
+
skipped
);
}
return
null
;
}
}
else
{
byte
[]
segmentData
=
new
byte
[
segmentLength
];
if
(
segmentLength
!=
streamReader
.
read
(
segmentData
)
)
{
int
read
=
streamReader
.
read
(
segmentData
);
if
(
read
!=
segmentLength
)
{
if
(
Log
.
isLoggable
(
TAG
,
Log
.
DEBUG
))
{
Log
.
d
(
TAG
,
"Unable to read segment data for type="
+
segmentType
+
" length="
+
segmentLength
);
Log
.
d
(
TAG
,
"Unable to read segment data"
+
", type: "
+
segmentType
+
", length: "
+
segmentLength
+
", actually read: "
+
read
);
}
return
null
;
}
else
{
...
...
@@ -229,7 +236,7 @@ public class ImageHeaderParser {
// 12 is max format code.
if
(
formatCode
<
1
||
formatCode
>
12
)
{
if
(
Log
.
isLoggable
(
TAG
,
Log
.
DEBUG
))
{
Log
.
d
(
TAG
,
"Got invalid format code
=
"
+
formatCode
);
Log
.
d
(
TAG
,
"Got invalid format code
=
"
+
formatCode
);
}
continue
;
}
...
...
@@ -244,7 +251,7 @@ public class ImageHeaderParser {
}
if
(
Log
.
isLoggable
(
TAG
,
Log
.
DEBUG
))
{
Log
.
d
(
TAG
,
"Got tagIndex="
+
i
+
" tagType="
+
tagType
+
" formatCode
="
+
formatCode
Log
.
d
(
TAG
,
"Got tagIndex="
+
i
+
" tagType="
+
tagType
+
" formatCode="
+
formatCode
+
" componentCount="
+
componentCount
);
}
...
...
@@ -332,11 +339,39 @@ public class ImageHeaderParser {
}
public
long
skip
(
long
total
)
throws
IOException
{
return
is
.
skip
(
total
);
if
(
total
<
0
)
{
return
0
;
}
long
skipped
;
long
toSkip
=
total
;
while
(
toSkip
>
0
)
{
skipped
=
is
.
skip
(
toSkip
);
if
(
skipped
>
0
)
{
toSkip
-=
skipped
;
}
else
{
// Skip has no specific contract as to what happens when you reach the end of
// the stream. To differentiate between temporarily not having more data and
// having finished the stream, we read a single byte when we fail to skip any
// amount of data.
int
testEofByte
=
is
.
read
();
if
(
testEofByte
==
-
1
)
{
break
;
}
else
{
toSkip
--;
}
}
}
return
total
-
toSkip
;
}
public
int
read
(
byte
[]
buffer
)
throws
IOException
{
return
is
.
read
(
buffer
);
int
toRead
=
buffer
.
length
;
int
read
;
while
(
toRead
>
0
&&
((
read
=
is
.
read
(
buffer
,
buffer
.
length
-
toRead
,
toRead
))
!=
-
1
))
{
toRead
-=
read
;
}
return
buffer
.
length
-
toRead
;
}
public
int
getByte
()
throws
IOException
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录