Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
OpenDAS
dlib
Commits
11101b6f
Commit
11101b6f
authored
Aug 05, 2021
by
Adrià Arrufat
Committed by
Davis E. King
Aug 05, 2021
Browse files
update libpng to version 1.6.37
parent
23e50632
Changes
23
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
1318 additions
and
1557 deletions
+1318
-1557
dlib/external/libpng/pngwrite.c
dlib/external/libpng/pngwrite.c
+644
-579
dlib/external/libpng/pngwtran.c
dlib/external/libpng/pngwtran.c
+92
-154
dlib/external/libpng/pngwutil.c
dlib/external/libpng/pngwutil.c
+582
-824
No files found.
dlib/external/libpng/pngwrite.c
View file @
11101b6f
/* pngwrite.c - general routines to write a PNG file
/* pngwrite.c - general routines to write a PNG file
*
*
*
Last changed in libpng 1.6.2 [April 25, 2013]
*
Copyright (c) 2018-2019 Cosmin Truta
* Copyright (c) 1998-20
13
Glenn Randers-Pehrson
* Copyright (c) 1998-20
02,2004,2006-2018
Glenn Randers-Pehrson
*
(Version 0.96
Copyright (c) 1996
,
1997 Andreas Dilger
)
* Copyright (c) 1996
-
1997 Andreas Dilger
*
(Version 0.88
Copyright (c) 1995
,
1996 Guy Eric Schalnat, Group 42, Inc.
)
* Copyright (c) 1995
-
1996 Guy Eric Schalnat, Group 42, Inc.
*
*
* This code is released under the libpng license.
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* For conditions of distribution and use, see the disclaimer
...
@@ -12,9 +12,9 @@
...
@@ -12,9 +12,9 @@
*/
*/
#include "pngpriv.h"
#include "pngpriv.h"
#if
def
ined(
PNG_SIMPLIFIED_WRITE_
SUPPORTED) && defined(PNG_
STDIO_SUPPORTED
)
#ifdef
PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
# include <errno.h>
# include <errno.h>
#endif
#endif
/* SIMPLIFIED_WRITE_STDIO */
#ifdef PNG_WRITE_SUPPORTED
#ifdef PNG_WRITE_SUPPORTED
...
@@ -22,9 +22,9 @@
...
@@ -22,9 +22,9 @@
/* Write out all the unknown chunks for the current given location */
/* Write out all the unknown chunks for the current given location */
static
void
static
void
write_unknown_chunks
(
png_structrp
png_ptr
,
png_const_inforp
info_ptr
,
write_unknown_chunks
(
png_structrp
png_ptr
,
png_const_inforp
info_ptr
,
unsigned
int
where
)
unsigned
int
where
)
{
{
if
(
info_ptr
->
unknown_chunks_num
)
if
(
info_ptr
->
unknown_chunks_num
!=
0
)
{
{
png_const_unknown_chunkp
up
;
png_const_unknown_chunkp
up
;
...
@@ -33,7 +33,7 @@ write_unknown_chunks(png_structrp png_ptr, png_const_inforp info_ptr,
...
@@ -33,7 +33,7 @@ write_unknown_chunks(png_structrp png_ptr, png_const_inforp info_ptr,
for
(
up
=
info_ptr
->
unknown_chunks
;
for
(
up
=
info_ptr
->
unknown_chunks
;
up
<
info_ptr
->
unknown_chunks
+
info_ptr
->
unknown_chunks_num
;
up
<
info_ptr
->
unknown_chunks
+
info_ptr
->
unknown_chunks_num
;
++
up
)
++
up
)
if
(
up
->
location
&
where
)
if
(
(
up
->
location
&
where
)
!=
0
)
{
{
/* If per-chunk unknown chunk handling is enabled use it, otherwise
/* If per-chunk unknown chunk handling is enabled use it, otherwise
* just write the chunks the application has set.
* just write the chunks the application has set.
...
@@ -69,7 +69,7 @@ write_unknown_chunks(png_structrp png_ptr, png_const_inforp info_ptr,
...
@@ -69,7 +69,7 @@ write_unknown_chunks(png_structrp png_ptr, png_const_inforp info_ptr,
}
}
}
}
}
}
#endif
/*
PNG_
WRITE_UNKNOWN_CHUNKS
_SUPPORTED
*/
#endif
/* WRITE_UNKNOWN_CHUNKS */
/* Writes all the PNG information. This is the suggested way to use the
/* Writes all the PNG information. This is the suggested way to use the
* library. If you have a new chunk to add, make a function to write it,
* library. If you have a new chunk to add, make a function to write it,
...
@@ -88,99 +88,100 @@ png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr)
...
@@ -88,99 +88,100 @@ png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr)
if
(
png_ptr
==
NULL
||
info_ptr
==
NULL
)
if
(
png_ptr
==
NULL
||
info_ptr
==
NULL
)
return
;
return
;
if
(
!
(
png_ptr
->
mode
&
PNG_WROTE_INFO_BEFORE_PLTE
))
if
((
png_ptr
->
mode
&
PNG_WROTE_INFO_BEFORE_PLTE
)
==
0
)
{
{
/* Write PNG signature */
/* Write PNG signature */
png_write_sig
(
png_ptr
);
png_write_sig
(
png_ptr
);
#ifdef PNG_MNG_FEATURES_SUPPORTED
#ifdef PNG_MNG_FEATURES_SUPPORTED
if
((
png_ptr
->
mode
&
PNG_HAVE_PNG_SIGNATURE
)
&&
\
if
((
png_ptr
->
mode
&
PNG_HAVE_PNG_SIGNATURE
)
!=
0
&&
\
(
png_ptr
->
mng_features_permitted
))
png_ptr
->
mng_features_permitted
!=
0
)
{
{
png_warning
(
png_ptr
,
"MNG features are not allowed in a PNG datastream"
);
png_warning
(
png_ptr
,
png_ptr
->
mng_features_permitted
=
0
;
"MNG features are not allowed in a PNG datastream"
);
}
png_ptr
->
mng_features_permitted
=
0
;
}
#endif
#endif
/* Write IHDR information. */
/* Write IHDR information. */
png_write_IHDR
(
png_ptr
,
info_ptr
->
width
,
info_ptr
->
height
,
png_write_IHDR
(
png_ptr
,
info_ptr
->
width
,
info_ptr
->
height
,
info_ptr
->
bit_depth
,
info_ptr
->
color_type
,
info_ptr
->
compression_type
,
info_ptr
->
bit_depth
,
info_ptr
->
color_type
,
info_ptr
->
compression_type
,
info_ptr
->
filter_type
,
info_ptr
->
filter_type
,
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
info_ptr
->
interlace_type
info_ptr
->
interlace_type
#else
#else
0
0
#endif
#endif
);
);
/* The rest of these check to see if the valid field has the appropriate
/* The rest of these check to see if the valid field has the appropriate
* flag set, and if it does, writes the chunk.
* flag set, and if it does, writes the chunk.
*
*
* 1.6.0: COLORSPACE support controls the writing of these chunks too, and
* 1.6.0: COLORSPACE support controls the writing of these chunks too, and
* the chunks will be written if the WRITE routine is there and
information
* the chunks will be written if the WRITE routine is there and
* is available in the COLORSPACE.
(See
png_colorspace_sync_info in png.c
* information
* is available in the COLORSPACE. (See
*
for where the valid flags get set.)
* png_colorspace_sync_info in png.c
for where the valid flags get set.)
*
*
* Under certain circumstances the colorspace can be invalidated without
* Under certain circumstances the colorspace can be invalidated without
* syncing the info_struct 'valid' flags; this happens if libpng detects
and
* syncing the info_struct 'valid' flags; this happens if libpng detects
*
error and calls png_error while the color space is being set, yet
the
* an
error and calls png_error while the color space is being set, yet
*
application continues writing the PNG. So check the 'invalid'
flag here
* the
application continues writing the PNG. So check the 'invalid'
*
too.
* flag here
too.
*/
*/
#ifdef PNG_GAMMA_SUPPORTED
#ifdef PNG_GAMMA_SUPPORTED
# ifdef PNG_WRITE_gAMA_SUPPORTED
# ifdef PNG_WRITE_gAMA_SUPPORTED
if
(
!
(
info_ptr
->
colorspace
.
flags
&
PNG_COLORSPACE_INVALID
)
&&
if
((
info_ptr
->
colorspace
.
flags
&
PNG_COLORSPACE_INVALID
)
==
0
&&
(
info_ptr
->
colorspace
.
flags
&
PNG_COLORSPACE_FROM_gAMA
)
&&
(
info_ptr
->
colorspace
.
flags
&
PNG_COLORSPACE_FROM_gAMA
)
!=
0
&&
(
info_ptr
->
valid
&
PNG_INFO_gAMA
))
(
info_ptr
->
valid
&
PNG_INFO_gAMA
)
!=
0
)
png_write_gAMA_fixed
(
png_ptr
,
info_ptr
->
colorspace
.
gamma
);
png_write_gAMA_fixed
(
png_ptr
,
info_ptr
->
colorspace
.
gamma
);
# endif
# endif
#endif
#endif
#ifdef PNG_COLORSPACE_SUPPORTED
#ifdef PNG_COLORSPACE_SUPPORTED
/* Write only one of sRGB or an ICC profile. If a profile was supplied
/* Write only one of sRGB or an ICC profile. If a profile was supplied
* and it matches one of the known sRGB ones issue a warning.
* and it matches one of the known sRGB ones issue a warning.
*/
*/
# ifdef PNG_WRITE_iCCP_SUPPORTED
# ifdef PNG_WRITE_iCCP_SUPPORTED
if
(
!
(
info_ptr
->
colorspace
.
flags
&
PNG_COLORSPACE_INVALID
)
&&
if
((
info_ptr
->
colorspace
.
flags
&
PNG_COLORSPACE_INVALID
)
==
0
&&
(
info_ptr
->
valid
&
PNG_INFO_iCCP
))
(
info_ptr
->
valid
&
PNG_INFO_iCCP
)
!=
0
)
{
{
#
ifdef PNG_WRITE_sRGB_SUPPORTED
# ifdef PNG_WRITE_sRGB_SUPPORTED
if
(
info_ptr
->
valid
&
PNG_INFO_sRGB
)
if
(
(
info_ptr
->
valid
&
PNG_INFO_sRGB
)
!=
0
)
png_app_warning
(
png_ptr
,
png_app_warning
(
png_ptr
,
"profile matches sRGB but writing iCCP instead"
);
"profile matches sRGB but writing iCCP instead"
);
#
endif
# endif
png_write_iCCP
(
png_ptr
,
info_ptr
->
iccp_name
,
png_write_iCCP
(
png_ptr
,
info_ptr
->
iccp_name
,
info_ptr
->
iccp_profile
);
info_ptr
->
iccp_profile
);
}
}
# ifdef PNG_WRITE_sRGB_SUPPORTED
# ifdef PNG_WRITE_sRGB_SUPPORTED
else
else
# endif
# endif
# endif
# endif
# ifdef PNG_WRITE_sRGB_SUPPORTED
# ifdef PNG_WRITE_sRGB_SUPPORTED
if
(
!
(
info_ptr
->
colorspace
.
flags
&
PNG_COLORSPACE_INVALID
)
&&
if
((
info_ptr
->
colorspace
.
flags
&
PNG_COLORSPACE_INVALID
)
==
0
&&
(
info_ptr
->
valid
&
PNG_INFO_sRGB
))
(
info_ptr
->
valid
&
PNG_INFO_sRGB
)
!=
0
)
png_write_sRGB
(
png_ptr
,
info_ptr
->
colorspace
.
rendering_intent
);
png_write_sRGB
(
png_ptr
,
info_ptr
->
colorspace
.
rendering_intent
);
# endif
/* WRITE_sRGB */
# endif
/* WRITE_sRGB */
#endif
/* COLORSPACE */
#endif
/* COLORSPACE */
#ifdef PNG_WRITE_sBIT_SUPPORTED
#ifdef PNG_WRITE_sBIT_SUPPORTED
if
(
info_ptr
->
valid
&
PNG_INFO_sBIT
)
if
(
(
info_ptr
->
valid
&
PNG_INFO_sBIT
)
!=
0
)
png_write_sBIT
(
png_ptr
,
&
(
info_ptr
->
sig_bit
),
info_ptr
->
color_type
);
png_write_sBIT
(
png_ptr
,
&
(
info_ptr
->
sig_bit
),
info_ptr
->
color_type
);
#endif
#endif
#ifdef PNG_COLORSPACE_SUPPORTED
#ifdef PNG_COLORSPACE_SUPPORTED
# ifdef PNG_WRITE_cHRM_SUPPORTED
# ifdef PNG_WRITE_cHRM_SUPPORTED
if
(
!
(
info_ptr
->
colorspace
.
flags
&
PNG_COLORSPACE_INVALID
)
&&
if
((
info_ptr
->
colorspace
.
flags
&
PNG_COLORSPACE_INVALID
)
==
0
&&
(
info_ptr
->
colorspace
.
flags
&
PNG_COLORSPACE_FROM_cHRM
)
&&
(
info_ptr
->
colorspace
.
flags
&
PNG_COLORSPACE_FROM_cHRM
)
!=
0
&&
(
info_ptr
->
valid
&
PNG_INFO_cHRM
))
(
info_ptr
->
valid
&
PNG_INFO_cHRM
)
!=
0
)
png_write_cHRM_fixed
(
png_ptr
,
&
info_ptr
->
colorspace
.
end_points_xy
);
png_write_cHRM_fixed
(
png_ptr
,
&
info_ptr
->
colorspace
.
end_points_xy
);
# endif
# endif
#endif
#endif
#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
write_unknown_chunks
(
png_ptr
,
info_ptr
,
PNG_HAVE_IHDR
);
write_unknown_chunks
(
png_ptr
,
info_ptr
,
PNG_HAVE_IHDR
);
#endif
#endif
png_ptr
->
mode
|=
PNG_WROTE_INFO_BEFORE_PLTE
;
png_ptr
->
mode
|=
PNG_WROTE_INFO_BEFORE_PLTE
;
...
@@ -201,7 +202,7 @@ png_write_info(png_structrp png_ptr, png_const_inforp info_ptr)
...
@@ -201,7 +202,7 @@ png_write_info(png_structrp png_ptr, png_const_inforp info_ptr)
png_write_info_before_PLTE
(
png_ptr
,
info_ptr
);
png_write_info_before_PLTE
(
png_ptr
,
info_ptr
);
if
(
info_ptr
->
valid
&
PNG_INFO_PLTE
)
if
(
(
info_ptr
->
valid
&
PNG_INFO_PLTE
)
!=
0
)
png_write_PLTE
(
png_ptr
,
info_ptr
->
palette
,
png_write_PLTE
(
png_ptr
,
info_ptr
->
palette
,
(
png_uint_32
)
info_ptr
->
num_palette
);
(
png_uint_32
)
info_ptr
->
num_palette
);
...
@@ -209,15 +210,20 @@ png_write_info(png_structrp png_ptr, png_const_inforp info_ptr)
...
@@ -209,15 +210,20 @@ png_write_info(png_structrp png_ptr, png_const_inforp info_ptr)
png_error
(
png_ptr
,
"Valid palette required for paletted images"
);
png_error
(
png_ptr
,
"Valid palette required for paletted images"
);
#ifdef PNG_WRITE_tRNS_SUPPORTED
#ifdef PNG_WRITE_tRNS_SUPPORTED
if
(
info_ptr
->
valid
&
PNG_INFO_tRNS
)
if
(
(
info_ptr
->
valid
&
PNG_INFO_tRNS
)
!=
0
)
{
{
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
/* Invert the alpha channel (in tRNS) */
/* Invert the alpha channel (in tRNS) */
if
((
png_ptr
->
transformations
&
PNG_INVERT_ALPHA
)
&&
if
((
png_ptr
->
transformations
&
PNG_INVERT_ALPHA
)
!=
0
&&
info_ptr
->
color_type
==
PNG_COLOR_TYPE_PALETTE
)
info_ptr
->
color_type
==
PNG_COLOR_TYPE_PALETTE
)
{
{
int
j
;
int
j
,
jend
;
for
(
j
=
0
;
j
<
(
int
)
info_ptr
->
num_trans
;
j
++
)
jend
=
info_ptr
->
num_trans
;
if
(
jend
>
PNG_MAX_PALETTE_LENGTH
)
jend
=
PNG_MAX_PALETTE_LENGTH
;
for
(
j
=
0
;
j
<
jend
;
++
j
)
info_ptr
->
trans_alpha
[
j
]
=
info_ptr
->
trans_alpha
[
j
]
=
(
png_byte
)(
255
-
info_ptr
->
trans_alpha
[
j
]);
(
png_byte
)(
255
-
info_ptr
->
trans_alpha
[
j
]);
}
}
...
@@ -227,42 +233,47 @@ png_write_info(png_structrp png_ptr, png_const_inforp info_ptr)
...
@@ -227,42 +233,47 @@ png_write_info(png_structrp png_ptr, png_const_inforp info_ptr)
}
}
#endif
#endif
#ifdef PNG_WRITE_bKGD_SUPPORTED
#ifdef PNG_WRITE_bKGD_SUPPORTED
if
(
info_ptr
->
valid
&
PNG_INFO_bKGD
)
if
(
(
info_ptr
->
valid
&
PNG_INFO_bKGD
)
!=
0
)
png_write_bKGD
(
png_ptr
,
&
(
info_ptr
->
background
),
info_ptr
->
color_type
);
png_write_bKGD
(
png_ptr
,
&
(
info_ptr
->
background
),
info_ptr
->
color_type
);
#endif
#endif
#ifdef PNG_WRITE_eXIf_SUPPORTED
if
((
info_ptr
->
valid
&
PNG_INFO_eXIf
)
!=
0
)
png_write_eXIf
(
png_ptr
,
info_ptr
->
exif
,
info_ptr
->
num_exif
);
#endif
#ifdef PNG_WRITE_hIST_SUPPORTED
#ifdef PNG_WRITE_hIST_SUPPORTED
if
(
info_ptr
->
valid
&
PNG_INFO_hIST
)
if
(
(
info_ptr
->
valid
&
PNG_INFO_hIST
)
!=
0
)
png_write_hIST
(
png_ptr
,
info_ptr
->
hist
,
info_ptr
->
num_palette
);
png_write_hIST
(
png_ptr
,
info_ptr
->
hist
,
info_ptr
->
num_palette
);
#endif
#endif
#ifdef PNG_WRITE_oFFs_SUPPORTED
#ifdef PNG_WRITE_oFFs_SUPPORTED
if
(
info_ptr
->
valid
&
PNG_INFO_oFFs
)
if
(
(
info_ptr
->
valid
&
PNG_INFO_oFFs
)
!=
0
)
png_write_oFFs
(
png_ptr
,
info_ptr
->
x_offset
,
info_ptr
->
y_offset
,
png_write_oFFs
(
png_ptr
,
info_ptr
->
x_offset
,
info_ptr
->
y_offset
,
info_ptr
->
offset_unit_type
);
info_ptr
->
offset_unit_type
);
#endif
#endif
#ifdef PNG_WRITE_pCAL_SUPPORTED
#ifdef PNG_WRITE_pCAL_SUPPORTED
if
(
info_ptr
->
valid
&
PNG_INFO_pCAL
)
if
(
(
info_ptr
->
valid
&
PNG_INFO_pCAL
)
!=
0
)
png_write_pCAL
(
png_ptr
,
info_ptr
->
pcal_purpose
,
info_ptr
->
pcal_X0
,
png_write_pCAL
(
png_ptr
,
info_ptr
->
pcal_purpose
,
info_ptr
->
pcal_X0
,
info_ptr
->
pcal_X1
,
info_ptr
->
pcal_type
,
info_ptr
->
pcal_nparams
,
info_ptr
->
pcal_X1
,
info_ptr
->
pcal_type
,
info_ptr
->
pcal_nparams
,
info_ptr
->
pcal_units
,
info_ptr
->
pcal_params
);
info_ptr
->
pcal_units
,
info_ptr
->
pcal_params
);
#endif
#endif
#ifdef PNG_WRITE_sCAL_SUPPORTED
#ifdef PNG_WRITE_sCAL_SUPPORTED
if
(
info_ptr
->
valid
&
PNG_INFO_sCAL
)
if
(
(
info_ptr
->
valid
&
PNG_INFO_sCAL
)
!=
0
)
png_write_sCAL_s
(
png_ptr
,
(
int
)
info_ptr
->
scal_unit
,
png_write_sCAL_s
(
png_ptr
,
(
int
)
info_ptr
->
scal_unit
,
info_ptr
->
scal_s_width
,
info_ptr
->
scal_s_height
);
info_ptr
->
scal_s_width
,
info_ptr
->
scal_s_height
);
#endif
/* sCAL */
#endif
/* sCAL */
#ifdef PNG_WRITE_pHYs_SUPPORTED
#ifdef PNG_WRITE_pHYs_SUPPORTED
if
(
info_ptr
->
valid
&
PNG_INFO_pHYs
)
if
(
(
info_ptr
->
valid
&
PNG_INFO_pHYs
)
!=
0
)
png_write_pHYs
(
png_ptr
,
info_ptr
->
x_pixels_per_unit
,
png_write_pHYs
(
png_ptr
,
info_ptr
->
x_pixels_per_unit
,
info_ptr
->
y_pixels_per_unit
,
info_ptr
->
phys_unit_type
);
info_ptr
->
y_pixels_per_unit
,
info_ptr
->
phys_unit_type
);
#endif
/* pHYs */
#endif
/* pHYs */
#ifdef PNG_WRITE_tIME_SUPPORTED
#ifdef PNG_WRITE_tIME_SUPPORTED
if
(
info_ptr
->
valid
&
PNG_INFO_tIME
)
if
(
(
info_ptr
->
valid
&
PNG_INFO_tIME
)
!=
0
)
{
{
png_write_tIME
(
png_ptr
,
&
(
info_ptr
->
mod_time
));
png_write_tIME
(
png_ptr
,
&
(
info_ptr
->
mod_time
));
png_ptr
->
mode
|=
PNG_WROTE_tIME
;
png_ptr
->
mode
|=
PNG_WROTE_tIME
;
...
@@ -270,7 +281,7 @@ png_write_info(png_structrp png_ptr, png_const_inforp info_ptr)
...
@@ -270,7 +281,7 @@ png_write_info(png_structrp png_ptr, png_const_inforp info_ptr)
#endif
/* tIME */
#endif
/* tIME */
#ifdef PNG_WRITE_sPLT_SUPPORTED
#ifdef PNG_WRITE_sPLT_SUPPORTED
if
(
info_ptr
->
valid
&
PNG_INFO_sPLT
)
if
(
(
info_ptr
->
valid
&
PNG_INFO_sPLT
)
!=
0
)
for
(
i
=
0
;
i
<
(
int
)
info_ptr
->
splt_palettes_num
;
i
++
)
for
(
i
=
0
;
i
<
(
int
)
info_ptr
->
splt_palettes_num
;
i
++
)
png_write_sPLT
(
png_ptr
,
info_ptr
->
splt_palettes
+
i
);
png_write_sPLT
(
png_ptr
,
info_ptr
->
splt_palettes
+
i
);
#endif
/* sPLT */
#endif
/* sPLT */
...
@@ -292,11 +303,14 @@ png_write_info(png_structrp png_ptr, png_const_inforp info_ptr)
...
@@ -292,11 +303,14 @@ png_write_info(png_structrp png_ptr, png_const_inforp info_ptr)
info_ptr
->
text
[
i
].
lang
,
info_ptr
->
text
[
i
].
lang
,
info_ptr
->
text
[
i
].
lang_key
,
info_ptr
->
text
[
i
].
lang_key
,
info_ptr
->
text
[
i
].
text
);
info_ptr
->
text
[
i
].
text
);
/* Mark this chunk as written */
if
(
info_ptr
->
text
[
i
].
compression
==
PNG_TEXT_COMPRESSION_NONE
)
info_ptr
->
text
[
i
].
compression
=
PNG_TEXT_COMPRESSION_NONE_WR
;
else
info_ptr
->
text
[
i
].
compression
=
PNG_TEXT_COMPRESSION_zTXt_WR
;
#else
#else
png_warning
(
png_ptr
,
"Unable to write international text"
);
png_warning
(
png_ptr
,
"Unable to write international text"
);
#endif
#endif
/* Mark this chunk as written */
info_ptr
->
text
[
i
].
compression
=
PNG_TEXT_COMPRESSION_NONE_WR
;
}
}
/* If we want a compressed text chunk */
/* If we want a compressed text chunk */
...
@@ -305,13 +319,12 @@ png_write_info(png_structrp png_ptr, png_const_inforp info_ptr)
...
@@ -305,13 +319,12 @@ png_write_info(png_structrp png_ptr, png_const_inforp info_ptr)
#ifdef PNG_WRITE_zTXt_SUPPORTED
#ifdef PNG_WRITE_zTXt_SUPPORTED
/* Write compressed chunk */
/* Write compressed chunk */
png_write_zTXt
(
png_ptr
,
info_ptr
->
text
[
i
].
key
,
png_write_zTXt
(
png_ptr
,
info_ptr
->
text
[
i
].
key
,
info_ptr
->
text
[
i
].
text
,
0
,
info_ptr
->
text
[
i
].
text
,
info_ptr
->
text
[
i
].
compression
);
info_ptr
->
text
[
i
].
compression
);
/* Mark this chunk as written */
info_ptr
->
text
[
i
].
compression
=
PNG_TEXT_COMPRESSION_zTXt_WR
;
#else
#else
png_warning
(
png_ptr
,
"Unable to write compressed text"
);
png_warning
(
png_ptr
,
"Unable to write compressed text"
);
#endif
#endif
/* Mark this chunk as written */
info_ptr
->
text
[
i
].
compression
=
PNG_TEXT_COMPRESSION_zTXt_WR
;
}
}
else
if
(
info_ptr
->
text
[
i
].
compression
==
PNG_TEXT_COMPRESSION_NONE
)
else
if
(
info_ptr
->
text
[
i
].
compression
==
PNG_TEXT_COMPRESSION_NONE
)
...
@@ -349,7 +362,7 @@ png_write_end(png_structrp png_ptr, png_inforp info_ptr)
...
@@ -349,7 +362,7 @@ png_write_end(png_structrp png_ptr, png_inforp info_ptr)
if
(
png_ptr
==
NULL
)
if
(
png_ptr
==
NULL
)
return
;
return
;
if
(
!
(
png_ptr
->
mode
&
PNG_HAVE_IDAT
))
if
((
png_ptr
->
mode
&
PNG_HAVE_IDAT
)
==
0
)
png_error
(
png_ptr
,
"No IDATs written into file"
);
png_error
(
png_ptr
,
"No IDATs written into file"
);
#ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
#ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
...
@@ -365,8 +378,8 @@ png_write_end(png_structrp png_ptr, png_inforp info_ptr)
...
@@ -365,8 +378,8 @@ png_write_end(png_structrp png_ptr, png_inforp info_ptr)
#endif
#endif
#ifdef PNG_WRITE_tIME_SUPPORTED
#ifdef PNG_WRITE_tIME_SUPPORTED
/* Check to see if user has supplied a time chunk */
/* Check to see if user has supplied a time chunk */
if
((
info_ptr
->
valid
&
PNG_INFO_tIME
)
&&
if
((
info_ptr
->
valid
&
PNG_INFO_tIME
)
!=
0
&&
!
(
png_ptr
->
mode
&
PNG_WROTE_tIME
))
(
png_ptr
->
mode
&
PNG_WROTE_tIME
)
==
0
)
png_write_tIME
(
png_ptr
,
&
(
info_ptr
->
mod_time
));
png_write_tIME
(
png_ptr
,
&
(
info_ptr
->
mod_time
));
#endif
#endif
...
@@ -375,7 +388,7 @@ png_write_end(png_structrp png_ptr, png_inforp info_ptr)
...
@@ -375,7 +388,7 @@ png_write_end(png_structrp png_ptr, png_inforp info_ptr)
for
(
i
=
0
;
i
<
info_ptr
->
num_text
;
i
++
)
for
(
i
=
0
;
i
<
info_ptr
->
num_text
;
i
++
)
{
{
png_debug2
(
2
,
"Writing trailer text chunk %d, type %d"
,
i
,
png_debug2
(
2
,
"Writing trailer text chunk %d, type %d"
,
i
,
info_ptr
->
text
[
i
].
compression
);
info_ptr
->
text
[
i
].
compression
);
/* An internationalized chunk? */
/* An internationalized chunk? */
if
(
info_ptr
->
text
[
i
].
compression
>
0
)
if
(
info_ptr
->
text
[
i
].
compression
>
0
)
{
{
...
@@ -387,11 +400,14 @@ png_write_end(png_structrp png_ptr, png_inforp info_ptr)
...
@@ -387,11 +400,14 @@ png_write_end(png_structrp png_ptr, png_inforp info_ptr)
info_ptr
->
text
[
i
].
lang
,
info_ptr
->
text
[
i
].
lang
,
info_ptr
->
text
[
i
].
lang_key
,
info_ptr
->
text
[
i
].
lang_key
,
info_ptr
->
text
[
i
].
text
);
info_ptr
->
text
[
i
].
text
);
/* Mark this chunk as written */
if
(
info_ptr
->
text
[
i
].
compression
==
PNG_TEXT_COMPRESSION_NONE
)
info_ptr
->
text
[
i
].
compression
=
PNG_TEXT_COMPRESSION_NONE_WR
;
else
info_ptr
->
text
[
i
].
compression
=
PNG_TEXT_COMPRESSION_zTXt_WR
;
#else
#else
png_warning
(
png_ptr
,
"Unable to write international text"
);
png_warning
(
png_ptr
,
"Unable to write international text"
);
#endif
#endif
/* Mark this chunk as written */
info_ptr
->
text
[
i
].
compression
=
PNG_TEXT_COMPRESSION_NONE_WR
;
}
}
else
if
(
info_ptr
->
text
[
i
].
compression
>=
PNG_TEXT_COMPRESSION_zTXt
)
else
if
(
info_ptr
->
text
[
i
].
compression
>=
PNG_TEXT_COMPRESSION_zTXt
)
...
@@ -399,13 +415,12 @@ png_write_end(png_structrp png_ptr, png_inforp info_ptr)
...
@@ -399,13 +415,12 @@ png_write_end(png_structrp png_ptr, png_inforp info_ptr)
#ifdef PNG_WRITE_zTXt_SUPPORTED
#ifdef PNG_WRITE_zTXt_SUPPORTED
/* Write compressed chunk */
/* Write compressed chunk */
png_write_zTXt
(
png_ptr
,
info_ptr
->
text
[
i
].
key
,
png_write_zTXt
(
png_ptr
,
info_ptr
->
text
[
i
].
key
,
info_ptr
->
text
[
i
].
text
,
0
,
info_ptr
->
text
[
i
].
text
,
info_ptr
->
text
[
i
].
compression
);
info_ptr
->
text
[
i
].
compression
);
/* Mark this chunk as written */
info_ptr
->
text
[
i
].
compression
=
PNG_TEXT_COMPRESSION_zTXt_WR
;
#else
#else
png_warning
(
png_ptr
,
"Unable to write compressed text"
);
png_warning
(
png_ptr
,
"Unable to write compressed text"
);
#endif
#endif
/* Mark this chunk as written */
info_ptr
->
text
[
i
].
compression
=
PNG_TEXT_COMPRESSION_zTXt_WR
;
}
}
else
if
(
info_ptr
->
text
[
i
].
compression
==
PNG_TEXT_COMPRESSION_NONE
)
else
if
(
info_ptr
->
text
[
i
].
compression
==
PNG_TEXT_COMPRESSION_NONE
)
...
@@ -414,15 +429,20 @@ png_write_end(png_structrp png_ptr, png_inforp info_ptr)
...
@@ -414,15 +429,20 @@ png_write_end(png_structrp png_ptr, png_inforp info_ptr)
/* Write uncompressed chunk */
/* Write uncompressed chunk */
png_write_tEXt
(
png_ptr
,
info_ptr
->
text
[
i
].
key
,
png_write_tEXt
(
png_ptr
,
info_ptr
->
text
[
i
].
key
,
info_ptr
->
text
[
i
].
text
,
0
);
info_ptr
->
text
[
i
].
text
,
0
);
/* Mark this chunk as written */
info_ptr
->
text
[
i
].
compression
=
PNG_TEXT_COMPRESSION_NONE_WR
;
#else
#else
png_warning
(
png_ptr
,
"Unable to write uncompressed text"
);
png_warning
(
png_ptr
,
"Unable to write uncompressed text"
);
#endif
#endif
/* Mark this chunk as written */
info_ptr
->
text
[
i
].
compression
=
PNG_TEXT_COMPRESSION_NONE_WR
;
}
}
}
}
#endif
#endif
#ifdef PNG_WRITE_eXIf_SUPPORTED
if
((
info_ptr
->
valid
&
PNG_INFO_eXIf
)
!=
0
)
png_write_eXIf
(
png_ptr
,
info_ptr
->
exif
,
info_ptr
->
num_exif
);
#endif
#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
write_unknown_chunks
(
png_ptr
,
info_ptr
,
PNG_AFTER_IDAT
);
write_unknown_chunks
(
png_ptr
,
info_ptr
,
PNG_AFTER_IDAT
);
#endif
#endif
...
@@ -432,6 +452,7 @@ png_write_end(png_structrp png_ptr, png_inforp info_ptr)
...
@@ -432,6 +452,7 @@ png_write_end(png_structrp png_ptr, png_inforp info_ptr)
/* Write end of PNG file */
/* Write end of PNG file */
png_write_IEND
(
png_ptr
);
png_write_IEND
(
png_ptr
);
/* This flush, added in libpng-1.0.8, removed from libpng-1.0.9beta03,
/* This flush, added in libpng-1.0.8, removed from libpng-1.0.9beta03,
* and restored again in libpng-1.2.30, may cause some applications that
* and restored again in libpng-1.2.30, may cause some applications that
* do not set png_ptr->output_flush_fn to crash. If your application
* do not set png_ptr->output_flush_fn to crash. If your application
...
@@ -448,7 +469,7 @@ png_write_end(png_structrp png_ptr, png_inforp info_ptr)
...
@@ -448,7 +469,7 @@ png_write_end(png_structrp png_ptr, png_inforp info_ptr)
#ifdef PNG_CONVERT_tIME_SUPPORTED
#ifdef PNG_CONVERT_tIME_SUPPORTED
void
PNGAPI
void
PNGAPI
png_convert_from_struct_tm
(
png_timep
ptime
,
PNG_CONST
struct
tm
*
ttime
)
png_convert_from_struct_tm
(
png_timep
ptime
,
const
struct
tm
*
ttime
)
{
{
png_debug
(
1
,
"in png_convert_from_struct_tm"
);
png_debug
(
1
,
"in png_convert_from_struct_tm"
);
...
@@ -479,7 +500,7 @@ png_create_write_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
...
@@ -479,7 +500,7 @@ png_create_write_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
{
{
#ifndef PNG_USER_MEM_SUPPORTED
#ifndef PNG_USER_MEM_SUPPORTED
png_structrp
png_ptr
=
png_create_png_struct
(
user_png_ver
,
error_ptr
,
png_structrp
png_ptr
=
png_create_png_struct
(
user_png_ver
,
error_ptr
,
error_fn
,
warn_fn
,
NULL
,
NULL
,
NULL
);
error_fn
,
warn_fn
,
NULL
,
NULL
,
NULL
);
#else
#else
return
png_create_write_struct_2
(
user_png_ver
,
error_ptr
,
error_fn
,
return
png_create_write_struct_2
(
user_png_ver
,
error_ptr
,
error_fn
,
warn_fn
,
NULL
,
NULL
,
NULL
);
warn_fn
,
NULL
,
NULL
,
NULL
);
...
@@ -492,8 +513,8 @@ png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
...
@@ -492,8 +513,8 @@ png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
png_malloc_ptr
malloc_fn
,
png_free_ptr
free_fn
),
PNG_ALLOCATED
)
png_malloc_ptr
malloc_fn
,
png_free_ptr
free_fn
),
PNG_ALLOCATED
)
{
{
png_structrp
png_ptr
=
png_create_png_struct
(
user_png_ver
,
error_ptr
,
png_structrp
png_ptr
=
png_create_png_struct
(
user_png_ver
,
error_ptr
,
error_fn
,
warn_fn
,
mem_ptr
,
malloc_fn
,
free_fn
);
error_fn
,
warn_fn
,
mem_ptr
,
malloc_fn
,
free_fn
);
#endif
/*
PNG_
USER_MEM
_SUPPORTED
*/
#endif
/* USER_MEM */
if
(
png_ptr
!=
NULL
)
if
(
png_ptr
!=
NULL
)
{
{
/* Set the zlib control values to defaults; they can be overridden by the
/* Set the zlib control values to defaults; they can be overridden by the
...
@@ -517,7 +538,7 @@ png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
...
@@ -517,7 +538,7 @@ png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
png_ptr
->
zlib_text_mem_level
=
8
;
png_ptr
->
zlib_text_mem_level
=
8
;
png_ptr
->
zlib_text_window_bits
=
15
;
png_ptr
->
zlib_text_window_bits
=
15
;
png_ptr
->
zlib_text_method
=
8
;
png_ptr
->
zlib_text_method
=
8
;
#endif
/*
PNG_
WRITE_COMPRESSED_TEXT
_SUPPORTED
*/
#endif
/* WRITE_COMPRESSED_TEXT */
/* This is a highly dubious configuration option; by default it is off,
/* This is a highly dubious configuration option; by default it is off,
* but it may be appropriate for private builds that are testing
* but it may be appropriate for private builds that are testing
...
@@ -525,16 +546,16 @@ png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
...
@@ -525,16 +546,16 @@ png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
* applications that must not fail to write at all costs!
* applications that must not fail to write at all costs!
*/
*/
#ifdef PNG_BENIGN_WRITE_ERRORS_SUPPORTED
#ifdef PNG_BENIGN_WRITE_ERRORS_SUPPORTED
png_ptr
->
flags
|=
PNG_FLAG_BENIGN_ERRORS_WARN
;
/* In stable builds only warn if an application error can be completely
/* In stable builds only warn if an application error can be completely
* handled.
* handled.
*/
*/
png_ptr
->
flags
|=
PNG_FLAG_BENIGN_ERRORS_WARN
;
#endif
#endif
/* App warnings are warnings in release (or release candidate) builds but
/* App warnings are warnings in release (or release candidate) builds but
* are errors during development.
* are errors during development.
*/
*/
#if PNG_
LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG
_BUILD
_RC
#if PNG_
RELEASE
_BUILD
png_ptr
->
flags
|=
PNG_FLAG_APP_WARNINGS_WARN
;
png_ptr
->
flags
|=
PNG_FLAG_APP_WARNINGS_WARN
;
#endif
#endif
...
@@ -607,6 +628,71 @@ png_write_image(png_structrp png_ptr, png_bytepp image)
...
@@ -607,6 +628,71 @@ png_write_image(png_structrp png_ptr, png_bytepp image)
}
}
}
}
#ifdef PNG_MNG_FEATURES_SUPPORTED
/* Performs intrapixel differencing */
static
void
png_do_write_intrapixel
(
png_row_infop
row_info
,
png_bytep
row
)
{
png_debug
(
1
,
"in png_do_write_intrapixel"
);
if
((
row_info
->
color_type
&
PNG_COLOR_MASK_COLOR
)
!=
0
)
{
int
bytes_per_pixel
;
png_uint_32
row_width
=
row_info
->
width
;
if
(
row_info
->
bit_depth
==
8
)
{
png_bytep
rp
;
png_uint_32
i
;
if
(
row_info
->
color_type
==
PNG_COLOR_TYPE_RGB
)
bytes_per_pixel
=
3
;
else
if
(
row_info
->
color_type
==
PNG_COLOR_TYPE_RGB_ALPHA
)
bytes_per_pixel
=
4
;
else
return
;
for
(
i
=
0
,
rp
=
row
;
i
<
row_width
;
i
++
,
rp
+=
bytes_per_pixel
)
{
*
(
rp
)
=
(
png_byte
)(
*
rp
-
*
(
rp
+
1
));
*
(
rp
+
2
)
=
(
png_byte
)(
*
(
rp
+
2
)
-
*
(
rp
+
1
));
}
}
#ifdef PNG_WRITE_16BIT_SUPPORTED
else
if
(
row_info
->
bit_depth
==
16
)
{
png_bytep
rp
;
png_uint_32
i
;
if
(
row_info
->
color_type
==
PNG_COLOR_TYPE_RGB
)
bytes_per_pixel
=
6
;
else
if
(
row_info
->
color_type
==
PNG_COLOR_TYPE_RGB_ALPHA
)
bytes_per_pixel
=
8
;
else
return
;
for
(
i
=
0
,
rp
=
row
;
i
<
row_width
;
i
++
,
rp
+=
bytes_per_pixel
)
{
png_uint_32
s0
=
(
png_uint_32
)(
*
(
rp
)
<<
8
)
|
*
(
rp
+
1
);
png_uint_32
s1
=
(
png_uint_32
)(
*
(
rp
+
2
)
<<
8
)
|
*
(
rp
+
3
);
png_uint_32
s2
=
(
png_uint_32
)(
*
(
rp
+
4
)
<<
8
)
|
*
(
rp
+
5
);
png_uint_32
red
=
(
png_uint_32
)((
s0
-
s1
)
&
0xffffL
);
png_uint_32
blue
=
(
png_uint_32
)((
s2
-
s1
)
&
0xffffL
);
*
(
rp
)
=
(
png_byte
)(
red
>>
8
);
*
(
rp
+
1
)
=
(
png_byte
)
red
;
*
(
rp
+
4
)
=
(
png_byte
)(
blue
>>
8
);
*
(
rp
+
5
)
=
(
png_byte
)
blue
;
}
}
#endif
/* WRITE_16BIT */
}
}
#endif
/* MNG_FEATURES */
/* Called by user to write a row of image data */
/* Called by user to write a row of image data */
void
PNGAPI
void
PNGAPI
png_write_row
(
png_structrp
png_ptr
,
png_const_bytep
row
)
png_write_row
(
png_structrp
png_ptr
,
png_const_bytep
row
)
...
@@ -618,50 +704,50 @@ png_write_row(png_structrp png_ptr, png_const_bytep row)
...
@@ -618,50 +704,50 @@ png_write_row(png_structrp png_ptr, png_const_bytep row)
return
;
return
;
png_debug2
(
1
,
"in png_write_row (row %u, pass %d)"
,
png_debug2
(
1
,
"in png_write_row (row %u, pass %d)"
,
png_ptr
->
row_number
,
png_ptr
->
pass
);
png_ptr
->
row_number
,
png_ptr
->
pass
);
/* Initialize transformations and other stuff if first time */
/* Initialize transformations and other stuff if first time */
if
(
png_ptr
->
row_number
==
0
&&
png_ptr
->
pass
==
0
)
if
(
png_ptr
->
row_number
==
0
&&
png_ptr
->
pass
==
0
)
{
{
/* Make sure we wrote the header info */
/* Make sure we wrote the header info */
if
(
!
(
png_ptr
->
mode
&
PNG_WROTE_INFO_BEFORE_PLTE
))
if
((
png_ptr
->
mode
&
PNG_WROTE_INFO_BEFORE_PLTE
)
==
0
)
png_error
(
png_ptr
,
png_error
(
png_ptr
,
"png_write_info was never called before png_write_row"
);
"png_write_info was never called before png_write_row"
);
/* Check for transforms that have been set but were defined out */
/* Check for transforms that have been set but were defined out */
#if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED)
#if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED)
if
(
png_ptr
->
transformations
&
PNG_INVERT_MONO
)
if
(
(
png_ptr
->
transformations
&
PNG_INVERT_MONO
)
!=
0
)
png_warning
(
png_ptr
,
"PNG_WRITE_INVERT_SUPPORTED is not defined"
);
png_warning
(
png_ptr
,
"PNG_WRITE_INVERT_SUPPORTED is not defined"
);
#endif
#endif
#if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED)
#if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED)
if
(
png_ptr
->
transformations
&
PNG_FILLER
)
if
(
(
png_ptr
->
transformations
&
PNG_FILLER
)
!=
0
)
png_warning
(
png_ptr
,
"PNG_WRITE_FILLER_SUPPORTED is not defined"
);
png_warning
(
png_ptr
,
"PNG_WRITE_FILLER_SUPPORTED is not defined"
);
#endif
#endif
#if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \
#if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \
defined(PNG_READ_PACKSWAP_SUPPORTED)
defined(PNG_READ_PACKSWAP_SUPPORTED)
if
(
png_ptr
->
transformations
&
PNG_PACKSWAP
)
if
(
(
png_ptr
->
transformations
&
PNG_PACKSWAP
)
!=
0
)
png_warning
(
png_ptr
,
png_warning
(
png_ptr
,
"PNG_WRITE_PACKSWAP_SUPPORTED is not defined"
);
"PNG_WRITE_PACKSWAP_SUPPORTED is not defined"
);
#endif
#endif
#if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED)
#if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED)
if
(
png_ptr
->
transformations
&
PNG_PACK
)
if
(
(
png_ptr
->
transformations
&
PNG_PACK
)
!=
0
)
png_warning
(
png_ptr
,
"PNG_WRITE_PACK_SUPPORTED is not defined"
);
png_warning
(
png_ptr
,
"PNG_WRITE_PACK_SUPPORTED is not defined"
);
#endif
#endif
#if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED)
#if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED)
if
(
png_ptr
->
transformations
&
PNG_SHIFT
)
if
(
(
png_ptr
->
transformations
&
PNG_SHIFT
)
!=
0
)
png_warning
(
png_ptr
,
"PNG_WRITE_SHIFT_SUPPORTED is not defined"
);
png_warning
(
png_ptr
,
"PNG_WRITE_SHIFT_SUPPORTED is not defined"
);
#endif
#endif
#if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED)
#if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED)
if
(
png_ptr
->
transformations
&
PNG_BGR
)
if
(
(
png_ptr
->
transformations
&
PNG_BGR
)
!=
0
)
png_warning
(
png_ptr
,
"PNG_WRITE_BGR_SUPPORTED is not defined"
);
png_warning
(
png_ptr
,
"PNG_WRITE_BGR_SUPPORTED is not defined"
);
#endif
#endif
#if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED)
#if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED)
if
(
png_ptr
->
transformations
&
PNG_SWAP_BYTES
)
if
(
(
png_ptr
->
transformations
&
PNG_SWAP_BYTES
)
!=
0
)
png_warning
(
png_ptr
,
"PNG_WRITE_SWAP_SUPPORTED is not defined"
);
png_warning
(
png_ptr
,
"PNG_WRITE_SWAP_SUPPORTED is not defined"
);
#endif
#endif
...
@@ -670,12 +756,13 @@ png_write_row(png_structrp png_ptr, png_const_bytep row)
...
@@ -670,12 +756,13 @@ png_write_row(png_structrp png_ptr, png_const_bytep row)
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
/* If interlaced and not interested in row, return */
/* If interlaced and not interested in row, return */
if
(
png_ptr
->
interlaced
&&
(
png_ptr
->
transformations
&
PNG_INTERLACE
))
if
(
png_ptr
->
interlaced
!=
0
&&
(
png_ptr
->
transformations
&
PNG_INTERLACE
)
!=
0
)
{
{
switch
(
png_ptr
->
pass
)
switch
(
png_ptr
->
pass
)
{
{
case
0
:
case
0
:
if
(
png_ptr
->
row_number
&
0x07
)
if
(
(
png_ptr
->
row_number
&
0x07
)
!=
0
)
{
{
png_write_finish_row
(
png_ptr
);
png_write_finish_row
(
png_ptr
);
return
;
return
;
...
@@ -683,7 +770,7 @@ png_write_row(png_structrp png_ptr, png_const_bytep row)
...
@@ -683,7 +770,7 @@ png_write_row(png_structrp png_ptr, png_const_bytep row)
break
;
break
;
case
1
:
case
1
:
if
((
png_ptr
->
row_number
&
0x07
)
||
png_ptr
->
width
<
5
)
if
((
png_ptr
->
row_number
&
0x07
)
!=
0
||
png_ptr
->
width
<
5
)
{
{
png_write_finish_row
(
png_ptr
);
png_write_finish_row
(
png_ptr
);
return
;
return
;
...
@@ -699,7 +786,7 @@ png_write_row(png_structrp png_ptr, png_const_bytep row)
...
@@ -699,7 +786,7 @@ png_write_row(png_structrp png_ptr, png_const_bytep row)
break
;
break
;
case
3
:
case
3
:
if
((
png_ptr
->
row_number
&
0x03
)
||
png_ptr
->
width
<
3
)
if
((
png_ptr
->
row_number
&
0x03
)
!=
0
||
png_ptr
->
width
<
3
)
{
{
png_write_finish_row
(
png_ptr
);
png_write_finish_row
(
png_ptr
);
return
;
return
;
...
@@ -715,7 +802,7 @@ png_write_row(png_structrp png_ptr, png_const_bytep row)
...
@@ -715,7 +802,7 @@ png_write_row(png_structrp png_ptr, png_const_bytep row)
break
;
break
;
case
5
:
case
5
:
if
((
png_ptr
->
row_number
&
0x01
)
||
png_ptr
->
width
<
2
)
if
((
png_ptr
->
row_number
&
0x01
)
!=
0
||
png_ptr
->
width
<
2
)
{
{
png_write_finish_row
(
png_ptr
);
png_write_finish_row
(
png_ptr
);
return
;
return
;
...
@@ -723,7 +810,7 @@ png_write_row(png_structrp png_ptr, png_const_bytep row)
...
@@ -723,7 +810,7 @@ png_write_row(png_structrp png_ptr, png_const_bytep row)
break
;
break
;
case
6
:
case
6
:
if
(
!
(
png_ptr
->
row_number
&
0x01
))
if
((
png_ptr
->
row_number
&
0x01
)
==
0
)
{
{
png_write_finish_row
(
png_ptr
);
png_write_finish_row
(
png_ptr
);
return
;
return
;
...
@@ -757,11 +844,11 @@ png_write_row(png_structrp png_ptr, png_const_bytep row)
...
@@ -757,11 +844,11 @@ png_write_row(png_structrp png_ptr, png_const_bytep row)
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
/* Handle interlacing */
/* Handle interlacing */
if
(
png_ptr
->
interlaced
&&
png_ptr
->
pass
<
6
&&
if
(
png_ptr
->
interlaced
&&
png_ptr
->
pass
<
6
&&
(
png_ptr
->
transformations
&
PNG_INTERLACE
))
(
png_ptr
->
transformations
&
PNG_INTERLACE
)
!=
0
)
{
{
png_do_write_interlace
(
&
row_info
,
png_ptr
->
row_buf
+
1
,
png_ptr
->
pass
);
png_do_write_interlace
(
&
row_info
,
png_ptr
->
row_buf
+
1
,
png_ptr
->
pass
);
/* This should always get caught above, but still ... */
/* This should always get caught above, but still ... */
if
(
!
(
row_info
.
width
)
)
if
(
row_info
.
width
==
0
)
{
{
png_write_finish_row
(
png_ptr
);
png_write_finish_row
(
png_ptr
);
return
;
return
;
...
@@ -771,7 +858,7 @@ png_write_row(png_structrp png_ptr, png_const_bytep row)
...
@@ -771,7 +858,7 @@ png_write_row(png_structrp png_ptr, png_const_bytep row)
#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
/* Handle other transformations */
/* Handle other transformations */
if
(
png_ptr
->
transformations
)
if
(
png_ptr
->
transformations
!=
0
)
png_do_write_transformations
(
png_ptr
,
&
row_info
);
png_do_write_transformations
(
png_ptr
,
&
row_info
);
#endif
#endif
...
@@ -779,7 +866,7 @@ png_write_row(png_structrp png_ptr, png_const_bytep row)
...
@@ -779,7 +866,7 @@ png_write_row(png_structrp png_ptr, png_const_bytep row)
* which is also the output depth.
* which is also the output depth.
*/
*/
if
(
row_info
.
pixel_depth
!=
png_ptr
->
pixel_depth
||
if
(
row_info
.
pixel_depth
!=
png_ptr
->
pixel_depth
||
row_info
.
pixel_depth
!=
png_ptr
->
transformed_pixel_depth
)
row_info
.
pixel_depth
!=
png_ptr
->
transformed_pixel_depth
)
png_error
(
png_ptr
,
"internal write transform logic error"
);
png_error
(
png_ptr
,
"internal write transform logic error"
);
#ifdef PNG_MNG_FEATURES_SUPPORTED
#ifdef PNG_MNG_FEATURES_SUPPORTED
...
@@ -792,7 +879,7 @@ png_write_row(png_structrp png_ptr, png_const_bytep row)
...
@@ -792,7 +879,7 @@ png_write_row(png_structrp png_ptr, png_const_bytep row)
* 4. The filter_method is 64 and
* 4. The filter_method is 64 and
* 5. The color_type is RGB or RGBA
* 5. The color_type is RGB or RGBA
*/
*/
if
((
png_ptr
->
mng_features_permitted
&
PNG_FLAG_MNG_FILTER_64
)
&&
if
((
png_ptr
->
mng_features_permitted
&
PNG_FLAG_MNG_FILTER_64
)
!=
0
&&
(
png_ptr
->
filter_type
==
PNG_INTRAPIXEL_DIFFERENCING
))
(
png_ptr
->
filter_type
==
PNG_INTRAPIXEL_DIFFERENCING
))
{
{
/* Intrapixel differencing */
/* Intrapixel differencing */
...
@@ -825,7 +912,7 @@ png_set_flush(png_structrp png_ptr, int nrows)
...
@@ -825,7 +912,7 @@ png_set_flush(png_structrp png_ptr, int nrows)
if
(
png_ptr
==
NULL
)
if
(
png_ptr
==
NULL
)
return
;
return
;
png_ptr
->
flush_dist
=
(
nrows
<
0
?
0
:
nrows
);
png_ptr
->
flush_dist
=
(
nrows
<
0
?
0
:
(
png_uint_32
)
nrows
);
}
}
/* Flush the current output buffers now */
/* Flush the current output buffers now */
...
@@ -845,11 +932,7 @@ png_write_flush(png_structrp png_ptr)
...
@@ -845,11 +932,7 @@ png_write_flush(png_structrp png_ptr)
png_ptr
->
flush_rows
=
0
;
png_ptr
->
flush_rows
=
0
;
png_flush
(
png_ptr
);
png_flush
(
png_ptr
);
}
}
#endif
/* PNG_WRITE_FLUSH_SUPPORTED */
#endif
/* WRITE_FLUSH */
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
static
void
png_reset_filter_heuristics
(
png_structrp
png_ptr
);
/* forward decl */
#endif
/* Free any memory used in png_ptr struct without freeing the struct itself. */
/* Free any memory used in png_ptr struct without freeing the struct itself. */
static
void
static
void
...
@@ -858,29 +941,25 @@ png_write_destroy(png_structrp png_ptr)
...
@@ -858,29 +941,25 @@ png_write_destroy(png_structrp png_ptr)
png_debug
(
1
,
"in png_write_destroy"
);
png_debug
(
1
,
"in png_write_destroy"
);
/* Free any memory zlib uses */
/* Free any memory zlib uses */
if
(
png_ptr
->
flags
&
PNG_FLAG_ZSTREAM_INITIALIZED
)
if
(
(
png_ptr
->
flags
&
PNG_FLAG_ZSTREAM_INITIALIZED
)
!=
0
)
deflateEnd
(
&
png_ptr
->
zstream
);
deflateEnd
(
&
png_ptr
->
zstream
);
/* Free our memory. png_free checks NULL for us. */
/* Free our memory. png_free checks NULL for us. */
png_free_buffer_list
(
png_ptr
,
&
png_ptr
->
zbuffer_list
);
png_free_buffer_list
(
png_ptr
,
&
png_ptr
->
zbuffer_list
);
png_free
(
png_ptr
,
png_ptr
->
row_buf
);
png_free
(
png_ptr
,
png_ptr
->
row_buf
);
png_ptr
->
row_buf
=
NULL
;
#ifdef PNG_WRITE_FILTER_SUPPORTED
#ifdef PNG_WRITE_FILTER_SUPPORTED
png_free
(
png_ptr
,
png_ptr
->
prev_row
);
png_free
(
png_ptr
,
png_ptr
->
prev_row
);
png_free
(
png_ptr
,
png_ptr
->
sub_row
);
png_free
(
png_ptr
,
png_ptr
->
try_row
);
png_free
(
png_ptr
,
png_ptr
->
up_row
);
png_free
(
png_ptr
,
png_ptr
->
tst_row
);
png_free
(
png_ptr
,
png_ptr
->
avg_row
);
png_ptr
->
prev_row
=
NULL
;
png_free
(
png_ptr
,
png_ptr
->
paeth_row
);
png_ptr
->
try_row
=
NULL
;
#endif
png_ptr
->
tst_row
=
NULL
;
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
/* Use this to save a little code space, it doesn't free the filter_costs */
png_reset_filter_heuristics
(
png_ptr
);
png_free
(
png_ptr
,
png_ptr
->
filter_costs
);
png_free
(
png_ptr
,
png_ptr
->
inv_filter_costs
);
#endif
#endif
#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
png_free
(
png_ptr
,
png_ptr
->
chunk_list
);
png_free
(
png_ptr
,
png_ptr
->
chunk_list
);
png_ptr
->
chunk_list
=
NULL
;
#endif
#endif
/* The error handling and memory handling information is left intact at this
/* The error handling and memory handling information is left intact at this
...
@@ -926,7 +1005,7 @@ png_set_filter(png_structrp png_ptr, int method, int filters)
...
@@ -926,7 +1005,7 @@ png_set_filter(png_structrp png_ptr, int method, int filters)
return
;
return
;
#ifdef PNG_MNG_FEATURES_SUPPORTED
#ifdef PNG_MNG_FEATURES_SUPPORTED
if
((
png_ptr
->
mng_features_permitted
&
PNG_FLAG_MNG_FILTER_64
)
&&
if
((
png_ptr
->
mng_features_permitted
&
PNG_FLAG_MNG_FILTER_64
)
!=
0
&&
(
method
==
PNG_INTRAPIXEL_DIFFERENCING
))
(
method
==
PNG_INTRAPIXEL_DIFFERENCING
))
method
=
PNG_FILTER_TYPE_BASE
;
method
=
PNG_FILTER_TYPE_BASE
;
...
@@ -939,8 +1018,8 @@ png_set_filter(png_structrp png_ptr, int method, int filters)
...
@@ -939,8 +1018,8 @@ png_set_filter(png_structrp png_ptr, int method, int filters)
case
5
:
case
5
:
case
6
:
case
6
:
case
7
:
png_app_error
(
png_ptr
,
"Unknown row filter for method 0"
);
case
7
:
png_app_error
(
png_ptr
,
"Unknown row filter for method 0"
);
/* FALL THROUGH
*/
#endif
/* WRITE_FILTER
*/
#endif
/* PNG_WRITE_FILTER_SUPPORTED
*/
/* FALLTHROUGH
*/
case
PNG_FILTER_VALUE_NONE
:
case
PNG_FILTER_VALUE_NONE
:
png_ptr
->
do_filter
=
PNG_FILTER_NONE
;
break
;
png_ptr
->
do_filter
=
PNG_FILTER_NONE
;
break
;
...
@@ -962,211 +1041,88 @@ png_set_filter(png_structrp png_ptr, int method, int filters)
...
@@ -962,211 +1041,88 @@ png_set_filter(png_structrp png_ptr, int method, int filters)
#else
#else
default:
default:
png_app_error
(
png_ptr
,
"Unknown row filter for method 0"
);
png_app_error
(
png_ptr
,
"Unknown row filter for method 0"
);
#endif
/*
PNG_
WRITE_FILTER
_SUPPORTED
*/
#endif
/* WRITE_FILTER */
}
}
#ifdef PNG_WRITE_FILTER_SUPPORTED
/* If we have allocated the row_buf, this means we have already started
/* If we have allocated the row_buf, this means we have already started
* with the image and we should have allocated all of the filter buffers
* with the image and we should have allocated all of the filter buffers
* that have been selected. If prev_row isn't already allocated, then
* that have been selected. If prev_row isn't already allocated, then
* it is too late to start using the filters that need it, since we
* it is too late to start using the filters that need it, since we
* will be missing the data in the previous row. If an application
* will be missing the data in the previous row. If an application
* wants to start and stop using particular filters during compression,
* wants to start and stop using particular filters during compression,
* it should start out with all of the filters, and then add and
* it should start out with all of the filters, and then remove them
* remove them after the start of compression.
* or add them back after the start of compression.
*
* NOTE: this is a nasty constraint on the code, because it means that the
* prev_row buffer must be maintained even if there are currently no
* 'prev_row' requiring filters active.
*/
*/
if
(
png_ptr
->
row_buf
!=
NULL
)
if
(
png_ptr
->
row_buf
!=
NULL
)
{
{
#ifdef PNG_WRITE_FILTER_SUPPORTED
int
num_filters
;
if
((
png_ptr
->
do_filter
&
PNG_FILTER_SUB
)
&&
png_ptr
->
sub_row
==
NULL
)
png_alloc_size_t
buf_size
;
{
png_ptr
->
sub_row
=
(
png_bytep
)
png_malloc
(
png_ptr
,
(
png_ptr
->
rowbytes
+
1
));
png_ptr
->
sub_row
[
0
]
=
PNG_FILTER_VALUE_SUB
;
}
if
((
png_ptr
->
do_filter
&
PNG_FILTER_UP
)
&&
png_ptr
->
up_row
==
NULL
)
/* Repeat the checks in png_write_start_row; 1 pixel high or wide
{
* images cannot benefit from certain filters. If this isn't done here
if
(
png_ptr
->
prev_row
==
NULL
)
* the check below will fire on 1 pixel high images.
{
*/
png_warning
(
png_ptr
,
"Can't add Up filter after starting"
);
if
(
png_ptr
->
height
==
1
)
png_ptr
->
do_filter
=
(
png_byte
)(
png_ptr
->
do_filter
&
filters
&=
~
(
PNG_FILTER_UP
|
PNG_FILTER_AVG
|
PNG_FILTER_PAETH
);
~
PNG_FILTER_UP
);
}
else
{
png_ptr
->
up_row
=
(
png_bytep
)
png_malloc
(
png_ptr
,
(
png_ptr
->
rowbytes
+
1
));
png_ptr
->
up_row
[
0
]
=
PNG_FILTER_VALUE_UP
;
}
}
if
((
png_ptr
->
do_filter
&
PNG_FILTER_AVG
)
&&
png_ptr
->
avg_row
==
NULL
)
{
if
(
png_ptr
->
prev_row
==
NULL
)
{
png_warning
(
png_ptr
,
"Can't add Average filter after starting"
);
png_ptr
->
do_filter
=
(
png_byte
)(
png_ptr
->
do_filter
&
~
PNG_FILTER_AVG
);
}
else
if
(
png_ptr
->
width
==
1
)
{
filters
&=
~
(
PNG_FILTER_SUB
|
PNG_FILTER_AVG
|
PNG_FILTER_PAETH
);
png_ptr
->
avg_row
=
(
png_bytep
)
png_malloc
(
png_ptr
,
(
png_ptr
->
rowbytes
+
1
));
png_ptr
->
avg_row
[
0
]
=
PNG_FILTER_VALUE_AVG
;
}
}
if
((
png_ptr
->
do_
filter
&
PNG_FILTER_PAETH
)
&&
if
((
filter
s
&
(
PNG_FILTER_UP
|
PNG_FILTER_AVG
|
PNG_FILTER_PAETH
)
)
!=
0
png_ptr
->
p
aeth
_row
==
NULL
)
&&
png_ptr
->
p
rev
_row
==
NULL
)
{
{
if
(
png_ptr
->
prev_row
==
NULL
)
/* This is the error case, however it is benign - the previous row
{
* is not available so the filter can't be used. Just warn here.
png_warning
(
png_ptr
,
"Can't add Paeth filter after starting"
);
*/
png_ptr
->
do_filter
&=
(
png_byte
)(
~
PNG_FILTER_PAETH
);
png_app_warning
(
png_ptr
,
}
"png_set_filter: UP/AVG/PAETH cannot be added after start"
);
filters
&=
~
(
PNG_FILTER_UP
|
PNG_FILTER_AVG
|
PNG_FILTER_PAETH
);
else
{
png_ptr
->
paeth_row
=
(
png_bytep
)
png_malloc
(
png_ptr
,
(
png_ptr
->
rowbytes
+
1
));
png_ptr
->
paeth_row
[
0
]
=
PNG_FILTER_VALUE_PAETH
;
}
}
}
if
(
png_ptr
->
do_filter
==
PNG_NO_FILTERS
)
num_filters
=
0
;
#endif
/* PNG_WRITE_FILTER_SUPPORTED */
png_ptr
->
do_filter
=
PNG_FILTER_NONE
;
}
}
else
png_error
(
png_ptr
,
"Unknown custom filter method"
);
}
/* This allows us to influence the way in which libpng chooses the "best"
* filter for the current scanline. While the "minimum-sum-of-absolute-
* differences metric is relatively fast and effective, there is some
* question as to whether it can be improved upon by trying to keep the
* filtered data going to zlib more consistent, hopefully resulting in
* better compression.
*/
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
/* GRR 970116 */
/* Convenience reset API. */
static
void
png_reset_filter_heuristics
(
png_structrp
png_ptr
)
{
/* Clear out any old values in the 'weights' - this must be done because if
* the app calls set_filter_heuristics multiple times with different
* 'num_weights' values we would otherwise potentially have wrong sized
* arrays.
*/
png_ptr
->
num_prev_filters
=
0
;
png_ptr
->
heuristic_method
=
PNG_FILTER_HEURISTIC_UNWEIGHTED
;
if
(
png_ptr
->
prev_filters
!=
NULL
)
{
png_bytep
old
=
png_ptr
->
prev_filters
;
png_ptr
->
prev_filters
=
NULL
;
png_free
(
png_ptr
,
old
);
}
if
(
png_ptr
->
filter_weights
!=
NULL
)
{
png_uint_16p
old
=
png_ptr
->
filter_weights
;
png_ptr
->
filter_weights
=
NULL
;
png_free
(
png_ptr
,
old
);
}
if
(
png_ptr
->
inv_filter_weights
!=
NULL
)
{
png_uint_16p
old
=
png_ptr
->
inv_filter_weights
;
png_ptr
->
inv_filter_weights
=
NULL
;
png_free
(
png_ptr
,
old
);
}
/* Leave the filter_costs - this array is fixed size. */
if
(
filters
&
PNG_FILTER_SUB
)
}
num_filters
++
;
static
int
if
(
filters
&
PNG_FILTER_UP
)
png_init_filter_heuristics
(
png_structrp
png_ptr
,
int
heuristic_method
,
num_filters
++
;
int
num_weights
)
{
if
(
png_ptr
==
NULL
)
return
0
;
/* Clear out the arrays */
if
(
filters
&
PNG_FILTER_AVG
)
png_reset_filter_heuristics
(
png_ptr
)
;
num_filters
++
;
/* Check arguments; the 'reset' function makes the correct settings for the
if
(
filters
&
PNG_FILTER_PAETH
)
* unweighted case, but we must handle the weight case by initializing the
num_filters
++
;
* arrays for the caller.
*/
if
(
heuristic_method
==
PNG_FILTER_HEURISTIC_WEIGHTED
)
{
int
i
;
if
(
num_weights
>
0
)
{
png_ptr
->
prev_filters
=
(
png_bytep
)
png_malloc
(
png_ptr
,
(
png_uint_32
)((
sizeof
(
png_byte
))
*
num_weights
));
/* To make sure that the weighting starts out fairly */
/* Allocate needed row buffers if they have not already been
for
(
i
=
0
;
i
<
num_weights
;
i
++
)
* allocated.
{
*/
png_ptr
->
prev_filters
[
i
]
=
255
;
buf_size
=
PNG_ROWBYTES
(
png_ptr
->
usr_channels
*
png_ptr
->
usr_bit_depth
,
}
png_ptr
->
width
)
+
1
;
png_ptr
->
filter_weights
=
(
png_uint_16p
)
png_malloc
(
png_ptr
,
(
png_uint_32
)((
sizeof
(
png_uint_16
))
*
num_weights
));
png_ptr
->
inv_filter_weights
=
(
png_uint_16p
)
png_malloc
(
png_ptr
,
if
(
png_ptr
->
try_row
==
NULL
)
(
png_uint_32
)((
sizeof
(
png_uint_16
))
*
num_weights
));
png_ptr
->
try_row
=
png_voidcast
(
png_bytep
,
png_malloc
(
png_ptr
,
buf_size
));
for
(
i
=
0
;
i
<
num_weights
;
i
++
)
if
(
num_filters
>
1
)
{
{
png_ptr
->
inv_filter_weights
[
i
]
=
if
(
png_ptr
->
tst_row
==
NULL
)
png_ptr
->
filter_weights
[
i
]
=
PNG_WEIGHT_FACTOR
;
png_ptr
->
tst_row
=
png_voidcast
(
png_bytep
,
png_malloc
(
png_ptr
,
buf_size
));
}
}
/* Safe to set this now */
png_ptr
->
num_prev_filters
=
(
png_byte
)
num_weights
;
}
/* If, in the future, there are other filter methods, this would
* need to be based on png_ptr->filter.
*/
if
(
png_ptr
->
filter_costs
==
NULL
)
{
png_ptr
->
filter_costs
=
(
png_uint_16p
)
png_malloc
(
png_ptr
,
(
png_uint_32
)((
sizeof
(
png_uint_16
))
*
PNG_FILTER_VALUE_LAST
));
png_ptr
->
inv_filter_costs
=
(
png_uint_16p
)
png_malloc
(
png_ptr
,
(
png_uint_32
)((
sizeof
(
png_uint_16
))
*
PNG_FILTER_VALUE_LAST
));
}
}
png_ptr
->
do_filter
=
(
png_byte
)
filters
;
for
(
i
=
0
;
i
<
PNG_FILTER_VALUE_LAST
;
i
++
)
#endif
{
png_ptr
->
inv_filter_costs
[
i
]
=
png_ptr
->
filter_costs
[
i
]
=
PNG_COST_FACTOR
;
}
/* All the arrays are inited, safe to set this: */
png_ptr
->
heuristic_method
=
PNG_FILTER_HEURISTIC_WEIGHTED
;
/* Return the 'ok' code. */
return
1
;
}
else
if
(
heuristic_method
==
PNG_FILTER_HEURISTIC_DEFAULT
||
heuristic_method
==
PNG_FILTER_HEURISTIC_UNWEIGHTED
)
{
return
1
;
}
}
else
else
{
png_error
(
png_ptr
,
"Unknown custom filter method"
);
png_warning
(
png_ptr
,
"Unknown filter heuristic method"
);
return
0
;
}
}
}
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
/* DEPRECATED */
/* Provide floating and fixed point APIs */
/* Provide floating and fixed point APIs */
#ifdef PNG_FLOATING_POINT_SUPPORTED
#ifdef PNG_FLOATING_POINT_SUPPORTED
void
PNGAPI
void
PNGAPI
...
@@ -1174,52 +1130,11 @@ png_set_filter_heuristics(png_structrp png_ptr, int heuristic_method,
...
@@ -1174,52 +1130,11 @@ png_set_filter_heuristics(png_structrp png_ptr, int heuristic_method,
int
num_weights
,
png_const_doublep
filter_weights
,
int
num_weights
,
png_const_doublep
filter_weights
,
png_const_doublep
filter_costs
)
png_const_doublep
filter_costs
)
{
{
png_debug
(
1
,
"in png_set_filter_heuristics"
);
PNG_UNUSED
(
png_ptr
)
PNG_UNUSED
(
heuristic_method
)
/* The internal API allocates all the arrays and ensures that the elements of
PNG_UNUSED
(
num_weights
)
* those arrays are set to the default value.
PNG_UNUSED
(
filter_weights
)
*/
PNG_UNUSED
(
filter_costs
)
if
(
!
png_init_filter_heuristics
(
png_ptr
,
heuristic_method
,
num_weights
))
return
;
/* If using the weighted method copy in the weights. */
if
(
heuristic_method
==
PNG_FILTER_HEURISTIC_WEIGHTED
)
{
int
i
;
for
(
i
=
0
;
i
<
num_weights
;
i
++
)
{
if
(
filter_weights
[
i
]
<=
0
.
0
)
{
png_ptr
->
inv_filter_weights
[
i
]
=
png_ptr
->
filter_weights
[
i
]
=
PNG_WEIGHT_FACTOR
;
}
else
{
png_ptr
->
inv_filter_weights
[
i
]
=
(
png_uint_16
)(
PNG_WEIGHT_FACTOR
*
filter_weights
[
i
]
+
.
5
);
png_ptr
->
filter_weights
[
i
]
=
(
png_uint_16
)(
PNG_WEIGHT_FACTOR
/
filter_weights
[
i
]
+
.
5
);
}
}
/* Here is where we set the relative costs of the different filters. We
* should take the desired compression level into account when setting
* the costs, so that Paeth, for instance, has a high relative cost at low
* compression levels, while it has a lower relative cost at higher
* compression settings. The filter types are in order of increasing
* relative cost, so it would be possible to do this with an algorithm.
*/
for
(
i
=
0
;
i
<
PNG_FILTER_VALUE_LAST
;
i
++
)
if
(
filter_costs
[
i
]
>=
1
.
0
)
{
png_ptr
->
inv_filter_costs
[
i
]
=
(
png_uint_16
)(
PNG_COST_FACTOR
/
filter_costs
[
i
]
+
.
5
);
png_ptr
->
filter_costs
[
i
]
=
(
png_uint_16
)(
PNG_COST_FACTOR
*
filter_costs
[
i
]
+
.
5
);
}
}
}
}
#endif
/* FLOATING_POINT */
#endif
/* FLOATING_POINT */
...
@@ -1229,67 +1144,16 @@ png_set_filter_heuristics_fixed(png_structrp png_ptr, int heuristic_method,
...
@@ -1229,67 +1144,16 @@ png_set_filter_heuristics_fixed(png_structrp png_ptr, int heuristic_method,
int
num_weights
,
png_const_fixed_point_p
filter_weights
,
int
num_weights
,
png_const_fixed_point_p
filter_weights
,
png_const_fixed_point_p
filter_costs
)
png_const_fixed_point_p
filter_costs
)
{
{
png_debug
(
1
,
"in png_set_filter_heuristics_fixed"
);
PNG_UNUSED
(
png_ptr
)
PNG_UNUSED
(
heuristic_method
)
/* The internal API allocates all the arrays and ensures that the elements of
PNG_UNUSED
(
num_weights
)
* those arrays are set to the default value.
PNG_UNUSED
(
filter_weights
)
*/
PNG_UNUSED
(
filter_costs
)
if
(
!
png_init_filter_heuristics
(
png_ptr
,
heuristic_method
,
num_weights
))
return
;
/* If using the weighted method copy in the weights. */
if
(
heuristic_method
==
PNG_FILTER_HEURISTIC_WEIGHTED
)
{
int
i
;
for
(
i
=
0
;
i
<
num_weights
;
i
++
)
{
if
(
filter_weights
[
i
]
<=
0
)
{
png_ptr
->
inv_filter_weights
[
i
]
=
png_ptr
->
filter_weights
[
i
]
=
PNG_WEIGHT_FACTOR
;
}
else
{
png_ptr
->
inv_filter_weights
[
i
]
=
(
png_uint_16
)
((
PNG_WEIGHT_FACTOR
*
filter_weights
[
i
]
+
PNG_FP_HALF
)
/
PNG_FP_1
);
png_ptr
->
filter_weights
[
i
]
=
(
png_uint_16
)((
PNG_WEIGHT_FACTOR
*
PNG_FP_1
+
(
filter_weights
[
i
]
/
2
))
/
filter_weights
[
i
]);
}
}
/* Here is where we set the relative costs of the different filters. We
* should take the desired compression level into account when setting
* the costs, so that Paeth, for instance, has a high relative cost at low
* compression levels, while it has a lower relative cost at higher
* compression settings. The filter types are in order of increasing
* relative cost, so it would be possible to do this with an algorithm.
*/
for
(
i
=
0
;
i
<
PNG_FILTER_VALUE_LAST
;
i
++
)
if
(
filter_costs
[
i
]
>=
PNG_FP_1
)
{
png_uint_32
tmp
;
/* Use a 32 bit unsigned temporary here because otherwise the
* intermediate value will be a 32 bit *signed* integer (ANSI rules)
* and this will get the wrong answer on division.
*/
tmp
=
PNG_COST_FACTOR
*
PNG_FP_1
+
(
filter_costs
[
i
]
/
2
);
tmp
/=
filter_costs
[
i
];
png_ptr
->
inv_filter_costs
[
i
]
=
(
png_uint_16
)
tmp
;
tmp
=
PNG_COST_FACTOR
*
filter_costs
[
i
]
+
PNG_FP_HALF
;
tmp
/=
PNG_FP_1
;
png_ptr
->
filter_costs
[
i
]
=
(
png_uint_16
)
tmp
;
}
}
}
}
#endif
/* FIXED_POINT */
#endif
/* FIXED_POINT */
#endif
/*
PNG_
WRITE_WEIGHTED_FILTER
_SUPPORTED
*/
#endif
/* WRITE_WEIGHTED_FILTER */
#ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
void
PNGAPI
void
PNGAPI
png_set_compression_level
(
png_structrp
png_ptr
,
int
level
)
png_set_compression_level
(
png_structrp
png_ptr
,
int
level
)
{
{
...
@@ -1335,8 +1199,8 @@ png_set_compression_window_bits(png_structrp png_ptr, int window_bits)
...
@@ -1335,8 +1199,8 @@ png_set_compression_window_bits(png_structrp png_ptr, int window_bits)
if
(
png_ptr
==
NULL
)
if
(
png_ptr
==
NULL
)
return
;
return
;
/* Prior to 1.6.0 this would warn but then set the window_bits value
, t
his
/* Prior to 1.6.0 this would warn but then set the window_bits value
. T
his
* meant that negative window bits values could be selected
which
would cause
* meant that negative window bits values could be selected
that
would cause
* libpng to write a non-standard PNG file with raw deflate or gzip
* libpng to write a non-standard PNG file with raw deflate or gzip
* compressed IDAT or ancillary chunks. Such files can be read and there is
* compressed IDAT or ancillary chunks. Such files can be read and there is
* no warning on read, so this seems like a very bad idea.
* no warning on read, so this seems like a very bad idea.
...
@@ -1372,6 +1236,7 @@ png_set_compression_method(png_structrp png_ptr, int method)
...
@@ -1372,6 +1236,7 @@ png_set_compression_method(png_structrp png_ptr, int method)
png_ptr
->
zlib_method
=
method
;
png_ptr
->
zlib_method
=
method
;
}
}
#endif
/* WRITE_CUSTOMIZE_COMPRESSION */
/* The following were added to libpng-1.5.4 */
/* The following were added to libpng-1.5.4 */
#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
...
@@ -1445,7 +1310,7 @@ png_set_text_compression_method(png_structrp png_ptr, int method)
...
@@ -1445,7 +1310,7 @@ png_set_text_compression_method(png_structrp png_ptr, int method)
png_ptr
->
zlib_text_method
=
method
;
png_ptr
->
zlib_text_method
=
method
;
}
}
#endif
/*
PNG_
WRITE_CUSTOMIZE_ZTXT_COMPRESSION
_SUPPORTED
*/
#endif
/* WRITE_CUSTOMIZE_ZTXT_COMPRESSION */
/* end of API added to libpng-1.5.4 */
/* end of API added to libpng-1.5.4 */
void
PNGAPI
void
PNGAPI
...
@@ -1481,94 +1346,129 @@ png_write_png(png_structrp png_ptr, png_inforp info_ptr,
...
@@ -1481,94 +1346,129 @@ png_write_png(png_structrp png_ptr, png_inforp info_ptr,
if
(
png_ptr
==
NULL
||
info_ptr
==
NULL
)
if
(
png_ptr
==
NULL
||
info_ptr
==
NULL
)
return
;
return
;
if
((
info_ptr
->
valid
&
PNG_INFO_IDAT
)
==
0
)
{
png_app_error
(
png_ptr
,
"no rows for png_write_image to write"
);
return
;
}
/* Write the file header information. */
/* Write the file header information. */
png_write_info
(
png_ptr
,
info_ptr
);
png_write_info
(
png_ptr
,
info_ptr
);
/* ------ these transformations don't touch the info structure ------- */
/* ------ these transformations don't touch the info structure ------- */
#ifdef PNG_WRITE_INVERT_SUPPORTED
/* Invert monochrome pixels */
/* Invert monochrome pixels */
if
(
transforms
&
PNG_TRANSFORM_INVERT_MONO
)
if
((
transforms
&
PNG_TRANSFORM_INVERT_MONO
)
!=
0
)
#ifdef PNG_WRITE_INVERT_SUPPORTED
png_set_invert_mono
(
png_ptr
);
png_set_invert_mono
(
png_ptr
);
#else
png_app_error
(
png_ptr
,
"PNG_TRANSFORM_INVERT_MONO not supported"
);
#endif
#endif
#ifdef PNG_WRITE_SHIFT_SUPPORTED
/* Shift the pixels up to a legal bit depth and fill in
/* Shift the pixels up to a legal bit depth and fill in
* as appropriate to correctly scale the image.
* as appropriate to correctly scale the image.
*/
*/
if
((
transforms
&
PNG_TRANSFORM_SHIFT
)
if
((
transforms
&
PNG_TRANSFORM_SHIFT
)
!=
0
)
&&
(
info_ptr
->
valid
&
PNG_INFO_sBIT
))
#ifdef PNG_WRITE_SHIFT_SUPPORTED
png_set_shift
(
png_ptr
,
&
info_ptr
->
sig_bit
);
if
((
info_ptr
->
valid
&
PNG_INFO_sBIT
)
!=
0
)
png_set_shift
(
png_ptr
,
&
info_ptr
->
sig_bit
);
#else
png_app_error
(
png_ptr
,
"PNG_TRANSFORM_SHIFT not supported"
);
#endif
#endif
#ifdef PNG_WRITE_PACK_SUPPORTED
/* Pack pixels into bytes */
/* Pack pixels into bytes */
if
(
transforms
&
PNG_TRANSFORM_PACKING
)
if
((
transforms
&
PNG_TRANSFORM_PACKING
)
!=
0
)
png_set_packing
(
png_ptr
);
#ifdef PNG_WRITE_PACK_SUPPORTED
png_set_packing
(
png_ptr
);
#else
png_app_error
(
png_ptr
,
"PNG_TRANSFORM_PACKING not supported"
);
#endif
#endif
#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
/* Swap location of alpha bytes from ARGB to RGBA */
/* Swap location of alpha bytes from ARGB to RGBA */
if
(
transforms
&
PNG_TRANSFORM_SWAP_ALPHA
)
if
((
transforms
&
PNG_TRANSFORM_SWAP_ALPHA
)
!=
0
)
#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
png_set_swap_alpha
(
png_ptr
);
png_set_swap_alpha
(
png_ptr
);
#else
png_app_error
(
png_ptr
,
"PNG_TRANSFORM_SWAP_ALPHA not supported"
);
#endif
#endif
/* Remove a filler (X) from XRGB/RGBX/AG/GA into to convert it into
* RGB, note that the code expects the input color type to be G or RGB; no
* alpha channel.
*/
if
((
transforms
&
(
PNG_TRANSFORM_STRIP_FILLER_AFTER
|
PNG_TRANSFORM_STRIP_FILLER_BEFORE
))
!=
0
)
{
#ifdef PNG_WRITE_FILLER_SUPPORTED
#ifdef PNG_WRITE_FILLER_SUPPORTED
/* Pack XRGB/RGBX/ARGB/RGBA into RGB (4 channels -> 3 channels) */
if
((
transforms
&
PNG_TRANSFORM_STRIP_FILLER_AFTER
)
!=
0
)
if
(
transforms
&
PNG_TRANSFORM_STRIP_FILLER_AFTER
)
{
png_set_filler
(
png_ptr
,
0
,
PNG_FILLER_AFTER
);
if
((
transforms
&
PNG_TRANSFORM_STRIP_FILLER_BEFORE
)
!=
0
)
png_app_error
(
png_ptr
,
"PNG_TRANSFORM_STRIP_FILLER: BEFORE+AFTER not supported"
);
else
if
(
transforms
&
PNG_TRANSFORM_STRIP_FILLER_BEFORE
)
/* Continue if ignored - this is the pre-1.6.10 behavior */
png_set_filler
(
png_ptr
,
0
,
PNG_FILLER_BEFORE
);
png_set_filler
(
png_ptr
,
0
,
PNG_FILLER_AFTER
);
}
else
if
((
transforms
&
PNG_TRANSFORM_STRIP_FILLER_BEFORE
)
!=
0
)
png_set_filler
(
png_ptr
,
0
,
PNG_FILLER_BEFORE
);
#else
png_app_error
(
png_ptr
,
"PNG_TRANSFORM_STRIP_FILLER not supported"
);
#endif
#endif
}
#ifdef PNG_WRITE_BGR_SUPPORTED
/* Flip BGR pixels to RGB */
/* Flip BGR pixels to RGB */
if
(
transforms
&
PNG_TRANSFORM_BGR
)
if
((
transforms
&
PNG_TRANSFORM_BGR
)
!=
0
)
#ifdef PNG_WRITE_BGR_SUPPORTED
png_set_bgr
(
png_ptr
);
png_set_bgr
(
png_ptr
);
#else
png_app_error
(
png_ptr
,
"PNG_TRANSFORM_BGR not supported"
);
#endif
#endif
#ifdef PNG_WRITE_SWAP_SUPPORTED
/* Swap bytes of 16-bit files to most significant byte first */
/* Swap bytes of 16-bit files to most significant byte first */
if
(
transforms
&
PNG_TRANSFORM_SWAP_ENDIAN
)
if
((
transforms
&
PNG_TRANSFORM_SWAP_ENDIAN
)
!=
0
)
#ifdef PNG_WRITE_SWAP_SUPPORTED
png_set_swap
(
png_ptr
);
png_set_swap
(
png_ptr
);
#else
png_app_error
(
png_ptr
,
"PNG_TRANSFORM_SWAP_ENDIAN not supported"
);
#endif
#endif
/* Swap bits of 1-bit, 2-bit, 4-bit packed pixel formats */
if
((
transforms
&
PNG_TRANSFORM_PACKSWAP
)
!=
0
)
#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
/* Swap bits of 1, 2, 4 bit packed pixel formats */
if
(
transforms
&
PNG_TRANSFORM_PACKSWAP
)
png_set_packswap
(
png_ptr
);
png_set_packswap
(
png_ptr
);
#else
png_app_error
(
png_ptr
,
"PNG_TRANSFORM_PACKSWAP not supported"
);
#endif
#endif
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
/* Invert the alpha channel from opacity to transparency */
/* Invert the alpha channel from opacity to transparency */
if
(
transforms
&
PNG_TRANSFORM_INVERT_ALPHA
)
if
((
transforms
&
PNG_TRANSFORM_INVERT_ALPHA
)
!=
0
)
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
png_set_invert_alpha
(
png_ptr
);
png_set_invert_alpha
(
png_ptr
);
#else
png_app_error
(
png_ptr
,
"PNG_TRANSFORM_INVERT_ALPHA not supported"
);
#endif
#endif
/* ----------------------- end of transformations ------------------- */
/* ----------------------- end of transformations ------------------- */
/* Write the bits */
/* Write the bits */
if
(
info_ptr
->
valid
&
PNG_INFO_IDAT
)
png_write_image
(
png_ptr
,
info_ptr
->
row_pointers
);
png_write_image
(
png_ptr
,
info_ptr
->
row_pointers
);
/* It is REQUIRED to call this to finish writing the rest of the file */
/* It is REQUIRED to call this to finish writing the rest of the file */
png_write_end
(
png_ptr
,
info_ptr
);
png_write_end
(
png_ptr
,
info_ptr
);
PNG_UNUSED
(
transforms
)
/* Quiet compiler warnings */
PNG_UNUSED
(
params
)
PNG_UNUSED
(
params
)
}
}
#endif
#endif
#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
#ifdef PNG_STDIO_SUPPORTED
/* currently required for png_image_write_* */
/* Initialize the write structure - general purpose utility. */
/* Initialize the write structure - general purpose utility. */
static
int
static
int
png_image_write_init
(
png_imagep
image
)
png_image_write_init
(
png_imagep
image
)
{
{
png_structp
png_ptr
=
png_create_write_struct
(
PNG_LIBPNG_VER_STRING
,
image
,
png_structp
png_ptr
=
png_create_write_struct
(
PNG_LIBPNG_VER_STRING
,
image
,
png_safe_error
,
png_safe_warning
);
png_safe_error
,
png_safe_warning
);
if
(
png_ptr
!=
NULL
)
if
(
png_ptr
!=
NULL
)
{
{
...
@@ -1577,7 +1477,7 @@ png_image_write_init(png_imagep image)
...
@@ -1577,7 +1477,7 @@ png_image_write_init(png_imagep image)
if
(
info_ptr
!=
NULL
)
if
(
info_ptr
!=
NULL
)
{
{
png_controlp
control
=
png_voidcast
(
png_controlp
,
png_controlp
control
=
png_voidcast
(
png_controlp
,
png_malloc_warn
(
png_ptr
,
(
sizeof
*
control
)));
png_malloc_warn
(
png_ptr
,
(
sizeof
*
control
)));
if
(
control
!=
NULL
)
if
(
control
!=
NULL
)
{
{
...
@@ -1614,6 +1514,10 @@ typedef struct
...
@@ -1614,6 +1514,10 @@ typedef struct
png_const_voidp
first_row
;
png_const_voidp
first_row
;
ptrdiff_t
row_bytes
;
ptrdiff_t
row_bytes
;
png_voidp
local_row
;
png_voidp
local_row
;
/* Byte count for memory writing */
png_bytep
memory
;
png_alloc_size_t
memory_bytes
;
/* not used for STDIO */
png_alloc_size_t
output_bytes
;
/* running total */
}
png_image_write_control
;
}
png_image_write_control
;
/* Write png_uint_16 input to a 16-bit PNG; the png_ptr has already been set to
/* Write png_uint_16 input to a 16-bit PNG; the png_ptr has already been set to
...
@@ -1624,29 +1528,33 @@ static int
...
@@ -1624,29 +1528,33 @@ static int
png_write_image_16bit
(
png_voidp
argument
)
png_write_image_16bit
(
png_voidp
argument
)
{
{
png_image_write_control
*
display
=
png_voidcast
(
png_image_write_control
*
,
png_image_write_control
*
display
=
png_voidcast
(
png_image_write_control
*
,
argument
);
argument
);
png_imagep
image
=
display
->
image
;
png_imagep
image
=
display
->
image
;
png_structrp
png_ptr
=
image
->
opaque
->
png_ptr
;
png_structrp
png_ptr
=
image
->
opaque
->
png_ptr
;
png_const_uint_16p
input_row
=
png_voidcast
(
png_const_uint_16p
,
png_const_uint_16p
input_row
=
png_voidcast
(
png_const_uint_16p
,
display
->
first_row
);
display
->
first_row
);
png_uint_16p
output_row
=
png_voidcast
(
png_uint_16p
,
display
->
local_row
);
png_uint_16p
output_row
=
png_voidcast
(
png_uint_16p
,
display
->
local_row
);
png_uint_16p
row_end
;
png_uint_16p
row_end
;
const
int
channels
=
(
image
->
format
&
PNG_FORMAT_FLAG_COLOR
)
?
3
:
1
;
unsigned
int
channels
=
(
image
->
format
&
PNG_FORMAT_FLAG_COLOR
)
!=
0
?
3
:
1
;
int
aindex
=
0
;
int
aindex
=
0
;
png_uint_32
y
=
image
->
height
;
png_uint_32
y
=
image
->
height
;
if
(
image
->
format
&
PNG_FORMAT_FLAG_ALPHA
)
if
(
(
image
->
format
&
PNG_FORMAT_FLAG_ALPHA
)
!=
0
)
{
{
if
(
image
->
format
&
PNG_FORMAT_FLAG_AFIRST
)
# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
if
((
image
->
format
&
PNG_FORMAT_FLAG_AFIRST
)
!=
0
)
{
{
aindex
=
-
1
;
aindex
=
-
1
;
++
input_row
;
/* To point to the first component */
++
input_row
;
/* To point to the first component */
++
output_row
;
++
output_row
;
}
}
else
else
aindex
=
(
int
)
channels
;
aindex
=
channels
;
# else
aindex
=
(
int
)
channels
;
# endif
}
}
else
else
...
@@ -1658,14 +1566,14 @@ png_write_image_16bit(png_voidp argument)
...
@@ -1658,14 +1566,14 @@ png_write_image_16bit(png_voidp argument)
*/
*/
row_end
=
output_row
+
image
->
width
*
(
channels
+
1
);
row_end
=
output_row
+
image
->
width
*
(
channels
+
1
);
while
(
y
--
>
0
)
for
(;
y
>
0
;
--
y
)
{
{
png_const_uint_16p
in_ptr
=
input_row
;
png_const_uint_16p
in_ptr
=
input_row
;
png_uint_16p
out_ptr
=
output_row
;
png_uint_16p
out_ptr
=
output_row
;
while
(
out_ptr
<
row_end
)
while
(
out_ptr
<
row_end
)
{
{
const
png_uint_16
alpha
=
in_ptr
[
aindex
];
png_uint_16
alpha
=
in_ptr
[
aindex
];
png_uint_32
reciprocal
=
0
;
png_uint_32
reciprocal
=
0
;
int
c
;
int
c
;
...
@@ -1679,7 +1587,7 @@ png_write_image_16bit(png_voidp argument)
...
@@ -1679,7 +1587,7 @@ png_write_image_16bit(png_voidp argument)
if
(
alpha
>
0
&&
alpha
<
65535
)
if
(
alpha
>
0
&&
alpha
<
65535
)
reciprocal
=
((
0xffff
<<
15
)
+
(
alpha
>>
1
))
/
alpha
;
reciprocal
=
((
0xffff
<<
15
)
+
(
alpha
>>
1
))
/
alpha
;
c
=
channels
;
c
=
(
int
)
channels
;
do
/* always at least one channel */
do
/* always at least one channel */
{
{
png_uint_16
component
=
*
in_ptr
++
;
png_uint_16
component
=
*
in_ptr
++
;
...
@@ -1714,7 +1622,7 @@ png_write_image_16bit(png_voidp argument)
...
@@ -1714,7 +1622,7 @@ png_write_image_16bit(png_voidp argument)
}
}
png_write_row
(
png_ptr
,
png_voidcast
(
png_const_bytep
,
display
->
local_row
));
png_write_row
(
png_ptr
,
png_voidcast
(
png_const_bytep
,
display
->
local_row
));
input_row
+=
display
->
row_bytes
/
(
sizeof
(
png_uint_16
));
input_row
+=
(
png_uint_16
)
display
->
row_bytes
/
(
sizeof
(
png_uint_16
));
}
}
return
1
;
return
1
;
...
@@ -1728,11 +1636,11 @@ png_write_image_16bit(png_voidp argument)
...
@@ -1728,11 +1636,11 @@ png_write_image_16bit(png_voidp argument)
* calculation can be done to 15 bits of accuracy; however, the output needs to
* calculation can be done to 15 bits of accuracy; however, the output needs to
* be scaled in the range 0..255*65535, so include that scaling here.
* be scaled in the range 0..255*65535, so include that scaling here.
*/
*/
#define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+(alpha>>1))/alpha)
#
define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+(
(
alpha
)
>>1))/
(
alpha)
)
static
png_byte
static
png_byte
png_unpremultiply
(
png_uint_32
component
,
png_uint_32
alpha
,
png_unpremultiply
(
png_uint_32
component
,
png_uint_32
alpha
,
png_uint_32
reciprocal
/*from the above macro*/
)
png_uint_32
reciprocal
/*from the above macro*/
)
{
{
/* The following gives 1.0 for an alpha of 0, which is fine, otherwise if 0/0
/* The following gives 1.0 for an alpha of 0, which is fine, otherwise if 0/0
* is represented as some other value there is more likely to be a
* is represented as some other value there is more likely to be a
...
@@ -1779,22 +1687,24 @@ static int
...
@@ -1779,22 +1687,24 @@ static int
png_write_image_8bit
(
png_voidp
argument
)
png_write_image_8bit
(
png_voidp
argument
)
{
{
png_image_write_control
*
display
=
png_voidcast
(
png_image_write_control
*
,
png_image_write_control
*
display
=
png_voidcast
(
png_image_write_control
*
,
argument
);
argument
);
png_imagep
image
=
display
->
image
;
png_imagep
image
=
display
->
image
;
png_structrp
png_ptr
=
image
->
opaque
->
png_ptr
;
png_structrp
png_ptr
=
image
->
opaque
->
png_ptr
;
png_const_uint_16p
input_row
=
png_voidcast
(
png_const_uint_16p
,
png_const_uint_16p
input_row
=
png_voidcast
(
png_const_uint_16p
,
display
->
first_row
);
display
->
first_row
);
png_bytep
output_row
=
png_voidcast
(
png_bytep
,
display
->
local_row
);
png_bytep
output_row
=
png_voidcast
(
png_bytep
,
display
->
local_row
);
png_uint_32
y
=
image
->
height
;
png_uint_32
y
=
image
->
height
;
const
int
channels
=
(
image
->
format
&
PNG_FORMAT_FLAG_COLOR
)
?
3
:
1
;
unsigned
int
channels
=
(
image
->
format
&
PNG_FORMAT_FLAG_COLOR
)
!=
0
?
3
:
1
;
if
(
image
->
format
&
PNG_FORMAT_FLAG_ALPHA
)
if
(
(
image
->
format
&
PNG_FORMAT_FLAG_ALPHA
)
!=
0
)
{
{
png_bytep
row_end
;
png_bytep
row_end
;
int
aindex
;
int
aindex
;
if
(
image
->
format
&
PNG_FORMAT_FLAG_AFIRST
)
# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
if
((
image
->
format
&
PNG_FORMAT_FLAG_AFIRST
)
!=
0
)
{
{
aindex
=
-
1
;
aindex
=
-
1
;
++
input_row
;
/* To point to the first component */
++
input_row
;
/* To point to the first component */
...
@@ -1802,12 +1712,13 @@ png_write_image_8bit(png_voidp argument)
...
@@ -1802,12 +1712,13 @@ png_write_image_8bit(png_voidp argument)
}
}
else
else
aindex
=
channels
;
# endif
aindex
=
(
int
)
channels
;
/* Use row_end in place of a loop counter: */
/* Use row_end in place of a loop counter: */
row_end
=
output_row
+
image
->
width
*
(
channels
+
1
);
row_end
=
output_row
+
image
->
width
*
(
channels
+
1
);
while
(
y
--
>
0
)
for
(;
y
>
0
;
--
y
)
{
{
png_const_uint_16p
in_ptr
=
input_row
;
png_const_uint_16p
in_ptr
=
input_row
;
png_bytep
out_ptr
=
output_row
;
png_bytep
out_ptr
=
output_row
;
...
@@ -1825,7 +1736,7 @@ png_write_image_8bit(png_voidp argument)
...
@@ -1825,7 +1736,7 @@ png_write_image_8bit(png_voidp argument)
if
(
alphabyte
>
0
&&
alphabyte
<
255
)
if
(
alphabyte
>
0
&&
alphabyte
<
255
)
reciprocal
=
UNP_RECIPROCAL
(
alpha
);
reciprocal
=
UNP_RECIPROCAL
(
alpha
);
c
=
channels
;
c
=
(
int
)
channels
;
do
/* always at least one channel */
do
/* always at least one channel */
*
out_ptr
++
=
png_unpremultiply
(
*
in_ptr
++
,
alpha
,
reciprocal
);
*
out_ptr
++
=
png_unpremultiply
(
*
in_ptr
++
,
alpha
,
reciprocal
);
while
(
--
c
>
0
);
while
(
--
c
>
0
);
...
@@ -1836,8 +1747,8 @@ png_write_image_8bit(png_voidp argument)
...
@@ -1836,8 +1747,8 @@ png_write_image_8bit(png_voidp argument)
}
/* while out_ptr < row_end */
}
/* while out_ptr < row_end */
png_write_row
(
png_ptr
,
png_voidcast
(
png_const_bytep
,
png_write_row
(
png_ptr
,
png_voidcast
(
png_const_bytep
,
display
->
local_row
));
display
->
local_row
));
input_row
+=
display
->
row_bytes
/
(
sizeof
(
png_uint_16
));
input_row
+=
(
png_uint_16
)
display
->
row_bytes
/
(
sizeof
(
png_uint_16
));
}
/* while y */
}
/* while y */
}
}
...
@@ -1848,7 +1759,7 @@ png_write_image_8bit(png_voidp argument)
...
@@ -1848,7 +1759,7 @@ png_write_image_8bit(png_voidp argument)
*/
*/
png_bytep
row_end
=
output_row
+
image
->
width
*
channels
;
png_bytep
row_end
=
output_row
+
image
->
width
*
channels
;
while
(
y
--
>
0
)
for
(;
y
>
0
;
--
y
)
{
{
png_const_uint_16p
in_ptr
=
input_row
;
png_const_uint_16p
in_ptr
=
input_row
;
png_bytep
out_ptr
=
output_row
;
png_bytep
out_ptr
=
output_row
;
...
@@ -1862,7 +1773,7 @@ png_write_image_8bit(png_voidp argument)
...
@@ -1862,7 +1773,7 @@ png_write_image_8bit(png_voidp argument)
}
}
png_write_row
(
png_ptr
,
output_row
);
png_write_row
(
png_ptr
,
output_row
);
input_row
+=
display
->
row_bytes
/
(
sizeof
(
png_uint_16
));
input_row
+=
(
png_uint_16
)
display
->
row_bytes
/
(
sizeof
(
png_uint_16
));
}
}
}
}
...
@@ -1872,27 +1783,28 @@ png_write_image_8bit(png_voidp argument)
...
@@ -1872,27 +1783,28 @@ png_write_image_8bit(png_voidp argument)
static
void
static
void
png_image_set_PLTE
(
png_image_write_control
*
display
)
png_image_set_PLTE
(
png_image_write_control
*
display
)
{
{
const
png_imagep
image
=
display
->
image
;
png_imagep
image
=
display
->
image
;
const
void
*
cmap
=
display
->
colormap
;
const
void
*
cmap
=
display
->
colormap
;
const
int
entries
=
image
->
colormap_entries
>
256
?
256
:
int
entries
=
image
->
colormap_entries
>
256
?
256
:
(
int
)
image
->
colormap_entries
;
(
int
)
image
->
colormap_entries
;
/* NOTE: the caller must check for cmap != NULL and entries != 0 */
/* NOTE: the caller must check for cmap != NULL and entries != 0 */
const
png_uint_32
format
=
image
->
format
;
png_uint_32
format
=
image
->
format
;
const
int
channels
=
PNG_IMAGE_SAMPLE_CHANNELS
(
format
);
unsigned
int
channels
=
PNG_IMAGE_SAMPLE_CHANNELS
(
format
);
# ifdef PNG_FORMAT_BGR_SUPPORTED
# if defined(PNG_FORMAT_BGR_SUPPORTED) &&\
const
int
afirst
=
(
format
&
PNG_FORMAT_FLAG_AFIRST
)
!=
0
&&
defined(PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED)
(
format
&
PNG_FORMAT_FLAG_ALPHA
)
!=
0
;
int
afirst
=
(
format
&
PNG_FORMAT_FLAG_AFIRST
)
!=
0
&&
# else
(
format
&
PNG_FORMAT_FLAG_ALPHA
)
!=
0
;
# else
# define afirst 0
# define afirst 0
# endif
#
endif
# ifdef PNG_FORMAT_BGR_SUPPORTED
#
ifdef PNG_FORMAT_BGR_SUPPORTED
const
int
bgr
=
(
format
&
PNG_FORMAT_FLAG_BGR
)
?
2
:
0
;
int
bgr
=
(
format
&
PNG_FORMAT_FLAG_BGR
)
!=
0
?
2
:
0
;
# else
#
else
# define bgr 0
# define bgr 0
# endif
#
endif
int
i
,
num_trans
;
int
i
,
num_trans
;
png_color
palette
[
256
];
png_color
palette
[
256
];
...
@@ -1906,22 +1818,22 @@ png_image_set_PLTE(png_image_write_control *display)
...
@@ -1906,22 +1818,22 @@ png_image_set_PLTE(png_image_write_control *display)
/* This gets automatically converted to sRGB with reversal of the
/* This gets automatically converted to sRGB with reversal of the
* pre-multiplication if the color-map has an alpha channel.
* pre-multiplication if the color-map has an alpha channel.
*/
*/
if
(
format
&
PNG_FORMAT_FLAG_LINEAR
)
if
(
(
format
&
PNG_FORMAT_FLAG_LINEAR
)
!=
0
)
{
{
png_const_uint_16p
entry
=
png_voidcast
(
png_const_uint_16p
,
cmap
);
png_const_uint_16p
entry
=
png_voidcast
(
png_const_uint_16p
,
cmap
);
entry
+=
i
*
channels
;
entry
+=
(
unsigned
int
)
i
*
channels
;
if
(
channels
&
1
)
/* no alpha */
if
(
(
channels
&
1
)
!=
0
)
/* no alpha */
{
{
if
(
channels
>=
3
)
/* RGB */
if
(
channels
>=
3
)
/* RGB */
{
{
palette
[
i
].
blue
=
(
png_byte
)
PNG_sRGB_FROM_LINEAR
(
255
*
palette
[
i
].
blue
=
(
png_byte
)
PNG_sRGB_FROM_LINEAR
(
255
*
entry
[(
2
^
bgr
)]);
entry
[(
2
^
bgr
)]);
palette
[
i
].
green
=
(
png_byte
)
PNG_sRGB_FROM_LINEAR
(
255
*
palette
[
i
].
green
=
(
png_byte
)
PNG_sRGB_FROM_LINEAR
(
255
*
entry
[
1
]);
entry
[
1
]);
palette
[
i
].
red
=
(
png_byte
)
PNG_sRGB_FROM_LINEAR
(
255
*
palette
[
i
].
red
=
(
png_byte
)
PNG_sRGB_FROM_LINEAR
(
255
*
entry
[
bgr
]);
entry
[
bgr
]);
}
}
else
/* Gray */
else
/* Gray */
...
@@ -1949,16 +1861,16 @@ png_image_set_PLTE(png_image_write_control *display)
...
@@ -1949,16 +1861,16 @@ png_image_set_PLTE(png_image_write_control *display)
if
(
channels
>=
3
)
/* RGB */
if
(
channels
>=
3
)
/* RGB */
{
{
palette
[
i
].
blue
=
png_unpremultiply
(
entry
[
afirst
+
(
2
^
bgr
)],
palette
[
i
].
blue
=
png_unpremultiply
(
entry
[
afirst
+
(
2
^
bgr
)],
alpha
,
reciprocal
);
alpha
,
reciprocal
);
palette
[
i
].
green
=
png_unpremultiply
(
entry
[
afirst
+
1
],
alpha
,
palette
[
i
].
green
=
png_unpremultiply
(
entry
[
afirst
+
1
],
alpha
,
reciprocal
);
reciprocal
);
palette
[
i
].
red
=
png_unpremultiply
(
entry
[
afirst
+
bgr
],
alpha
,
palette
[
i
].
red
=
png_unpremultiply
(
entry
[
afirst
+
bgr
],
alpha
,
reciprocal
);
reciprocal
);
}
}
else
/* gray */
else
/* gray */
palette
[
i
].
blue
=
palette
[
i
].
red
=
palette
[
i
].
green
=
palette
[
i
].
blue
=
palette
[
i
].
red
=
palette
[
i
].
green
=
png_unpremultiply
(
entry
[
afirst
],
alpha
,
reciprocal
);
png_unpremultiply
(
entry
[
afirst
],
alpha
,
reciprocal
);
}
}
}
}
...
@@ -1966,7 +1878,7 @@ png_image_set_PLTE(png_image_write_control *display)
...
@@ -1966,7 +1878,7 @@ png_image_set_PLTE(png_image_write_control *display)
{
{
png_const_bytep
entry
=
png_voidcast
(
png_const_bytep
,
cmap
);
png_const_bytep
entry
=
png_voidcast
(
png_const_bytep
,
cmap
);
entry
+=
i
*
channels
;
entry
+=
(
unsigned
int
)
i
*
channels
;
switch
(
channels
)
switch
(
channels
)
{
{
...
@@ -1974,7 +1886,7 @@ png_image_set_PLTE(png_image_write_control *display)
...
@@ -1974,7 +1886,7 @@ png_image_set_PLTE(png_image_write_control *display)
tRNS
[
i
]
=
entry
[
afirst
?
0
:
3
];
tRNS
[
i
]
=
entry
[
afirst
?
0
:
3
];
if
(
tRNS
[
i
]
<
255
)
if
(
tRNS
[
i
]
<
255
)
num_trans
=
i
+
1
;
num_trans
=
i
+
1
;
/* FALL
THROUGH */
/* FALLTHROUGH */
case
3
:
case
3
:
palette
[
i
].
blue
=
entry
[
afirst
+
(
2
^
bgr
)];
palette
[
i
].
blue
=
entry
[
afirst
+
(
2
^
bgr
)];
palette
[
i
].
green
=
entry
[
afirst
+
1
];
palette
[
i
].
green
=
entry
[
afirst
+
1
];
...
@@ -1985,7 +1897,7 @@ png_image_set_PLTE(png_image_write_control *display)
...
@@ -1985,7 +1897,7 @@ png_image_set_PLTE(png_image_write_control *display)
tRNS
[
i
]
=
entry
[
1
^
afirst
];
tRNS
[
i
]
=
entry
[
1
^
afirst
];
if
(
tRNS
[
i
]
<
255
)
if
(
tRNS
[
i
]
<
255
)
num_trans
=
i
+
1
;
num_trans
=
i
+
1
;
/* FALL
THROUGH */
/* FALLTHROUGH */
case
1
:
case
1
:
palette
[
i
].
blue
=
palette
[
i
].
red
=
palette
[
i
].
green
=
palette
[
i
].
blue
=
palette
[
i
].
red
=
palette
[
i
].
green
=
entry
[
afirst
];
entry
[
afirst
];
...
@@ -1997,73 +1909,108 @@ png_image_set_PLTE(png_image_write_control *display)
...
@@ -1997,73 +1909,108 @@ png_image_set_PLTE(png_image_write_control *display)
}
}
}
}
# ifdef afirst
#
ifdef afirst
# undef afirst
# undef afirst
# endif
#
endif
# ifdef bgr
#
ifdef bgr
# undef bgr
# undef bgr
# endif
#
endif
png_set_PLTE
(
image
->
opaque
->
png_ptr
,
image
->
opaque
->
info_ptr
,
palette
,
png_set_PLTE
(
image
->
opaque
->
png_ptr
,
image
->
opaque
->
info_ptr
,
palette
,
entries
);
entries
);
if
(
num_trans
>
0
)
if
(
num_trans
>
0
)
png_set_tRNS
(
image
->
opaque
->
png_ptr
,
image
->
opaque
->
info_ptr
,
tRNS
,
png_set_tRNS
(
image
->
opaque
->
png_ptr
,
image
->
opaque
->
info_ptr
,
tRNS
,
num_trans
,
NULL
);
num_trans
,
NULL
);
image
->
colormap_entries
=
entries
;
image
->
colormap_entries
=
(
png_uint_32
)
entries
;
}
}
static
int
static
int
png_image_write_main
(
png_voidp
argument
)
png_image_write_main
(
png_voidp
argument
)
{
{
png_image_write_control
*
display
=
png_voidcast
(
png_image_write_control
*
,
png_image_write_control
*
display
=
png_voidcast
(
png_image_write_control
*
,
argument
);
argument
);
png_imagep
image
=
display
->
image
;
png_imagep
image
=
display
->
image
;
png_structrp
png_ptr
=
image
->
opaque
->
png_ptr
;
png_structrp
png_ptr
=
image
->
opaque
->
png_ptr
;
png_inforp
info_ptr
=
image
->
opaque
->
info_ptr
;
png_inforp
info_ptr
=
image
->
opaque
->
info_ptr
;
png_uint_32
format
=
image
->
format
;
png_uint_32
format
=
image
->
format
;
int
colormap
=
(
format
&
PNG_FORMAT_FLAG_COLORMAP
)
!=
0
;
/* The following four ints are actually booleans */
int
linear
=
!
colormap
&&
(
format
&
PNG_FORMAT_FLAG_LINEAR
)
!=
0
;
/* input */
int
colormap
=
(
format
&
PNG_FORMAT_FLAG_COLORMAP
);
int
alpha
=
!
colormap
&&
(
format
&
PNG_FORMAT_FLAG_ALPHA
)
!=
0
;
int
linear
=
!
colormap
&&
(
format
&
PNG_FORMAT_FLAG_LINEAR
);
/* input */
int
write_16bit
=
linear
&&
!
colormap
&&
!
display
->
convert_to_8bit
;
int
alpha
=
!
colormap
&&
(
format
&
PNG_FORMAT_FLAG_ALPHA
);
int
write_16bit
=
linear
&&
(
display
->
convert_to_8bit
==
0
);
# ifdef PNG_BENIGN_ERRORS_SUPPORTED
#
ifdef PNG_BENIGN_ERRORS_SUPPORTED
/* Make sure we error out on any bad situation */
/* Make sure we error out on any bad situation */
png_set_benign_errors
(
png_ptr
,
0
/*error*/
);
png_set_benign_errors
(
png_ptr
,
0
/*error*/
);
# endif
#
endif
/* Default the 'row_stride' parameter if required. */
/* Default the 'row_stride' parameter if required, also check the row stride
if
(
display
->
row_stride
==
0
)
* and total image size to ensure that they are within the system limits.
display
->
row_stride
=
PNG_IMAGE_ROW_STRIDE
(
*
image
);
*/
{
unsigned
int
channels
=
PNG_IMAGE_PIXEL_CHANNELS
(
image
->
format
);
if
(
image
->
width
<=
0x7fffffffU
/
channels
)
/* no overflow */
{
png_uint_32
check
;
png_uint_32
png_row_stride
=
image
->
width
*
channels
;
if
(
display
->
row_stride
==
0
)
display
->
row_stride
=
(
png_int_32
)
/*SAFE*/
png_row_stride
;
if
(
display
->
row_stride
<
0
)
check
=
(
png_uint_32
)(
-
display
->
row_stride
);
else
check
=
(
png_uint_32
)
display
->
row_stride
;
if
(
check
>=
png_row_stride
)
{
/* Now check for overflow of the image buffer calculation; this
* limits the whole image size to 32 bits for API compatibility with
* the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro.
*/
if
(
image
->
height
>
0xffffffffU
/
png_row_stride
)
png_error
(
image
->
opaque
->
png_ptr
,
"memory image too large"
);
}
else
png_error
(
image
->
opaque
->
png_ptr
,
"supplied row stride too small"
);
}
else
png_error
(
image
->
opaque
->
png_ptr
,
"image row stride too large"
);
}
/* Set the required transforms then write the rows in the correct order. */
/* Set the required transforms then write the rows in the correct order. */
if
(
format
&
PNG_FORMAT_FLAG_COLORMAP
)
if
(
(
format
&
PNG_FORMAT_FLAG_COLORMAP
)
!=
0
)
{
{
if
(
display
->
colormap
!=
NULL
&&
image
->
colormap_entries
>
0
)
if
(
display
->
colormap
!=
NULL
&&
image
->
colormap_entries
>
0
)
{
{
png_uint_32
entries
=
image
->
colormap_entries
;
png_uint_32
entries
=
image
->
colormap_entries
;
png_set_IHDR
(
png_ptr
,
info_ptr
,
image
->
width
,
image
->
height
,
png_set_IHDR
(
png_ptr
,
info_ptr
,
image
->
width
,
image
->
height
,
entries
>
16
?
8
:
(
entries
>
4
?
4
:
(
entries
>
2
?
2
:
1
)),
entries
>
16
?
8
:
(
entries
>
4
?
4
:
(
entries
>
2
?
2
:
1
)),
PNG_COLOR_TYPE_PALETTE
,
PNG_INTERLACE_NONE
,
PNG_COLOR_TYPE_PALETTE
,
PNG_INTERLACE_NONE
,
PNG_COMPRESSION_TYPE_BASE
,
PNG_FILTER_TYPE_BASE
);
PNG_COMPRESSION_TYPE_BASE
,
PNG_FILTER_TYPE_BASE
);
png_image_set_PLTE
(
display
);
png_image_set_PLTE
(
display
);
}
}
else
else
png_error
(
image
->
opaque
->
png_ptr
,
png_error
(
image
->
opaque
->
png_ptr
,
"no color-map for color-mapped image"
);
"no color-map for color-mapped image"
);
}
}
else
else
png_set_IHDR
(
png_ptr
,
info_ptr
,
image
->
width
,
image
->
height
,
png_set_IHDR
(
png_ptr
,
info_ptr
,
image
->
width
,
image
->
height
,
write_16bit
?
16
:
8
,
write_16bit
?
16
:
8
,
((
format
&
PNG_FORMAT_FLAG_COLOR
)
?
PNG_COLOR_MASK_COLOR
:
0
)
+
((
format
&
PNG_FORMAT_FLAG_COLOR
)
?
PNG_COLOR_MASK_COLOR
:
0
)
+
((
format
&
PNG_FORMAT_FLAG_ALPHA
)
?
PNG_COLOR_MASK_ALPHA
:
0
),
((
format
&
PNG_FORMAT_FLAG_ALPHA
)
?
PNG_COLOR_MASK_ALPHA
:
0
),
PNG_INTERLACE_NONE
,
PNG_COMPRESSION_TYPE_BASE
,
PNG_FILTER_TYPE_BASE
);
PNG_INTERLACE_NONE
,
PNG_COMPRESSION_TYPE_BASE
,
PNG_FILTER_TYPE_BASE
);
/* Counter-intuitively the data transformations must be called *after*
/* Counter-intuitively the data transformations must be called *after*
* png_write_info, not before as in the read code, but the 'set' functions
* png_write_info, not before as in the read code, but the 'set' functions
...
@@ -2071,22 +2018,22 @@ png_image_write_main(png_voidp argument)
...
@@ -2071,22 +2018,22 @@ png_image_write_main(png_voidp argument)
* write an interlaced image.
* write an interlaced image.
*/
*/
if
(
write_16bit
)
if
(
write_16bit
!=
0
)
{
{
/* The gamma here is 1.0 (linear) and the cHRM chunk matches sRGB. */
/* The gamma here is 1.0 (linear) and the cHRM chunk matches sRGB. */
png_set_gAMA_fixed
(
png_ptr
,
info_ptr
,
PNG_GAMMA_LINEAR
);
png_set_gAMA_fixed
(
png_ptr
,
info_ptr
,
PNG_GAMMA_LINEAR
);
if
(
!
(
image
->
flags
&
PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB
))
if
((
image
->
flags
&
PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB
)
==
0
)
png_set_cHRM_fixed
(
png_ptr
,
info_ptr
,
png_set_cHRM_fixed
(
png_ptr
,
info_ptr
,
/* color x y */
/* color x y */
/* white */
31270
,
32900
,
/* white */
31270
,
32900
,
/* red */
64000
,
33000
,
/* red */
64000
,
33000
,
/* green */
30000
,
60000
,
/* green */
30000
,
60000
,
/* blue */
15000
,
6000
/* blue */
15000
,
6000
);
);
}
}
else
if
(
!
(
image
->
flags
&
PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB
))
else
if
((
image
->
flags
&
PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB
)
==
0
)
png_set_sRGB
(
png_ptr
,
info_ptr
,
PNG_sRGB_INTENT_PERCEPTUAL
);
png_set_sRGB
(
png_ptr
,
info_ptr
,
PNG_sRGB_INTENT_PERCEPTUAL
);
/* Else writing an 8-bit file and the *colors* aren't sRGB, but the 8-bit
/* Else writing an 8-bit file and the *colors* aren't sRGB, but the 8-bit
...
@@ -2101,38 +2048,38 @@ png_image_write_main(png_voidp argument)
...
@@ -2101,38 +2048,38 @@ png_image_write_main(png_voidp argument)
/* Now set up the data transformations (*after* the header is written),
/* Now set up the data transformations (*after* the header is written),
* remove the handled transformations from the 'format' flags for checking.
* remove the handled transformations from the 'format' flags for checking.
*
*
* First check for a little endian system if writing 16
bit files.
* First check for a little endian system if writing 16
-
bit files.
*/
*/
if
(
write_16bit
)
if
(
write_16bit
!=
0
)
{
{
PNG_CONST
png_uint_16
le
=
0x0001
;
png_uint_16
le
=
0x0001
;
if
(
*
(
png_const_bytep
)
&
le
)
if
(
(
*
(
png_const_bytep
)
&
le
)
!=
0
)
png_set_swap
(
png_ptr
);
png_set_swap
(
png_ptr
);
}
}
# ifdef PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED
#
ifdef PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED
if
(
format
&
PNG_FORMAT_FLAG_BGR
)
if
(
(
format
&
PNG_FORMAT_FLAG_BGR
)
!=
0
)
{
{
if
(
!
colormap
&&
(
format
&
PNG_FORMAT_FLAG_COLOR
)
!=
0
)
if
(
colormap
==
0
&&
(
format
&
PNG_FORMAT_FLAG_COLOR
)
!=
0
)
png_set_bgr
(
png_ptr
);
png_set_bgr
(
png_ptr
);
format
&=
~
PNG_FORMAT_FLAG_BGR
;
format
&=
~
PNG_FORMAT_FLAG_BGR
;
}
}
# endif
#
endif
# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
#
ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
if
(
format
&
PNG_FORMAT_FLAG_AFIRST
)
if
(
(
format
&
PNG_FORMAT_FLAG_AFIRST
)
!=
0
)
{
{
if
(
!
colormap
&&
(
format
&
PNG_FORMAT_FLAG_ALPHA
)
!=
0
)
if
(
colormap
==
0
&&
(
format
&
PNG_FORMAT_FLAG_ALPHA
)
!=
0
)
png_set_swap_alpha
(
png_ptr
);
png_set_swap_alpha
(
png_ptr
);
format
&=
~
PNG_FORMAT_FLAG_AFIRST
;
format
&=
~
PNG_FORMAT_FLAG_AFIRST
;
}
}
# endif
#
endif
/* If there are 16 or fewer color-map entries we wrote a lower bit depth
/* If there are 16 or fewer color-map entries we wrote a lower bit depth
* above, but the application data is still byte packed.
* above, but the application data is still byte packed.
*/
*/
if
(
colormap
&&
image
->
colormap_entries
<=
16
)
if
(
colormap
!=
0
&&
image
->
colormap_entries
<=
16
)
png_set_packing
(
png_ptr
);
png_set_packing
(
png_ptr
);
/* That should have handled all (both) the transforms. */
/* That should have handled all (both) the transforms. */
...
@@ -2144,7 +2091,7 @@ png_image_write_main(png_voidp argument)
...
@@ -2144,7 +2091,7 @@ png_image_write_main(png_voidp argument)
png_const_bytep
row
=
png_voidcast
(
png_const_bytep
,
display
->
buffer
);
png_const_bytep
row
=
png_voidcast
(
png_const_bytep
,
display
->
buffer
);
ptrdiff_t
row_bytes
=
display
->
row_stride
;
ptrdiff_t
row_bytes
=
display
->
row_stride
;
if
(
linear
)
if
(
linear
!=
0
)
row_bytes
*=
(
sizeof
(
png_uint_16
));
row_bytes
*=
(
sizeof
(
png_uint_16
));
if
(
row_bytes
<
0
)
if
(
row_bytes
<
0
)
...
@@ -2163,21 +2110,24 @@ png_image_write_main(png_voidp argument)
...
@@ -2163,21 +2110,24 @@ png_image_write_main(png_voidp argument)
* it about 50 times. The speed-up in pngstest was about 10-20% of the
* it about 50 times. The speed-up in pngstest was about 10-20% of the
* total (user) time on a heavily loaded system.
* total (user) time on a heavily loaded system.
*/
*/
# ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
png_set_compression_level
(
png_ptr
,
3
);
png_set_compression_level
(
png_ptr
,
3
);
# endif
}
}
/* Check for the cases that currently require a pre-transform on the row
/* Check for the cases that currently require a pre-transform on the row
* before it is written. This only applies when the input is 16-bit and
* before it is written. This only applies when the input is 16-bit and
* either there is an alpha channel or it is converted to 8-bit.
* either there is an alpha channel or it is converted to 8-bit.
*/
*/
if
((
linear
&&
alpha
)
||
(
!
colormap
&&
display
->
convert_to_8bit
))
if
((
linear
!=
0
&&
alpha
!=
0
)
||
(
colormap
==
0
&&
display
->
convert_to_8bit
!=
0
))
{
{
png_bytep
row
=
png_voidcast
(
png_bytep
,
png_malloc
(
png_ptr
,
png_bytep
row
=
png_voidcast
(
png_bytep
,
png_malloc
(
png_ptr
,
png_get_rowbytes
(
png_ptr
,
info_ptr
)));
png_get_rowbytes
(
png_ptr
,
info_ptr
)));
int
result
;
int
result
;
display
->
local_row
=
row
;
display
->
local_row
=
row
;
if
(
write_16bit
)
if
(
write_16bit
!=
0
)
result
=
png_safe_execute
(
image
,
png_write_image_16bit
,
display
);
result
=
png_safe_execute
(
image
,
png_write_image_16bit
,
display
);
else
else
result
=
png_safe_execute
(
image
,
png_write_image_8bit
,
display
);
result
=
png_safe_execute
(
image
,
png_write_image_8bit
,
display
);
...
@@ -2186,7 +2136,7 @@ png_image_write_main(png_voidp argument)
...
@@ -2186,7 +2136,7 @@ png_image_write_main(png_voidp argument)
png_free
(
png_ptr
,
row
);
png_free
(
png_ptr
,
row
);
/* Skip the 'write_end' on error: */
/* Skip the 'write_end' on error: */
if
(
!
result
)
if
(
result
==
0
)
return
0
;
return
0
;
}
}
...
@@ -2199,7 +2149,7 @@ png_image_write_main(png_voidp argument)
...
@@ -2199,7 +2149,7 @@ png_image_write_main(png_voidp argument)
ptrdiff_t
row_bytes
=
display
->
row_bytes
;
ptrdiff_t
row_bytes
=
display
->
row_bytes
;
png_uint_32
y
=
image
->
height
;
png_uint_32
y
=
image
->
height
;
while
(
y
--
>
0
)
for
(;
y
>
0
;
--
y
)
{
{
png_write_row
(
png_ptr
,
row
);
png_write_row
(
png_ptr
,
row
);
row
+=
row_bytes
;
row
+=
row_bytes
;
...
@@ -2210,16 +2160,131 @@ png_image_write_main(png_voidp argument)
...
@@ -2210,16 +2160,131 @@ png_image_write_main(png_voidp argument)
return
1
;
return
1
;
}
}
static
void
(
PNGCBAPI
image_memory_write
)(
png_structp
png_ptr
,
png_bytep
/*const*/
data
,
size_t
size
)
{
png_image_write_control
*
display
=
png_voidcast
(
png_image_write_control
*
,
png_ptr
->
io_ptr
/*backdoor: png_get_io_ptr(png_ptr)*/
);
png_alloc_size_t
ob
=
display
->
output_bytes
;
/* Check for overflow; this should never happen: */
if
(
size
<=
((
png_alloc_size_t
)
-
1
)
-
ob
)
{
/* I don't think libpng ever does this, but just in case: */
if
(
size
>
0
)
{
if
(
display
->
memory_bytes
>=
ob
+
size
)
/* writing */
memcpy
(
display
->
memory
+
ob
,
data
,
size
);
/* Always update the size: */
display
->
output_bytes
=
ob
+
size
;
}
}
else
png_error
(
png_ptr
,
"png_image_write_to_memory: PNG too big"
);
}
static
void
(
PNGCBAPI
image_memory_flush
)(
png_structp
png_ptr
)
{
PNG_UNUSED
(
png_ptr
)
}
static
int
png_image_write_memory
(
png_voidp
argument
)
{
png_image_write_control
*
display
=
png_voidcast
(
png_image_write_control
*
,
argument
);
/* The rest of the memory-specific init and write_main in an error protected
* environment. This case needs to use callbacks for the write operations
* since libpng has no built in support for writing to memory.
*/
png_set_write_fn
(
display
->
image
->
opaque
->
png_ptr
,
display
/*io_ptr*/
,
image_memory_write
,
image_memory_flush
);
return
png_image_write_main
(
display
);
}
int
PNGAPI
png_image_write_to_memory
(
png_imagep
image
,
void
*
memory
,
png_alloc_size_t
*
PNG_RESTRICT
memory_bytes
,
int
convert_to_8bit
,
const
void
*
buffer
,
png_int_32
row_stride
,
const
void
*
colormap
)
{
/* Write the image to the given buffer, or count the bytes if it is NULL */
if
(
image
!=
NULL
&&
image
->
version
==
PNG_IMAGE_VERSION
)
{
if
(
memory_bytes
!=
NULL
&&
buffer
!=
NULL
)
{
/* This is to give the caller an easier error detection in the NULL
* case and guard against uninitialized variable problems:
*/
if
(
memory
==
NULL
)
*
memory_bytes
=
0
;
if
(
png_image_write_init
(
image
)
!=
0
)
{
png_image_write_control
display
;
int
result
;
memset
(
&
display
,
0
,
(
sizeof
display
));
display
.
image
=
image
;
display
.
buffer
=
buffer
;
display
.
row_stride
=
row_stride
;
display
.
colormap
=
colormap
;
display
.
convert_to_8bit
=
convert_to_8bit
;
display
.
memory
=
png_voidcast
(
png_bytep
,
memory
);
display
.
memory_bytes
=
*
memory_bytes
;
display
.
output_bytes
=
0
;
result
=
png_safe_execute
(
image
,
png_image_write_memory
,
&
display
);
png_image_free
(
image
);
/* write_memory returns true even if we ran out of buffer. */
if
(
result
)
{
/* On out-of-buffer this function returns '0' but still updates
* memory_bytes:
*/
if
(
memory
!=
NULL
&&
display
.
output_bytes
>
*
memory_bytes
)
result
=
0
;
*
memory_bytes
=
display
.
output_bytes
;
}
return
result
;
}
else
return
0
;
}
else
return
png_image_error
(
image
,
"png_image_write_to_memory: invalid argument"
);
}
else
if
(
image
!=
NULL
)
return
png_image_error
(
image
,
"png_image_write_to_memory: incorrect PNG_IMAGE_VERSION"
);
else
return
0
;
}
#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
int
PNGAPI
int
PNGAPI
png_image_write_to_stdio
(
png_imagep
image
,
FILE
*
file
,
int
convert_to_8bit
,
png_image_write_to_stdio
(
png_imagep
image
,
FILE
*
file
,
int
convert_to_8bit
,
const
void
*
buffer
,
png_int_32
row_stride
,
const
void
*
colormap
)
const
void
*
buffer
,
png_int_32
row_stride
,
const
void
*
colormap
)
{
{
/* Write the image to the given (FILE*). */
/* Write the image to the given (FILE*). */
if
(
image
!=
NULL
&&
image
->
version
==
PNG_IMAGE_VERSION
)
if
(
image
!=
NULL
&&
image
->
version
==
PNG_IMAGE_VERSION
)
{
{
if
(
file
!=
NULL
)
if
(
file
!=
NULL
&&
buffer
!=
NULL
)
{
{
if
(
png_image_write_init
(
image
))
if
(
png_image_write_init
(
image
)
!=
0
)
{
{
png_image_write_control
display
;
png_image_write_control
display
;
int
result
;
int
result
;
...
@@ -2248,12 +2313,12 @@ png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit,
...
@@ -2248,12 +2313,12 @@ png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit,
else
else
return
png_image_error
(
image
,
return
png_image_error
(
image
,
"png_image_write_to_stdio: invalid argument"
);
"png_image_write_to_stdio: invalid argument"
);
}
}
else
if
(
image
!=
NULL
)
else
if
(
image
!=
NULL
)
return
png_image_error
(
image
,
return
png_image_error
(
image
,
"png_image_write_to_stdio: incorrect PNG_IMAGE_VERSION"
);
"png_image_write_to_stdio: incorrect PNG_IMAGE_VERSION"
);
else
else
return
0
;
return
0
;
...
@@ -2261,20 +2326,20 @@ png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit,
...
@@ -2261,20 +2326,20 @@ png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit,
int
PNGAPI
int
PNGAPI
png_image_write_to_file
(
png_imagep
image
,
const
char
*
file_name
,
png_image_write_to_file
(
png_imagep
image
,
const
char
*
file_name
,
int
convert_to_8bit
,
const
void
*
buffer
,
png_int_32
row_stride
,
int
convert_to_8bit
,
const
void
*
buffer
,
png_int_32
row_stride
,
const
void
*
colormap
)
const
void
*
colormap
)
{
{
/* Write the image to the named file. */
/* Write the image to the named file. */
if
(
image
!=
NULL
&&
image
->
version
==
PNG_IMAGE_VERSION
)
if
(
image
!=
NULL
&&
image
->
version
==
PNG_IMAGE_VERSION
)
{
{
if
(
file_name
!=
NULL
)
if
(
file_name
!=
NULL
&&
buffer
!=
NULL
)
{
{
FILE
*
fp
=
fopen
(
file_name
,
"wb"
);
FILE
*
fp
=
fopen
(
file_name
,
"wb"
);
if
(
fp
!=
NULL
)
if
(
fp
!=
NULL
)
{
{
if
(
png_image_write_to_stdio
(
image
,
fp
,
convert_to_8bit
,
buffer
,
if
(
png_image_write_to_stdio
(
image
,
fp
,
convert_to_8bit
,
buffer
,
row_stride
,
colormap
))
row_stride
,
colormap
)
!=
0
)
{
{
int
error
;
/* from fflush/fclose */
int
error
;
/* from fflush/fclose */
...
@@ -2315,16 +2380,16 @@ png_image_write_to_file(png_imagep image, const char *file_name,
...
@@ -2315,16 +2380,16 @@ png_image_write_to_file(png_imagep image, const char *file_name,
else
else
return
png_image_error
(
image
,
return
png_image_error
(
image
,
"png_image_write_to_file: invalid argument"
);
"png_image_write_to_file: invalid argument"
);
}
}
else
if
(
image
!=
NULL
)
else
if
(
image
!=
NULL
)
return
png_image_error
(
image
,
return
png_image_error
(
image
,
"png_image_write_to_file: incorrect PNG_IMAGE_VERSION"
);
"png_image_write_to_file: incorrect PNG_IMAGE_VERSION"
);
else
else
return
0
;
return
0
;
}
}
#endif
/*
PNG_STDIO_SUPPORTED
*/
#endif
/*
SIMPLIFIED_WRITE_STDIO
*/
#endif
/* SIMPLIFIED_WRITE */
#endif
/* SIMPLIFIED_WRITE */
#endif
/*
PNG_
WRITE
_SUPPORTED
*/
#endif
/* WRITE */
dlib/external/libpng/pngwtran.c
View file @
11101b6f
/* pngwtran.c - transforms the data in a row for PNG writers
/* pngwtran.c - transforms the data in a row for PNG writers
*
*
*
Last changed in libpng 1.6.0 [February 14, 2013]
*
Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-20
13
Glenn Randers-Pehrson
* Copyright (c) 1998-20
02,2004,2006-2016,2018
Glenn Randers-Pehrson
*
(Version 0.96
Copyright (c) 1996
,
1997 Andreas Dilger
)
* Copyright (c) 1996
-
1997 Andreas Dilger
*
(Version 0.88
Copyright (c) 1995
,
1996 Guy Eric Schalnat, Group 42, Inc.
)
* Copyright (c) 1995
-
1996 Guy Eric Schalnat, Group 42, Inc.
*
*
* This code is released under the libpng license.
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* For conditions of distribution and use, see the disclaimer
...
@@ -14,90 +14,14 @@
...
@@ -14,90 +14,14 @@
#include "pngpriv.h"
#include "pngpriv.h"
#ifdef PNG_WRITE_SUPPORTED
#ifdef PNG_WRITE_SUPPORTED
#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
/* Transform the data according to the user's wishes. The order of
* transformations is significant.
*/
void
/* PRIVATE */
png_do_write_transformations
(
png_structrp
png_ptr
,
png_row_infop
row_info
)
{
png_debug
(
1
,
"in png_do_write_transformations"
);
if
(
png_ptr
==
NULL
)
return
;
#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
if
(
png_ptr
->
transformations
&
PNG_USER_TRANSFORM
)
if
(
png_ptr
->
write_user_transform_fn
!=
NULL
)
(
*
(
png_ptr
->
write_user_transform_fn
))
/* User write transform
function */
(
png_ptr
,
/* png_ptr */
row_info
,
/* row_info: */
/* png_uint_32 width; width of row */
/* png_size_t rowbytes; number of bytes in row */
/* png_byte color_type; color type of pixels */
/* png_byte bit_depth; bit depth of samples */
/* png_byte channels; number of channels (1-4) */
/* png_byte pixel_depth; bits per pixel (depth*channels) */
png_ptr
->
row_buf
+
1
);
/* start of pixel data for row */
#endif
#ifdef PNG_WRITE_FILLER_SUPPORTED
if
(
png_ptr
->
transformations
&
PNG_FILLER
)
png_do_strip_channel
(
row_info
,
png_ptr
->
row_buf
+
1
,
!
(
png_ptr
->
flags
&
PNG_FLAG_FILLER_AFTER
));
#endif
#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
if
(
png_ptr
->
transformations
&
PNG_PACKSWAP
)
png_do_packswap
(
row_info
,
png_ptr
->
row_buf
+
1
);
#endif
#ifdef PNG_WRITE_PACK_SUPPORTED
if
(
png_ptr
->
transformations
&
PNG_PACK
)
png_do_pack
(
row_info
,
png_ptr
->
row_buf
+
1
,
(
png_uint_32
)
png_ptr
->
bit_depth
);
#endif
#ifdef PNG_WRITE_SWAP_SUPPORTED
if
(
png_ptr
->
transformations
&
PNG_SWAP_BYTES
)
png_do_swap
(
row_info
,
png_ptr
->
row_buf
+
1
);
#endif
#ifdef PNG_WRITE_SHIFT_SUPPORTED
if
(
png_ptr
->
transformations
&
PNG_SHIFT
)
png_do_shift
(
row_info
,
png_ptr
->
row_buf
+
1
,
&
(
png_ptr
->
shift
));
#endif
#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
if
(
png_ptr
->
transformations
&
PNG_SWAP_ALPHA
)
png_do_write_swap_alpha
(
row_info
,
png_ptr
->
row_buf
+
1
);
#endif
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
if
(
png_ptr
->
transformations
&
PNG_INVERT_ALPHA
)
png_do_write_invert_alpha
(
row_info
,
png_ptr
->
row_buf
+
1
);
#endif
#ifdef PNG_WRITE_BGR_SUPPORTED
if
(
png_ptr
->
transformations
&
PNG_BGR
)
png_do_bgr
(
row_info
,
png_ptr
->
row_buf
+
1
);
#endif
#ifdef PNG_WRITE_INVERT_SUPPORTED
if
(
png_ptr
->
transformations
&
PNG_INVERT_MONO
)
png_do_invert
(
row_info
,
png_ptr
->
row_buf
+
1
);
#endif
}
#ifdef PNG_WRITE_PACK_SUPPORTED
#ifdef PNG_WRITE_PACK_SUPPORTED
/* Pack pixels into bytes. Pass the true bit depth in bit_depth. The
/* Pack pixels into bytes. Pass the true bit depth in bit_depth. The
* row_info bit depth should be 8 (one pixel per byte). The channels
* row_info bit depth should be 8 (one pixel per byte). The channels
* should be 1 (this only happens on grayscale and paletted images).
* should be 1 (this only happens on grayscale and paletted images).
*/
*/
void
/* PRIVATE */
static
void
png_do_pack
(
png_row_infop
row_info
,
png_bytep
row
,
png_uint_32
bit_depth
)
png_do_pack
(
png_row_infop
row_info
,
png_bytep
row
,
png_uint_32
bit_depth
)
{
{
png_debug
(
1
,
"in png_do_pack"
);
png_debug
(
1
,
"in png_do_pack"
);
...
@@ -147,7 +71,8 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
...
@@ -147,7 +71,8 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
case
2
:
case
2
:
{
{
png_bytep
sp
,
dp
;
png_bytep
sp
,
dp
;
int
shift
,
v
;
unsigned
int
shift
;
int
v
;
png_uint_32
i
;
png_uint_32
i
;
png_uint_32
row_width
=
row_info
->
width
;
png_uint_32
row_width
=
row_info
->
width
;
...
@@ -186,7 +111,8 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
...
@@ -186,7 +111,8 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
case
4
:
case
4
:
{
{
png_bytep
sp
,
dp
;
png_bytep
sp
,
dp
;
int
shift
,
v
;
unsigned
int
shift
;
int
v
;
png_uint_32
i
;
png_uint_32
i
;
png_uint_32
row_width
=
row_info
->
width
;
png_uint_32
row_width
=
row_info
->
width
;
...
@@ -242,7 +168,7 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
...
@@ -242,7 +168,7 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
* would pass 3 as bit_depth, and this routine would translate the
* would pass 3 as bit_depth, and this routine would translate the
* data to 0 to 15.
* data to 0 to 15.
*/
*/
void
/* PRIVATE */
static
void
png_do_shift
(
png_row_infop
row_info
,
png_bytep
row
,
png_do_shift
(
png_row_infop
row_info
,
png_bytep
row
,
png_const_color_8p
bit_depth
)
png_const_color_8p
bit_depth
)
{
{
...
@@ -251,9 +177,9 @@ png_do_shift(png_row_infop row_info, png_bytep row,
...
@@ -251,9 +177,9 @@ png_do_shift(png_row_infop row_info, png_bytep row,
if
(
row_info
->
color_type
!=
PNG_COLOR_TYPE_PALETTE
)
if
(
row_info
->
color_type
!=
PNG_COLOR_TYPE_PALETTE
)
{
{
int
shift_start
[
4
],
shift_dec
[
4
];
int
shift_start
[
4
],
shift_dec
[
4
];
int
channels
=
0
;
unsigned
int
channels
=
0
;
if
(
row_info
->
color_type
&
PNG_COLOR_MASK_COLOR
)
if
(
(
row_info
->
color_type
&
PNG_COLOR_MASK_COLOR
)
!=
0
)
{
{
shift_start
[
channels
]
=
row_info
->
bit_depth
-
bit_depth
->
red
;
shift_start
[
channels
]
=
row_info
->
bit_depth
-
bit_depth
->
red
;
shift_dec
[
channels
]
=
bit_depth
->
red
;
shift_dec
[
channels
]
=
bit_depth
->
red
;
...
@@ -275,7 +201,7 @@ png_do_shift(png_row_infop row_info, png_bytep row,
...
@@ -275,7 +201,7 @@ png_do_shift(png_row_infop row_info, png_bytep row,
channels
++
;
channels
++
;
}
}
if
(
row_info
->
color_type
&
PNG_COLOR_MASK_ALPHA
)
if
(
(
row_info
->
color_type
&
PNG_COLOR_MASK_ALPHA
)
!=
0
)
{
{
shift_start
[
channels
]
=
row_info
->
bit_depth
-
bit_depth
->
alpha
;
shift_start
[
channels
]
=
row_info
->
bit_depth
-
bit_depth
->
alpha
;
shift_dec
[
channels
]
=
bit_depth
->
alpha
;
shift_dec
[
channels
]
=
bit_depth
->
alpha
;
...
@@ -286,9 +212,9 @@ png_do_shift(png_row_infop row_info, png_bytep row,
...
@@ -286,9 +212,9 @@ png_do_shift(png_row_infop row_info, png_bytep row,
if
(
row_info
->
bit_depth
<
8
)
if
(
row_info
->
bit_depth
<
8
)
{
{
png_bytep
bp
=
row
;
png_bytep
bp
=
row
;
png_
size_t
i
;
size_t
i
;
unsigned
int
mask
;
unsigned
int
mask
;
png_
size_t
row_bytes
=
row_info
->
rowbytes
;
size_t
row_bytes
=
row_info
->
rowbytes
;
if
(
bit_depth
->
gray
==
1
&&
row_info
->
bit_depth
==
2
)
if
(
bit_depth
->
gray
==
1
&&
row_info
->
bit_depth
==
2
)
mask
=
0x55
;
mask
=
0x55
;
...
@@ -328,8 +254,7 @@ png_do_shift(png_row_infop row_info, png_bytep row,
...
@@ -328,8 +254,7 @@ png_do_shift(png_row_infop row_info, png_bytep row,
for
(
i
=
0
;
i
<
istop
;
i
++
,
bp
++
)
for
(
i
=
0
;
i
<
istop
;
i
++
,
bp
++
)
{
{
unsigned
int
c
=
i
%
channels
;
const
unsigned
int
c
=
i
%
channels
;
int
j
;
int
j
;
unsigned
int
v
,
out
;
unsigned
int
v
,
out
;
...
@@ -357,7 +282,7 @@ png_do_shift(png_row_infop row_info, png_bytep row,
...
@@ -357,7 +282,7 @@ png_do_shift(png_row_infop row_info, png_bytep row,
for
(
bp
=
row
,
i
=
0
;
i
<
istop
;
i
++
)
for
(
bp
=
row
,
i
=
0
;
i
<
istop
;
i
++
)
{
{
const
unsigned
int
c
=
i
%
channels
;
unsigned
int
c
=
i
%
channels
;
int
j
;
int
j
;
unsigned
int
value
,
v
;
unsigned
int
value
,
v
;
...
@@ -381,7 +306,7 @@ png_do_shift(png_row_infop row_info, png_bytep row,
...
@@ -381,7 +306,7 @@ png_do_shift(png_row_infop row_info, png_bytep row,
#endif
#endif
#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
void
/* PRIVATE */
static
void
png_do_write_swap_alpha
(
png_row_infop
row_info
,
png_bytep
row
)
png_do_write_swap_alpha
(
png_row_infop
row_info
,
png_bytep
row
)
{
{
png_debug
(
1
,
"in png_do_write_swap_alpha"
);
png_debug
(
1
,
"in png_do_write_swap_alpha"
);
...
@@ -429,7 +354,7 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
...
@@ -429,7 +354,7 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
*
(
dp
++
)
=
save
[
1
];
*
(
dp
++
)
=
save
[
1
];
}
}
}
}
#endif
/*
PNG_
WRITE_16BIT
_SUPPORTED
*/
#endif
/* WRITE_16BIT */
}
}
else
if
(
row_info
->
color_type
==
PNG_COLOR_TYPE_GRAY_ALPHA
)
else
if
(
row_info
->
color_type
==
PNG_COLOR_TYPE_GRAY_ALPHA
)
...
@@ -468,14 +393,14 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
...
@@ -468,14 +393,14 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
*
(
dp
++
)
=
save
[
1
];
*
(
dp
++
)
=
save
[
1
];
}
}
}
}
#endif
/*
PNG_
WRITE_16BIT
_SUPPORTED
*/
#endif
/* WRITE_16BIT */
}
}
}
}
}
}
#endif
#endif
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
void
/* PRIVATE */
static
void
png_do_write_invert_alpha
(
png_row_infop
row_info
,
png_bytep
row
)
png_do_write_invert_alpha
(
png_row_infop
row_info
,
png_bytep
row
)
{
{
png_debug
(
1
,
"in png_do_write_invert_alpha"
);
png_debug
(
1
,
"in png_do_write_invert_alpha"
);
...
@@ -498,7 +423,7 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
...
@@ -498,7 +423,7 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
*(dp++) = *(sp++);
*(dp++) = *(sp++);
*/
*/
sp
+=
3
;
dp
=
sp
;
sp
+=
3
;
dp
=
sp
;
*
(
dp
++
)
=
(
png_byte
)(
255
-
*
(
sp
++
));
*
dp
=
(
png_byte
)(
255
-
*
(
sp
++
));
}
}
}
}
...
@@ -522,10 +447,10 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
...
@@ -522,10 +447,10 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
*/
*/
sp
+=
6
;
dp
=
sp
;
sp
+=
6
;
dp
=
sp
;
*
(
dp
++
)
=
(
png_byte
)(
255
-
*
(
sp
++
));
*
(
dp
++
)
=
(
png_byte
)(
255
-
*
(
sp
++
));
*
(
dp
++
)
=
(
png_byte
)(
255
-
*
(
sp
++
));
*
dp
=
(
png_byte
)(
255
-
*
(
sp
++
));
}
}
}
}
#endif
/*
PNG_
WRITE_16BIT
_SUPPORTED
*/
#endif
/* WRITE_16BIT */
}
}
else
if
(
row_info
->
color_type
==
PNG_COLOR_TYPE_GRAY_ALPHA
)
else
if
(
row_info
->
color_type
==
PNG_COLOR_TYPE_GRAY_ALPHA
)
...
@@ -560,78 +485,91 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
...
@@ -560,78 +485,91 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
*/
*/
sp
+=
2
;
dp
=
sp
;
sp
+=
2
;
dp
=
sp
;
*
(
dp
++
)
=
(
png_byte
)(
255
-
*
(
sp
++
));
*
(
dp
++
)
=
(
png_byte
)(
255
-
*
(
sp
++
));
*
(
dp
++
)
=
(
png_byte
)(
255
-
*
(
sp
++
));
*
dp
=
(
png_byte
)(
255
-
*
(
sp
++
));
}
}
}
}
#endif
/*
PNG_
WRITE_16BIT
_SUPPORTED
*/
#endif
/* WRITE_16BIT */
}
}
}
}
}
}
#endif
#endif
#endif
/* PNG_WRITE_TRANSFORMS_SUPPORTED */
#ifdef PNG_MNG_FEATURES_SUPPORTED
/* Transform the data according to the user's wishes. The order of
/* Undoes intrapixel differencing */
* transformations is significant.
*/
void
/* PRIVATE */
void
/* PRIVATE */
png_do_write_
in
tra
pixel
(
png_row_infop
row_info
,
png_bytep
row
)
png_do_write_tra
nsformations
(
png_structrp
png_ptr
,
png_row_infop
row_info
)
{
{
png_debug
(
1
,
"in png_do_write_
intrapixel
"
);
png_debug
(
1
,
"in png_do_write_
transformations
"
);
if
((
row_info
->
color_type
&
PNG_COLOR_MASK_COLOR
))
if
(
png_ptr
==
NULL
)
{
return
;
int
bytes_per_pixel
;
png_uint_32
row_width
=
row_info
->
width
;
if
(
row_info
->
bit_depth
==
8
)
{
png_bytep
rp
;
png_uint_32
i
;
if
(
row_info
->
color_type
==
PNG_COLOR_TYPE_RGB
)
#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
bytes_per_pixel
=
3
;
if
((
png_ptr
->
transformations
&
PNG_USER_TRANSFORM
)
!=
0
)
if
(
png_ptr
->
write_user_transform_fn
!=
NULL
)
(
*
(
png_ptr
->
write_user_transform_fn
))
/* User write transform
function */
(
png_ptr
,
/* png_ptr */
row_info
,
/* row_info: */
/* png_uint_32 width; width of row */
/* size_t rowbytes; number of bytes in row */
/* png_byte color_type; color type of pixels */
/* png_byte bit_depth; bit depth of samples */
/* png_byte channels; number of channels (1-4) */
/* png_byte pixel_depth; bits per pixel (depth*channels) */
png_ptr
->
row_buf
+
1
);
/* start of pixel data for row */
#endif
else
if
(
row_info
->
color_type
==
PNG_COLOR_TYPE_RGB_ALPHA
)
#ifdef PNG_WRITE_FILLER_SUPPORTED
bytes_per_pixel
=
4
;
if
((
png_ptr
->
transformations
&
PNG_FILLER
)
!=
0
)
png_do_strip_channel
(
row_info
,
png_ptr
->
row_buf
+
1
,
!
(
png_ptr
->
flags
&
PNG_FLAG_FILLER_AFTER
));
#endif
else
#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
return
;
if
((
png_ptr
->
transformations
&
PNG_PACKSWAP
)
!=
0
)
png_do_packswap
(
row_info
,
png_ptr
->
row_buf
+
1
);
#endif
for
(
i
=
0
,
rp
=
row
;
i
<
row_width
;
i
++
,
rp
+=
bytes_per_pixel
)
#ifdef PNG_WRITE_PACK_SUPPORTED
{
if
((
png_ptr
->
transformations
&
PNG_PACK
)
!=
0
)
*
(
rp
)
=
(
png_byte
)((
*
rp
-
*
(
rp
+
1
))
&
0xff
);
png_do_pack
(
row_info
,
png_ptr
->
row_buf
+
1
,
*
(
rp
+
2
)
=
(
png_byte
)((
*
(
rp
+
2
)
-
*
(
rp
+
1
))
&
0xff
);
(
png_uint_32
)
png_ptr
->
bit_depth
);
}
#endif
}
#ifdef PNG_WRITE_16BIT_SUPPORTED
#ifdef PNG_WRITE_SWAP_SUPPORTED
else
if
(
row_info
->
bit_depth
==
16
)
# ifdef PNG_16BIT_SUPPORTED
{
if
((
png_ptr
->
transformations
&
PNG_SWAP_BYTES
)
!=
0
)
png_bytep
rp
;
png_do_swap
(
row_info
,
png_ptr
->
row_buf
+
1
);
png_uint_32
i
;
# endif
#endif
if
(
row_info
->
color_type
==
PNG_COLOR_TYPE_RGB
)
#ifdef PNG_WRITE_SHIFT_SUPPORTED
bytes_per_pixel
=
6
;
if
((
png_ptr
->
transformations
&
PNG_SHIFT
)
!=
0
)
png_do_shift
(
row_info
,
png_ptr
->
row_buf
+
1
,
&
(
png_ptr
->
shift
));
#endif
else
if
(
row_info
->
color_type
==
PNG_COLOR_TYPE_RGB_ALPHA
)
#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
bytes_per_pixel
=
8
;
if
((
png_ptr
->
transformations
&
PNG_SWAP_ALPHA
)
!=
0
)
png_do_write_swap_alpha
(
row_info
,
png_ptr
->
row_buf
+
1
);
#endif
else
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
return
;
if
((
png_ptr
->
transformations
&
PNG_INVERT_ALPHA
)
!=
0
)
png_do_write_invert_alpha
(
row_info
,
png_ptr
->
row_buf
+
1
);
#endif
for
(
i
=
0
,
rp
=
row
;
i
<
row_width
;
i
++
,
rp
+=
bytes_per_pixel
)
#ifdef PNG_WRITE_BGR_SUPPORTED
{
if
((
png_ptr
->
transformations
&
PNG_BGR
)
!=
0
)
png_uint_32
s0
=
(
*
(
rp
)
<<
8
)
|
*
(
rp
+
1
);
png_do_bgr
(
row_info
,
png_ptr
->
row_buf
+
1
);
png_uint_32
s1
=
(
*
(
rp
+
2
)
<<
8
)
|
*
(
rp
+
3
);
#endif
png_uint_32
s2
=
(
*
(
rp
+
4
)
<<
8
)
|
*
(
rp
+
5
);
png_uint_32
red
=
(
png_uint_32
)((
s0
-
s1
)
&
0xffffL
);
#ifdef PNG_WRITE_INVERT_SUPPORTED
png_uint_32
blue
=
(
png_uint_32
)((
s2
-
s1
)
&
0xffffL
);
if
((
png_ptr
->
transformations
&
PNG_INVERT_MONO
)
!=
0
)
*
(
rp
)
=
(
png_byte
)((
red
>>
8
)
&
0xff
);
png_do_invert
(
row_info
,
png_ptr
->
row_buf
+
1
);
*
(
rp
+
1
)
=
(
png_byte
)(
red
&
0xff
);
#endif
*
(
rp
+
4
)
=
(
png_byte
)((
blue
>>
8
)
&
0xff
);
*
(
rp
+
5
)
=
(
png_byte
)(
blue
&
0xff
);
}
}
#endif
/* PNG_WRITE_16BIT_SUPPORTED */
}
}
}
#endif
/*
PNG_MNG_FEATURES_SUPPORTED
*/
#endif
/*
WRITE_TRANSFORMS
*/
#endif
/*
PNG_
WRITE
_SUPPORTED
*/
#endif
/* WRITE */
dlib/external/libpng/pngwutil.c
View file @
11101b6f
/* pngwutil.c - utilities to write a PNG file
/* pngwutil.c - utilities to write a PNG file
*
*
*
Last changed in libpng 1.6.2 [April 25, 2013]
*
Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-20
13
Glenn Randers-Pehrson
* Copyright (c) 1998-20
02,2004,2006-2018
Glenn Randers-Pehrson
*
(Version 0.96
Copyright (c) 1996
,
1997 Andreas Dilger
)
* Copyright (c) 1996
-
1997 Andreas Dilger
*
(Version 0.88
Copyright (c) 1995
,
1996 Guy Eric Schalnat, Group 42, Inc.
)
* Copyright (c) 1995
-
1996 Guy Eric Schalnat, Group 42, Inc.
*
*
* This code is released under the libpng license.
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* For conditions of distribution and use, see the disclaimer
...
@@ -23,10 +23,10 @@
...
@@ -23,10 +23,10 @@
void
PNGAPI
void
PNGAPI
png_save_uint_32
(
png_bytep
buf
,
png_uint_32
i
)
png_save_uint_32
(
png_bytep
buf
,
png_uint_32
i
)
{
{
buf
[
0
]
=
(
png_byte
)((
i
>>
24
)
&
0xff
);
buf
[
0
]
=
(
png_byte
)((
i
>>
24
)
&
0xff
U
);
buf
[
1
]
=
(
png_byte
)((
i
>>
16
)
&
0xff
);
buf
[
1
]
=
(
png_byte
)((
i
>>
16
)
&
0xff
U
);
buf
[
2
]
=
(
png_byte
)((
i
>>
8
)
&
0xff
);
buf
[
2
]
=
(
png_byte
)((
i
>>
8
)
&
0xff
U
);
buf
[
3
]
=
(
png_byte
)(
i
&
0xff
);
buf
[
3
]
=
(
png_byte
)(
i
&
0xff
U
);
}
}
/* Place a 16-bit number into a buffer in PNG byte order.
/* Place a 16-bit number into a buffer in PNG byte order.
...
@@ -36,8 +36,8 @@ png_save_uint_32(png_bytep buf, png_uint_32 i)
...
@@ -36,8 +36,8 @@ png_save_uint_32(png_bytep buf, png_uint_32 i)
void
PNGAPI
void
PNGAPI
png_save_uint_16
(
png_bytep
buf
,
unsigned
int
i
)
png_save_uint_16
(
png_bytep
buf
,
unsigned
int
i
)
{
{
buf
[
0
]
=
(
png_byte
)((
i
>>
8
)
&
0xff
);
buf
[
0
]
=
(
png_byte
)((
i
>>
8
)
&
0xff
U
);
buf
[
1
]
=
(
png_byte
)(
i
&
0xff
);
buf
[
1
]
=
(
png_byte
)(
i
&
0xff
U
);
}
}
#endif
#endif
...
@@ -59,7 +59,7 @@ png_write_sig(png_structrp png_ptr)
...
@@ -59,7 +59,7 @@ png_write_sig(png_structrp png_ptr)
/* Write the rest of the 8 byte signature */
/* Write the rest of the 8 byte signature */
png_write_data
(
png_ptr
,
&
png_signature
[
png_ptr
->
sig_bytes
],
png_write_data
(
png_ptr
,
&
png_signature
[
png_ptr
->
sig_bytes
],
(
png_
size_t
)(
8
-
png_ptr
->
sig_bytes
));
(
size_t
)(
8
-
png_ptr
->
sig_bytes
));
if
(
png_ptr
->
sig_bytes
<
3
)
if
(
png_ptr
->
sig_bytes
<
3
)
png_ptr
->
mode
|=
PNG_HAVE_PNG_SIGNATURE
;
png_ptr
->
mode
|=
PNG_HAVE_PNG_SIGNATURE
;
...
@@ -124,8 +124,7 @@ png_write_chunk_start(png_structrp png_ptr, png_const_bytep chunk_string,
...
@@ -124,8 +124,7 @@ png_write_chunk_start(png_structrp png_ptr, png_const_bytep chunk_string,
* given to png_write_chunk_header().
* given to png_write_chunk_header().
*/
*/
void
PNGAPI
void
PNGAPI
png_write_chunk_data
(
png_structrp
png_ptr
,
png_const_bytep
data
,
png_write_chunk_data
(
png_structrp
png_ptr
,
png_const_bytep
data
,
size_t
length
)
png_size_t
length
)
{
{
/* Write the data, and run the CRC over it */
/* Write the data, and run the CRC over it */
if
(
png_ptr
==
NULL
)
if
(
png_ptr
==
NULL
)
...
@@ -136,7 +135,7 @@ png_write_chunk_data(png_structrp png_ptr, png_const_bytep data,
...
@@ -136,7 +135,7 @@ png_write_chunk_data(png_structrp png_ptr, png_const_bytep data,
png_write_data
(
png_ptr
,
data
,
length
);
png_write_data
(
png_ptr
,
data
,
length
);
/* Update the CRC after writing the data,
/* Update the CRC after writing the data,
* in case
that
the user I/O routine alters it.
* in case the user I/O routine alters it.
*/
*/
png_calculate_crc
(
png_ptr
,
data
,
length
);
png_calculate_crc
(
png_ptr
,
data
,
length
);
}
}
...
@@ -160,7 +159,7 @@ png_write_chunk_end(png_structrp png_ptr)
...
@@ -160,7 +159,7 @@ png_write_chunk_end(png_structrp png_ptr)
/* Write the crc in a single operation */
/* Write the crc in a single operation */
png_save_uint_32
(
buf
,
png_ptr
->
crc
);
png_save_uint_32
(
buf
,
png_ptr
->
crc
);
png_write_data
(
png_ptr
,
buf
,
(
png_size_t
)
4
);
png_write_data
(
png_ptr
,
buf
,
4
);
}
}
/* Write a PNG chunk all at once. The type is an array of ASCII characters
/* Write a PNG chunk all at once. The type is an array of ASCII characters
...
@@ -174,14 +173,14 @@ png_write_chunk_end(png_structrp png_ptr)
...
@@ -174,14 +173,14 @@ png_write_chunk_end(png_structrp png_ptr)
*/
*/
static
void
static
void
png_write_complete_chunk
(
png_structrp
png_ptr
,
png_uint_32
chunk_name
,
png_write_complete_chunk
(
png_structrp
png_ptr
,
png_uint_32
chunk_name
,
png_const_bytep
data
,
png_
size_t
length
)
png_const_bytep
data
,
size_t
length
)
{
{
if
(
png_ptr
==
NULL
)
if
(
png_ptr
==
NULL
)
return
;
return
;
/* On 64
bit architectures 'length' may not fit in a png_uint_32. */
/* On 64
-
bit architectures 'length' may not fit in a png_uint_32. */
if
(
length
>
PNG_UINT_31_MAX
)
if
(
length
>
PNG_UINT_31_MAX
)
png_error
(
png_ptr
,
"length exceeds PNG maxim
a
"
);
png_error
(
png_ptr
,
"length exceeds PNG maxim
um
"
);
png_write_chunk_header
(
png_ptr
,
chunk_name
,
(
png_uint_32
)
length
);
png_write_chunk_header
(
png_ptr
,
chunk_name
,
(
png_uint_32
)
length
);
png_write_chunk_data
(
png_ptr
,
data
,
length
);
png_write_chunk_data
(
png_ptr
,
data
,
length
);
...
@@ -191,10 +190,10 @@ png_write_complete_chunk(png_structrp png_ptr, png_uint_32 chunk_name,
...
@@ -191,10 +190,10 @@ png_write_complete_chunk(png_structrp png_ptr, png_uint_32 chunk_name,
/* This is the API that calls the internal function above. */
/* This is the API that calls the internal function above. */
void
PNGAPI
void
PNGAPI
png_write_chunk
(
png_structrp
png_ptr
,
png_const_bytep
chunk_string
,
png_write_chunk
(
png_structrp
png_ptr
,
png_const_bytep
chunk_string
,
png_const_bytep
data
,
png_
size_t
length
)
png_const_bytep
data
,
size_t
length
)
{
{
png_write_complete_chunk
(
png_ptr
,
PNG_CHUNK_FROM_STRING
(
chunk_string
),
data
,
png_write_complete_chunk
(
png_ptr
,
PNG_CHUNK_FROM_STRING
(
chunk_string
),
data
,
length
);
length
);
}
}
/* This is used below to find the size of an image to pass to png_deflate_claim,
/* This is used below to find the size of an image to pass to png_deflate_claim,
...
@@ -204,14 +203,14 @@ png_write_chunk(png_structrp png_ptr, png_const_bytep chunk_string,
...
@@ -204,14 +203,14 @@ png_write_chunk(png_structrp png_ptr, png_const_bytep chunk_string,
static
png_alloc_size_t
static
png_alloc_size_t
png_image_size
(
png_structrp
png_ptr
)
png_image_size
(
png_structrp
png_ptr
)
{
{
/* Only return sizes up to the maximum of a png_uint_32
,
do this by limiting
/* Only return sizes up to the maximum of a png_uint_32
;
do this by limiting
* the width and height used to 15 bits.
* the width and height used to 15 bits.
*/
*/
png_uint_32
h
=
png_ptr
->
height
;
png_uint_32
h
=
png_ptr
->
height
;
if
(
png_ptr
->
rowbytes
<
32768
&&
h
<
32768
)
if
(
png_ptr
->
rowbytes
<
32768
&&
h
<
32768
)
{
{
if
(
png_ptr
->
interlaced
)
if
(
png_ptr
->
interlaced
!=
0
)
{
{
/* Interlacing makes the image larger because of the replication of
/* Interlacing makes the image larger because of the replication of
* both the filter byte and the padding to a byte boundary.
* both the filter byte and the padding to a byte boundary.
...
@@ -286,17 +285,16 @@ optimize_cmf(png_bytep data, png_alloc_size_t data_size)
...
@@ -286,17 +285,16 @@ optimize_cmf(png_bytep data, png_alloc_size_t data_size)
}
}
}
}
}
}
#else
#endif
/* WRITE_OPTIMIZE_CMF */
# define optimize_cmf(dp,dl) ((void)0)
#endif
/* PNG_WRITE_OPTIMIZE_CMF_SUPPORTED */
/* Initialize the compressor for the appropriate type of compression. */
/* Initialize the compressor for the appropriate type of compression. */
static
int
static
int
png_deflate_claim
(
png_structrp
png_ptr
,
png_uint_32
owner
,
png_deflate_claim
(
png_structrp
png_ptr
,
png_uint_32
owner
,
png_alloc_size_t
data_size
)
png_alloc_size_t
data_size
)
{
{
if
(
png_ptr
->
zowner
!=
0
)
if
(
png_ptr
->
zowner
!=
0
)
{
{
#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_ERROR_TEXT_SUPPORTED)
char
msg
[
64
];
char
msg
[
64
];
PNG_STRING_FROM_CHUNK
(
msg
,
owner
);
PNG_STRING_FROM_CHUNK
(
msg
,
owner
);
...
@@ -308,7 +306,8 @@ png_deflate_claim(png_structrp png_ptr, png_uint_32 owner,
...
@@ -308,7 +306,8 @@ png_deflate_claim(png_structrp png_ptr, png_uint_32 owner,
* are minimal.
* are minimal.
*/
*/
(
void
)
png_safecat
(
msg
,
(
sizeof
msg
),
10
,
" using zstream"
);
(
void
)
png_safecat
(
msg
,
(
sizeof
msg
),
10
,
" using zstream"
);
# if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC
#endif
#if PNG_RELEASE_BUILD
png_warning
(
png_ptr
,
msg
);
png_warning
(
png_ptr
,
msg
);
/* Attempt sane error recovery */
/* Attempt sane error recovery */
...
@@ -319,9 +318,9 @@ png_deflate_claim(png_structrp png_ptr, png_uint_32 owner,
...
@@ -319,9 +318,9 @@ png_deflate_claim(png_structrp png_ptr, png_uint_32 owner,
}
}
png_ptr
->
zowner
=
0
;
png_ptr
->
zowner
=
0
;
#
else
#else
png_error
(
png_ptr
,
msg
);
png_error
(
png_ptr
,
msg
);
#
endif
#endif
}
}
{
{
...
@@ -334,7 +333,7 @@ png_deflate_claim(png_structrp png_ptr, png_uint_32 owner,
...
@@ -334,7 +333,7 @@ png_deflate_claim(png_structrp png_ptr, png_uint_32 owner,
if
(
owner
==
png_IDAT
)
if
(
owner
==
png_IDAT
)
{
{
if
(
png_ptr
->
flags
&
PNG_FLAG_ZLIB_CUSTOM_STRATEGY
)
if
(
(
png_ptr
->
flags
&
PNG_FLAG_ZLIB_CUSTOM_STRATEGY
)
!=
0
)
strategy
=
png_ptr
->
zlib_strategy
;
strategy
=
png_ptr
->
zlib_strategy
;
else
if
(
png_ptr
->
do_filter
!=
PNG_FILTER_NONE
)
else
if
(
png_ptr
->
do_filter
!=
PNG_FILTER_NONE
)
...
@@ -346,20 +345,20 @@ png_deflate_claim(png_structrp png_ptr, png_uint_32 owner,
...
@@ -346,20 +345,20 @@ png_deflate_claim(png_structrp png_ptr, png_uint_32 owner,
else
else
{
{
#
ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
level
=
png_ptr
->
zlib_text_level
;
level
=
png_ptr
->
zlib_text_level
;
method
=
png_ptr
->
zlib_text_method
;
method
=
png_ptr
->
zlib_text_method
;
windowBits
=
png_ptr
->
zlib_text_window_bits
;
windowBits
=
png_ptr
->
zlib_text_window_bits
;
memLevel
=
png_ptr
->
zlib_text_mem_level
;
memLevel
=
png_ptr
->
zlib_text_mem_level
;
strategy
=
png_ptr
->
zlib_text_strategy
;
strategy
=
png_ptr
->
zlib_text_strategy
;
#
else
#else
/* If customization is not supported the values all come from the
/* If customization is not supported the values all come from the
* IDAT values except for the strategy, which is fixed to the
* IDAT values except for the strategy, which is fixed to the
* default. (This is the pre-1.6.0 behavior too, although it was
* default. (This is the pre-1.6.0 behavior too, although it was
* implemented in a very different way.)
* implemented in a very different way.)
*/
*/
strategy
=
Z_DEFAULT_STRATEGY
;
strategy
=
Z_DEFAULT_STRATEGY
;
#
endif
#endif
}
}
/* Adjust 'windowBits' down if larger than 'data_size'; to stop this
/* Adjust 'windowBits' down if larger than 'data_size'; to stop this
...
@@ -386,7 +385,7 @@ png_deflate_claim(png_structrp png_ptr, png_uint_32 owner,
...
@@ -386,7 +385,7 @@ png_deflate_claim(png_structrp png_ptr, png_uint_32 owner,
}
}
/* Check against the previous initialized values, if any. */
/* Check against the previous initialized values, if any. */
if
((
png_ptr
->
flags
&
PNG_FLAG_ZSTREAM_INITIALIZED
)
&&
if
((
png_ptr
->
flags
&
PNG_FLAG_ZSTREAM_INITIALIZED
)
!=
0
&&
(
png_ptr
->
zlib_set_level
!=
level
||
(
png_ptr
->
zlib_set_level
!=
level
||
png_ptr
->
zlib_set_method
!=
method
||
png_ptr
->
zlib_set_method
!=
method
||
png_ptr
->
zlib_set_window_bits
!=
windowBits
||
png_ptr
->
zlib_set_window_bits
!=
windowBits
||
...
@@ -408,15 +407,15 @@ png_deflate_claim(png_structrp png_ptr, png_uint_32 owner,
...
@@ -408,15 +407,15 @@ png_deflate_claim(png_structrp png_ptr, png_uint_32 owner,
png_ptr
->
zstream
.
avail_out
=
0
;
png_ptr
->
zstream
.
avail_out
=
0
;
/* Now initialize if required, setting the new parameters, otherwise just
/* Now initialize if required, setting the new parameters, otherwise just
*
t
o a simple reset to the previous parameters.
*
d
o a simple reset to the previous parameters.
*/
*/
if
(
png_ptr
->
flags
&
PNG_FLAG_ZSTREAM_INITIALIZED
)
if
(
(
png_ptr
->
flags
&
PNG_FLAG_ZSTREAM_INITIALIZED
)
!=
0
)
ret
=
deflateReset
(
&
png_ptr
->
zstream
);
ret
=
deflateReset
(
&
png_ptr
->
zstream
);
else
else
{
{
ret
=
deflateInit2
(
&
png_ptr
->
zstream
,
level
,
method
,
windowBits
,
ret
=
deflateInit2
(
&
png_ptr
->
zstream
,
level
,
method
,
windowBits
,
memLevel
,
strategy
);
memLevel
,
strategy
);
if
(
ret
==
Z_OK
)
if
(
ret
==
Z_OK
)
png_ptr
->
flags
|=
PNG_FLAG_ZSTREAM_INITIALIZED
;
png_ptr
->
flags
|=
PNG_FLAG_ZSTREAM_INITIALIZED
;
...
@@ -477,7 +476,7 @@ typedef struct
...
@@ -477,7 +476,7 @@ typedef struct
static
void
static
void
png_text_compress_init
(
compression_state
*
comp
,
png_const_bytep
input
,
png_text_compress_init
(
compression_state
*
comp
,
png_const_bytep
input
,
png_alloc_size_t
input_len
)
png_alloc_size_t
input_len
)
{
{
comp
->
input
=
input
;
comp
->
input
=
input
;
comp
->
input_len
=
input_len
;
comp
->
input_len
=
input_len
;
...
@@ -487,12 +486,12 @@ png_text_compress_init(compression_state *comp, png_const_bytep input,
...
@@ -487,12 +486,12 @@ png_text_compress_init(compression_state *comp, png_const_bytep input,
/* Compress the data in the compression state input */
/* Compress the data in the compression state input */
static
int
static
int
png_text_compress
(
png_structrp
png_ptr
,
png_uint_32
chunk_name
,
png_text_compress
(
png_structrp
png_ptr
,
png_uint_32
chunk_name
,
compression_state
*
comp
,
png_uint_32
prefix_len
)
compression_state
*
comp
,
png_uint_32
prefix_len
)
{
{
int
ret
;
int
ret
;
/* To find the length of the output it is necessary to first compress the
/* To find the length of the output it is necessary to first compress the
* input
, t
he result is buffered rather than using the two-pass algorithm
* input
. T
he result is buffered rather than using the two-pass algorithm
* that is used on the inflate side; deflate is assumed to be slower and a
* that is used on the inflate side; deflate is assumed to be slower and a
* PNG writer is assumed to have more memory available than a PNG reader.
* PNG writer is assumed to have more memory available than a PNG reader.
*
*
...
@@ -579,7 +578,7 @@ png_text_compress(png_structrp png_ptr, png_uint_32 chunk_name,
...
@@ -579,7 +578,7 @@ png_text_compress(png_structrp png_ptr, png_uint_32 chunk_name,
/* Compress the data */
/* Compress the data */
ret
=
deflate
(
&
png_ptr
->
zstream
,
ret
=
deflate
(
&
png_ptr
->
zstream
,
input_len
>
0
?
Z_NO_FLUSH
:
Z_FINISH
);
input_len
>
0
?
Z_NO_FLUSH
:
Z_FINISH
);
/* Claw back input data that was not consumed (because avail_in is
/* Claw back input data that was not consumed (because avail_in is
* reset above every time round the loop).
* reset above every time round the loop).
...
@@ -589,7 +588,7 @@ png_text_compress(png_structrp png_ptr, png_uint_32 chunk_name,
...
@@ -589,7 +588,7 @@ png_text_compress(png_structrp png_ptr, png_uint_32 chunk_name,
}
}
while
(
ret
==
Z_OK
);
while
(
ret
==
Z_OK
);
/* There may be some space left in the last output buffer
, t
his needs to
/* There may be some space left in the last output buffer
. T
his needs to
* be subtracted from output_len.
* be subtracted from output_len.
*/
*/
output_len
-=
png_ptr
->
zstream
.
avail_out
;
output_len
-=
png_ptr
->
zstream
.
avail_out
;
...
@@ -612,14 +611,15 @@ png_text_compress(png_structrp png_ptr, png_uint_32 chunk_name,
...
@@ -612,14 +611,15 @@ png_text_compress(png_structrp png_ptr, png_uint_32 chunk_name,
/* Reset zlib for another zTXt/iTXt or image data */
/* Reset zlib for another zTXt/iTXt or image data */
png_ptr
->
zowner
=
0
;
png_ptr
->
zowner
=
0
;
/* The only success case is Z_STREAM_END, input_len must be 0
,
if not this
/* The only success case is Z_STREAM_END, input_len must be 0
;
if not this
* is an internal error.
* is an internal error.
*/
*/
if
(
ret
==
Z_STREAM_END
&&
input_len
==
0
)
if
(
ret
==
Z_STREAM_END
&&
input_len
==
0
)
{
{
#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
/* Fix up the deflate header, if required */
/* Fix up the deflate header, if required */
optimize_cmf
(
comp
->
output
,
comp
->
input_len
);
optimize_cmf
(
comp
->
output
,
comp
->
input_len
);
#endif
/* But Z_OK is returned, not Z_STREAM_END; this allows the claim
/* But Z_OK is returned, not Z_STREAM_END; this allows the claim
* function above to return Z_STREAM_END on an error (though it never
* function above to return Z_STREAM_END on an error (though it never
* does in the current versions of zlib.)
* does in the current versions of zlib.)
...
@@ -662,89 +662,7 @@ png_write_compressed_data_out(png_structrp png_ptr, compression_state *comp)
...
@@ -662,89 +662,7 @@ png_write_compressed_data_out(png_structrp png_ptr, compression_state *comp)
if
(
output_len
>
0
)
if
(
output_len
>
0
)
png_error
(
png_ptr
,
"error writing ancillary chunked compressed data"
);
png_error
(
png_ptr
,
"error writing ancillary chunked compressed data"
);
}
}
#endif
/* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */
#endif
/* WRITE_COMPRESSED_TEXT */
#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \
defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
* and if invalid, correct the keyword rather than discarding the entire
* chunk. The PNG 1.0 specification requires keywords 1-79 characters in
* length, forbids leading or trailing whitespace, multiple internal spaces,
* and the non-break space (0x80) from ISO 8859-1. Returns keyword length.
*
* The 'new_key' buffer must be 80 characters in size (for the keyword plus a
* trailing '\0'). If this routine returns 0 then there was no keyword, or a
* valid one could not be generated, and the caller must png_error.
*/
static
png_uint_32
png_check_keyword
(
png_structrp
png_ptr
,
png_const_charp
key
,
png_bytep
new_key
)
{
png_const_charp
orig_key
=
key
;
png_uint_32
key_len
=
0
;
int
bad_character
=
0
;
int
space
=
1
;
png_debug
(
1
,
"in png_check_keyword"
);
if
(
key
==
NULL
)
{
*
new_key
=
0
;
return
0
;
}
while
(
*
key
&&
key_len
<
79
)
{
png_byte
ch
=
(
png_byte
)(
0xff
&
*
key
++
);
if
((
ch
>
32
&&
ch
<=
126
)
||
(
ch
>=
161
/*&& ch <= 255*/
))
*
new_key
++
=
ch
,
++
key_len
,
space
=
0
;
else
if
(
!
space
)
{
/* A space or an invalid character when one wasn't seen immediately
* before; output just a space.
*/
*
new_key
++
=
32
,
++
key_len
,
space
=
1
;
/* If the character was not a space then it is invalid. */
if
(
ch
!=
32
)
bad_character
=
ch
;
}
else
if
(
!
bad_character
)
bad_character
=
ch
;
/* just skip it, record the first error */
}
if
(
key_len
>
0
&&
space
)
/* trailing space */
{
--
key_len
,
--
new_key
;
if
(
!
bad_character
)
bad_character
=
32
;
}
/* Terminate the keyword */
*
new_key
=
0
;
if
(
key_len
==
0
)
return
0
;
/* Try to only output one warning per keyword: */
if
(
*
key
)
/* keyword too long */
png_warning
(
png_ptr
,
"keyword truncated"
);
else
if
(
bad_character
)
{
PNG_WARNING_PARAMETERS
(
p
)
png_warning_parameter
(
p
,
1
,
orig_key
);
png_warning_parameter_signed
(
p
,
2
,
PNG_NUMBER_FORMAT_02x
,
bad_character
);
png_formatted_warning
(
png_ptr
,
p
,
"keyword
\"
@1
\"
: bad character '0x@2'"
);
}
return
key_len
;
}
#endif
/* Write the IHDR chunk, and update the png_struct with the necessary
/* Write the IHDR chunk, and update the png_struct with the necessary
* information. Note that the rest of this code depends upon this
* information. Note that the rest of this code depends upon this
...
@@ -756,6 +674,7 @@ png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height,
...
@@ -756,6 +674,7 @@ png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height,
int
interlace_type
)
int
interlace_type
)
{
{
png_byte
buf
[
13
];
/* Buffer to store the IHDR info */
png_byte
buf
[
13
];
/* Buffer to store the IHDR info */
int
is_invalid_depth
;
png_debug
(
1
,
"in png_write_IHDR"
);
png_debug
(
1
,
"in png_write_IHDR"
);
...
@@ -781,11 +700,11 @@ png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height,
...
@@ -781,11 +700,11 @@ png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height,
break
;
break
;
case
PNG_COLOR_TYPE_RGB
:
case
PNG_COLOR_TYPE_RGB
:
is_invalid_depth
=
(
bit_depth
!=
8
);
#ifdef PNG_WRITE_16BIT_SUPPORTED
#ifdef PNG_WRITE_16BIT_SUPPORTED
if
(
bit_depth
!=
8
&&
bit_depth
!=
16
)
is_invalid_depth
=
(
is_invalid_depth
&&
bit_depth
!=
16
);
#else
if
(
bit_depth
!=
8
)
#endif
#endif
if
(
is_invalid_depth
)
png_error
(
png_ptr
,
"Invalid bit depth for RGB image"
);
png_error
(
png_ptr
,
"Invalid bit depth for RGB image"
);
png_ptr
->
channels
=
3
;
png_ptr
->
channels
=
3
;
...
@@ -807,18 +726,22 @@ png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height,
...
@@ -807,18 +726,22 @@ png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height,
break
;
break
;
case
PNG_COLOR_TYPE_GRAY_ALPHA
:
case
PNG_COLOR_TYPE_GRAY_ALPHA
:
if
(
bit_depth
!=
8
&&
bit_depth
!=
16
)
is_invalid_depth
=
(
bit_depth
!=
8
);
#ifdef PNG_WRITE_16BIT_SUPPORTED
is_invalid_depth
=
(
is_invalid_depth
&&
bit_depth
!=
16
);
#endif
if
(
is_invalid_depth
)
png_error
(
png_ptr
,
"Invalid bit depth for grayscale+alpha image"
);
png_error
(
png_ptr
,
"Invalid bit depth for grayscale+alpha image"
);
png_ptr
->
channels
=
2
;
png_ptr
->
channels
=
2
;
break
;
break
;
case
PNG_COLOR_TYPE_RGB_ALPHA
:
case
PNG_COLOR_TYPE_RGB_ALPHA
:
is_invalid_depth
=
(
bit_depth
!=
8
);
#ifdef PNG_WRITE_16BIT_SUPPORTED
#ifdef PNG_WRITE_16BIT_SUPPORTED
if
(
bit_depth
!=
8
&&
bit_depth
!=
16
)
is_invalid_depth
=
(
is_invalid_depth
&&
bit_depth
!=
16
);
#else
if
(
bit_depth
!=
8
)
#endif
#endif
if
(
is_invalid_depth
)
png_error
(
png_ptr
,
"Invalid bit depth for RGBA image"
);
png_error
(
png_ptr
,
"Invalid bit depth for RGBA image"
);
png_ptr
->
channels
=
4
;
png_ptr
->
channels
=
4
;
...
@@ -845,8 +768,8 @@ png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height,
...
@@ -845,8 +768,8 @@ png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height,
*/
*/
if
(
if
(
#ifdef PNG_MNG_FEATURES_SUPPORTED
#ifdef PNG_MNG_FEATURES_SUPPORTED
!
((
png_ptr
->
mng_features_permitted
&
PNG_FLAG_MNG_FILTER_64
)
&&
!
((
png_ptr
->
mng_features_permitted
&
PNG_FLAG_MNG_FILTER_64
)
!=
0
&&
((
png_ptr
->
mode
&
PNG_HAVE_PNG_SIGNATURE
)
==
0
)
&&
((
png_ptr
->
mode
&
PNG_HAVE_PNG_SIGNATURE
)
==
0
)
&&
(
color_type
==
PNG_COLOR_TYPE_RGB
||
(
color_type
==
PNG_COLOR_TYPE_RGB
||
color_type
==
PNG_COLOR_TYPE_RGB_ALPHA
)
&&
color_type
==
PNG_COLOR_TYPE_RGB_ALPHA
)
&&
(
filter_type
==
PNG_INTRAPIXEL_DIFFERENCING
))
&&
(
filter_type
==
PNG_INTRAPIXEL_DIFFERENCING
))
&&
...
@@ -896,9 +819,9 @@ png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height,
...
@@ -896,9 +819,9 @@ png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height,
buf
[
12
]
=
(
png_byte
)
interlace_type
;
buf
[
12
]
=
(
png_byte
)
interlace_type
;
/* Write the chunk */
/* Write the chunk */
png_write_complete_chunk
(
png_ptr
,
png_IHDR
,
buf
,
(
png_size_t
)
13
);
png_write_complete_chunk
(
png_ptr
,
png_IHDR
,
buf
,
13
);
if
(
!
(
png_ptr
->
do_filter
))
if
((
png_ptr
->
do_filter
)
==
PNG_NO_FILTERS
)
{
{
if
(
png_ptr
->
color_type
==
PNG_COLOR_TYPE_PALETTE
||
if
(
png_ptr
->
color_type
==
PNG_COLOR_TYPE_PALETTE
||
png_ptr
->
bit_depth
<
8
)
png_ptr
->
bit_depth
<
8
)
...
@@ -919,17 +842,20 @@ void /* PRIVATE */
...
@@ -919,17 +842,20 @@ void /* PRIVATE */
png_write_PLTE
(
png_structrp
png_ptr
,
png_const_colorp
palette
,
png_write_PLTE
(
png_structrp
png_ptr
,
png_const_colorp
palette
,
png_uint_32
num_pal
)
png_uint_32
num_pal
)
{
{
png_uint_32
i
;
png_uint_32
max_palette_length
,
i
;
png_const_colorp
pal_ptr
;
png_const_colorp
pal_ptr
;
png_byte
buf
[
3
];
png_byte
buf
[
3
];
png_debug
(
1
,
"in png_write_PLTE"
);
png_debug
(
1
,
"in png_write_PLTE"
);
max_palette_length
=
(
png_ptr
->
color_type
==
PNG_COLOR_TYPE_PALETTE
)
?
(
1
<<
png_ptr
->
bit_depth
)
:
PNG_MAX_PALETTE_LENGTH
;
if
((
if
((
#ifdef PNG_MNG_FEATURES_SUPPORTED
#ifdef PNG_MNG_FEATURES_SUPPORTED
!
(
png_ptr
->
mng_features_permitted
&
PNG_FLAG_MNG_EMPTY_PLTE
)
&&
(
png_ptr
->
mng_features_permitted
&
PNG_FLAG_MNG_EMPTY_PLTE
)
==
0
&&
#endif
#endif
num_pal
==
0
)
||
num_pal
>
256
)
num_pal
==
0
)
||
num_pal
>
max_palette_length
)
{
{
if
(
png_ptr
->
color_type
==
PNG_COLOR_TYPE_PALETTE
)
if
(
png_ptr
->
color_type
==
PNG_COLOR_TYPE_PALETTE
)
{
{
...
@@ -943,7 +869,7 @@ png_write_PLTE(png_structrp png_ptr, png_const_colorp palette,
...
@@ -943,7 +869,7 @@ png_write_PLTE(png_structrp png_ptr, png_const_colorp palette,
}
}
}
}
if
(
!
(
png_ptr
->
color_type
&
PNG_COLOR_MASK_COLOR
))
if
((
png_ptr
->
color_type
&
PNG_COLOR_MASK_COLOR
)
==
0
)
{
{
png_warning
(
png_ptr
,
png_warning
(
png_ptr
,
"Ignoring request to write a PLTE chunk in grayscale PNG"
);
"Ignoring request to write a PLTE chunk in grayscale PNG"
);
...
@@ -962,7 +888,7 @@ png_write_PLTE(png_structrp png_ptr, png_const_colorp palette,
...
@@ -962,7 +888,7 @@ png_write_PLTE(png_structrp png_ptr, png_const_colorp palette,
buf
[
0
]
=
pal_ptr
->
red
;
buf
[
0
]
=
pal_ptr
->
red
;
buf
[
1
]
=
pal_ptr
->
green
;
buf
[
1
]
=
pal_ptr
->
green
;
buf
[
2
]
=
pal_ptr
->
blue
;
buf
[
2
]
=
pal_ptr
->
blue
;
png_write_chunk_data
(
png_ptr
,
buf
,
(
png_size_t
)
3
);
png_write_chunk_data
(
png_ptr
,
buf
,
3
);
}
}
#else
#else
...
@@ -976,7 +902,7 @@ png_write_PLTE(png_structrp png_ptr, png_const_colorp palette,
...
@@ -976,7 +902,7 @@ png_write_PLTE(png_structrp png_ptr, png_const_colorp palette,
buf
[
0
]
=
pal_ptr
[
i
].
red
;
buf
[
0
]
=
pal_ptr
[
i
].
red
;
buf
[
1
]
=
pal_ptr
[
i
].
green
;
buf
[
1
]
=
pal_ptr
[
i
].
green
;
buf
[
2
]
=
pal_ptr
[
i
].
blue
;
buf
[
2
]
=
pal_ptr
[
i
].
blue
;
png_write_chunk_data
(
png_ptr
,
buf
,
(
png_size_t
)
3
);
png_write_chunk_data
(
png_ptr
,
buf
,
3
);
}
}
#endif
#endif
...
@@ -998,12 +924,12 @@ png_write_PLTE(png_structrp png_ptr, png_const_colorp palette,
...
@@ -998,12 +924,12 @@ png_write_PLTE(png_structrp png_ptr, png_const_colorp palette,
* Z_FINISH: this is the end of the input, do a Z_FINISH and clean up
* Z_FINISH: this is the end of the input, do a Z_FINISH and clean up
*
*
* The routine manages the acquire and release of the png_ptr->zstream by
* The routine manages the acquire and release of the png_ptr->zstream by
* checking and (at the end) clearing png_ptr->zowner
,
it does some sanity
* checking and (at the end) clearing png_ptr->zowner
;
it does some sanity
* checks on the 'mode' flags while doing this.
* checks on the 'mode' flags while doing this.
*/
*/
void
/* PRIVATE */
void
/* PRIVATE */
png_compress_IDAT
(
png_structrp
png_ptr
,
png_const_bytep
input
,
png_compress_IDAT
(
png_structrp
png_ptr
,
png_const_bytep
input
,
png_alloc_size_t
input_len
,
int
flush
)
png_alloc_size_t
input_len
,
int
flush
)
{
{
if
(
png_ptr
->
zowner
!=
png_IDAT
)
if
(
png_ptr
->
zowner
!=
png_IDAT
)
{
{
...
@@ -1015,7 +941,7 @@ png_compress_IDAT(png_structrp png_ptr, png_const_bytep input,
...
@@ -1015,7 +941,7 @@ png_compress_IDAT(png_structrp png_ptr, png_const_bytep input,
if
(
png_ptr
->
zbuffer_list
==
NULL
)
if
(
png_ptr
->
zbuffer_list
==
NULL
)
{
{
png_ptr
->
zbuffer_list
=
png_voidcast
(
png_compression_bufferp
,
png_ptr
->
zbuffer_list
=
png_voidcast
(
png_compression_bufferp
,
png_malloc
(
png_ptr
,
PNG_COMPRESSION_BUFFER_SIZE
(
png_ptr
)));
png_malloc
(
png_ptr
,
PNG_COMPRESSION_BUFFER_SIZE
(
png_ptr
)));
png_ptr
->
zbuffer_list
->
next
=
NULL
;
png_ptr
->
zbuffer_list
->
next
=
NULL
;
}
}
...
@@ -1058,7 +984,7 @@ png_compress_IDAT(png_structrp png_ptr, png_const_bytep input,
...
@@ -1058,7 +984,7 @@ png_compress_IDAT(png_structrp png_ptr, png_const_bytep input,
input_len
+=
png_ptr
->
zstream
.
avail_in
;
input_len
+=
png_ptr
->
zstream
.
avail_in
;
png_ptr
->
zstream
.
avail_in
=
0
;
png_ptr
->
zstream
.
avail_in
=
0
;
/* OUTPUT: write complete IDAT chunks when avail_out drops to zero
, n
ote
/* OUTPUT: write complete IDAT chunks when avail_out drops to zero
. N
ote
* that these two zstream fields are preserved across the calls, therefore
* that these two zstream fields are preserved across the calls, therefore
* there is no need to set these up on entry to the loop.
* there is no need to set these up on entry to the loop.
*/
*/
...
@@ -1070,13 +996,14 @@ png_compress_IDAT(png_structrp png_ptr, png_const_bytep input,
...
@@ -1070,13 +996,14 @@ png_compress_IDAT(png_structrp png_ptr, png_const_bytep input,
/* Write an IDAT containing the data then reset the buffer. The
/* Write an IDAT containing the data then reset the buffer. The
* first IDAT may need deflate header optimization.
* first IDAT may need deflate header optimization.
*/
*/
#
ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
if
(
!
(
png_ptr
->
mode
&
PNG_HAVE_IDAT
)
&&
if
((
png_ptr
->
mode
&
PNG_HAVE_IDAT
)
==
0
&&
png_ptr
->
compression_type
==
PNG_COMPRESSION_TYPE_BASE
)
png_ptr
->
compression_type
==
PNG_COMPRESSION_TYPE_BASE
)
optimize_cmf
(
data
,
png_image_size
(
png_ptr
));
optimize_cmf
(
data
,
png_image_size
(
png_ptr
));
#
endif
#endif
png_write_complete_chunk
(
png_ptr
,
png_IDAT
,
data
,
size
);
if
(
size
>
0
)
png_write_complete_chunk
(
png_ptr
,
png_IDAT
,
data
,
size
);
png_ptr
->
mode
|=
PNG_HAVE_IDAT
;
png_ptr
->
mode
|=
PNG_HAVE_IDAT
;
png_ptr
->
zstream
.
next_out
=
data
;
png_ptr
->
zstream
.
next_out
=
data
;
...
@@ -1090,7 +1017,7 @@ png_compress_IDAT(png_structrp png_ptr, png_const_bytep input,
...
@@ -1090,7 +1017,7 @@ png_compress_IDAT(png_structrp png_ptr, png_const_bytep input,
continue
;
continue
;
}
}
/* The order of these checks doesn't matter much; it just
e
ffect which
/* The order of these checks doesn't matter much; it just
a
ffect
s
which
* possible error might be detected if multiple things go wrong at once.
* possible error might be detected if multiple things go wrong at once.
*/
*/
if
(
ret
==
Z_OK
)
/* most likely return code! */
if
(
ret
==
Z_OK
)
/* most likely return code! */
...
@@ -1116,13 +1043,14 @@ png_compress_IDAT(png_structrp png_ptr, png_const_bytep input,
...
@@ -1116,13 +1043,14 @@ png_compress_IDAT(png_structrp png_ptr, png_const_bytep input,
png_bytep
data
=
png_ptr
->
zbuffer_list
->
output
;
png_bytep
data
=
png_ptr
->
zbuffer_list
->
output
;
uInt
size
=
png_ptr
->
zbuffer_size
-
png_ptr
->
zstream
.
avail_out
;
uInt
size
=
png_ptr
->
zbuffer_size
-
png_ptr
->
zstream
.
avail_out
;
#
ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
if
(
!
(
png_ptr
->
mode
&
PNG_HAVE_IDAT
)
&&
if
((
png_ptr
->
mode
&
PNG_HAVE_IDAT
)
==
0
&&
png_ptr
->
compression_type
==
PNG_COMPRESSION_TYPE_BASE
)
png_ptr
->
compression_type
==
PNG_COMPRESSION_TYPE_BASE
)
optimize_cmf
(
data
,
png_image_size
(
png_ptr
));
optimize_cmf
(
data
,
png_image_size
(
png_ptr
));
#
endif
#endif
png_write_complete_chunk
(
png_ptr
,
png_IDAT
,
data
,
size
);
if
(
size
>
0
)
png_write_complete_chunk
(
png_ptr
,
png_IDAT
,
data
,
size
);
png_ptr
->
zstream
.
avail_out
=
0
;
png_ptr
->
zstream
.
avail_out
=
0
;
png_ptr
->
zstream
.
next_out
=
NULL
;
png_ptr
->
zstream
.
next_out
=
NULL
;
png_ptr
->
mode
|=
PNG_HAVE_IDAT
|
PNG_AFTER_IDAT
;
png_ptr
->
mode
|=
PNG_HAVE_IDAT
|
PNG_AFTER_IDAT
;
...
@@ -1146,7 +1074,7 @@ png_write_IEND(png_structrp png_ptr)
...
@@ -1146,7 +1074,7 @@ png_write_IEND(png_structrp png_ptr)
{
{
png_debug
(
1
,
"in png_write_IEND"
);
png_debug
(
1
,
"in png_write_IEND"
);
png_write_complete_chunk
(
png_ptr
,
png_IEND
,
NULL
,
(
png_size_t
)
0
);
png_write_complete_chunk
(
png_ptr
,
png_IEND
,
NULL
,
0
);
png_ptr
->
mode
|=
PNG_HAVE_IEND
;
png_ptr
->
mode
|=
PNG_HAVE_IEND
;
}
}
...
@@ -1161,7 +1089,7 @@ png_write_gAMA_fixed(png_structrp png_ptr, png_fixed_point file_gamma)
...
@@ -1161,7 +1089,7 @@ png_write_gAMA_fixed(png_structrp png_ptr, png_fixed_point file_gamma)
/* file_gamma is saved in 1/100,000ths */
/* file_gamma is saved in 1/100,000ths */
png_save_uint_32
(
buf
,
(
png_uint_32
)
file_gamma
);
png_save_uint_32
(
buf
,
(
png_uint_32
)
file_gamma
);
png_write_complete_chunk
(
png_ptr
,
png_gAMA
,
buf
,
(
png_size_t
)
4
);
png_write_complete_chunk
(
png_ptr
,
png_gAMA
,
buf
,
4
);
}
}
#endif
#endif
...
@@ -1179,7 +1107,7 @@ png_write_sRGB(png_structrp png_ptr, int srgb_intent)
...
@@ -1179,7 +1107,7 @@ png_write_sRGB(png_structrp png_ptr, int srgb_intent)
"Invalid sRGB rendering intent specified"
);
"Invalid sRGB rendering intent specified"
);
buf
[
0
]
=
(
png_byte
)
srgb_intent
;
buf
[
0
]
=
(
png_byte
)
srgb_intent
;
png_write_complete_chunk
(
png_ptr
,
png_sRGB
,
buf
,
(
png_size_t
)
1
);
png_write_complete_chunk
(
png_ptr
,
png_sRGB
,
buf
,
1
);
}
}
#endif
#endif
...
@@ -1193,6 +1121,7 @@ png_write_iCCP(png_structrp png_ptr, png_const_charp name,
...
@@ -1193,6 +1121,7 @@ png_write_iCCP(png_structrp png_ptr, png_const_charp name,
png_uint_32
profile_len
;
png_uint_32
profile_len
;
png_byte
new_name
[
81
];
/* 1 byte for the compression byte */
png_byte
new_name
[
81
];
/* 1 byte for the compression byte */
compression_state
comp
;
compression_state
comp
;
png_uint_32
temp
;
png_debug
(
1
,
"in png_write_iCCP"
);
png_debug
(
1
,
"in png_write_iCCP"
);
...
@@ -1207,7 +1136,8 @@ png_write_iCCP(png_structrp png_ptr, png_const_charp name,
...
@@ -1207,7 +1136,8 @@ png_write_iCCP(png_structrp png_ptr, png_const_charp name,
if
(
profile_len
<
132
)
if
(
profile_len
<
132
)
png_error
(
png_ptr
,
"ICC profile too short"
);
png_error
(
png_ptr
,
"ICC profile too short"
);
if
(
profile_len
&
0x03
)
temp
=
(
png_uint_32
)
(
*
(
profile
+
8
));
if
(
temp
>
3
&&
(
profile_len
&
0x03
))
png_error
(
png_ptr
,
"ICC profile length invalid (not a multiple of 4)"
);
png_error
(
png_ptr
,
"ICC profile length invalid (not a multiple of 4)"
);
{
{
...
@@ -1251,8 +1181,8 @@ png_write_sPLT(png_structrp png_ptr, png_const_sPLT_tp spalette)
...
@@ -1251,8 +1181,8 @@ png_write_sPLT(png_structrp png_ptr, png_const_sPLT_tp spalette)
png_uint_32
name_len
;
png_uint_32
name_len
;
png_byte
new_name
[
80
];
png_byte
new_name
[
80
];
png_byte
entrybuf
[
10
];
png_byte
entrybuf
[
10
];
png_
size_t
entry_size
=
(
spalette
->
depth
==
8
?
6
:
10
);
size_t
entry_size
=
(
spalette
->
depth
==
8
?
6
:
10
);
png_
size_t
palette_size
=
entry_size
*
spalette
->
nentries
;
size_t
palette_size
=
entry_size
*
(
size_t
)
spalette
->
nentries
;
png_sPLT_entryp
ep
;
png_sPLT_entryp
ep
;
#ifndef PNG_POINTER_INDEXING_SUPPORTED
#ifndef PNG_POINTER_INDEXING_SUPPORTED
int
i
;
int
i
;
...
@@ -1269,10 +1199,9 @@ png_write_sPLT(png_structrp png_ptr, png_const_sPLT_tp spalette)
...
@@ -1269,10 +1199,9 @@ png_write_sPLT(png_structrp png_ptr, png_const_sPLT_tp spalette)
png_write_chunk_header
(
png_ptr
,
png_sPLT
,
png_write_chunk_header
(
png_ptr
,
png_sPLT
,
(
png_uint_32
)(
name_len
+
2
+
palette_size
));
(
png_uint_32
)(
name_len
+
2
+
palette_size
));
png_write_chunk_data
(
png_ptr
,
(
png_bytep
)
new_name
,
png_write_chunk_data
(
png_ptr
,
(
png_bytep
)
new_name
,
(
size_t
)(
name_len
+
1
));
(
png_size_t
)(
name_len
+
1
));
png_write_chunk_data
(
png_ptr
,
&
spalette
->
depth
,
(
png_size_t
)
1
);
png_write_chunk_data
(
png_ptr
,
&
spalette
->
depth
,
1
);
/* Loop through each palette entry, writing appropriately */
/* Loop through each palette entry, writing appropriately */
#ifdef PNG_POINTER_INDEXING_SUPPORTED
#ifdef PNG_POINTER_INDEXING_SUPPORTED
...
@@ -1334,12 +1263,12 @@ void /* PRIVATE */
...
@@ -1334,12 +1263,12 @@ void /* PRIVATE */
png_write_sBIT
(
png_structrp
png_ptr
,
png_const_color_8p
sbit
,
int
color_type
)
png_write_sBIT
(
png_structrp
png_ptr
,
png_const_color_8p
sbit
,
int
color_type
)
{
{
png_byte
buf
[
4
];
png_byte
buf
[
4
];
png_
size_t
size
;
size_t
size
;
png_debug
(
1
,
"in png_write_sBIT"
);
png_debug
(
1
,
"in png_write_sBIT"
);
/* Make sure we don't depend upon the order of PNG_COLOR_8 */
/* Make sure we don't depend upon the order of PNG_COLOR_8 */
if
(
color_type
&
PNG_COLOR_MASK_COLOR
)
if
(
(
color_type
&
PNG_COLOR_MASK_COLOR
)
!=
0
)
{
{
png_byte
maxbits
;
png_byte
maxbits
;
...
@@ -1372,7 +1301,7 @@ png_write_sBIT(png_structrp png_ptr, png_const_color_8p sbit, int color_type)
...
@@ -1372,7 +1301,7 @@ png_write_sBIT(png_structrp png_ptr, png_const_color_8p sbit, int color_type)
size
=
1
;
size
=
1
;
}
}
if
(
color_type
&
PNG_COLOR_MASK_ALPHA
)
if
(
(
color_type
&
PNG_COLOR_MASK_ALPHA
)
!=
0
)
{
{
if
(
sbit
->
alpha
==
0
||
sbit
->
alpha
>
png_ptr
->
usr_bit_depth
)
if
(
sbit
->
alpha
==
0
||
sbit
->
alpha
>
png_ptr
->
usr_bit_depth
)
{
{
...
@@ -1434,12 +1363,12 @@ png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha,
...
@@ -1434,12 +1363,12 @@ png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha,
/* Write the chunk out as it is */
/* Write the chunk out as it is */
png_write_complete_chunk
(
png_ptr
,
png_tRNS
,
trans_alpha
,
png_write_complete_chunk
(
png_ptr
,
png_tRNS
,
trans_alpha
,
(
png_
size_t
)
num_trans
);
(
size_t
)
num_trans
);
}
}
else
if
(
color_type
==
PNG_COLOR_TYPE_GRAY
)
else
if
(
color_type
==
PNG_COLOR_TYPE_GRAY
)
{
{
/* One 16
bit value */
/* One 16
-
bit value */
if
(
tran
->
gray
>=
(
1
<<
png_ptr
->
bit_depth
))
if
(
tran
->
gray
>=
(
1
<<
png_ptr
->
bit_depth
))
{
{
png_app_warning
(
png_ptr
,
png_app_warning
(
png_ptr
,
...
@@ -1449,27 +1378,27 @@ png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha,
...
@@ -1449,27 +1378,27 @@ png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha,
}
}
png_save_uint_16
(
buf
,
tran
->
gray
);
png_save_uint_16
(
buf
,
tran
->
gray
);
png_write_complete_chunk
(
png_ptr
,
png_tRNS
,
buf
,
(
png_size_t
)
2
);
png_write_complete_chunk
(
png_ptr
,
png_tRNS
,
buf
,
2
);
}
}
else
if
(
color_type
==
PNG_COLOR_TYPE_RGB
)
else
if
(
color_type
==
PNG_COLOR_TYPE_RGB
)
{
{
/* Three 16
bit values */
/* Three 16
-
bit values */
png_save_uint_16
(
buf
,
tran
->
red
);
png_save_uint_16
(
buf
,
tran
->
red
);
png_save_uint_16
(
buf
+
2
,
tran
->
green
);
png_save_uint_16
(
buf
+
2
,
tran
->
green
);
png_save_uint_16
(
buf
+
4
,
tran
->
blue
);
png_save_uint_16
(
buf
+
4
,
tran
->
blue
);
#ifdef PNG_WRITE_16BIT_SUPPORTED
#ifdef PNG_WRITE_16BIT_SUPPORTED
if
(
png_ptr
->
bit_depth
==
8
&&
(
buf
[
0
]
|
buf
[
2
]
|
buf
[
4
]))
if
(
png_ptr
->
bit_depth
==
8
&&
(
buf
[
0
]
|
buf
[
2
]
|
buf
[
4
])
!=
0
)
#else
#else
if
(
buf
[
0
]
|
buf
[
2
]
|
buf
[
4
])
if
(
(
buf
[
0
]
|
buf
[
2
]
|
buf
[
4
])
!=
0
)
#endif
#endif
{
{
png_app_warning
(
png_ptr
,
png_app_warning
(
png_ptr
,
"Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8"
);
"Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8"
);
return
;
return
;
}
}
png_write_complete_chunk
(
png_ptr
,
png_tRNS
,
buf
,
(
png_size_t
)
6
);
png_write_complete_chunk
(
png_ptr
,
png_tRNS
,
buf
,
6
);
}
}
else
else
...
@@ -1492,8 +1421,8 @@ png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type)
...
@@ -1492,8 +1421,8 @@ png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type)
{
{
if
(
if
(
#ifdef PNG_MNG_FEATURES_SUPPORTED
#ifdef PNG_MNG_FEATURES_SUPPORTED
(
png_ptr
->
num_palette
||
(
png_ptr
->
num_palette
!=
0
||
(
!
(
png_ptr
->
mng_features_permitted
&
PNG_FLAG_MNG_EMPTY_PLTE
)
)
)
&&
(
png_ptr
->
mng_features_permitted
&
PNG_FLAG_MNG_EMPTY_PLTE
)
==
0
)
&&
#endif
#endif
back
->
index
>=
png_ptr
->
num_palette
)
back
->
index
>=
png_ptr
->
num_palette
)
{
{
...
@@ -1502,27 +1431,28 @@ png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type)
...
@@ -1502,27 +1431,28 @@ png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type)
}
}
buf
[
0
]
=
back
->
index
;
buf
[
0
]
=
back
->
index
;
png_write_complete_chunk
(
png_ptr
,
png_bKGD
,
buf
,
(
png_size_t
)
1
);
png_write_complete_chunk
(
png_ptr
,
png_bKGD
,
buf
,
1
);
}
}
else
if
(
color_type
&
PNG_COLOR_MASK_COLOR
)
else
if
(
(
color_type
&
PNG_COLOR_MASK_COLOR
)
!=
0
)
{
{
png_save_uint_16
(
buf
,
back
->
red
);
png_save_uint_16
(
buf
,
back
->
red
);
png_save_uint_16
(
buf
+
2
,
back
->
green
);
png_save_uint_16
(
buf
+
2
,
back
->
green
);
png_save_uint_16
(
buf
+
4
,
back
->
blue
);
png_save_uint_16
(
buf
+
4
,
back
->
blue
);
#ifdef PNG_WRITE_16BIT_SUPPORTED
#ifdef PNG_WRITE_16BIT_SUPPORTED
if
(
png_ptr
->
bit_depth
==
8
&&
(
buf
[
0
]
|
buf
[
2
]
|
buf
[
4
]))
if
(
png_ptr
->
bit_depth
==
8
&&
(
buf
[
0
]
|
buf
[
2
]
|
buf
[
4
])
!=
0
)
#else
#else
if
(
buf
[
0
]
|
buf
[
2
]
|
buf
[
4
])
if
(
(
buf
[
0
]
|
buf
[
2
]
|
buf
[
4
])
!=
0
)
#endif
#endif
{
{
png_warning
(
png_ptr
,
png_warning
(
png_ptr
,
"Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8"
);
"Ignoring attempt to write 16-bit bKGD chunk "
"when bit_depth is 8"
);
return
;
return
;
}
}
png_write_complete_chunk
(
png_ptr
,
png_bKGD
,
buf
,
(
png_size_t
)
6
);
png_write_complete_chunk
(
png_ptr
,
png_bKGD
,
buf
,
6
);
}
}
else
else
...
@@ -1536,8 +1466,30 @@ png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type)
...
@@ -1536,8 +1466,30 @@ png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type)
}
}
png_save_uint_16
(
buf
,
back
->
gray
);
png_save_uint_16
(
buf
,
back
->
gray
);
png_write_complete_chunk
(
png_ptr
,
png_bKGD
,
buf
,
(
png_size_t
)
2
);
png_write_complete_chunk
(
png_ptr
,
png_bKGD
,
buf
,
2
);
}
}
#endif
#ifdef PNG_WRITE_eXIf_SUPPORTED
/* Write the Exif data */
void
/* PRIVATE */
png_write_eXIf
(
png_structrp
png_ptr
,
png_bytep
exif
,
int
num_exif
)
{
int
i
;
png_byte
buf
[
1
];
png_debug
(
1
,
"in png_write_eXIf"
);
png_write_chunk_header
(
png_ptr
,
png_eXIf
,
(
png_uint_32
)(
num_exif
));
for
(
i
=
0
;
i
<
num_exif
;
i
++
)
{
buf
[
0
]
=
exif
[
i
];
png_write_chunk_data
(
png_ptr
,
buf
,
1
);
}
}
png_write_chunk_end
(
png_ptr
);
}
}
#endif
#endif
...
@@ -1565,7 +1517,7 @@ png_write_hIST(png_structrp png_ptr, png_const_uint_16p hist, int num_hist)
...
@@ -1565,7 +1517,7 @@ png_write_hIST(png_structrp png_ptr, png_const_uint_16p hist, int num_hist)
for
(
i
=
0
;
i
<
num_hist
;
i
++
)
for
(
i
=
0
;
i
<
num_hist
;
i
++
)
{
{
png_save_uint_16
(
buf
,
hist
[
i
]);
png_save_uint_16
(
buf
,
hist
[
i
]);
png_write_chunk_data
(
png_ptr
,
buf
,
(
png_size_t
)
2
);
png_write_chunk_data
(
png_ptr
,
buf
,
2
);
}
}
png_write_chunk_end
(
png_ptr
);
png_write_chunk_end
(
png_ptr
);
...
@@ -1576,7 +1528,7 @@ png_write_hIST(png_structrp png_ptr, png_const_uint_16p hist, int num_hist)
...
@@ -1576,7 +1528,7 @@ png_write_hIST(png_structrp png_ptr, png_const_uint_16p hist, int num_hist)
/* Write a tEXt chunk */
/* Write a tEXt chunk */
void
/* PRIVATE */
void
/* PRIVATE */
png_write_tEXt
(
png_structrp
png_ptr
,
png_const_charp
key
,
png_const_charp
text
,
png_write_tEXt
(
png_structrp
png_ptr
,
png_const_charp
key
,
png_const_charp
text
,
png_
size_t
text_len
)
size_t
text_len
)
{
{
png_uint_32
key_len
;
png_uint_32
key_len
;
png_byte
new_key
[
80
];
png_byte
new_key
[
80
];
...
@@ -1608,7 +1560,7 @@ png_write_tEXt(png_structrp png_ptr, png_const_charp key, png_const_charp text,
...
@@ -1608,7 +1560,7 @@ png_write_tEXt(png_structrp png_ptr, png_const_charp key, png_const_charp text,
*/
*/
png_write_chunk_data
(
png_ptr
,
new_key
,
key_len
+
1
);
png_write_chunk_data
(
png_ptr
,
new_key
,
key_len
+
1
);
if
(
text_len
)
if
(
text_len
!=
0
)
png_write_chunk_data
(
png_ptr
,
(
png_const_bytep
)
text
,
text_len
);
png_write_chunk_data
(
png_ptr
,
(
png_const_bytep
)
text
,
text_len
);
png_write_chunk_end
(
png_ptr
);
png_write_chunk_end
(
png_ptr
);
...
@@ -1619,14 +1571,13 @@ png_write_tEXt(png_structrp png_ptr, png_const_charp key, png_const_charp text,
...
@@ -1619,14 +1571,13 @@ png_write_tEXt(png_structrp png_ptr, png_const_charp key, png_const_charp text,
/* Write a compressed text chunk */
/* Write a compressed text chunk */
void
/* PRIVATE */
void
/* PRIVATE */
png_write_zTXt
(
png_structrp
png_ptr
,
png_const_charp
key
,
png_const_charp
text
,
png_write_zTXt
(
png_structrp
png_ptr
,
png_const_charp
key
,
png_const_charp
text
,
png_size_t
text_len
,
int
compression
)
int
compression
)
{
{
png_uint_32
key_len
;
png_uint_32
key_len
;
png_byte
new_key
[
81
];
png_byte
new_key
[
81
];
compression_state
comp
;
compression_state
comp
;
png_debug
(
1
,
"in png_write_zTXt"
);
png_debug
(
1
,
"in png_write_zTXt"
);
PNG_UNUSED
(
text_len
)
/* Always use strlen */
if
(
compression
==
PNG_TEXT_COMPRESSION_NONE
)
if
(
compression
==
PNG_TEXT_COMPRESSION_NONE
)
{
{
...
@@ -1648,7 +1599,7 @@ png_write_zTXt(png_structrp png_ptr, png_const_charp key, png_const_charp text,
...
@@ -1648,7 +1599,7 @@ png_write_zTXt(png_structrp png_ptr, png_const_charp key, png_const_charp text,
/* Compute the compressed data; do it now for the length */
/* Compute the compressed data; do it now for the length */
png_text_compress_init
(
&
comp
,
(
png_const_bytep
)
text
,
png_text_compress_init
(
&
comp
,
(
png_const_bytep
)
text
,
text
==
NULL
?
0
:
strlen
(
text
));
text
==
NULL
?
0
:
strlen
(
text
));
if
(
png_text_compress
(
png_ptr
,
png_zTXt
,
&
comp
,
key_len
)
!=
Z_OK
)
if
(
png_text_compress
(
png_ptr
,
png_zTXt
,
&
comp
,
key_len
)
!=
Z_OK
)
png_error
(
png_ptr
,
png_ptr
->
zstream
.
msg
);
png_error
(
png_ptr
,
png_ptr
->
zstream
.
msg
);
...
@@ -1674,7 +1625,7 @@ png_write_iTXt(png_structrp png_ptr, int compression, png_const_charp key,
...
@@ -1674,7 +1625,7 @@ png_write_iTXt(png_structrp png_ptr, int compression, png_const_charp key,
png_const_charp
lang
,
png_const_charp
lang_key
,
png_const_charp
text
)
png_const_charp
lang
,
png_const_charp
lang_key
,
png_const_charp
text
)
{
{
png_uint_32
key_len
,
prefix_len
;
png_uint_32
key_len
,
prefix_len
;
png_
size_t
lang_len
,
lang_key_len
;
size_t
lang_len
,
lang_key_len
;
png_byte
new_key
[
82
];
png_byte
new_key
[
82
];
compression_state
comp
;
compression_state
comp
;
...
@@ -1734,7 +1685,7 @@ png_write_iTXt(png_structrp png_ptr, int compression, png_const_charp key,
...
@@ -1734,7 +1685,7 @@ png_write_iTXt(png_structrp png_ptr, int compression, png_const_charp key,
png_text_compress_init
(
&
comp
,
(
png_const_bytep
)
text
,
strlen
(
text
));
png_text_compress_init
(
&
comp
,
(
png_const_bytep
)
text
,
strlen
(
text
));
if
(
compression
)
if
(
compression
!=
0
)
{
{
if
(
png_text_compress
(
png_ptr
,
png_iTXt
,
&
comp
,
prefix_len
)
!=
Z_OK
)
if
(
png_text_compress
(
png_ptr
,
png_iTXt
,
&
comp
,
prefix_len
)
!=
Z_OK
)
png_error
(
png_ptr
,
png_ptr
->
zstream
.
msg
);
png_error
(
png_ptr
,
png_ptr
->
zstream
.
msg
);
...
@@ -1757,11 +1708,11 @@ png_write_iTXt(png_structrp png_ptr, int compression, png_const_charp key,
...
@@ -1757,11 +1708,11 @@ png_write_iTXt(png_structrp png_ptr, int compression, png_const_charp key,
png_write_chunk_data
(
png_ptr
,
(
png_const_bytep
)
lang_key
,
lang_key_len
);
png_write_chunk_data
(
png_ptr
,
(
png_const_bytep
)
lang_key
,
lang_key_len
);
if
(
compression
)
if
(
compression
!=
0
)
png_write_compressed_data_out
(
png_ptr
,
&
comp
);
png_write_compressed_data_out
(
png_ptr
,
&
comp
);
else
else
png_write_chunk_data
(
png_ptr
,
(
png_const_bytep
)
text
,
comp
.
in
put_len
);
png_write_chunk_data
(
png_ptr
,
(
png_const_bytep
)
text
,
comp
.
out
put_len
);
png_write_chunk_end
(
png_ptr
);
png_write_chunk_end
(
png_ptr
);
}
}
...
@@ -1784,7 +1735,7 @@ png_write_oFFs(png_structrp png_ptr, png_int_32 x_offset, png_int_32 y_offset,
...
@@ -1784,7 +1735,7 @@ png_write_oFFs(png_structrp png_ptr, png_int_32 x_offset, png_int_32 y_offset,
png_save_int_32
(
buf
+
4
,
y_offset
);
png_save_int_32
(
buf
+
4
,
y_offset
);
buf
[
8
]
=
(
png_byte
)
unit_type
;
buf
[
8
]
=
(
png_byte
)
unit_type
;
png_write_complete_chunk
(
png_ptr
,
png_oFFs
,
buf
,
(
png_size_t
)
9
);
png_write_complete_chunk
(
png_ptr
,
png_oFFs
,
buf
,
9
);
}
}
#endif
#endif
#ifdef PNG_WRITE_pCAL_SUPPORTED
#ifdef PNG_WRITE_pCAL_SUPPORTED
...
@@ -1795,7 +1746,7 @@ png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0,
...
@@ -1795,7 +1746,7 @@ png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0,
png_charpp
params
)
png_charpp
params
)
{
{
png_uint_32
purpose_len
;
png_uint_32
purpose_len
;
png_
size_t
units_len
,
total_len
;
size_t
units_len
,
total_len
;
png_size_tp
params_len
;
png_size_tp
params_len
;
png_byte
buf
[
10
];
png_byte
buf
[
10
];
png_byte
new_purpose
[
80
];
png_byte
new_purpose
[
80
];
...
@@ -1819,7 +1770,7 @@ png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0,
...
@@ -1819,7 +1770,7 @@ png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0,
total_len
=
purpose_len
+
units_len
+
10
;
total_len
=
purpose_len
+
units_len
+
10
;
params_len
=
(
png_size_tp
)
png_malloc
(
png_ptr
,
params_len
=
(
png_size_tp
)
png_malloc
(
png_ptr
,
(
png_alloc_size_t
)(
nparams
*
(
sizeof
(
png_
size_t
))));
(
png_alloc_size_t
)(
(
png_alloc_size_t
)
nparams
*
(
sizeof
(
size_t
))));
/* Find the length of each parameter, making sure we don't count the
/* Find the length of each parameter, making sure we don't count the
* null terminator for the last parameter.
* null terminator for the last parameter.
...
@@ -1839,8 +1790,8 @@ png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0,
...
@@ -1839,8 +1790,8 @@ png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0,
png_save_int_32
(
buf
+
4
,
X1
);
png_save_int_32
(
buf
+
4
,
X1
);
buf
[
8
]
=
(
png_byte
)
type
;
buf
[
8
]
=
(
png_byte
)
type
;
buf
[
9
]
=
(
png_byte
)
nparams
;
buf
[
9
]
=
(
png_byte
)
nparams
;
png_write_chunk_data
(
png_ptr
,
buf
,
(
png_size_t
)
10
);
png_write_chunk_data
(
png_ptr
,
buf
,
10
);
png_write_chunk_data
(
png_ptr
,
(
png_const_bytep
)
units
,
(
png_
size_t
)
units_len
);
png_write_chunk_data
(
png_ptr
,
(
png_const_bytep
)
units
,
(
size_t
)
units_len
);
for
(
i
=
0
;
i
<
nparams
;
i
++
)
for
(
i
=
0
;
i
<
nparams
;
i
++
)
{
{
...
@@ -1859,7 +1810,7 @@ png_write_sCAL_s(png_structrp png_ptr, int unit, png_const_charp width,
...
@@ -1859,7 +1810,7 @@ png_write_sCAL_s(png_structrp png_ptr, int unit, png_const_charp width,
png_const_charp
height
)
png_const_charp
height
)
{
{
png_byte
buf
[
64
];
png_byte
buf
[
64
];
png_
size_t
wlen
,
hlen
,
total_len
;
size_t
wlen
,
hlen
,
total_len
;
png_debug
(
1
,
"in png_write_sCAL_s"
);
png_debug
(
1
,
"in png_write_sCAL_s"
);
...
@@ -1900,7 +1851,7 @@ png_write_pHYs(png_structrp png_ptr, png_uint_32 x_pixels_per_unit,
...
@@ -1900,7 +1851,7 @@ png_write_pHYs(png_structrp png_ptr, png_uint_32 x_pixels_per_unit,
png_save_uint_32
(
buf
+
4
,
y_pixels_per_unit
);
png_save_uint_32
(
buf
+
4
,
y_pixels_per_unit
);
buf
[
8
]
=
(
png_byte
)
unit_type
;
buf
[
8
]
=
(
png_byte
)
unit_type
;
png_write_complete_chunk
(
png_ptr
,
png_pHYs
,
buf
,
(
png_size_t
)
9
);
png_write_complete_chunk
(
png_ptr
,
png_pHYs
,
buf
,
9
);
}
}
#endif
#endif
...
@@ -1930,7 +1881,7 @@ png_write_tIME(png_structrp png_ptr, png_const_timep mod_time)
...
@@ -1930,7 +1881,7 @@ png_write_tIME(png_structrp png_ptr, png_const_timep mod_time)
buf
[
5
]
=
mod_time
->
minute
;
buf
[
5
]
=
mod_time
->
minute
;
buf
[
6
]
=
mod_time
->
second
;
buf
[
6
]
=
mod_time
->
second
;
png_write_complete_chunk
(
png_ptr
,
png_tIME
,
buf
,
(
png_size_t
)
7
);
png_write_complete_chunk
(
png_ptr
,
png_tIME
,
buf
,
7
);
}
}
#endif
#endif
...
@@ -1942,21 +1893,25 @@ png_write_start_row(png_structrp png_ptr)
...
@@ -1942,21 +1893,25 @@ png_write_start_row(png_structrp png_ptr)
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Start of interlace block */
/* Start of interlace block */
static
PNG_CONST
png_byte
png_pass_start
[
7
]
=
{
0
,
4
,
0
,
2
,
0
,
1
,
0
};
static
const
png_byte
png_pass_start
[
7
]
=
{
0
,
4
,
0
,
2
,
0
,
1
,
0
};
/* Offset to next interlace block */
/* Offset to next interlace block */
static
PNG_CONST
png_byte
png_pass_inc
[
7
]
=
{
8
,
8
,
4
,
4
,
2
,
2
,
1
};
static
const
png_byte
png_pass_inc
[
7
]
=
{
8
,
8
,
4
,
4
,
2
,
2
,
1
};
/* Start of interlace block in the y direction */
/* Start of interlace block in the y direction */
static
PNG_CONST
png_byte
png_pass_ystart
[
7
]
=
{
0
,
0
,
4
,
0
,
2
,
0
,
1
};
static
const
png_byte
png_pass_ystart
[
7
]
=
{
0
,
0
,
4
,
0
,
2
,
0
,
1
};
/* Offset to next interlace block in the y direction */
/* Offset to next interlace block in the y direction */
static
PNG_CONST
png_byte
png_pass_yinc
[
7
]
=
{
8
,
8
,
8
,
4
,
4
,
2
,
2
};
static
const
png_byte
png_pass_yinc
[
7
]
=
{
8
,
8
,
8
,
4
,
4
,
2
,
2
};
#endif
#endif
png_alloc_size_t
buf_size
;
png_alloc_size_t
buf_size
;
int
usr_pixel_depth
;
int
usr_pixel_depth
;
#ifdef PNG_WRITE_FILTER_SUPPORTED
png_byte
filters
;
#endif
png_debug
(
1
,
"in png_write_start_row"
);
png_debug
(
1
,
"in png_write_start_row"
);
usr_pixel_depth
=
png_ptr
->
usr_channels
*
png_ptr
->
usr_bit_depth
;
usr_pixel_depth
=
png_ptr
->
usr_channels
*
png_ptr
->
usr_bit_depth
;
...
@@ -1967,56 +1922,61 @@ png_write_start_row(png_structrp png_ptr)
...
@@ -1967,56 +1922,61 @@ png_write_start_row(png_structrp png_ptr)
png_ptr
->
maximum_pixel_depth
=
(
png_byte
)
usr_pixel_depth
;
png_ptr
->
maximum_pixel_depth
=
(
png_byte
)
usr_pixel_depth
;
/* Set up row buffer */
/* Set up row buffer */
png_ptr
->
row_buf
=
(
png_bytep
)
png_malloc
(
png_ptr
,
buf_size
);
png_ptr
->
row_buf
=
png_voidcast
(
png_bytep
,
png_malloc
(
png_ptr
,
buf_size
)
)
;
png_ptr
->
row_buf
[
0
]
=
PNG_FILTER_VALUE_NONE
;
png_ptr
->
row_buf
[
0
]
=
PNG_FILTER_VALUE_NONE
;
#ifdef PNG_WRITE_FILTER_SUPPORTED
#ifdef PNG_WRITE_FILTER_SUPPORTED
/* Set up filtering buffer, if using this filter */
filters
=
png_ptr
->
do_filter
;
if
(
png_ptr
->
do_filter
&
PNG_FILTER_SUB
)
{
png_ptr
->
sub_row
=
(
png_bytep
)
png_malloc
(
png_ptr
,
png_ptr
->
rowbytes
+
1
);
png_ptr
->
sub_row
[
0
]
=
PNG_FILTER_VALUE_SUB
;
if
(
png_ptr
->
height
==
1
)
}
filters
&=
0xff
&
~
(
PNG_FILTER_UP
|
PNG_FILTER_AVG
|
PNG_FILTER_PAETH
);
if
(
png_ptr
->
width
==
1
)
filters
&=
0xff
&
~
(
PNG_FILTER_SUB
|
PNG_FILTER_AVG
|
PNG_FILTER_PAETH
);
if
(
filters
==
0
)
filters
=
PNG_FILTER_NONE
;
/* We only need to keep the previous row if we are using one of these. */
png_ptr
->
do_filter
=
filters
;
if
(
png_ptr
->
do_filter
&
(
PNG_FILTER_AVG
|
PNG_FILTER_UP
|
PNG_FILTER_PAETH
))
if
(((
filters
&
(
PNG_FILTER_SUB
|
PNG_FILTER_UP
|
PNG_FILTER_AVG
|
PNG_FILTER_PAETH
))
!=
0
)
&&
png_ptr
->
try_row
==
NULL
)
{
{
/* Set up previous row buffer */
int
num_filters
=
0
;
png_ptr
->
prev_row
=
(
png_bytep
)
png_calloc
(
png_ptr
,
buf_size
);
if
(
png_ptr
->
do_filter
&
PNG_FILTER_UP
)
png_ptr
->
try_row
=
png_voidcast
(
png_bytep
,
png_malloc
(
png_ptr
,
buf_size
));
{
png_ptr
->
up_row
=
(
png_bytep
)
png_malloc
(
png_ptr
,
png_ptr
->
rowbytes
+
1
);
png_ptr
->
up_row
[
0
]
=
PNG_FILTER_
VALUE_UP
;
if
(
filters
&
PNG_FILTER_
SUB
)
}
num_filters
++
;
if
(
png_ptr
->
do_filter
&
PNG_FILTER_AVG
)
if
(
filters
&
PNG_FILTER_UP
)
{
num_filters
++
;
png_ptr
->
avg_row
=
(
png_bytep
)
png_malloc
(
png_ptr
,
png_ptr
->
rowbytes
+
1
);
png_ptr
->
avg_row
[
0
]
=
PNG_FILTER_
VALUE_
AVG
;
if
(
filters
&
PNG_FILTER_AVG
)
}
num_filters
++
;
if
(
png_ptr
->
do_filter
&
PNG_FILTER_PAETH
)
if
(
filters
&
PNG_FILTER_PAETH
)
{
num_filters
++
;
png_ptr
->
paeth_row
=
(
png_bytep
)
png_malloc
(
png_ptr
,
png_ptr
->
rowbytes
+
1
);
png_ptr
->
paeth_row
[
0
]
=
PNG_FILTER_VALUE_PAETH
;
if
(
num_filters
>
1
)
}
png_ptr
->
tst_row
=
png_voidcast
(
png_bytep
,
png_malloc
(
png_ptr
,
buf_size
));
}
}
#endif
/* PNG_WRITE_FILTER_SUPPORTED */
/* We only need to keep the previous row if we are using one of the following
* filters.
*/
if
((
filters
&
(
PNG_FILTER_AVG
|
PNG_FILTER_UP
|
PNG_FILTER_PAETH
))
!=
0
)
png_ptr
->
prev_row
=
png_voidcast
(
png_bytep
,
png_calloc
(
png_ptr
,
buf_size
));
#endif
/* WRITE_FILTER */
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
/* If interlaced, we need to set up width and height of pass */
/* If interlaced, we need to set up width and height of pass */
if
(
png_ptr
->
interlaced
)
if
(
png_ptr
->
interlaced
!=
0
)
{
{
if
(
!
(
png_ptr
->
transformations
&
PNG_INTERLACE
))
if
((
png_ptr
->
transformations
&
PNG_INTERLACE
)
==
0
)
{
{
png_ptr
->
num_rows
=
(
png_ptr
->
height
+
png_pass_yinc
[
0
]
-
1
-
png_ptr
->
num_rows
=
(
png_ptr
->
height
+
png_pass_yinc
[
0
]
-
1
-
png_pass_ystart
[
0
])
/
png_pass_yinc
[
0
];
png_pass_ystart
[
0
])
/
png_pass_yinc
[
0
];
...
@@ -2048,16 +2008,16 @@ png_write_finish_row(png_structrp png_ptr)
...
@@ -2048,16 +2008,16 @@ png_write_finish_row(png_structrp png_ptr)
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Start of interlace block */
/* Start of interlace block */
static
PNG_CONST
png_byte
png_pass_start
[
7
]
=
{
0
,
4
,
0
,
2
,
0
,
1
,
0
};
static
const
png_byte
png_pass_start
[
7
]
=
{
0
,
4
,
0
,
2
,
0
,
1
,
0
};
/* Offset to next interlace block */
/* Offset to next interlace block */
static
PNG_CONST
png_byte
png_pass_inc
[
7
]
=
{
8
,
8
,
4
,
4
,
2
,
2
,
1
};
static
const
png_byte
png_pass_inc
[
7
]
=
{
8
,
8
,
4
,
4
,
2
,
2
,
1
};
/* Start of interlace block in the y direction */
/* Start of interlace block in the y direction */
static
PNG_CONST
png_byte
png_pass_ystart
[
7
]
=
{
0
,
0
,
4
,
0
,
2
,
0
,
1
};
static
const
png_byte
png_pass_ystart
[
7
]
=
{
0
,
0
,
4
,
0
,
2
,
0
,
1
};
/* Offset to next interlace block in the y direction */
/* Offset to next interlace block in the y direction */
static
PNG_CONST
png_byte
png_pass_yinc
[
7
]
=
{
8
,
8
,
8
,
4
,
4
,
2
,
2
};
static
const
png_byte
png_pass_yinc
[
7
]
=
{
8
,
8
,
8
,
4
,
4
,
2
,
2
};
#endif
#endif
png_debug
(
1
,
"in png_write_finish_row"
);
png_debug
(
1
,
"in png_write_finish_row"
);
...
@@ -2071,10 +2031,10 @@ png_write_finish_row(png_structrp png_ptr)
...
@@ -2071,10 +2031,10 @@ png_write_finish_row(png_structrp png_ptr)
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
/* If interlaced, go to next pass */
/* If interlaced, go to next pass */
if
(
png_ptr
->
interlaced
)
if
(
png_ptr
->
interlaced
!=
0
)
{
{
png_ptr
->
row_number
=
0
;
png_ptr
->
row_number
=
0
;
if
(
png_ptr
->
transformations
&
PNG_INTERLACE
)
if
(
(
png_ptr
->
transformations
&
PNG_INTERLACE
)
!=
0
)
{
{
png_ptr
->
pass
++
;
png_ptr
->
pass
++
;
}
}
...
@@ -2099,7 +2059,7 @@ png_write_finish_row(png_structrp png_ptr)
...
@@ -2099,7 +2059,7 @@ png_write_finish_row(png_structrp png_ptr)
png_pass_ystart
[
png_ptr
->
pass
])
/
png_pass_ystart
[
png_ptr
->
pass
])
/
png_pass_yinc
[
png_ptr
->
pass
];
png_pass_yinc
[
png_ptr
->
pass
];
if
(
png_ptr
->
transformations
&
PNG_INTERLACE
)
if
(
(
png_ptr
->
transformations
&
PNG_INTERLACE
)
!=
0
)
break
;
break
;
}
while
(
png_ptr
->
usr_width
==
0
||
png_ptr
->
num_rows
==
0
);
}
while
(
png_ptr
->
usr_width
==
0
||
png_ptr
->
num_rows
==
0
);
...
@@ -2111,8 +2071,8 @@ png_write_finish_row(png_structrp png_ptr)
...
@@ -2111,8 +2071,8 @@ png_write_finish_row(png_structrp png_ptr)
{
{
if
(
png_ptr
->
prev_row
!=
NULL
)
if
(
png_ptr
->
prev_row
!=
NULL
)
memset
(
png_ptr
->
prev_row
,
0
,
memset
(
png_ptr
->
prev_row
,
0
,
(
png_size_t
)(
PNG_ROWBYTES
(
png_ptr
->
usr_channels
*
PNG_ROWBYTES
(
png_ptr
->
usr_channels
*
png_ptr
->
usr_bit_depth
,
png_ptr
->
width
)
)
+
1
);
png_ptr
->
usr_bit_depth
,
png_ptr
->
width
)
+
1
);
return
;
return
;
}
}
...
@@ -2138,10 +2098,10 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
...
@@ -2138,10 +2098,10 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Start of interlace block */
/* Start of interlace block */
static
PNG_CONST
png_byte
png_pass_start
[
7
]
=
{
0
,
4
,
0
,
2
,
0
,
1
,
0
};
static
const
png_byte
png_pass_start
[
7
]
=
{
0
,
4
,
0
,
2
,
0
,
1
,
0
};
/* Offset to next interlace block */
/* Offset to next interlace block */
static
PNG_CONST
png_byte
png_pass_inc
[
7
]
=
{
8
,
8
,
4
,
4
,
2
,
2
,
1
};
static
const
png_byte
png_pass_inc
[
7
]
=
{
8
,
8
,
4
,
4
,
2
,
2
,
1
};
png_debug
(
1
,
"in png_do_write_interlace"
);
png_debug
(
1
,
"in png_do_write_interlace"
);
...
@@ -2155,7 +2115,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
...
@@ -2155,7 +2115,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
{
{
png_bytep
sp
;
png_bytep
sp
;
png_bytep
dp
;
png_bytep
dp
;
int
shift
;
unsigned
int
shift
;
int
d
;
int
d
;
int
value
;
int
value
;
png_uint_32
i
;
png_uint_32
i
;
...
@@ -2168,7 +2128,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
...
@@ -2168,7 +2128,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
for
(
i
=
png_pass_start
[
pass
];
i
<
row_width
;
for
(
i
=
png_pass_start
[
pass
];
i
<
row_width
;
i
+=
png_pass_inc
[
pass
])
i
+=
png_pass_inc
[
pass
])
{
{
sp
=
row
+
(
png_
size_t
)(
i
>>
3
);
sp
=
row
+
(
size_t
)(
i
>>
3
);
value
=
(
int
)(
*
sp
>>
(
7
-
(
int
)(
i
&
0x07
)))
&
0x01
;
value
=
(
int
)(
*
sp
>>
(
7
-
(
int
)(
i
&
0x07
)))
&
0x01
;
d
|=
(
value
<<
shift
);
d
|=
(
value
<<
shift
);
...
@@ -2193,7 +2153,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
...
@@ -2193,7 +2153,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
{
{
png_bytep
sp
;
png_bytep
sp
;
png_bytep
dp
;
png_bytep
dp
;
int
shift
;
unsigned
int
shift
;
int
d
;
int
d
;
int
value
;
int
value
;
png_uint_32
i
;
png_uint_32
i
;
...
@@ -2206,7 +2166,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
...
@@ -2206,7 +2166,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
for
(
i
=
png_pass_start
[
pass
];
i
<
row_width
;
for
(
i
=
png_pass_start
[
pass
];
i
<
row_width
;
i
+=
png_pass_inc
[
pass
])
i
+=
png_pass_inc
[
pass
])
{
{
sp
=
row
+
(
png_
size_t
)(
i
>>
2
);
sp
=
row
+
(
size_t
)(
i
>>
2
);
value
=
(
*
sp
>>
((
3
-
(
int
)(
i
&
0x03
))
<<
1
))
&
0x03
;
value
=
(
*
sp
>>
((
3
-
(
int
)(
i
&
0x03
))
<<
1
))
&
0x03
;
d
|=
(
value
<<
shift
);
d
|=
(
value
<<
shift
);
...
@@ -2230,7 +2190,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
...
@@ -2230,7 +2190,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
{
{
png_bytep
sp
;
png_bytep
sp
;
png_bytep
dp
;
png_bytep
dp
;
int
shift
;
unsigned
int
shift
;
int
d
;
int
d
;
int
value
;
int
value
;
png_uint_32
i
;
png_uint_32
i
;
...
@@ -2242,7 +2202,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
...
@@ -2242,7 +2202,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
for
(
i
=
png_pass_start
[
pass
];
i
<
row_width
;
for
(
i
=
png_pass_start
[
pass
];
i
<
row_width
;
i
+=
png_pass_inc
[
pass
])
i
+=
png_pass_inc
[
pass
])
{
{
sp
=
row
+
(
png_
size_t
)(
i
>>
1
);
sp
=
row
+
(
size_t
)(
i
>>
1
);
value
=
(
*
sp
>>
((
1
-
(
int
)(
i
&
0x01
))
<<
2
))
&
0x0f
;
value
=
(
*
sp
>>
((
1
-
(
int
)(
i
&
0x01
))
<<
2
))
&
0x0f
;
d
|=
(
value
<<
shift
);
d
|=
(
value
<<
shift
);
...
@@ -2268,7 +2228,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
...
@@ -2268,7 +2228,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
png_bytep
dp
;
png_bytep
dp
;
png_uint_32
i
;
png_uint_32
i
;
png_uint_32
row_width
=
row_info
->
width
;
png_uint_32
row_width
=
row_info
->
width
;
png_
size_t
pixel_bytes
;
size_t
pixel_bytes
;
/* Start at the beginning */
/* Start at the beginning */
dp
=
row
;
dp
=
row
;
...
@@ -2281,7 +2241,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
...
@@ -2281,7 +2241,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
i
+=
png_pass_inc
[
pass
])
i
+=
png_pass_inc
[
pass
])
{
{
/* Find out where the original pixel is */
/* Find out where the original pixel is */
sp
=
row
+
(
png_
size_t
)
i
*
pixel_bytes
;
sp
=
row
+
(
size_t
)
i
*
pixel_bytes
;
/* Move the pixel */
/* Move the pixel */
if
(
dp
!=
sp
)
if
(
dp
!=
sp
)
...
@@ -2305,691 +2265,487 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
...
@@ -2305,691 +2265,487 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
}
}
#endif
#endif
/* This filters the row, chooses which filter to use, if it has not already
/* This filters the row, chooses which filter to use, if it has not already
* been specified by the application, and then writes the row out with the
* been specified by the application, and then writes the row out with the
* chosen filter.
* chosen filter.
*/
*/
static
void
png_write_filtered_row
(
png_structrp
png_ptr
,
png_bytep
filtered_row
,
static
void
/* PRIVATE */
png_size_t
row_bytes
);
png_write_filtered_row
(
png_structrp
png_ptr
,
png_bytep
filtered_row
,
size_t
row_bytes
);
#define PNG_MAXSUM (((png_uint_32)(-1)) >> 1)
#define PNG_HISHIFT 10
#define PNG_LOMASK ((png_uint_32)0xffffL)
#define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT))
void
/* PRIVATE */
png_write_find_filter
(
png_structrp
png_ptr
,
png_row_infop
row_info
)
{
png_bytep
best_row
;
#ifdef PNG_WRITE_FILTER_SUPPORTED
png_bytep
prev_row
,
row_buf
;
png_uint_32
mins
,
bpp
;
png_byte
filter_to_do
=
png_ptr
->
do_filter
;
png_size_t
row_bytes
=
row_info
->
rowbytes
;
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
int
num_p_filters
=
png_ptr
->
num_prev_filters
;
#endif
png_debug
(
1
,
"in png_write_find_filter"
);
#ifndef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
if
(
png_ptr
->
row_number
==
0
&&
filter_to_do
==
PNG_ALL_FILTERS
)
{
/* These will never be selected so we need not test them. */
filter_to_do
&=
~
(
PNG_FILTER_UP
|
PNG_FILTER_PAETH
);
}
#endif
/* Find out how many bytes offset each pixel is */
bpp
=
(
row_info
->
pixel_depth
+
7
)
>>
3
;
prev_row
=
png_ptr
->
prev_row
;
#endif
best_row
=
png_ptr
->
row_buf
;
#ifdef PNG_WRITE_FILTER_SUPPORTED
#ifdef PNG_WRITE_FILTER_SUPPORTED
row_buf
=
best_row
;
static
size_t
/* PRIVATE */
mins
=
PNG_MAXSUM
;
png_setup_sub_row
(
png_structrp
png_ptr
,
png_uint_32
bpp
,
size_t
row_bytes
,
size_t
lmins
)
/* The prediction method we use is to find which method provides the
{
* smallest value when summing the absolute values of the distances
png_bytep
rp
,
dp
,
lp
;
* from zero, using anything >= 128 as negative numbers. This is known
size_t
i
;
* as the "minimum sum of absolute differences" heuristic. Other
size_t
sum
=
0
;
* heuristics are the "weighted minimum sum of absolute differences"
unsigned
int
v
;
* (experimental and can in theory improve compression), and the "zlib
* predictive" method (not implemented yet), which does test compressions
* of lines using different filter methods, and then chooses the
* (series of) filter(s) that give minimum compressed data size (VERY
* computationally expensive).
*
* GRR 980525: consider also
*
* (1) minimum sum of absolute differences from running average (i.e.,
* keep running sum of non-absolute differences & count of bytes)
* [track dispersion, too? restart average if dispersion too large?]
*
* (1b) minimum sum of absolute differences from sliding average, probably
* with window size <= deflate window (usually 32K)
*
* (2) minimum sum of squared differences from zero or running average
* (i.e., ~ root-mean-square approach)
*/
png_ptr
->
try_row
[
0
]
=
PNG_FILTER_VALUE_SUB
;
/* We don't need to test the 'no filter' case if this is the only filter
for
(
i
=
0
,
rp
=
png_ptr
->
row_buf
+
1
,
dp
=
png_ptr
->
try_row
+
1
;
i
<
bpp
;
* that has been chosen, as it doesn't actually do anything to the data.
i
++
,
rp
++
,
dp
++
)
*/
if
((
filter_to_do
&
PNG_FILTER_NONE
)
&&
filter_to_do
!=
PNG_FILTER_NONE
)
{
{
png_bytep
rp
;
v
=
*
dp
=
*
rp
;
png_uint_32
sum
=
0
;
#ifdef PNG_USE_ABS
png_size_t
i
;
sum
+=
128
-
abs
((
int
)
v
-
128
);
int
v
;
#else
sum
+=
(
v
<
128
)
?
v
:
256
-
v
;
for
(
i
=
0
,
rp
=
row_buf
+
1
;
i
<
row_bytes
;
i
++
,
rp
++
)
{
v
=
*
rp
;
sum
+=
(
v
<
128
)
?
v
:
256
-
v
;
}
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
if
(
png_ptr
->
heuristic_method
==
PNG_FILTER_HEURISTIC_WEIGHTED
)
{
png_uint_32
sumhi
,
sumlo
;
int
j
;
sumlo
=
sum
&
PNG_LOMASK
;
sumhi
=
(
sum
>>
PNG_HISHIFT
)
&
PNG_HIMASK
;
/* Gives us some footroom */
/* Reduce the sum if we match any of the previous rows */
for
(
j
=
0
;
j
<
num_p_filters
;
j
++
)
{
if
(
png_ptr
->
prev_filters
[
j
]
==
PNG_FILTER_VALUE_NONE
)
{
sumlo
=
(
sumlo
*
png_ptr
->
filter_weights
[
j
])
>>
PNG_WEIGHT_SHIFT
;
sumhi
=
(
sumhi
*
png_ptr
->
filter_weights
[
j
])
>>
PNG_WEIGHT_SHIFT
;
}
}
/* Factor in the cost of this filter (this is here for completeness,
* but it makes no sense to have a "cost" for the NONE filter, as
* it has the minimum possible computational cost - none).
*/
sumlo
=
(
sumlo
*
png_ptr
->
filter_costs
[
PNG_FILTER_VALUE_NONE
])
>>
PNG_COST_SHIFT
;
sumhi
=
(
sumhi
*
png_ptr
->
filter_costs
[
PNG_FILTER_VALUE_NONE
])
>>
PNG_COST_SHIFT
;
if
(
sumhi
>
PNG_HIMASK
)
sum
=
PNG_MAXSUM
;
else
sum
=
(
sumhi
<<
PNG_HISHIFT
)
+
sumlo
;
}
#endif
#endif
mins
=
sum
;
}
}
/* Sub filter */
for
(
lp
=
png_ptr
->
row_buf
+
1
;
i
<
row_bytes
;
if
(
filter_to_do
==
PNG_FILTER_SUB
)
i
++
,
rp
++
,
lp
++
,
dp
++
)
/* It's the only filter so no testing is needed */
{
{
png_bytep
rp
,
lp
,
dp
;
v
=
*
dp
=
(
png_byte
)(((
int
)
*
rp
-
(
int
)
*
lp
)
&
0xff
);
png_size_t
i
;
#ifdef PNG_USE_ABS
sum
+=
128
-
abs
((
int
)
v
-
128
);
for
(
i
=
0
,
rp
=
row_buf
+
1
,
dp
=
png_ptr
->
sub_row
+
1
;
i
<
bpp
;
#else
i
++
,
rp
++
,
dp
++
)
sum
+=
(
v
<
128
)
?
v
:
256
-
v
;
{
#endif
*
dp
=
*
rp
;
}
for
(
lp
=
row_buf
+
1
;
i
<
row_bytes
;
i
++
,
rp
++
,
lp
++
,
dp
++
)
{
*
dp
=
(
png_byte
)(((
int
)
*
rp
-
(
int
)
*
lp
)
&
0xff
);
}
best_row
=
png_ptr
->
sub_row
;
if
(
sum
>
lmins
)
/* We are already worse, don't continue. */
break
;
}
}
else
if
(
filter_to_do
&
PNG_FILTER_SUB
)
return
(
sum
);
{
}
png_bytep
rp
,
dp
,
lp
;
png_uint_32
sum
=
0
,
lmins
=
mins
;
png_size_t
i
;
int
v
;
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
static
void
/* PRIVATE */
/* We temporarily increase the "minimum sum" by the factor we
png_setup_sub_row_only
(
png_structrp
png_ptr
,
png_uint_32
bpp
,
* would reduce the sum of this filter, so that we can do the
size_t
row_bytes
)
* early exit comparison without scaling the sum each time.
{
*/
png_bytep
rp
,
dp
,
lp
;
if
(
png_ptr
->
heuristic_method
==
PNG_FILTER_HEURISTIC_WEIGHTED
)
size_t
i
;
{
int
j
;
png_uint_32
lmhi
,
lmlo
;
lmlo
=
lmins
&
PNG_LOMASK
;
lmhi
=
(
lmins
>>
PNG_HISHIFT
)
&
PNG_HIMASK
;
for
(
j
=
0
;
j
<
num_p_filters
;
j
++
)
png_ptr
->
try_row
[
0
]
=
PNG_FILTER_VALUE_SUB
;
{
if
(
png_ptr
->
prev_filters
[
j
]
==
PNG_FILTER_VALUE_SUB
)
{
lmlo
=
(
lmlo
*
png_ptr
->
inv_filter_weights
[
j
])
>>
PNG_WEIGHT_SHIFT
;
lmhi
=
(
lmhi
*
png_ptr
->
inv_filter_weights
[
j
])
>>
for
(
i
=
0
,
rp
=
png_ptr
->
row_buf
+
1
,
dp
=
png_ptr
->
try_row
+
1
;
i
<
bpp
;
PNG_WEIGHT_SHIFT
;
i
++
,
rp
++
,
dp
++
)
}
{
}
*
dp
=
*
rp
;
}
lmlo
=
(
lmlo
*
png_ptr
->
inv_filter_costs
[
PNG_FILTER_VALUE_SUB
])
>>
for
(
lp
=
png_ptr
->
row_buf
+
1
;
i
<
row_bytes
;
PNG_COST_SHIFT
;
i
++
,
rp
++
,
lp
++
,
dp
++
)
{
*
dp
=
(
png_byte
)(((
int
)
*
rp
-
(
int
)
*
lp
)
&
0xff
);
}
}
lmhi
=
(
lmhi
*
png_ptr
->
inv_filter_costs
[
PNG_FILTER_VALUE_SUB
])
>>
static
size_t
/* PRIVATE */
PNG_COST_SHIFT
;
png_setup_up_row
(
png_structrp
png_ptr
,
size_t
row_bytes
,
size_t
lmins
)
{
png_bytep
rp
,
dp
,
pp
;
size_t
i
;
size_t
sum
=
0
;
unsigned
int
v
;
if
(
lmhi
>
PNG_HIMASK
)
png_ptr
->
try_row
[
0
]
=
PNG_FILTER_VALUE_UP
;
lmins
=
PNG_MAXSUM
;
else
for
(
i
=
0
,
rp
=
png_ptr
->
row_buf
+
1
,
dp
=
png_ptr
->
try_row
+
1
,
lmins
=
(
lmhi
<<
PNG_HISHIFT
)
+
lmlo
;
pp
=
png_ptr
->
prev_row
+
1
;
i
<
row_bytes
;
}
i
++
,
rp
++
,
pp
++
,
dp
++
)
{
v
=
*
dp
=
(
png_byte
)(((
int
)
*
rp
-
(
int
)
*
pp
)
&
0xff
);
#ifdef PNG_USE_ABS
sum
+=
128
-
abs
((
int
)
v
-
128
);
#else
sum
+=
(
v
<
128
)
?
v
:
256
-
v
;
#endif
#endif
for
(
i
=
0
,
rp
=
row_buf
+
1
,
dp
=
png_ptr
->
sub_row
+
1
;
i
<
bpp
;
if
(
sum
>
lmins
)
/* We are already worse, don't continue. */
i
++
,
rp
++
,
dp
++
)
break
;
{
}
v
=
*
dp
=
*
rp
;
sum
+=
(
v
<
128
)
?
v
:
256
-
v
;
}
for
(
lp
=
row_buf
+
1
;
i
<
row_bytes
;
i
++
,
rp
++
,
lp
++
,
dp
++
)
{
v
=
*
dp
=
(
png_byte
)(((
int
)
*
rp
-
(
int
)
*
lp
)
&
0xff
);
sum
+=
(
v
<
128
)
?
v
:
256
-
v
;
if
(
sum
>
lmins
)
/* We are already worse, don't continue. */
break
;
}
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
return
(
sum
);
if
(
png_ptr
->
heuristic_method
==
PNG_FILTER_HEURISTIC_WEIGHTED
)
}
{
static
void
/* PRIVATE */
int
j
;
png_setup_up_row_only
(
png_structrp
png_ptr
,
size_t
row_bytes
)
png_uint_32
sumhi
,
sumlo
;
{
sumlo
=
sum
&
PNG_LOMASK
;
png_bytep
rp
,
dp
,
pp
;
sumhi
=
(
sum
>>
PNG_HISHIFT
)
&
PNG_HIMASK
;
size_t
i
;
for
(
j
=
0
;
j
<
num_p_filters
;
j
++
)
png_ptr
->
try_row
[
0
]
=
PNG_FILTER_VALUE_UP
;
{
if
(
png_ptr
->
prev_filters
[
j
]
==
PNG_FILTER_VALUE_SUB
)
{
sumlo
=
(
sumlo
*
png_ptr
->
inv_filter_weights
[
j
])
>>
PNG_WEIGHT_SHIFT
;
sumhi
=
(
sumhi
*
png_ptr
->
inv_filter_weights
[
j
])
>>
for
(
i
=
0
,
rp
=
png_ptr
->
row_buf
+
1
,
dp
=
png_ptr
->
try_row
+
1
,
PNG_WEIGHT_SHIFT
;
pp
=
png_ptr
->
prev_row
+
1
;
i
<
row_bytes
;
}
i
++
,
rp
++
,
pp
++
,
dp
++
)
}
{
*
dp
=
(
png_byte
)(((
int
)
*
rp
-
(
int
)
*
pp
)
&
0xff
);
}
}
sumlo
=
(
sumlo
*
png_ptr
->
inv_filter_costs
[
PNG_FILTER_VALUE_SUB
])
>>
static
size_t
/* PRIVATE */
PNG_COST_SHIFT
;
png_setup_avg_row
(
png_structrp
png_ptr
,
png_uint_32
bpp
,
size_t
row_bytes
,
size_t
lmins
)
{
png_bytep
rp
,
dp
,
pp
,
lp
;
png_uint_32
i
;
size_t
sum
=
0
;
unsigned
int
v
;
sumhi
=
(
sumhi
*
png_ptr
->
inv_filter_costs
[
PNG_FILTER_VALUE_SUB
])
>>
png_ptr
->
try_row
[
0
]
=
PNG_FILTER_VALUE_AVG
;
PNG_COST_SHIFT
;
if
(
sumhi
>
PNG_HIMASK
)
for
(
i
=
0
,
rp
=
png_ptr
->
row_buf
+
1
,
dp
=
png_ptr
->
try_row
+
1
,
sum
=
PNG_MAXSUM
;
pp
=
png_ptr
->
prev_row
+
1
;
i
<
bpp
;
i
++
)
{
v
=
*
dp
++
=
(
png_byte
)(((
int
)
*
rp
++
-
((
int
)
*
pp
++
/
2
))
&
0xff
);
else
#ifdef PNG_USE_ABS
sum
=
(
sumhi
<<
PNG_HISHIFT
)
+
sumlo
;
sum
+=
128
-
abs
((
int
)
v
-
128
);
}
#else
sum
+=
(
v
<
128
)
?
v
:
256
-
v
;
#endif
#endif
if
(
sum
<
mins
)
{
mins
=
sum
;
best_row
=
png_ptr
->
sub_row
;
}
}
}
/* Up filter */
for
(
lp
=
png_ptr
->
row_buf
+
1
;
i
<
row_bytes
;
i
++
)
if
(
filter_to_do
==
PNG_FILTER_UP
)
{
{
png_bytep
rp
,
dp
,
pp
;
v
=
*
dp
++
=
(
png_byte
)(((
int
)
*
rp
++
-
(((
int
)
*
pp
++
+
(
int
)
*
lp
++
)
/
2
))
png_size_t
i
;
&
0xff
)
;
for
(
i
=
0
,
rp
=
row_buf
+
1
,
dp
=
png_ptr
->
up_row
+
1
,
#ifdef PNG_USE_ABS
pp
=
prev_row
+
1
;
i
<
row_bytes
;
sum
+=
128
-
abs
((
int
)
v
-
128
);
i
++
,
rp
++
,
pp
++
,
dp
++
)
#else
{
sum
+=
(
v
<
128
)
?
v
:
256
-
v
;
*
dp
=
(
png_byte
)(((
int
)
*
rp
-
(
int
)
*
pp
)
&
0xff
);
#endif
}
best_row
=
png_ptr
->
up_row
;
if
(
sum
>
lmins
)
/* We are already worse, don't continue. */
break
;
}
}
else
if
(
filter_to_do
&
PNG_FILTER_UP
)
return
(
sum
);
{
}
png_bytep
rp
,
dp
,
pp
;
static
void
/* PRIVATE */
png_uint_32
sum
=
0
,
lmins
=
mins
;
png_setup_avg_row_only
(
png_structrp
png_ptr
,
png_uint_32
bpp
,
png_size_t
i
;
size_t
row_bytes
)
int
v
;
{
png_bytep
rp
,
dp
,
pp
,
lp
;
png_uint_32
i
;
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
png_ptr
->
try_row
[
0
]
=
PNG_FILTER_VALUE_AVG
;
if
(
png_ptr
->
heuristic_method
==
PNG_FILTER_HEURISTIC_WEIGHTED
)
{
int
j
;
png_uint_32
lmhi
,
lmlo
;
lmlo
=
lmins
&
PNG_LOMASK
;
lmhi
=
(
lmins
>>
PNG_HISHIFT
)
&
PNG_HIMASK
;
for
(
j
=
0
;
j
<
num_p_filters
;
j
++
)
for
(
i
=
0
,
rp
=
png_ptr
->
row_buf
+
1
,
dp
=
png_ptr
->
try_row
+
1
,
{
pp
=
png_ptr
->
prev_row
+
1
;
i
<
bpp
;
i
++
)
if
(
png_ptr
->
prev_filters
[
j
]
==
PNG_FILTER_VALUE_UP
)
{
{
*
dp
++
=
(
png_byte
)(((
int
)
*
rp
++
-
((
int
)
*
pp
++
/
2
))
&
0xff
);
lmlo
=
(
lmlo
*
png_ptr
->
inv_filter_weights
[
j
])
>>
}
PNG_WEIGHT_SHIFT
;
lmhi
=
(
lmhi
*
png_ptr
->
inv_filter_weights
[
j
])
>>
for
(
lp
=
png_ptr
->
row_buf
+
1
;
i
<
row_bytes
;
i
++
)
PNG_WEIGHT_SHIFT
;
{
}
*
dp
++
=
(
png_byte
)(((
int
)
*
rp
++
-
(((
int
)
*
pp
++
+
(
int
)
*
lp
++
)
/
2
))
}
&
0xff
);
}
}
lmlo
=
(
lmlo
*
png_ptr
->
inv_filter_costs
[
PNG_FILTER_VALUE_UP
])
>>
static
size_t
/* PRIVATE */
PNG_COST_SHIFT
;
png_setup_paeth_row
(
png_structrp
png_ptr
,
png_uint_32
bpp
,
size_t
row_bytes
,
size_t
lmins
)
{
png_bytep
rp
,
dp
,
pp
,
cp
,
lp
;
size_t
i
;
size_t
sum
=
0
;
unsigned
int
v
;
lmhi
=
(
lmhi
*
png_ptr
->
inv_filter_costs
[
PNG_FILTER_VALUE_UP
])
>>
png_ptr
->
try_row
[
0
]
=
PNG_FILTER_VALUE_PAETH
;
PNG_COST_SHIFT
;
if
(
lmhi
>
PNG_HIMASK
)
for
(
i
=
0
,
rp
=
png_ptr
->
row_buf
+
1
,
dp
=
png_ptr
->
try_row
+
1
,
lmins
=
PNG_MAXSUM
;
pp
=
png_ptr
->
prev_row
+
1
;
i
<
bpp
;
i
++
)
{
v
=
*
dp
++
=
(
png_byte
)(((
int
)
*
rp
++
-
(
int
)
*
pp
++
)
&
0xff
);
else
#ifdef PNG_USE_ABS
lmins
=
(
lmhi
<<
PNG_HISHIFT
)
+
lmlo
;
sum
+=
128
-
abs
((
int
)
v
-
128
);
}
#else
sum
+=
(
v
<
128
)
?
v
:
256
-
v
;
#endif
#endif
}
for
(
i
=
0
,
rp
=
row_buf
+
1
,
dp
=
png_ptr
->
up_row
+
1
,
for
(
lp
=
png_ptr
->
row_buf
+
1
,
cp
=
png_ptr
->
prev_row
+
1
;
i
<
row_bytes
;
pp
=
prev_row
+
1
;
i
<
row_bytes
;
i
++
)
i
++
)
{
{
v
=
*
dp
++
=
(
png_byte
)(((
int
)
*
rp
++
-
(
int
)
*
pp
++
)
&
0xff
);
int
a
,
b
,
c
,
pa
,
pb
,
pc
,
p
;
sum
+=
(
v
<
128
)
?
v
:
256
-
v
;
if
(
sum
>
lmins
)
/* We are already worse, don't continue. */
break
;
}
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
if
(
png_ptr
->
heuristic_method
==
PNG_FILTER_HEURISTIC_WEIGHTED
)
{
int
j
;
png_uint_32
sumhi
,
sumlo
;
sumlo
=
sum
&
PNG_LOMASK
;
sumhi
=
(
sum
>>
PNG_HISHIFT
)
&
PNG_HIMASK
;
for
(
j
=
0
;
j
<
num_p_filters
;
j
++
)
b
=
*
pp
++
;
{
c
=
*
cp
++
;
if
(
png_ptr
->
prev_filters
[
j
]
==
PNG_FILTER_VALUE_UP
)
a
=
*
lp
++
;
{
sumlo
=
(
sumlo
*
png_ptr
->
filter_weights
[
j
])
>>
PNG_WEIGHT_SHIFT
;
sumhi
=
(
sumhi
*
png_ptr
->
filter_weights
[
j
])
>>
p
=
b
-
c
;
PNG_WEIGHT_SHIFT
;
pc
=
a
-
c
;
}
}
sumlo
=
(
sumlo
*
png_ptr
->
filter_costs
[
PNG_FILTER_VALUE_UP
])
>>
#ifdef PNG_USE_ABS
PNG_COST_SHIFT
;
pa
=
abs
(
p
);
pb
=
abs
(
pc
);
pc
=
abs
(
p
+
pc
);
#else
pa
=
p
<
0
?
-
p
:
p
;
pb
=
pc
<
0
?
-
pc
:
pc
;
pc
=
(
p
+
pc
)
<
0
?
-
(
p
+
pc
)
:
p
+
pc
;
#endif
sumhi
=
(
sumhi
*
png_ptr
->
filter_costs
[
PNG_FILTER_VALUE_UP
])
>>
p
=
(
pa
<=
pb
&&
pa
<=
pc
)
?
a
:
(
pb
<=
pc
)
?
b
:
c
;
PNG_COST_SHIFT
;
if
(
sumhi
>
PNG_HIMASK
)
v
=
*
dp
++
=
(
png_byte
)(((
int
)
*
rp
++
-
p
)
&
0xff
);
sum
=
PNG_MAXSUM
;
else
#ifdef PNG_USE_ABS
sum
=
(
sumhi
<<
PNG_HISHIFT
)
+
sumlo
;
sum
+=
128
-
abs
((
int
)
v
-
128
);
}
#else
sum
+=
(
v
<
128
)
?
v
:
256
-
v
;
#endif
#endif
if
(
sum
<
mins
)
if
(
sum
>
lmins
)
/* We are already worse, don't continue. */
{
break
;
mins
=
sum
;
best_row
=
png_ptr
->
up_row
;
}
}
}
/* Avg filter */
return
(
sum
);
if
(
filter_to_do
==
PNG_FILTER_AVG
)
}
{
static
void
/* PRIVATE */
png_bytep
rp
,
dp
,
pp
,
lp
;
png_setup_paeth_row_only
(
png_structrp
png_ptr
,
png_uint_32
bpp
,
png_uint_32
i
;
size_t
row_bytes
)
{
png_bytep
rp
,
dp
,
pp
,
cp
,
lp
;
size_t
i
;
for
(
i
=
0
,
rp
=
row_buf
+
1
,
dp
=
png_ptr
->
avg_row
+
1
,
png_ptr
->
try_row
[
0
]
=
PNG_FILTER_VALUE_PAETH
;
pp
=
prev_row
+
1
;
i
<
bpp
;
i
++
)
{
*
dp
++
=
(
png_byte
)(((
int
)
*
rp
++
-
((
int
)
*
pp
++
/
2
))
&
0xff
);
}
for
(
lp
=
row_buf
+
1
;
i
<
row_bytes
;
i
++
)
for
(
i
=
0
,
rp
=
png_ptr
->
row_buf
+
1
,
dp
=
png_ptr
->
try_row
+
1
,
{
pp
=
png_ptr
->
prev_row
+
1
;
i
<
bpp
;
i
++
)
*
dp
++
=
(
png_byte
)(((
int
)
*
rp
++
-
(((
int
)
*
pp
++
+
(
int
)
*
lp
++
)
/
2
))
{
&
0xff
);
*
dp
++
=
(
png_byte
)(((
int
)
*
rp
++
-
(
int
)
*
pp
++
)
&
0xff
);
}
best_row
=
png_ptr
->
avg_row
;
}
}
else
if
(
filter_to_do
&
PNG_FILTER_AVG
)
for
(
lp
=
png_ptr
->
row_buf
+
1
,
cp
=
png_ptr
->
prev_row
+
1
;
i
<
row_bytes
;
i
++
)
{
{
png_bytep
rp
,
dp
,
pp
,
lp
;
int
a
,
b
,
c
,
pa
,
pb
,
pc
,
p
;
png_uint_32
sum
=
0
,
lmins
=
mins
;
png_size_t
i
;
int
v
;
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
if
(
png_ptr
->
heuristic_method
==
PNG_FILTER_HEURISTIC_WEIGHTED
)
{
int
j
;
png_uint_32
lmhi
,
lmlo
;
lmlo
=
lmins
&
PNG_LOMASK
;
lmhi
=
(
lmins
>>
PNG_HISHIFT
)
&
PNG_HIMASK
;
for
(
j
=
0
;
j
<
num_p_filters
;
j
++
)
{
if
(
png_ptr
->
prev_filters
[
j
]
==
PNG_FILTER_VALUE_AVG
)
{
lmlo
=
(
lmlo
*
png_ptr
->
inv_filter_weights
[
j
])
>>
PNG_WEIGHT_SHIFT
;
lmhi
=
(
lmhi
*
png_ptr
->
inv_filter_weights
[
j
])
>>
PNG_WEIGHT_SHIFT
;
}
}
lmlo
=
(
lmlo
*
png_ptr
->
inv_filter_costs
[
PNG_FILTER_VALUE_AVG
])
>>
b
=
*
pp
++
;
PNG_COST_SHIFT
;
c
=
*
cp
++
;
a
=
*
lp
++
;
lmhi
=
(
lmhi
*
png_ptr
->
inv_filter_costs
[
PNG_FILTER_VALUE_AVG
])
>>
p
=
b
-
c
;
PNG_COST_SHIFT
;
pc
=
a
-
c
;
if
(
lmhi
>
PNG_HIMASK
)
#ifdef PNG_USE_ABS
lmins
=
PNG_MAXSUM
;
pa
=
abs
(
p
);
pb
=
abs
(
pc
);
else
pc
=
abs
(
p
+
pc
);
lmins
=
(
lmhi
<<
PNG_HISHIFT
)
+
lmlo
;
#else
}
pa
=
p
<
0
?
-
p
:
p
;
pb
=
pc
<
0
?
-
pc
:
pc
;
pc
=
(
p
+
pc
)
<
0
?
-
(
p
+
pc
)
:
p
+
pc
;
#endif
#endif
for
(
i
=
0
,
rp
=
row_buf
+
1
,
dp
=
png_ptr
->
avg_row
+
1
,
p
=
(
pa
<=
pb
&&
pa
<=
pc
)
?
a
:
(
pb
<=
pc
)
?
b
:
c
;
pp
=
prev_row
+
1
;
i
<
bpp
;
i
++
)
{
v
=
*
dp
++
=
(
png_byte
)(((
int
)
*
rp
++
-
((
int
)
*
pp
++
/
2
))
&
0xff
);
sum
+=
(
v
<
128
)
?
v
:
256
-
v
;
}
for
(
lp
=
row_buf
+
1
;
i
<
row_bytes
;
i
++
)
*
dp
++
=
(
png_byte
)(((
int
)
*
rp
++
-
p
)
&
0xff
);
{
}
v
=
*
dp
++
=
}
(
png_byte
)(((
int
)
*
rp
++
-
(((
int
)
*
pp
++
+
(
int
)
*
lp
++
)
/
2
))
&
0xff
);
#endif
/* WRITE_FILTER */
sum
+=
(
v
<
128
)
?
v
:
256
-
v
;
if
(
sum
>
lmins
)
/* We are already worse, don't continue. */
break
;
}
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
void
/* PRIVATE */
if
(
png_ptr
->
heuristic_method
==
PNG_FILTER_HEURISTIC_WEIGHTED
)
png_write_find_filter
(
png_structrp
png_ptr
,
png_row_infop
row_info
)
{
{
int
j
;
#ifndef PNG_WRITE_FILTER_SUPPORTED
png_uint_32
sumhi
,
sumlo
;
png_write_filtered_row
(
png_ptr
,
png_ptr
->
row_buf
,
row_info
->
rowbytes
+
1
);
sumlo
=
sum
&
PNG_LOMASK
;
#else
sumhi
=
(
sum
>>
PNG_HISHIFT
)
&
PNG_HIMASK
;
unsigned
int
filter_to_do
=
png_ptr
->
do_filter
;
png_bytep
row_buf
;
png_bytep
best_row
;
png_uint_32
bpp
;
size_t
mins
;
size_t
row_bytes
=
row_info
->
rowbytes
;
for
(
j
=
0
;
j
<
num_p_filters
;
j
++
)
png_debug
(
1
,
"in png_write_find_filter"
);
{
if
(
png_ptr
->
prev_filters
[
j
]
==
PNG_FILTER_VALUE_NONE
)
{
sumlo
=
(
sumlo
*
png_ptr
->
filter_weights
[
j
])
>>
PNG_WEIGHT_SHIFT
;
sumhi
=
(
sumhi
*
png_ptr
->
filter_weights
[
j
])
>>
/* Find out how many bytes offset each pixel is */
PNG_WEIGHT_SHIFT
;
bpp
=
(
row_info
->
pixel_depth
+
7
)
>>
3
;
}
}
sumlo
=
(
sumlo
*
png_ptr
->
filter_costs
[
PNG_FILTER_VALUE_AVG
])
>>
row_buf
=
png_ptr
->
row_buf
;
PNG_COST_SHIFT
;
mins
=
PNG_SIZE_MAX
-
256
/* so we can detect potential overflow of the
running sum */
;
sumhi
=
(
sumhi
*
png_ptr
->
filter_costs
[
PNG_FILTER_VALUE_AVG
])
>>
/* The prediction method we use is to find which method provides the
PNG_COST_SHIFT
;
* smallest value when summing the absolute values of the distances
* from zero, using anything >= 128 as negative numbers. This is known
* as the "minimum sum of absolute differences" heuristic. Other
* heuristics are the "weighted minimum sum of absolute differences"
* (experimental and can in theory improve compression), and the "zlib
* predictive" method (not implemented yet), which does test compressions
* of lines using different filter methods, and then chooses the
* (series of) filter(s) that give minimum compressed data size (VERY
* computationally expensive).
*
* GRR 980525: consider also
*
* (1) minimum sum of absolute differences from running average (i.e.,
* keep running sum of non-absolute differences & count of bytes)
* [track dispersion, too? restart average if dispersion too large?]
*
* (1b) minimum sum of absolute differences from sliding average, probably
* with window size <= deflate window (usually 32K)
*
* (2) minimum sum of squared differences from zero or running average
* (i.e., ~ root-mean-square approach)
*/
if
(
sumhi
>
PNG_HIMASK
)
sum
=
PNG_MAXSUM
;
else
/* We don't need to test the 'no filter' case if this is the only filter
sum
=
(
sumhi
<<
PNG_HISHIFT
)
+
sumlo
;
* that has been chosen, as it doesn't actually do anything to the data.
}
*/
#endif
best_row
=
png_ptr
->
row_buf
;
if
(
sum
<
mins
)
if
(
PNG_SIZE_MAX
/
128
<=
row_bytes
)
{
{
mins
=
sum
;
/* Overflow can occur in the calculation, just select the lowest set
best_row
=
png_ptr
->
avg_row
;
* filter.
}
*/
filter_to_do
&=
0U
-
filter_to_do
;
}
}
else
if
((
filter_to_do
&
PNG_FILTER_NONE
)
!=
0
&&
/* Paeth filter */
filter_to_do
!=
PNG_FILTER_NONE
)
if
(
filter_to_do
==
PNG_FILTER_PAETH
)
{
{
png_bytep
rp
,
dp
,
pp
,
cp
,
lp
;
/* Overflow not possible and multiple filters in the list, including the
png_size_t
i
;
* 'none' filter.
*/
for
(
i
=
0
,
rp
=
row_buf
+
1
,
dp
=
png_ptr
->
paeth_row
+
1
,
png_bytep
rp
;
pp
=
prev_row
+
1
;
i
<
bpp
;
i
++
)
size_t
sum
=
0
;
{
size_t
i
;
*
dp
++
=
(
png_byte
)(((
int
)
*
rp
++
-
(
int
)
*
pp
++
)
&
0xff
);
unsigned
int
v
;
}
for
(
lp
=
row_buf
+
1
,
cp
=
prev_row
+
1
;
i
<
row_bytes
;
i
++
)
{
{
int
a
,
b
,
c
,
pa
,
pb
,
pc
,
p
;
for
(
i
=
0
,
rp
=
row_buf
+
1
;
i
<
row_bytes
;
i
++
,
rp
++
)
{
b
=
*
pp
++
;
v
=
*
rp
;
c
=
*
cp
++
;
a
=
*
lp
++
;
p
=
b
-
c
;
pc
=
a
-
c
;
#ifdef PNG_USE_ABS
#ifdef PNG_USE_ABS
pa
=
abs
(
p
);
sum
+=
128
-
abs
((
int
)
v
-
128
);
pb
=
abs
(
pc
);
pc
=
abs
(
p
+
pc
);
#else
#else
pa
=
p
<
0
?
-
p
:
p
;
sum
+=
(
v
<
128
)
?
v
:
256
-
v
;
pb
=
pc
<
0
?
-
pc
:
pc
;
pc
=
(
p
+
pc
)
<
0
?
-
(
p
+
pc
)
:
p
+
pc
;
#endif
#endif
}
}
p
=
(
pa
<=
pb
&&
pa
<=
pc
)
?
a
:
(
pb
<=
pc
)
?
b
:
c
;
mins
=
sum
;
}
*
dp
++
=
(
png_byte
)(((
int
)
*
rp
++
-
p
)
&
0xff
);
/* Sub filter */
}
if
(
filter_to_do
==
PNG_FILTER_SUB
)
best_row
=
png_ptr
->
paeth_row
;
/* It's the only filter so no testing is needed */
{
png_setup_sub_row_only
(
png_ptr
,
bpp
,
row_bytes
);
best_row
=
png_ptr
->
try_row
;
}
}
else
if
(
filter_to_do
&
PNG_FILTER_
PAETH
)
else
if
(
(
filter_to_do
&
PNG_FILTER_
SUB
)
!=
0
)
{
{
png_bytep
rp
,
dp
,
pp
,
cp
,
lp
;
size_t
sum
;
png_uint_32
sum
=
0
,
lmins
=
mins
;
size_t
lmins
=
mins
;
png_size_t
i
;
int
v
;
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
sum
=
png_setup_sub_row
(
png_ptr
,
bpp
,
row_bytes
,
lmins
);
if
(
png_ptr
->
heuristic_method
==
PNG_FILTER_HEURISTIC_WEIGHTED
)
{
int
j
;
png_uint_32
lmhi
,
lmlo
;
lmlo
=
lmins
&
PNG_LOMASK
;
lmhi
=
(
lmins
>>
PNG_HISHIFT
)
&
PNG_HIMASK
;
for
(
j
=
0
;
j
<
num_p_filters
;
j
++
)
if
(
sum
<
mins
)
{
mins
=
sum
;
best_row
=
png_ptr
->
try_row
;
if
(
png_ptr
->
tst_row
!=
NULL
)
{
{
if
(
png_ptr
->
prev_filters
[
j
]
==
PNG_FILTER_VALUE_PAETH
)
png_ptr
->
try_row
=
png_ptr
->
tst_row
;
{
png_ptr
->
tst_row
=
best_row
;
lmlo
=
(
lmlo
*
png_ptr
->
inv_filter_weights
[
j
])
>>
PNG_WEIGHT_SHIFT
;
lmhi
=
(
lmhi
*
png_ptr
->
inv_filter_weights
[
j
])
>>
PNG_WEIGHT_SHIFT
;
}
}
}
}
}
lmlo
=
(
lmlo
*
png_ptr
->
inv_filter_costs
[
PNG_FILTER_VALUE_PAETH
])
>>
/* Up filter */
PNG_COST_SHIFT
;
if
(
filter_to_do
==
PNG_FILTER_UP
)
{
lmhi
=
(
lmhi
*
png_ptr
->
inv_filter_costs
[
PNG_FILTER_VALUE_PAETH
])
>>
png_setup_up_row_only
(
png_ptr
,
row_bytes
);
PNG_COST_SHIFT
;
best_row
=
png_ptr
->
try_row
;
}
if
(
lmhi
>
PNG_HIMASK
)
else
if
((
filter_to_do
&
PNG_FILTER_UP
)
!=
0
)
lmins
=
PNG_MAXSUM
;
{
size_t
sum
;
size_t
lmins
=
mins
;
else
sum
=
png_setup_up_row
(
png_ptr
,
row_bytes
,
lmins
);
lmins
=
(
lmhi
<<
PNG_HISHIFT
)
+
lmlo
;
}
#endif
for
(
i
=
0
,
rp
=
row_buf
+
1
,
dp
=
png_ptr
->
paeth_row
+
1
,
if
(
sum
<
mins
)
pp
=
prev_row
+
1
;
i
<
bpp
;
i
++
)
{
{
v
=
*
dp
++
=
(
png_byte
)(((
int
)
*
rp
++
-
(
int
)
*
pp
++
)
&
0xff
);
mins
=
sum
;
best_row
=
png_ptr
->
try_row
;
sum
+=
(
v
<
128
)
?
v
:
256
-
v
;
if
(
png_ptr
->
tst_row
!=
NULL
)
{
png_ptr
->
try_row
=
png_ptr
->
tst_row
;
png_ptr
->
tst_row
=
best_row
;
}
}
}
}
for
(
lp
=
row_buf
+
1
,
cp
=
prev_row
+
1
;
i
<
row_bytes
;
i
++
)
/* Avg filter */
{
if
(
filter_to_do
==
PNG_FILTER_AVG
)
int
a
,
b
,
c
,
pa
,
pb
,
pc
,
p
;
{
png_setup_avg_row_only
(
png_ptr
,
bpp
,
row_bytes
);
b
=
*
pp
++
;
best_row
=
png_ptr
->
try_row
;
c
=
*
cp
++
;
}
a
=
*
lp
++
;
#ifndef PNG_SLOW_PAETH
p
=
b
-
c
;
pc
=
a
-
c
;
#ifdef PNG_USE_ABS
pa
=
abs
(
p
);
pb
=
abs
(
pc
);
pc
=
abs
(
p
+
pc
);
#else
pa
=
p
<
0
?
-
p
:
p
;
pb
=
pc
<
0
?
-
pc
:
pc
;
pc
=
(
p
+
pc
)
<
0
?
-
(
p
+
pc
)
:
p
+
pc
;
#endif
p
=
(
pa
<=
pb
&&
pa
<=
pc
)
?
a
:
(
pb
<=
pc
)
?
b
:
c
;
#else
/* PNG_SLOW_PAETH */
p
=
a
+
b
-
c
;
pa
=
abs
(
p
-
a
);
pb
=
abs
(
p
-
b
);
pc
=
abs
(
p
-
c
);
if
(
pa
<=
pb
&&
pa
<=
pc
)
p
=
a
;
else
if
(
pb
<=
pc
)
p
=
b
;
else
p
=
c
;
#endif
/* PNG_SLOW_PAETH */
v
=
*
dp
++
=
(
png_byte
)(((
int
)
*
rp
++
-
p
)
&
0xff
);
sum
+=
(
v
<
128
)
?
v
:
256
-
v
;
else
if
((
filter_to_do
&
PNG_FILTER_AVG
)
!=
0
)
{
size_t
sum
;
size_t
lmins
=
mins
;
if
(
sum
>
lmins
)
/* We are already worse, don't continue. */
sum
=
png_setup_avg_row
(
png_ptr
,
bpp
,
row_bytes
,
lmins
);
break
;
}
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
if
(
sum
<
mins
)
if
(
png_ptr
->
heuristic_method
==
PNG_FILTER_HEURISTIC_WEIGHTED
)
{
{
int
j
;
mins
=
sum
;
png_uint_32
sumhi
,
sumlo
;
best_row
=
png_ptr
->
try_row
;
sumlo
=
sum
&
PNG_LOMASK
;
if
(
png_ptr
->
tst_row
!=
NULL
)
sumhi
=
(
sum
>>
PNG_HISHIFT
)
&
PNG_HIMASK
;
for
(
j
=
0
;
j
<
num_p_filters
;
j
++
)
{
{
if
(
png_ptr
->
prev_filters
[
j
]
==
PNG_FILTER_VALUE_PAETH
)
png_ptr
->
try_row
=
png_ptr
->
tst_row
;
{
png_ptr
->
tst_row
=
best_row
;
sumlo
=
(
sumlo
*
png_ptr
->
filter_weights
[
j
])
>>
PNG_WEIGHT_SHIFT
;
sumhi
=
(
sumhi
*
png_ptr
->
filter_weights
[
j
])
>>
PNG_WEIGHT_SHIFT
;
}
}
}
}
}
sumlo
=
(
sumlo
*
png_ptr
->
filter_costs
[
PNG_FILTER_VALUE_PAETH
])
>>
/* Paeth filter */
PNG_COST_SHIFT
;
if
(
filter_to_do
==
PNG_FILTER_PAETH
)
{
png_setup_paeth_row_only
(
png_ptr
,
bpp
,
row_bytes
);
best_row
=
png_ptr
->
try_row
;
}
sumhi
=
(
sumhi
*
png_ptr
->
filter_costs
[
PNG_FILTER_VALUE_PAETH
])
>>
else
if
((
filter_to_do
&
PNG_FILTER_PAETH
)
!=
0
)
PNG_COST_SHIFT
;
{
size_t
sum
;
size_t
lmins
=
mins
;
if
(
sumhi
>
PNG_HIMASK
)
sum
=
png_setup_paeth_row
(
png_ptr
,
bpp
,
row_bytes
,
lmins
);
sum
=
PNG_MAXSUM
;
else
sum
=
(
sumhi
<<
PNG_HISHIFT
)
+
sumlo
;
}
#endif
if
(
sum
<
mins
)
if
(
sum
<
mins
)
{
{
best_row
=
png_ptr
->
paeth_row
;
best_row
=
png_ptr
->
try_row
;
if
(
png_ptr
->
tst_row
!=
NULL
)
{
png_ptr
->
try_row
=
png_ptr
->
tst_row
;
png_ptr
->
tst_row
=
best_row
;
}
}
}
}
}
#endif
/* PNG_WRITE_FILTER_SUPPORTED */
/* Do the actual writing of the filtered row data from the chosen filter. */
/* Do the actual writing of the filtered row data from the chosen filter. */
png_write_filtered_row
(
png_ptr
,
best_row
,
row_info
->
rowbytes
+
1
);
png_write_filtered_row
(
png_ptr
,
best_row
,
row_info
->
rowbytes
+
1
);
#ifdef PNG_WRITE_FILTER_SUPPORTED
#endif
/* WRITE_FILTER */
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
/* Save the type of filter we picked this time for future calculations */
if
(
png_ptr
->
num_prev_filters
>
0
)
{
int
j
;
for
(
j
=
1
;
j
<
num_p_filters
;
j
++
)
{
png_ptr
->
prev_filters
[
j
]
=
png_ptr
->
prev_filters
[
j
-
1
];
}
png_ptr
->
prev_filters
[
j
]
=
best_row
[
0
];
}
#endif
#endif
/* PNG_WRITE_FILTER_SUPPORTED */
}
}
/* Do the actual writing of a previously filtered row. */
/* Do the actual writing of a previously filtered row. */
static
void
static
void
png_write_filtered_row
(
png_structrp
png_ptr
,
png_bytep
filtered_row
,
png_write_filtered_row
(
png_structrp
png_ptr
,
png_bytep
filtered_row
,
png_
size_t
full_row_length
/*includes filter byte*/
)
size_t
full_row_length
/*includes filter byte*/
)
{
{
png_debug
(
1
,
"in png_write_filtered_row"
);
png_debug
(
1
,
"in png_write_filtered_row"
);
...
@@ -2997,6 +2753,7 @@ png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row,
...
@@ -2997,6 +2753,7 @@ png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row,
png_compress_IDAT
(
png_ptr
,
filtered_row
,
full_row_length
,
Z_NO_FLUSH
);
png_compress_IDAT
(
png_ptr
,
filtered_row
,
full_row_length
,
Z_NO_FLUSH
);
#ifdef PNG_WRITE_FILTER_SUPPORTED
/* Swap the current and previous rows */
/* Swap the current and previous rows */
if
(
png_ptr
->
prev_row
!=
NULL
)
if
(
png_ptr
->
prev_row
!=
NULL
)
{
{
...
@@ -3006,6 +2763,7 @@ png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row,
...
@@ -3006,6 +2763,7 @@ png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row,
png_ptr
->
prev_row
=
png_ptr
->
row_buf
;
png_ptr
->
prev_row
=
png_ptr
->
row_buf
;
png_ptr
->
row_buf
=
tptr
;
png_ptr
->
row_buf
=
tptr
;
}
}
#endif
/* WRITE_FILTER */
/* Finish row - updates counters and flushes zlib if last row */
/* Finish row - updates counters and flushes zlib if last row */
png_write_finish_row
(
png_ptr
);
png_write_finish_row
(
png_ptr
);
...
@@ -3018,6 +2776,6 @@ png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row,
...
@@ -3018,6 +2776,6 @@ png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row,
{
{
png_write_flush
(
png_ptr
);
png_write_flush
(
png_ptr
);
}
}
#endif
#endif
/* WRITE_FLUSH */
}
}
#endif
/*
PNG_
WRITE
_SUPPORTED
*/
#endif
/* WRITE */
Prev
1
2
Next
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