Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
F
ffmpeg.wasm-core
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Linshizhi
ffmpeg.wasm-core
Commits
51d4bca5
Commit
51d4bca5
authored
Aug 28, 2015
by
Donny Yang
Committed by
Paul B Mahol
Aug 31, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
avcodec/pngdec: fully support the tRNS chunk
Signed-off-by:
Donny Yang
<
work@kota.moe
>
parent
d5911e69
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
89 additions
and
9 deletions
+89
-9
pngdec.c
libavcodec/pngdec.c
+89
-9
No files found.
libavcodec/pngdec.c
View file @
51d4bca5
...
@@ -21,6 +21,7 @@
...
@@ -21,6 +21,7 @@
//#define DEBUG
//#define DEBUG
#include "libavutil/avassert.h"
#include "libavutil/bprint.h"
#include "libavutil/bprint.h"
#include "libavutil/imgutils.h"
#include "libavutil/imgutils.h"
#include "avcodec.h"
#include "avcodec.h"
...
@@ -59,6 +60,7 @@ typedef struct PNGDecContext {
...
@@ -59,6 +60,7 @@ typedef struct PNGDecContext {
int
bits_per_pixel
;
int
bits_per_pixel
;
int
bpp
;
int
bpp
;
int
has_trns
;
int
has_trns
;
uint8_t
transparent_color_be
[
6
];
uint8_t
*
image_buf
;
uint8_t
*
image_buf
;
int
image_linesize
;
int
image_linesize
;
...
@@ -590,6 +592,7 @@ static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s,
...
@@ -590,6 +592,7 @@ static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s,
uint32_t
length
,
AVFrame
*
p
)
uint32_t
length
,
AVFrame
*
p
)
{
{
int
ret
;
int
ret
;
size_t
byte_depth
=
s
->
bit_depth
>
8
?
2
:
1
;
if
(
!
(
s
->
state
&
PNG_IHDR
))
{
if
(
!
(
s
->
state
&
PNG_IHDR
))
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"IDAT without IHDR
\n
"
);
av_log
(
avctx
,
AV_LOG_ERROR
,
"IDAT without IHDR
\n
"
);
...
@@ -641,6 +644,31 @@ static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s,
...
@@ -641,6 +644,31 @@ static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s,
return
AVERROR_INVALIDDATA
;
return
AVERROR_INVALIDDATA
;
}
}
if
(
s
->
has_trns
&&
s
->
color_type
!=
PNG_COLOR_TYPE_PALETTE
)
{
switch
(
avctx
->
pix_fmt
)
{
case
AV_PIX_FMT_RGB24
:
avctx
->
pix_fmt
=
AV_PIX_FMT_RGBA
;
break
;
case
AV_PIX_FMT_RGB48BE
:
avctx
->
pix_fmt
=
AV_PIX_FMT_RGBA64BE
;
break
;
case
AV_PIX_FMT_GRAY8
:
avctx
->
pix_fmt
=
AV_PIX_FMT_YA8
;
break
;
case
AV_PIX_FMT_GRAY16BE
:
avctx
->
pix_fmt
=
AV_PIX_FMT_YA16BE
;
break
;
default
:
av_assert0
(
0
);
}
s
->
bpp
+=
byte_depth
;
}
if
((
ret
=
ff_thread_get_buffer
(
avctx
,
&
s
->
picture
,
AV_GET_BUFFER_FLAG_REF
))
<
0
)
if
((
ret
=
ff_thread_get_buffer
(
avctx
,
&
s
->
picture
,
AV_GET_BUFFER_FLAG_REF
))
<
0
)
return
ret
;
return
ret
;
if
(
avctx
->
codec_id
==
AV_CODEC_ID_APNG
&&
s
->
last_dispose_op
!=
APNG_DISPOSE_OP_PREVIOUS
)
{
if
(
avctx
->
codec_id
==
AV_CODEC_ID_APNG
&&
s
->
last_dispose_op
!=
APNG_DISPOSE_OP_PREVIOUS
)
{
...
@@ -691,9 +719,21 @@ static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s,
...
@@ -691,9 +719,21 @@ static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s,
s
->
zstream
.
avail_out
=
s
->
crow_size
;
s
->
zstream
.
avail_out
=
s
->
crow_size
;
s
->
zstream
.
next_out
=
s
->
crow_buf
;
s
->
zstream
.
next_out
=
s
->
crow_buf
;
}
}
s
->
state
|=
PNG_IDAT
;
s
->
state
|=
PNG_IDAT
;
if
((
ret
=
png_decode_idat
(
s
,
length
))
<
0
)
/* set image to non-transparent bpp while decompressing */
if
(
s
->
has_trns
&&
s
->
color_type
!=
PNG_COLOR_TYPE_PALETTE
)
s
->
bpp
-=
byte_depth
;
ret
=
png_decode_idat
(
s
,
length
);
if
(
s
->
has_trns
&&
s
->
color_type
!=
PNG_COLOR_TYPE_PALETTE
)
s
->
bpp
+=
byte_depth
;
if
(
ret
<
0
)
return
ret
;
return
ret
;
bytestream2_skip
(
&
s
->
gb
,
4
);
/* crc */
bytestream2_skip
(
&
s
->
gb
,
4
);
/* crc */
return
0
;
return
0
;
...
@@ -727,17 +767,33 @@ static int decode_trns_chunk(AVCodecContext *avctx, PNGDecContext *s,
...
@@ -727,17 +767,33 @@ static int decode_trns_chunk(AVCodecContext *avctx, PNGDecContext *s,
{
{
int
v
,
i
;
int
v
,
i
;
/* read the transparency. XXX: Only palette mode supported */
if
(
s
->
color_type
==
PNG_COLOR_TYPE_PALETTE
)
{
if
(
s
->
color_type
!=
PNG_COLOR_TYPE_PALETTE
||
if
(
length
>
256
||
!
(
s
->
state
&
PNG_PLTE
))
length
>
256
||
return
AVERROR_INVALIDDATA
;
!
(
s
->
state
&
PNG_PLTE
))
for
(
i
=
0
;
i
<
length
;
i
++
)
{
v
=
bytestream2_get_byte
(
&
s
->
gb
);
s
->
palette
[
i
]
=
(
s
->
palette
[
i
]
&
0x00ffffff
)
|
(
v
<<
24
);
}
}
else
if
(
s
->
color_type
==
PNG_COLOR_TYPE_GRAY
||
s
->
color_type
==
PNG_COLOR_TYPE_RGB
)
{
if
((
s
->
color_type
==
PNG_COLOR_TYPE_GRAY
&&
length
!=
2
)
||
(
s
->
color_type
==
PNG_COLOR_TYPE_RGB
&&
length
!=
6
))
return
AVERROR_INVALIDDATA
;
for
(
i
=
0
;
i
<
length
/
2
;
i
++
)
{
/* only use the least significant bits */
v
=
bytestream2_get_be16
(
&
s
->
gb
)
&
((
1
<<
s
->
bit_depth
)
-
1
);
if
(
s
->
bit_depth
>
8
)
AV_WB16
(
&
s
->
transparent_color_be
[
2
*
i
],
v
);
else
s
->
transparent_color_be
[
i
]
=
v
;
}
}
else
{
return
AVERROR_INVALIDDATA
;
return
AVERROR_INVALIDDATA
;
for
(
i
=
0
;
i
<
length
;
i
++
)
{
v
=
bytestream2_get_byte
(
&
s
->
gb
);
s
->
palette
[
i
]
=
(
s
->
palette
[
i
]
&
0x00ffffff
)
|
(
v
<<
24
);
}
}
bytestream2_skip
(
&
s
->
gb
,
4
);
/* crc */
bytestream2_skip
(
&
s
->
gb
,
4
);
/* crc */
s
->
has_trns
=
1
;
s
->
has_trns
=
1
;
return
0
;
return
0
;
...
@@ -1122,6 +1178,29 @@ exit_loop:
...
@@ -1122,6 +1178,29 @@ exit_loop:
if
(
s
->
bits_per_pixel
<=
4
)
if
(
s
->
bits_per_pixel
<=
4
)
handle_small_bpp
(
s
,
p
);
handle_small_bpp
(
s
,
p
);
/* apply transparency if needed */
if
(
s
->
has_trns
&&
s
->
color_type
!=
PNG_COLOR_TYPE_PALETTE
)
{
size_t
byte_depth
=
s
->
bit_depth
>
8
?
2
:
1
;
size_t
raw_bpp
=
s
->
bpp
-
byte_depth
;
unsigned
x
,
y
;
for
(
y
=
0
;
y
<
s
->
height
;
++
y
)
{
uint8_t
*
row
=
&
s
->
image_buf
[
s
->
image_linesize
*
y
];
/* since we're updating in-place, we have to go from right to left */
for
(
x
=
s
->
width
;
x
>
0
;
--
x
)
{
uint8_t
*
pixel
=
&
row
[
s
->
bpp
*
(
x
-
1
)];
memmove
(
pixel
,
&
row
[
raw_bpp
*
(
x
-
1
)],
raw_bpp
);
if
(
!
memcmp
(
pixel
,
s
->
transparent_color_be
,
raw_bpp
))
{
memset
(
&
pixel
[
raw_bpp
],
0
,
byte_depth
);
}
else
{
memset
(
&
pixel
[
raw_bpp
],
0xff
,
byte_depth
);
}
}
}
}
/* handle p-frames only if a predecessor frame is available */
/* handle p-frames only if a predecessor frame is available */
if
(
s
->
last_picture
.
f
->
data
[
0
])
{
if
(
s
->
last_picture
.
f
->
data
[
0
])
{
if
(
!
(
avpkt
->
flags
&
AV_PKT_FLAG_KEY
)
&&
avctx
->
codec_tag
!=
AV_RL32
(
"MPNG"
)
if
(
!
(
avpkt
->
flags
&
AV_PKT_FLAG_KEY
)
&&
avctx
->
codec_tag
!=
AV_RL32
(
"MPNG"
)
...
@@ -1285,6 +1364,7 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
...
@@ -1285,6 +1364,7 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
pdst
->
x_offset
=
psrc
->
x_offset
;
pdst
->
x_offset
=
psrc
->
x_offset
;
pdst
->
y_offset
=
psrc
->
y_offset
;
pdst
->
y_offset
=
psrc
->
y_offset
;
pdst
->
has_trns
=
psrc
->
has_trns
;
pdst
->
has_trns
=
psrc
->
has_trns
;
memcpy
(
pdst
->
transparent_color_be
,
psrc
->
transparent_color_be
,
sizeof
(
pdst
->
transparent_color_be
));
pdst
->
dispose_op
=
psrc
->
dispose_op
;
pdst
->
dispose_op
=
psrc
->
dispose_op
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment