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
c598b569
Commit
c598b569
authored
Mar 14, 2014
by
Vittorio Giovara
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
png: K&R formatting cosmetics
parent
f7518f1a
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
209 additions
and
185 deletions
+209
-185
png.c
libavcodec/png.c
+3
-3
pngdec.c
libavcodec/pngdec.c
+117
-104
pngdsp.c
libavcodec/pngdsp.c
+5
-4
pngenc.c
libavcodec/pngenc.c
+84
-74
No files found.
libavcodec/png.c
View file @
c598b569
...
...
@@ -22,8 +22,8 @@
#include "bytestream.h"
#include "png.h"
const
uint8_t
ff_pngsig
[
8
]
=
{
137
,
80
,
78
,
71
,
13
,
10
,
26
,
10
};
const
uint8_t
ff_mngsig
[
8
]
=
{
138
,
77
,
78
,
71
,
13
,
10
,
26
,
10
};
const
uint8_t
ff_pngsig
[
8
]
=
{
137
,
80
,
78
,
71
,
13
,
10
,
26
,
10
};
const
uint8_t
ff_mngsig
[
8
]
=
{
138
,
77
,
78
,
71
,
13
,
10
,
26
,
10
};
/* Mask to determine which y pixels are valid in a pass */
const
uint8_t
ff_png_pass_ymask
[
NB_PASSES
]
=
{
...
...
@@ -75,7 +75,7 @@ int ff_png_pass_row_size(int pass, int bits_per_pixel, int width)
xmin
=
ff_png_pass_xmin
[
pass
];
if
(
width
<=
xmin
)
return
0
;
shift
=
ff_png_pass_xshift
[
pass
];
shift
=
ff_png_pass_xshift
[
pass
];
pass_width
=
(
width
-
xmin
+
(
1
<<
shift
)
-
1
)
>>
shift
;
return
(
pass_width
*
bits_per_pixel
+
7
)
>>
3
;
}
libavcodec/pngdec.c
View file @
c598b569
...
...
@@ -73,8 +73,8 @@ static const uint8_t png_pass_dsp_mask[NB_PASSES] = {
};
/* NOTE: we try to construct a good looking image at each pass. width
is the original image width. We also do pixel format conversion at
this stage */
*
is the original image width. We also do pixel format conversion at
*
this stage */
static
void
png_put_interlaced_row
(
uint8_t
*
dst
,
int
width
,
int
bits_per_pixel
,
int
pass
,
int
color_type
,
const
uint8_t
*
src
)
...
...
@@ -117,7 +117,7 @@ static void png_put_interlaced_row(uint8_t *dst, int width,
s
+=
bpp
;
}
}
else
{
for
(
x
=
0
;
x
<
width
;
x
++
)
{
for
(
x
=
0
;
x
<
width
;
x
++
)
{
j
=
x
&
7
;
if
((
dsp_mask
<<
j
)
&
0x80
)
{
memcpy
(
d
,
s
,
bpp
);
...
...
@@ -131,7 +131,8 @@ static void png_put_interlaced_row(uint8_t *dst, int width,
}
}
void
ff_add_png_paeth_prediction
(
uint8_t
*
dst
,
uint8_t
*
src
,
uint8_t
*
top
,
int
w
,
int
bpp
)
void
ff_add_png_paeth_prediction
(
uint8_t
*
dst
,
uint8_t
*
src
,
uint8_t
*
top
,
int
w
,
int
bpp
)
{
int
i
;
for
(
i
=
0
;
i
<
w
;
i
++
)
{
...
...
@@ -158,34 +159,45 @@ void ff_add_png_paeth_prediction(uint8_t *dst, uint8_t *src, uint8_t *top, int w
}
}
#define UNROLL1(bpp, op) {\
r = dst[0];\
if(bpp >= 2) g = dst[1];\
if(bpp >= 3) b = dst[2];\
if(bpp >= 4) a = dst[3];\
for(; i < size; i+=bpp) {\
dst[i+0] = r = op(r, src[i+0], last[i+0]);\
if(bpp == 1) continue;\
dst[i+1] = g = op(g, src[i+1], last[i+1]);\
if(bpp == 2) continue;\
dst[i+2] = b = op(b, src[i+2], last[i+2]);\
if(bpp == 3) continue;\
dst[i+3] = a = op(a, src[i+3], last[i+3]);\
}\
#define UNROLL1(bpp, op) { \
r = dst[0]; \
if (bpp >= 2) \
g = dst[1]; \
if (bpp >= 3) \
b = dst[2]; \
if (bpp >= 4) \
a = dst[3]; \
for (; i < size; i += bpp) { \
dst[i + 0] = r = op(r, src[i + 0], last[i + 0]); \
if (bpp == 1) \
continue; \
dst[i + 1] = g = op(g, src[i + 1], last[i + 1]); \
if (bpp == 2) \
continue; \
dst[i + 2] = b = op(b, src[i + 2], last[i + 2]); \
if (bpp == 3) \
continue; \
dst[i + 3] = a = op(a, src[i + 3], last[i + 3]); \
} \
}
#define UNROLL_FILTER(op)\
if(bpp == 1) UNROLL1(1, op)\
else if(bpp == 2) UNROLL1(2, op)\
else if(bpp == 3) UNROLL1(3, op)\
else if(bpp == 4) UNROLL1(4, op)\
else {\
for (; i < size; i += bpp) {\
int j;\
for (j = 0; j < bpp; j++)\
dst[i+j] = op(dst[i+j-bpp], src[i+j], last[i+j]);\
}\
}
#define UNROLL_FILTER(op) \
if (bpp == 1) \
UNROLL1(1, op) \
else if (bpp == 2) \
UNROLL1(2, op) \
else if (bpp == 3) \
UNROLL1(3, op) \
else if (bpp == 4) \
UNROLL1(4, op) \
else { \
for (; i < size; i += bpp) { \
int j; \
for (j = 0; j < bpp; j++) \
dst[i + j] = op(dst[i + j - bpp], \
src[i + j], last[i + j]); \
} \
}
/* NOTE: 'dst' can be equal to 'last' */
static
void
png_filter_row
(
PNGDSPContext
*
dsp
,
uint8_t
*
dst
,
int
filter_type
,
...
...
@@ -198,18 +210,17 @@ static void png_filter_row(PNGDSPContext *dsp, uint8_t *dst, int filter_type,
memcpy
(
dst
,
src
,
size
);
break
;
case
PNG_FILTER_VALUE_SUB
:
for
(
i
=
0
;
i
<
bpp
;
i
++
)
{
for
(
i
=
0
;
i
<
bpp
;
i
++
)
dst
[
i
]
=
src
[
i
];
}
if
(
bpp
==
4
)
{
p
=
*
(
int
*
)
dst
;
p
=
*
(
int
*
)
dst
;
for
(;
i
<
size
;
i
+=
bpp
)
{
int
s
=
*
(
int
*
)(
src
+
i
);
int
s
=
*
(
int
*
)(
src
+
i
);
p
=
((
s
&
0x7f7f7f7f
)
+
(
p
&
0x7f7f7f7f
))
^
((
s
^
p
)
&
0x80808080
);
*
(
int
*
)(
dst
+
i
)
=
p
;
*
(
int
*
)(
dst
+
i
)
=
p
;
}
}
else
{
#define OP_SUB(x,
s,l) x+
s
#define OP_SUB(x,
s, l) x +
s
UNROLL_FILTER
(
OP_SUB
);
}
break
;
...
...
@@ -218,19 +229,20 @@ static void png_filter_row(PNGDSPContext *dsp, uint8_t *dst, int filter_type,
break
;
case
PNG_FILTER_VALUE_AVG
:
for
(
i
=
0
;
i
<
bpp
;
i
++
)
{
p
=
(
last
[
i
]
>>
1
);
p
=
(
last
[
i
]
>>
1
);
dst
[
i
]
=
p
+
src
[
i
];
}
#define OP_AVG(x,
s,
l) (((x + l) >> 1) + s) & 0xff
#define OP_AVG(x,
s,
l) (((x + l) >> 1) + s) & 0xff
UNROLL_FILTER
(
OP_AVG
);
break
;
case
PNG_FILTER_VALUE_PAETH
:
for
(
i
=
0
;
i
<
bpp
;
i
++
)
{
p
=
last
[
i
];
p
=
last
[
i
];
dst
[
i
]
=
p
+
src
[
i
];
}
if
(
bpp
>
1
&&
size
>
4
)
{
// would write off the end of the array if we let it process the last pixel with bpp=3
/* would write off the end of the array if we let it process
* the last pixel with bpp=3 */
int
w
=
bpp
==
4
?
size
:
size
-
3
;
dsp
->
add_paeth_prediction
(
dst
+
i
,
src
+
i
,
last
+
i
,
w
-
i
,
bpp
);
i
=
w
;
...
...
@@ -256,13 +268,14 @@ static av_always_inline void convert_to_rgb32_loco(uint8_t *dst,
r
=
(
r
+
g
)
&
0xff
;
b
=
(
b
+
g
)
&
0xff
;
}
*
(
uint32_t
*
)
dst
=
(
a
<<
24
)
|
(
r
<<
16
)
|
(
g
<<
8
)
|
b
;
*
(
uint32_t
*
)
dst
=
(
a
<<
24
)
|
(
r
<<
16
)
|
(
g
<<
8
)
|
b
;
dst
+=
4
;
src
+=
4
;
}
}
static
void
convert_to_rgb32
(
uint8_t
*
dst
,
const
uint8_t
*
src
,
int
width
,
int
loco
)
static
void
convert_to_rgb32
(
uint8_t
*
dst
,
const
uint8_t
*
src
,
int
width
,
int
loco
)
{
if
(
loco
)
convert_to_rgb32_loco
(
dst
,
src
,
width
,
1
);
...
...
@@ -292,8 +305,9 @@ static void png_handle_row(PNGDecContext *s)
if
(
s
->
color_type
==
PNG_COLOR_TYPE_RGB_ALPHA
)
{
png_filter_row
(
&
s
->
dsp
,
s
->
tmp_row
,
s
->
crow_buf
[
0
],
s
->
crow_buf
+
1
,
s
->
last_row
,
s
->
row_size
,
s
->
bpp
);
convert_to_rgb32
(
ptr
,
s
->
tmp_row
,
s
->
width
,
s
->
filter_type
==
PNG_FILTER_TYPE_LOCO
);
FFSWAP
(
uint8_t
*
,
s
->
last_row
,
s
->
tmp_row
);
convert_to_rgb32
(
ptr
,
s
->
tmp_row
,
s
->
width
,
s
->
filter_type
==
PNG_FILTER_TYPE_LOCO
);
FFSWAP
(
uint8_t
*
,
s
->
last_row
,
s
->
tmp_row
);
}
else
{
/* in normal case, we avoid one copy */
if
(
s
->
y
==
0
)
...
...
@@ -321,12 +335,12 @@ static void png_handle_row(PNGDecContext *s)
ptr
=
s
->
image_buf
+
s
->
image_linesize
*
s
->
y
;
if
((
ff_png_pass_ymask
[
s
->
pass
]
<<
(
s
->
y
&
7
))
&
0x80
)
{
/* if we already read one row, it is time to stop to
wait for the next one */
*
wait for the next one */
if
(
got_line
)
break
;
png_filter_row
(
&
s
->
dsp
,
s
->
tmp_row
,
s
->
crow_buf
[
0
],
s
->
crow_buf
+
1
,
s
->
last_row
,
s
->
pass_row_size
,
s
->
bpp
);
FFSWAP
(
uint8_t
*
,
s
->
last_row
,
s
->
tmp_row
);
FFSWAP
(
uint8_t
*
,
s
->
last_row
,
s
->
tmp_row
);
got_line
=
1
;
}
if
((
png_pass_dsp_ymask
[
s
->
pass
]
<<
(
s
->
y
&
7
))
&
0x80
)
{
...
...
@@ -344,8 +358,8 @@ static void png_handle_row(PNGDecContext *s)
s
->
pass
++
;
s
->
y
=
0
;
s
->
pass_row_size
=
ff_png_pass_row_size
(
s
->
pass
,
s
->
bits_per_pixel
,
s
->
width
);
s
->
bits_per_pixel
,
s
->
width
);
s
->
crow_size
=
s
->
pass_row_size
+
1
;
if
(
s
->
pass_row_size
!=
0
)
break
;
...
...
@@ -354,7 +368,7 @@ static void png_handle_row(PNGDecContext *s)
}
}
}
the_end:
;
the_end:
;
}
}
...
...
@@ -379,7 +393,8 @@ static int png_decode_idat(PNGDecContext *s, int length)
s
->
zstream
.
next_out
=
s
->
crow_buf
;
}
if
(
ret
==
Z_STREAM_END
&&
s
->
zstream
.
avail_in
>
0
)
{
av_log
(
NULL
,
AV_LOG_WARNING
,
"%d undecompressed bytes left in buffer
\n
"
,
s
->
zstream
.
avail_in
);
av_log
(
NULL
,
AV_LOG_WARNING
,
"%d undecompressed bytes left in buffer
\n
"
,
s
->
zstream
.
avail_in
);
return
0
;
}
}
...
...
@@ -390,11 +405,11 @@ static int decode_frame(AVCodecContext *avctx,
void
*
data
,
int
*
got_frame
,
AVPacket
*
avpkt
)
{
PNGDecContext
*
const
s
=
avctx
->
priv_data
;
const
uint8_t
*
buf
=
avpkt
->
data
;
int
buf_size
=
avpkt
->
size
;
AVFrame
*
p
=
data
;
uint8_t
*
crow_buf_base
=
NULL
;
PNGDecContext
*
const
s
=
avctx
->
priv_data
;
const
uint8_t
*
buf
=
avpkt
->
data
;
int
buf_size
=
avpkt
->
size
;
AVFrame
*
p
=
data
;
uint8_t
*
crow_buf_base
=
NULL
;
uint32_t
tag
,
length
;
int
ret
;
...
...
@@ -444,7 +459,7 @@ static int decode_frame(AVCodecContext *avctx,
bytestream2_skip
(
&
s
->
gb
,
4
);
/* crc */
s
->
state
|=
PNG_IHDR
;
av_dlog
(
avctx
,
"width=%d height=%d depth=%d color_type=%d "
"compression_type=%d filter_type=%d interlace_type=%d
\n
"
,
"compression_type=%d filter_type=%d interlace_type=%d
\n
"
,
s
->
width
,
s
->
height
,
s
->
bit_depth
,
s
->
color_type
,
s
->
compression_type
,
s
->
filter_type
,
s
->
interlace_type
);
break
;
...
...
@@ -501,10 +516,10 @@ static int decode_frame(AVCodecContext *avctx,
if
(
!
s
->
interlace_type
)
{
s
->
crow_size
=
s
->
row_size
+
1
;
}
else
{
s
->
pass
=
0
;
s
->
pass
=
0
;
s
->
pass_row_size
=
ff_png_pass_row_size
(
s
->
pass
,
s
->
bits_per_pixel
,
s
->
width
);
s
->
bits_per_pixel
,
s
->
width
);
s
->
crow_size
=
s
->
pass_row_size
+
1
;
}
av_dlog
(
avctx
,
"row_size=%d crow_size =%d
\n
"
,
...
...
@@ -540,42 +555,41 @@ static int decode_frame(AVCodecContext *avctx,
bytestream2_skip
(
&
s
->
gb
,
4
);
/* crc */
break
;
case
MKTAG
(
'P'
,
'L'
,
'T'
,
'E'
):
{
int
n
,
i
,
r
,
g
,
b
;
if
((
length
%
3
)
!=
0
||
length
>
256
*
3
)
goto
skip_tag
;
/* read the palette */
n
=
length
/
3
;
for
(
i
=
0
;
i
<
n
;
i
++
)
{
r
=
bytestream2_get_byte
(
&
s
->
gb
);
g
=
bytestream2_get_byte
(
&
s
->
gb
);
b
=
bytestream2_get_byte
(
&
s
->
gb
);
s
->
palette
[
i
]
=
(
0xff
<<
24
)
|
(
r
<<
16
)
|
(
g
<<
8
)
|
b
;
}
for
(;
i
<
256
;
i
++
)
{
s
->
palette
[
i
]
=
(
0xff
<<
24
);
}
s
->
state
|=
PNG_PLTE
;
bytestream2_skip
(
&
s
->
gb
,
4
);
/* crc */
{
int
n
,
i
,
r
,
g
,
b
;
if
((
length
%
3
)
!=
0
||
length
>
256
*
3
)
goto
skip_tag
;
/* read the palette */
n
=
length
/
3
;
for
(
i
=
0
;
i
<
n
;
i
++
)
{
r
=
bytestream2_get_byte
(
&
s
->
gb
);
g
=
bytestream2_get_byte
(
&
s
->
gb
);
b
=
bytestream2_get_byte
(
&
s
->
gb
);
s
->
palette
[
i
]
=
(
0xff
<<
24
)
|
(
r
<<
16
)
|
(
g
<<
8
)
|
b
;
}
break
;
for
(;
i
<
256
;
i
++
)
s
->
palette
[
i
]
=
(
0xff
<<
24
);
s
->
state
|=
PNG_PLTE
;
bytestream2_skip
(
&
s
->
gb
,
4
);
/* crc */
}
break
;
case
MKTAG
(
't'
,
'R'
,
'N'
,
'S'
):
{
int
v
,
i
;
/* read the transparency. XXX: Only palette mode supported */
if
(
s
->
color_type
!=
PNG_COLOR_TYPE_PALETTE
||
length
>
256
||
!
(
s
->
state
&
PNG_PLTE
))
goto
skip_tag
;
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 */
{
int
v
,
i
;
/* read the transparency. XXX: Only palette mode supported */
if
(
s
->
color_type
!=
PNG_COLOR_TYPE_PALETTE
||
length
>
256
||
!
(
s
->
state
&
PNG_PLTE
))
goto
skip_tag
;
for
(
i
=
0
;
i
<
length
;
i
++
)
{
v
=
bytestream2_get_byte
(
&
s
->
gb
);
s
->
palette
[
i
]
=
(
s
->
palette
[
i
]
&
0x00ffffff
)
|
(
v
<<
24
);
}
break
;
bytestream2_skip
(
&
s
->
gb
,
4
);
/* crc */
}
break
;
case
MKTAG
(
'I'
,
'E'
,
'N'
,
'D'
):
if
(
!
(
s
->
state
&
PNG_ALLIMAGE
))
goto
fail
;
...
...
@@ -583,44 +597,43 @@ static int decode_frame(AVCodecContext *avctx,
goto
exit_loop
;
default:
/* skip tag */
skip_tag:
skip_tag:
bytestream2_skip
(
&
s
->
gb
,
length
+
4
);
break
;
}
}
exit_loop:
/* handle p-frames only if a predecessor frame is available */
if
(
s
->
prev
->
data
[
0
])
{
if
(
!
(
avpkt
->
flags
&
AV_PKT_FLAG_KEY
))
{
exit_loop:
/* handle p-frames only if a predecessor frame is available */
if
(
s
->
prev
->
data
[
0
])
{
if
(
!
(
avpkt
->
flags
&
AV_PKT_FLAG_KEY
))
{
int
i
,
j
;
uint8_t
*
pd
=
p
->
data
[
0
];
uint8_t
*
pd_last
=
s
->
prev
->
data
[
0
];
for
(
j
=
0
;
j
<
s
->
height
;
j
++
)
{
for
(
i
=
0
;
i
<
s
->
width
*
s
->
bpp
;
i
++
)
{
for
(
i
=
0
;
i
<
s
->
width
*
s
->
bpp
;
i
++
)
pd
[
i
]
+=
pd_last
[
i
];
}
pd
+=
s
->
image_linesize
;
pd_last
+=
s
->
image_linesize
;
}
}
}
av_frame_unref
(
s
->
prev
);
if
((
ret
=
av_frame_ref
(
s
->
prev
,
p
))
<
0
)
goto
fail
;
av_frame_unref
(
s
->
prev
);
if
((
ret
=
av_frame_ref
(
s
->
prev
,
p
))
<
0
)
goto
fail
;
*
got_frame
=
1
;
ret
=
bytestream2_tell
(
&
s
->
gb
);
the_end:
the_end:
inflateEnd
(
&
s
->
zstream
);
av_free
(
crow_buf_base
);
s
->
crow_buf
=
NULL
;
av_freep
(
&
s
->
last_row
);
av_freep
(
&
s
->
tmp_row
);
return
ret
;
fail:
fail:
ret
=
-
1
;
goto
the_end
;
}
...
...
libavcodec/pngdsp.c
View file @
c598b569
...
...
@@ -25,13 +25,13 @@
#include "pngdsp.h"
// 0x7f7f7f7f or 0x7f7f7f7f7f7f7f7f or whatever, depending on the cpu's native arithmetic size
#define pb_7f (~0UL
/
255 * 0x7f)
#define pb_80 (~0UL
/
255 * 0x80)
#define pb_7f (~0UL
/
255 * 0x7f)
#define pb_80 (~0UL
/
255 * 0x80)
static
void
add_bytes_l2_c
(
uint8_t
*
dst
,
uint8_t
*
src1
,
uint8_t
*
src2
,
int
w
)
{
long
i
;
for
(
i
=
0
;
i
<=
w
-
(
int
)
sizeof
(
long
);
i
+=
sizeof
(
long
))
{
for
(
i
=
0
;
i
<=
w
-
(
int
)
sizeof
(
long
);
i
+=
sizeof
(
long
))
{
long
a
=
*
(
long
*
)(
src1
+
i
);
long
b
=
*
(
long
*
)(
src2
+
i
);
*
(
long
*
)(
dst
+
i
)
=
((
a
&
pb_7f
)
+
(
b
&
pb_7f
))
^
((
a
^
b
)
&
pb_80
);
...
...
@@ -45,5 +45,6 @@ av_cold void ff_pngdsp_init(PNGDSPContext *dsp)
dsp
->
add_bytes_l2
=
add_bytes_l2_c
;
dsp
->
add_paeth_prediction
=
ff_add_png_paeth_prediction
;
if
(
ARCH_X86
)
ff_pngdsp_init_x86
(
dsp
);
if
(
ARCH_X86
)
ff_pngdsp_init_x86
(
dsp
);
}
libavcodec/pngenc.c
View file @
c598b569
...
...
@@ -18,6 +18,7 @@
* License along with Libav; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "avcodec.h"
#include "bytestream.h"
#include "dsputil.h"
...
...
@@ -53,11 +54,11 @@ static void png_get_interlaced_row(uint8_t *dst, int row_size,
const
uint8_t
*
s
;
mask
=
ff_png_pass_mask
[
pass
];
switch
(
bits_per_pixel
)
{
switch
(
bits_per_pixel
)
{
case
1
:
memset
(
dst
,
0
,
row_size
);
dst_x
=
0
;
for
(
x
=
0
;
x
<
width
;
x
++
)
{
for
(
x
=
0
;
x
<
width
;
x
++
)
{
j
=
(
x
&
7
);
if
((
mask
<<
j
)
&
0x80
)
{
b
=
(
src
[
x
>>
3
]
>>
(
7
-
j
))
&
1
;
...
...
@@ -70,7 +71,7 @@ static void png_get_interlaced_row(uint8_t *dst, int row_size,
bpp
=
bits_per_pixel
>>
3
;
d
=
dst
;
s
=
src
;
for
(
x
=
0
;
x
<
width
;
x
++
)
{
for
(
x
=
0
;
x
<
width
;
x
++
)
{
j
=
x
&
7
;
if
((
mask
<<
j
)
&
0x80
)
{
memcpy
(
d
,
s
,
bpp
);
...
...
@@ -82,17 +83,18 @@ static void png_get_interlaced_row(uint8_t *dst, int row_size,
}
}
static
void
sub_png_paeth_prediction
(
uint8_t
*
dst
,
uint8_t
*
src
,
uint8_t
*
top
,
int
w
,
int
bpp
)
static
void
sub_png_paeth_prediction
(
uint8_t
*
dst
,
uint8_t
*
src
,
uint8_t
*
top
,
int
w
,
int
bpp
)
{
int
i
;
for
(
i
=
0
;
i
<
w
;
i
++
)
{
for
(
i
=
0
;
i
<
w
;
i
++
)
{
int
a
,
b
,
c
,
p
,
pa
,
pb
,
pc
;
a
=
src
[
i
-
bpp
];
b
=
top
[
i
];
c
=
top
[
i
-
bpp
];
p
=
b
-
c
;
p
=
b
-
c
;
pc
=
a
-
c
;
pa
=
abs
(
p
);
...
...
@@ -114,27 +116,27 @@ static void png_filter_row(DSPContext *dsp, uint8_t *dst, int filter_type,
{
int
i
;
switch
(
filter_type
)
{
switch
(
filter_type
)
{
case
PNG_FILTER_VALUE_NONE
:
memcpy
(
dst
,
src
,
size
);
break
;
case
PNG_FILTER_VALUE_SUB
:
dsp
->
diff_bytes
(
dst
,
src
,
src
-
bpp
,
size
);
dsp
->
diff_bytes
(
dst
,
src
,
src
-
bpp
,
size
);
memcpy
(
dst
,
src
,
bpp
);
break
;
case
PNG_FILTER_VALUE_UP
:
dsp
->
diff_bytes
(
dst
,
src
,
top
,
size
);
break
;
case
PNG_FILTER_VALUE_AVG
:
for
(
i
=
0
;
i
<
bpp
;
i
++
)
for
(
i
=
0
;
i
<
bpp
;
i
++
)
dst
[
i
]
=
src
[
i
]
-
(
top
[
i
]
>>
1
);
for
(;
i
<
size
;
i
++
)
dst
[
i
]
=
src
[
i
]
-
((
src
[
i
-
bpp
]
+
top
[
i
])
>>
1
);
for
(;
i
<
size
;
i
++
)
dst
[
i
]
=
src
[
i
]
-
((
src
[
i
-
bpp
]
+
top
[
i
])
>>
1
);
break
;
case
PNG_FILTER_VALUE_PAETH
:
for
(
i
=
0
;
i
<
bpp
;
i
++
)
for
(
i
=
0
;
i
<
bpp
;
i
++
)
dst
[
i
]
=
src
[
i
]
-
top
[
i
];
sub_png_paeth_prediction
(
dst
+
i
,
src
+
i
,
top
+
i
,
size
-
i
,
bpp
);
sub_png_paeth_prediction
(
dst
+
i
,
src
+
i
,
top
+
i
,
size
-
i
,
bpp
);
break
;
}
}
...
...
@@ -144,26 +146,26 @@ static uint8_t *png_choose_filter(PNGEncContext *s, uint8_t *dst,
{
int
pred
=
s
->
filter_type
;
assert
(
bpp
||
!
pred
);
if
(
!
top
&&
pred
)
if
(
!
top
&&
pred
)
pred
=
PNG_FILTER_VALUE_SUB
;
if
(
pred
==
PNG_FILTER_VALUE_MIXED
)
{
if
(
pred
==
PNG_FILTER_VALUE_MIXED
)
{
int
i
;
int
cost
,
bcost
=
INT_MAX
;
uint8_t
*
buf1
=
dst
,
*
buf2
=
dst
+
size
+
16
;
for
(
pred
=
0
;
pred
<
5
;
pred
++
)
{
png_filter_row
(
&
s
->
dsp
,
buf1
+
1
,
pred
,
src
,
top
,
size
,
bpp
);
for
(
pred
=
0
;
pred
<
5
;
pred
++
)
{
png_filter_row
(
&
s
->
dsp
,
buf1
+
1
,
pred
,
src
,
top
,
size
,
bpp
);
buf1
[
0
]
=
pred
;
cost
=
0
;
for
(
i
=
0
;
i
<=
size
;
i
++
)
cost
+=
abs
((
int8_t
)
buf1
[
i
]);
if
(
cost
<
bcost
)
{
for
(
i
=
0
;
i
<=
size
;
i
++
)
cost
+=
abs
((
int8_t
)
buf1
[
i
]);
if
(
cost
<
bcost
)
{
bcost
=
cost
;
FFSWAP
(
uint8_t
*
,
buf1
,
buf2
);
FFSWAP
(
uint8_t
*
,
buf1
,
buf2
);
}
}
return
buf2
;
}
else
{
png_filter_row
(
&
s
->
dsp
,
dst
+
1
,
pred
,
src
,
top
,
size
,
bpp
);
png_filter_row
(
&
s
->
dsp
,
dst
+
1
,
pred
,
src
,
top
,
size
,
bpp
);
dst
[
0
]
=
pred
;
return
dst
;
}
...
...
@@ -176,13 +178,13 @@ static void convert_from_rgb32(uint8_t *dst, const uint8_t *src, int width)
unsigned
int
v
;
d
=
dst
;
for
(
j
=
0
;
j
<
width
;
j
++
)
{
v
=
((
const
uint32_t
*
)
src
)[
j
];
for
(
j
=
0
;
j
<
width
;
j
++
)
{
v
=
((
const
uint32_t
*
)
src
)[
j
];
d
[
0
]
=
v
>>
16
;
d
[
1
]
=
v
>>
8
;
d
[
2
]
=
v
;
d
[
3
]
=
v
>>
24
;
d
+=
4
;
d
+=
4
;
}
}
...
...
@@ -211,16 +213,17 @@ static int png_write_row(PNGEncContext *s, const uint8_t *data, int size)
int
ret
;
s
->
zstream
.
avail_in
=
size
;
s
->
zstream
.
next_in
=
(
uint8_t
*
)
data
;
s
->
zstream
.
next_in
=
(
uint8_t
*
)
data
;
while
(
s
->
zstream
.
avail_in
>
0
)
{
ret
=
deflate
(
&
s
->
zstream
,
Z_NO_FLUSH
);
if
(
ret
!=
Z_OK
)
return
-
1
;
if
(
s
->
zstream
.
avail_out
==
0
)
{
if
(
s
->
bytestream_end
-
s
->
bytestream
>
IOBUF_SIZE
+
100
)
png_write_chunk
(
&
s
->
bytestream
,
MKTAG
(
'I'
,
'D'
,
'A'
,
'T'
),
s
->
buf
,
IOBUF_SIZE
);
if
(
s
->
bytestream_end
-
s
->
bytestream
>
IOBUF_SIZE
+
100
)
png_write_chunk
(
&
s
->
bytestream
,
MKTAG
(
'I'
,
'D'
,
'A'
,
'T'
),
s
->
buf
,
IOBUF_SIZE
);
s
->
zstream
.
avail_out
=
IOBUF_SIZE
;
s
->
zstream
.
next_out
=
s
->
buf
;
s
->
zstream
.
next_out
=
s
->
buf
;
}
}
return
0
;
...
...
@@ -229,55 +232,55 @@ static int png_write_row(PNGEncContext *s, const uint8_t *data, int size)
static
int
encode_frame
(
AVCodecContext
*
avctx
,
AVPacket
*
pkt
,
const
AVFrame
*
pict
,
int
*
got_packet
)
{
PNGEncContext
*
s
=
avctx
->
priv_data
;
const
AVFrame
*
const
p
=
pict
;
PNGEncContext
*
s
=
avctx
->
priv_data
;
const
AVFrame
*
const
p
=
pict
;
int
bit_depth
,
color_type
,
y
,
len
,
row_size
,
ret
,
is_progressive
;
int
bits_per_pixel
,
pass_row_size
,
enc_row_size
,
max_packet_size
;
int
compression_level
;
uint8_t
*
ptr
,
*
top
;
uint8_t
*
crow_base
=
NULL
,
*
crow_buf
,
*
crow
;
uint8_t
*
ptr
,
*
top
,
*
crow_buf
,
*
crow
;
uint8_t
*
crow_base
=
NULL
;
uint8_t
*
progressive_buf
=
NULL
;
uint8_t
*
rgba_buf
=
NULL
;
uint8_t
*
top_buf
=
NULL
;
uint8_t
*
rgba_buf
=
NULL
;
uint8_t
*
top_buf
=
NULL
;
is_progressive
=
!!
(
avctx
->
flags
&
CODEC_FLAG_INTERLACED_DCT
);
switch
(
avctx
->
pix_fmt
)
{
switch
(
avctx
->
pix_fmt
)
{
case
AV_PIX_FMT_RGB32
:
bit_depth
=
8
;
bit_depth
=
8
;
color_type
=
PNG_COLOR_TYPE_RGB_ALPHA
;
break
;
case
AV_PIX_FMT_RGB24
:
bit_depth
=
8
;
bit_depth
=
8
;
color_type
=
PNG_COLOR_TYPE_RGB
;
break
;
case
AV_PIX_FMT_GRAY16BE
:
bit_depth
=
16
;
bit_depth
=
16
;
color_type
=
PNG_COLOR_TYPE_GRAY
;
break
;
case
AV_PIX_FMT_GRAY8
:
bit_depth
=
8
;
bit_depth
=
8
;
color_type
=
PNG_COLOR_TYPE_GRAY
;
break
;
case
AV_PIX_FMT_MONOBLACK
:
bit_depth
=
1
;
bit_depth
=
1
;
color_type
=
PNG_COLOR_TYPE_GRAY
;
break
;
case
AV_PIX_FMT_PAL8
:
bit_depth
=
8
;
bit_depth
=
8
;
color_type
=
PNG_COLOR_TYPE_PALETTE
;
break
;
default:
return
-
1
;
}
bits_per_pixel
=
ff_png_get_nb_channels
(
color_type
)
*
bit_depth
;
row_size
=
(
avctx
->
width
*
bits_per_pixel
+
7
)
>>
3
;
row_size
=
(
avctx
->
width
*
bits_per_pixel
+
7
)
>>
3
;
s
->
zstream
.
zalloc
=
ff_png_zalloc
;
s
->
zstream
.
zfree
=
ff_png_zfree
;
s
->
zstream
.
zfree
=
ff_png_zfree
;
s
->
zstream
.
opaque
=
NULL
;
compression_level
=
avctx
->
compression_level
==
FF_COMPRESSION_DEFAULT
?
Z_DEFAULT_COMPRESSION
:
av_clip
(
avctx
->
compression_level
,
0
,
9
);
compression_level
=
avctx
->
compression_level
==
FF_COMPRESSION_DEFAULT
?
Z_DEFAULT_COMPRESSION
:
av_clip
(
avctx
->
compression_level
,
0
,
9
);
ret
=
deflateInit2
(
&
s
->
zstream
,
compression_level
,
Z_DEFLATED
,
15
,
8
,
Z_DEFAULT_STRATEGY
);
if
(
ret
!=
Z_OK
)
...
...
@@ -301,7 +304,8 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
crow_base
=
av_malloc
((
row_size
+
32
)
<<
(
s
->
filter_type
==
PNG_FILTER_VALUE_MIXED
));
if
(
!
crow_base
)
goto
fail
;
crow_buf
=
crow_base
+
15
;
// pixel data should be aligned, but there's a control byte before it
// pixel data should be aligned, but there's a control byte before it
crow_buf
=
crow_base
+
15
;
if
(
is_progressive
)
{
progressive_buf
=
av_malloc
(
row_size
+
1
);
if
(
!
progressive_buf
)
...
...
@@ -324,8 +328,8 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
AV_WB32
(
s
->
buf
,
avctx
->
width
);
AV_WB32
(
s
->
buf
+
4
,
avctx
->
height
);
s
->
buf
[
8
]
=
bit_depth
;
s
->
buf
[
9
]
=
color_type
;
s
->
buf
[
8
]
=
bit_depth
;
s
->
buf
[
9
]
=
color_type
;
s
->
buf
[
10
]
=
0
;
/* compression type */
s
->
buf
[
11
]
=
0
;
/* filter type */
s
->
buf
[
12
]
=
is_progressive
;
/* interlace type */
...
...
@@ -339,40 +343,42 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
uint32_t
*
palette
;
uint8_t
*
alpha_ptr
;
palette
=
(
uint32_t
*
)
p
->
data
[
1
];
ptr
=
s
->
buf
;
palette
=
(
uint32_t
*
)
p
->
data
[
1
];
ptr
=
s
->
buf
;
alpha_ptr
=
s
->
buf
+
256
*
3
;
has_alpha
=
0
;
for
(
i
=
0
;
i
<
256
;
i
++
)
{
v
=
palette
[
i
];
for
(
i
=
0
;
i
<
256
;
i
++
)
{
v
=
palette
[
i
];
alpha
=
v
>>
24
;
if
(
alpha
&&
alpha
!=
0xff
)
has_alpha
=
1
;
*
alpha_ptr
++
=
alpha
;
bytestream_put_be24
(
&
ptr
,
v
);
}
png_write_chunk
(
&
s
->
bytestream
,
MKTAG
(
'P'
,
'L'
,
'T'
,
'E'
),
s
->
buf
,
256
*
3
);
png_write_chunk
(
&
s
->
bytestream
,
MKTAG
(
'P'
,
'L'
,
'T'
,
'E'
),
s
->
buf
,
256
*
3
);
if
(
has_alpha
)
{
png_write_chunk
(
&
s
->
bytestream
,
MKTAG
(
't'
,
'R'
,
'N'
,
'S'
),
s
->
buf
+
256
*
3
,
256
);
png_write_chunk
(
&
s
->
bytestream
,
MKTAG
(
't'
,
'R'
,
'N'
,
'S'
),
s
->
buf
+
256
*
3
,
256
);
}
}
/* now put each row */
s
->
zstream
.
avail_out
=
IOBUF_SIZE
;
s
->
zstream
.
next_out
=
s
->
buf
;
s
->
zstream
.
next_out
=
s
->
buf
;
if
(
is_progressive
)
{
int
pass
;
for
(
pass
=
0
;
pass
<
NB_PASSES
;
pass
++
)
{
for
(
pass
=
0
;
pass
<
NB_PASSES
;
pass
++
)
{
/* NOTE: a pass is completely omitted if no pixels would be
output */
*
output */
pass_row_size
=
ff_png_pass_row_size
(
pass
,
bits_per_pixel
,
avctx
->
width
);
if
(
pass_row_size
>
0
)
{
top
=
NULL
;
for
(
y
=
0
;
y
<
avctx
->
height
;
y
++
)
{
for
(
y
=
0
;
y
<
avctx
->
height
;
y
++
)
if
((
ff_png_pass_ymask
[
pass
]
<<
(
y
&
7
))
&
0x80
)
{
ptr
=
p
->
data
[
0
]
+
y
*
p
->
linesize
[
0
];
FFSWAP
(
uint8_t
*
,
progressive_buf
,
top_buf
);
FFSWAP
(
uint8_t
*
,
progressive_buf
,
top_buf
);
if
(
color_type
==
PNG_COLOR_TYPE_RGB_ALPHA
)
{
convert_from_rgb32
(
rgba_buf
,
ptr
,
avctx
->
width
);
ptr
=
rgba_buf
;
...
...
@@ -380,29 +386,30 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
png_get_interlaced_row
(
progressive_buf
,
pass_row_size
,
bits_per_pixel
,
pass
,
ptr
,
avctx
->
width
);
crow
=
png_choose_filter
(
s
,
crow_buf
,
progressive_buf
,
top
,
pass_row_size
,
bits_per_pixel
>>
3
);
crow
=
png_choose_filter
(
s
,
crow_buf
,
progressive_buf
,
top
,
pass_row_size
,
bits_per_pixel
>>
3
);
png_write_row
(
s
,
crow
,
pass_row_size
+
1
);
top
=
progressive_buf
;
}
}
}
}
}
else
{
top
=
NULL
;
for
(
y
=
0
;
y
<
avctx
->
height
;
y
++
)
{
for
(
y
=
0
;
y
<
avctx
->
height
;
y
++
)
{
ptr
=
p
->
data
[
0
]
+
y
*
p
->
linesize
[
0
];
if
(
color_type
==
PNG_COLOR_TYPE_RGB_ALPHA
)
{
FFSWAP
(
uint8_t
*
,
rgba_buf
,
top_buf
);
FFSWAP
(
uint8_t
*
,
rgba_buf
,
top_buf
);
convert_from_rgb32
(
rgba_buf
,
ptr
,
avctx
->
width
);
ptr
=
rgba_buf
;
}
crow
=
png_choose_filter
(
s
,
crow_buf
,
ptr
,
top
,
row_size
,
bits_per_pixel
>>
3
);
crow
=
png_choose_filter
(
s
,
crow_buf
,
ptr
,
top
,
row_size
,
bits_per_pixel
>>
3
);
png_write_row
(
s
,
crow
,
row_size
+
1
);
top
=
ptr
;
}
}
/* compress last bytes */
for
(;;)
{
for
(;;)
{
ret
=
deflate
(
&
s
->
zstream
,
Z_FINISH
);
if
(
ret
==
Z_OK
||
ret
==
Z_STREAM_END
)
{
len
=
IOBUF_SIZE
-
s
->
zstream
.
avail_out
;
...
...
@@ -410,7 +417,7 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
png_write_chunk
(
&
s
->
bytestream
,
MKTAG
(
'I'
,
'D'
,
'A'
,
'T'
),
s
->
buf
,
len
);
}
s
->
zstream
.
avail_out
=
IOBUF_SIZE
;
s
->
zstream
.
next_out
=
s
->
buf
;
s
->
zstream
.
next_out
=
s
->
buf
;
if
(
ret
==
Z_STREAM_END
)
break
;
}
else
{
...
...
@@ -424,19 +431,20 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
*
got_packet
=
1
;
ret
=
0
;
the_end:
the_end:
av_free
(
crow_base
);
av_free
(
progressive_buf
);
av_free
(
rgba_buf
);
av_free
(
top_buf
);
deflateEnd
(
&
s
->
zstream
);
return
ret
;
fail:
fail:
ret
=
-
1
;
goto
the_end
;
}
static
av_cold
int
png_enc_init
(
AVCodecContext
*
avctx
){
static
av_cold
int
png_enc_init
(
AVCodecContext
*
avctx
)
{
PNGEncContext
*
s
=
avctx
->
priv_data
;
avctx
->
coded_frame
=
av_frame_alloc
();
...
...
@@ -448,8 +456,10 @@ static av_cold int png_enc_init(AVCodecContext *avctx){
ff_dsputil_init
(
&
s
->
dsp
,
avctx
);
s
->
filter_type
=
av_clip
(
avctx
->
prediction_method
,
PNG_FILTER_VALUE_NONE
,
PNG_FILTER_VALUE_MIXED
);
if
(
avctx
->
pix_fmt
==
AV_PIX_FMT_MONOBLACK
)
s
->
filter_type
=
av_clip
(
avctx
->
prediction_method
,
PNG_FILTER_VALUE_NONE
,
PNG_FILTER_VALUE_MIXED
);
if
(
avctx
->
pix_fmt
==
AV_PIX_FMT_MONOBLACK
)
s
->
filter_type
=
PNG_FILTER_VALUE_NONE
;
return
0
;
...
...
@@ -470,7 +480,7 @@ AVCodec ff_png_encoder = {
.
init
=
png_enc_init
,
.
close
=
png_enc_close
,
.
encode2
=
encode_frame
,
.
pix_fmts
=
(
const
enum
AVPixelFormat
[]){
.
pix_fmts
=
(
const
enum
AVPixelFormat
[])
{
AV_PIX_FMT_RGB24
,
AV_PIX_FMT_RGB32
,
AV_PIX_FMT_PAL8
,
AV_PIX_FMT_GRAY8
,
AV_PIX_FMT_GRAY16BE
,
AV_PIX_FMT_MONOBLACK
,
AV_PIX_FMT_NONE
...
...
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