mirror of
https://git.code.sf.net/p/libpng/code.git
synced 2025-07-10 18:04:09 +02:00
[libpng15] Simplified read/write API initial version; basic read/write tested
on a variety of images, limited documentation (in the header file.)
This commit is contained in:
parent
92a1d46c8d
commit
7875d534cb
2
ANNOUNCE
2
ANNOUNCE
@ -58,6 +58,8 @@ Version 1.5.7beta02 [November 8, 2011]
|
|||||||
Updated scripts/pnglibconf.mak and scripts/makefile.std to handle the
|
Updated scripts/pnglibconf.mak and scripts/makefile.std to handle the
|
||||||
new PNG_JOIN macro.
|
new PNG_JOIN macro.
|
||||||
Added versioning to pnglibconf.h comments.
|
Added versioning to pnglibconf.h comments.
|
||||||
|
Simplified read/write API initial version; basic read/write tested on
|
||||||
|
a variety of images, limited documentation (in the header file.)
|
||||||
|
|
||||||
Send comments/corrections/commendations to png-mng-implement at lists.sf.net:
|
Send comments/corrections/commendations to png-mng-implement at lists.sf.net:
|
||||||
(subscription required; visit
|
(subscription required; visit
|
||||||
|
|||||||
2
CHANGES
2
CHANGES
@ -3703,6 +3703,8 @@ Version 1.5.7beta02 [November 8, 2011]
|
|||||||
Updated scripts/pnglibconf.mak and scripts/makefile.std to handle the
|
Updated scripts/pnglibconf.mak and scripts/makefile.std to handle the
|
||||||
new PNG_JOIN macro.
|
new PNG_JOIN macro.
|
||||||
Added versioning to pnglibconf.h comments.
|
Added versioning to pnglibconf.h comments.
|
||||||
|
Simplified read/write API initial version; basic read/write tested on
|
||||||
|
a variety of images, limited documentation (in the header file.)
|
||||||
|
|
||||||
Send comments/corrections/commendations to png-mng-implement at lists.sf.net
|
Send comments/corrections/commendations to png-mng-implement at lists.sf.net
|
||||||
(subscription required; visit
|
(subscription required; visit
|
||||||
|
|||||||
418
png.c
418
png.c
@ -645,13 +645,13 @@ png_get_copyright(png_const_structp png_ptr)
|
|||||||
#else
|
#else
|
||||||
# ifdef __STDC__
|
# ifdef __STDC__
|
||||||
return PNG_STRING_NEWLINE \
|
return PNG_STRING_NEWLINE \
|
||||||
"libpng version 1.5.7beta02 - November 4, 2011" PNG_STRING_NEWLINE \
|
"libpng version 1.5.7beta02 - November 8, 2011" PNG_STRING_NEWLINE \
|
||||||
"Copyright (c) 1998-2011 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \
|
"Copyright (c) 1998-2011 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \
|
||||||
"Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
|
"Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
|
||||||
"Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \
|
"Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \
|
||||||
PNG_STRING_NEWLINE;
|
PNG_STRING_NEWLINE;
|
||||||
# else
|
# else
|
||||||
return "libpng version 1.5.7beta02 - November 4, 2011\
|
return "libpng version 1.5.7beta02 - November 8, 2011\
|
||||||
Copyright (c) 1998-2011 Glenn Randers-Pehrson\
|
Copyright (c) 1998-2011 Glenn Randers-Pehrson\
|
||||||
Copyright (c) 1996-1997 Andreas Dilger\
|
Copyright (c) 1996-1997 Andreas Dilger\
|
||||||
Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.";
|
Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.";
|
||||||
@ -2854,4 +2854,418 @@ png_build_gamma_table(png_structp png_ptr, int bit_depth)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* READ_GAMMA */
|
#endif /* READ_GAMMA */
|
||||||
|
|
||||||
|
/* sRGB support */
|
||||||
|
#if defined PNG_SIMPLIFIED_READ_SUPPORTED ||\
|
||||||
|
defined PNG_SIMPLIFIED_WRITE_SUPPORTED
|
||||||
|
/* sRGB conversion tables; these are machine generated with the following code.
|
||||||
|
*/
|
||||||
|
#ifdef PNG_INCLUDE_SELF_GENERATING_AND_SELF_DOCUMENTING_CODE
|
||||||
|
#define _C99_SOURCE 1
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
static unsigned int max_input = 255*65535;
|
||||||
|
|
||||||
|
double sRGB(unsigned int i)
|
||||||
|
{
|
||||||
|
double l = i;
|
||||||
|
l /= max_input;
|
||||||
|
|
||||||
|
if (l <= 0.0031308)
|
||||||
|
l *= 12.92;
|
||||||
|
|
||||||
|
else
|
||||||
|
l = 1.055 * pow(l, 1/2.4) - 0.055;
|
||||||
|
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int invsRGB(unsigned int i)
|
||||||
|
{
|
||||||
|
double l = i/255.;
|
||||||
|
|
||||||
|
if (l <= 0.04045)
|
||||||
|
l /= 12.92;
|
||||||
|
|
||||||
|
else
|
||||||
|
l = pow((l+0.055)/1.055, 2.4);
|
||||||
|
|
||||||
|
l *= 65535;
|
||||||
|
return nearbyint(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
unsigned int i, i16;
|
||||||
|
unsigned short base[512];
|
||||||
|
unsigned char delta[512];
|
||||||
|
double max_error = 0;
|
||||||
|
double max_error16 = 0;
|
||||||
|
unsigned int error_count = 0;
|
||||||
|
unsigned int error_count16 = 0;
|
||||||
|
|
||||||
|
for (i=0; i<=511; ++i)
|
||||||
|
{
|
||||||
|
double lo = 255 * sRGB(i << 15);
|
||||||
|
double hi = 255 * sRGB((i+1) << 15);
|
||||||
|
unsigned int calc;
|
||||||
|
|
||||||
|
calc = nearbyint((lo+.5) * 256);
|
||||||
|
if (calc > 65535)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "table[%d][0]: overflow %08x (%d)\n", i, calc, calc);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
base[i] = calc;
|
||||||
|
|
||||||
|
calc = nearbyint((hi-lo) * 32);
|
||||||
|
if (calc > 255)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "table[%d][1]: overflow %08x (%d)\n", i, calc, calc);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
delta[i] = calc;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0; i <= max_input; ++i)
|
||||||
|
{
|
||||||
|
unsigned int iexact = nearbyint(255*sRGB(i));
|
||||||
|
unsigned int icalc = base[i>>15] + (((i&0x7fff)*delta[i>>15])>>12);
|
||||||
|
icalc >>= 8;
|
||||||
|
|
||||||
|
if (icalc != iexact)
|
||||||
|
{
|
||||||
|
double err = fabs(255*sRGB(i) - icalc);
|
||||||
|
|
||||||
|
++error_count;
|
||||||
|
if (err > .646)
|
||||||
|
{
|
||||||
|
printf(
|
||||||
|
"/* 0x%08x: exact: %3d, got: %3d [tables: %08x, %08x] (%f) */\n",
|
||||||
|
i, iexact, icalc, base[i>>15], delta[i>>15], err);
|
||||||
|
if (err > max_error)
|
||||||
|
max_error = err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i16=0; i16 <= 65535; ++i16)
|
||||||
|
{
|
||||||
|
unsigned int i = 255*i16;
|
||||||
|
unsigned int iexact = nearbyint(255*sRGB(i));
|
||||||
|
unsigned int icalc = base[i>>15] + (((i&0x7fff)*delta[i>>15])>>12);
|
||||||
|
icalc >>= 8;
|
||||||
|
|
||||||
|
if (icalc != iexact)
|
||||||
|
{
|
||||||
|
double err = fabs(255*sRGB(i) - icalc);
|
||||||
|
|
||||||
|
++error_count16;
|
||||||
|
if (err > max_error16)
|
||||||
|
max_error16 = err;
|
||||||
|
|
||||||
|
if (abs(icalc - iexact) > 1)
|
||||||
|
printf(
|
||||||
|
"/* 0x%04x: exact: %3d, got: %3d [tables: %08x, %08x] (%f) */\n",
|
||||||
|
i16, iexact, icalc, base[i>>15], delta[i>>15], err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("/* maximum error: %g, %g%% of readings */\n", max_error,
|
||||||
|
(100.*error_count)/max_input);
|
||||||
|
printf("/* maximum 16-bit error: %g, %g%% of readings */\n", max_error16,
|
||||||
|
(100.*error_count16)/65535);
|
||||||
|
|
||||||
|
printf("PNG_CONST png_uint_16 png_sRGB_table[256] =\n{\n ");
|
||||||
|
for (i=0; i<255; )
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
printf("%d,", invsRGB(i++));
|
||||||
|
}
|
||||||
|
while ((i & 0x7) != 0 && i<255);
|
||||||
|
if (i<255) printf("\n ");
|
||||||
|
}
|
||||||
|
printf("%d\n};\n\n", invsRGB(i));
|
||||||
|
|
||||||
|
|
||||||
|
printf("PNG_CONST png_uint_16 png_sRGB_base[512] =\n{\n ");
|
||||||
|
for (i=0; i<511; )
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
printf("%d,", base[i++]);
|
||||||
|
}
|
||||||
|
while ((i & 0x7) != 0 && i<511);
|
||||||
|
if (i<511) printf("\n ");
|
||||||
|
}
|
||||||
|
printf("%d\n};\n\n", base[i]);
|
||||||
|
|
||||||
|
printf("PNG_CONST png_byte png_sRGB_delta[512] =\n{\n ");
|
||||||
|
for (i=0; i<511; )
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
printf("%d,", delta[i++]);
|
||||||
|
}
|
||||||
|
while ((i & 0xf) != 0 && i<511);
|
||||||
|
if (i<511) printf("\n ");
|
||||||
|
}
|
||||||
|
printf("%d\n};\n\n", delta[i]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* self documenting code */
|
||||||
|
|
||||||
|
/* The result is a set of tables with the following errors: */
|
||||||
|
/* 0x000148c1: exact: 16, got: 15 [tables: 00000d36, 0000009d] (0.646071) */
|
||||||
|
/* 0x000148c2: exact: 16, got: 15 [tables: 00000d36, 0000009d] (0.646218) */
|
||||||
|
/* 0x000148c3: exact: 16, got: 15 [tables: 00000d36, 0000009d] (0.646365) */
|
||||||
|
/* maximum error: 0.646365, 0.494416% of readings */
|
||||||
|
/* maximum 16-bit error: 0.644455, 0.5066% of readings */
|
||||||
|
|
||||||
|
#ifdef PNG_SIMPLIFIED_READ_SUPPORTED
|
||||||
|
/* The convert-to-sRGB table is only currently required for read. */
|
||||||
|
PNG_CONST png_uint_16 png_sRGB_table[256] =
|
||||||
|
{
|
||||||
|
0,20,40,60,80,99,119,139,
|
||||||
|
159,179,199,219,241,264,288,313,
|
||||||
|
340,367,396,427,458,491,526,562,
|
||||||
|
599,637,677,718,761,805,851,898,
|
||||||
|
947,997,1048,1101,1156,1212,1270,1330,
|
||||||
|
1391,1453,1517,1583,1651,1720,1790,1863,
|
||||||
|
1937,2013,2090,2170,2250,2333,2418,2504,
|
||||||
|
2592,2681,2773,2866,2961,3058,3157,3258,
|
||||||
|
3360,3464,3570,3678,3788,3900,4014,4129,
|
||||||
|
4247,4366,4488,4611,4736,4864,4993,5124,
|
||||||
|
5257,5392,5530,5669,5810,5953,6099,6246,
|
||||||
|
6395,6547,6700,6856,7014,7174,7335,7500,
|
||||||
|
7666,7834,8004,8177,8352,8528,8708,8889,
|
||||||
|
9072,9258,9445,9635,9828,10022,10219,10417,
|
||||||
|
10619,10822,11028,11235,11446,11658,11873,12090,
|
||||||
|
12309,12530,12754,12980,13209,13440,13673,13909,
|
||||||
|
14146,14387,14629,14874,15122,15371,15623,15878,
|
||||||
|
16135,16394,16656,16920,17187,17456,17727,18001,
|
||||||
|
18277,18556,18837,19121,19407,19696,19987,20281,
|
||||||
|
20577,20876,21177,21481,21787,22096,22407,22721,
|
||||||
|
23038,23357,23678,24002,24329,24658,24990,25325,
|
||||||
|
25662,26001,26344,26688,27036,27386,27739,28094,
|
||||||
|
28452,28813,29176,29542,29911,30282,30656,31033,
|
||||||
|
31412,31794,32179,32567,32957,33350,33745,34143,
|
||||||
|
34544,34948,35355,35764,36176,36591,37008,37429,
|
||||||
|
37852,38278,38706,39138,39572,40009,40449,40891,
|
||||||
|
41337,41785,42236,42690,43147,43606,44069,44534,
|
||||||
|
45002,45473,45947,46423,46903,47385,47871,48359,
|
||||||
|
48850,49344,49841,50341,50844,51349,51858,52369,
|
||||||
|
52884,53401,53921,54445,54971,55500,56032,56567,
|
||||||
|
57105,57646,58190,58737,59287,59840,60396,60955,
|
||||||
|
61517,62082,62650,63221,63795,64372,64952,65535
|
||||||
|
};
|
||||||
|
#endif /* simplified read only */
|
||||||
|
|
||||||
|
/* The base/delta tables are required for both read and write (but currently
|
||||||
|
* only the simplified versions.)
|
||||||
|
*/
|
||||||
|
PNG_CONST png_uint_16 png_sRGB_base[512] =
|
||||||
|
{
|
||||||
|
128,1782,3382,4641,5673,6563,7355,8072,
|
||||||
|
8732,9346,9920,10463,10977,11466,11935,12384,
|
||||||
|
12815,13232,13634,14024,14402,14768,15125,15473,
|
||||||
|
15811,16142,16465,16781,17090,17393,17689,17980,
|
||||||
|
18266,18546,18822,19093,19359,19621,19879,20133,
|
||||||
|
20383,20630,20873,21113,21349,21583,21813,22040,
|
||||||
|
22265,22487,22706,22923,23138,23350,23559,23767,
|
||||||
|
23972,24175,24376,24575,24772,24967,25160,25352,
|
||||||
|
25541,25729,25916,26100,26283,26465,26645,26823,
|
||||||
|
27000,27176,27350,27523,27694,27865,28033,28201,
|
||||||
|
28368,28533,28697,28860,29021,29182,29341,29500,
|
||||||
|
29657,29813,29969,30123,30276,30428,30580,30730,
|
||||||
|
30880,31028,31176,31323,31469,31614,31758,31902,
|
||||||
|
32044,32186,32327,32468,32607,32746,32884,33021,
|
||||||
|
33158,33294,33429,33563,33697,33830,33963,34095,
|
||||||
|
34226,34356,34486,34616,34744,34872,35000,35127,
|
||||||
|
35253,35379,35504,35629,35753,35876,35999,36122,
|
||||||
|
36244,36365,36486,36606,36726,36845,36964,37083,
|
||||||
|
37201,37318,37435,37551,37667,37783,37898,38013,
|
||||||
|
38127,38241,38354,38467,38580,38692,38803,38915,
|
||||||
|
39025,39136,39246,39356,39465,39574,39682,39790,
|
||||||
|
39898,40005,40112,40219,40325,40431,40537,40642,
|
||||||
|
40747,40851,40955,41059,41163,41266,41369,41471,
|
||||||
|
41573,41675,41776,41878,41978,42079,42179,42279,
|
||||||
|
42379,42478,42577,42676,42774,42873,42970,43068,
|
||||||
|
43165,43262,43359,43455,43552,43647,43743,43838,
|
||||||
|
43934,44028,44123,44217,44311,44405,44498,44592,
|
||||||
|
44685,44777,44870,44962,45054,45146,45238,45329,
|
||||||
|
45420,45511,45601,45692,45782,45872,45961,46051,
|
||||||
|
46140,46229,46318,46406,46494,46582,46670,46758,
|
||||||
|
46845,46933,47020,47107,47193,47280,47366,47452,
|
||||||
|
47538,47623,47708,47794,47879,47963,48048,48132,
|
||||||
|
48217,48301,48384,48468,48552,48635,48718,48801,
|
||||||
|
48884,48966,49048,49131,49213,49294,49376,49457,
|
||||||
|
49539,49620,49701,49781,49862,49942,50023,50103,
|
||||||
|
50183,50262,50342,50421,50501,50580,50659,50738,
|
||||||
|
50816,50895,50973,51051,51129,51207,51284,51362,
|
||||||
|
51439,51517,51594,51670,51747,51824,51900,51977,
|
||||||
|
52053,52129,52205,52280,52356,52431,52507,52582,
|
||||||
|
52657,52732,52807,52881,52956,53030,53104,53178,
|
||||||
|
53252,53326,53399,53473,53546,53620,53693,53766,
|
||||||
|
53839,53911,53984,54056,54129,54201,54273,54345,
|
||||||
|
54417,54489,54560,54632,54703,54774,54845,54916,
|
||||||
|
54987,55058,55128,55199,55269,55340,55410,55480,
|
||||||
|
55550,55619,55689,55759,55828,55897,55967,56036,
|
||||||
|
56105,56174,56242,56311,56380,56448,56516,56585,
|
||||||
|
56653,56721,56789,56857,56924,56992,57059,57127,
|
||||||
|
57194,57261,57328,57395,57462,57529,57595,57662,
|
||||||
|
57728,57795,57861,57927,57993,58059,58125,58191,
|
||||||
|
58256,58322,58387,58453,58518,58583,58648,58713,
|
||||||
|
58778,58843,58908,58972,59037,59101,59165,59230,
|
||||||
|
59294,59358,59422,59486,59549,59613,59677,59740,
|
||||||
|
59804,59867,59930,59993,60056,60119,60182,60245,
|
||||||
|
60308,60370,60433,60495,60558,60620,60682,60744,
|
||||||
|
60806,60868,60930,60992,61054,61115,61177,61238,
|
||||||
|
61300,61361,61422,61483,61544,61605,61666,61727,
|
||||||
|
61788,61848,61909,61969,62030,62090,62150,62210,
|
||||||
|
62271,62331,62391,62450,62510,62570,62630,62689,
|
||||||
|
62749,62808,62867,62927,62986,63045,63104,63163,
|
||||||
|
63222,63281,63339,63398,63457,63515,63574,63632,
|
||||||
|
63691,63749,63807,63865,63923,63981,64039,64097,
|
||||||
|
64155,64212,64270,64328,64385,64442,64500,64557,
|
||||||
|
64614,64671,64729,64786,64843,64899,64956,65013,
|
||||||
|
65070,65126,65183,65239,65296,65352,65408,65465
|
||||||
|
};
|
||||||
|
|
||||||
|
PNG_CONST png_byte png_sRGB_delta[512] =
|
||||||
|
{
|
||||||
|
207,200,157,129,111,99,90,82,77,72,68,64,61,59,56,54,
|
||||||
|
52,50,49,47,46,45,43,42,41,40,39,39,38,37,36,36,
|
||||||
|
35,34,34,33,33,32,32,31,31,30,30,30,29,29,28,28,
|
||||||
|
28,27,27,27,26,26,26,26,25,25,25,25,24,24,24,24,
|
||||||
|
23,23,23,23,23,22,22,22,22,22,22,21,21,21,21,21,
|
||||||
|
21,20,20,20,20,20,20,20,20,19,19,19,19,19,19,19,
|
||||||
|
19,18,18,18,18,18,18,18,18,18,18,17,17,17,17,17,
|
||||||
|
17,17,17,17,17,17,16,16,16,16,16,16,16,16,16,16,
|
||||||
|
16,16,16,16,15,15,15,15,15,15,15,15,15,15,15,15,
|
||||||
|
15,15,15,15,14,14,14,14,14,14,14,14,14,14,14,14,
|
||||||
|
14,14,14,14,14,14,14,13,13,13,13,13,13,13,13,13,
|
||||||
|
13,13,13,13,13,13,13,13,13,13,13,13,13,13,12,12,
|
||||||
|
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
|
||||||
|
12,12,12,12,12,12,12,12,12,12,12,12,11,11,11,11,
|
||||||
|
11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
|
||||||
|
11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
|
||||||
|
11,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
|
||||||
|
10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
|
||||||
|
10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
|
||||||
|
10,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
|
||||||
|
9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
|
||||||
|
9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
|
||||||
|
9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
|
||||||
|
9,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
||||||
|
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
||||||
|
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
||||||
|
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
||||||
|
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
|
||||||
|
8,8,8,8,8,8,8,8,8,7,7,7,7,7,7,7,
|
||||||
|
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
||||||
|
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
|
||||||
|
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Hence the define in pngpriv.h to calculate the sRGB value of a linear value
|
||||||
|
* expressed as a fixed point integer scaled by 255*65535 (note that the tables
|
||||||
|
* include the +.5 to do rounding correctly.)
|
||||||
|
*/
|
||||||
|
#endif /* SIMPLIFIED READ/WRITE sRGB support */
|
||||||
|
|
||||||
|
/* SIMPLIFIED READ/WRITE SUPPORT */
|
||||||
|
#if defined PNG_SIMPLIFIED_READ_SUPPORTED ||\
|
||||||
|
defined PNG_SIMPLIFIED_WRITE_SUPPORTED
|
||||||
|
static int
|
||||||
|
png_image_free_function(png_voidp argument)
|
||||||
|
{
|
||||||
|
png_imagep image = argument;
|
||||||
|
png_controlp cp = image->opaque;
|
||||||
|
png_control c;
|
||||||
|
|
||||||
|
/* Double check that we have a png_ptr - it should be impossible to get here
|
||||||
|
* without one.
|
||||||
|
*/
|
||||||
|
if (cp->png_ptr == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* First free any data held in the control structure. */
|
||||||
|
# ifdef PNG_STDIO_SUPPORTED
|
||||||
|
if (cp->owned_file)
|
||||||
|
{
|
||||||
|
FILE *fp = cp->png_ptr->io_ptr;
|
||||||
|
cp->owned_file = 0;
|
||||||
|
|
||||||
|
/* Ignore errors here. */
|
||||||
|
if (fp != NULL)
|
||||||
|
{
|
||||||
|
cp->png_ptr->io_ptr = NULL;
|
||||||
|
(void)fclose(fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* Copy the control structure so that the original, allocated, version can be
|
||||||
|
* safely freed. Notice that a png_error here stops the remainder of the
|
||||||
|
* cleanup, but this is probably fine because that would indicate bad memory
|
||||||
|
* problems anyway.
|
||||||
|
*/
|
||||||
|
c = *cp;
|
||||||
|
image->opaque = &c;
|
||||||
|
png_free(c.png_ptr, cp);
|
||||||
|
|
||||||
|
/* Then the structures, calling the correct API. */
|
||||||
|
if (c.for_write)
|
||||||
|
{
|
||||||
|
# ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
|
||||||
|
png_destroy_write_struct(&c.png_ptr, &c.info_ptr);
|
||||||
|
# else
|
||||||
|
png_error(c.png_ptr, "simplified write not supported");
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
# ifdef PNG_SIMPLIFIED_READ_SUPPORTED
|
||||||
|
png_destroy_read_struct(&c.png_ptr, &c.info_ptr, NULL);
|
||||||
|
# else
|
||||||
|
png_error(c.png_ptr, "simplified read not supported");
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Success. */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PNGAPI
|
||||||
|
png_image_free(png_imagep image)
|
||||||
|
{
|
||||||
|
/* Safely call the real function, but only if doing so is safe at this point
|
||||||
|
* (if not inside an error handling context). Otherwise assume
|
||||||
|
* png_safe_execute will call this API after the return.
|
||||||
|
*/
|
||||||
|
if (image != NULL && image->opaque != NULL &&
|
||||||
|
image->opaque->error_buf == NULL)
|
||||||
|
{
|
||||||
|
/* Ignore errors here: */
|
||||||
|
(void)png_safe_execute(image, png_image_free_function, image);
|
||||||
|
image->opaque = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int /* PRIVATE */
|
||||||
|
png_image_error(png_imagep image, png_const_charp error_message)
|
||||||
|
{
|
||||||
|
/* Utility to log an error. */
|
||||||
|
png_safecat(image->message, sizeof image->message, 0, error_message);
|
||||||
|
image->warning_or_error = 1;
|
||||||
|
png_image_free(image);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* SIMPLIFIED READ/WRITE */
|
||||||
#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */
|
#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */
|
||||||
|
|||||||
283
png.h
283
png.h
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
/* png.h - header file for PNG reference library
|
/* png.h - header file for PNG reference library
|
||||||
*
|
*
|
||||||
* libpng version 1.5.7beta02 - November 5, 2011
|
* libpng version 1.5.7beta02 - November 8, 2011
|
||||||
* Copyright (c) 1998-2011 Glenn Randers-Pehrson
|
* Copyright (c) 1998-2011 Glenn Randers-Pehrson
|
||||||
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
|
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
|
||||||
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
|
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
|
||||||
@ -11,7 +11,7 @@
|
|||||||
* Authors and maintainers:
|
* Authors and maintainers:
|
||||||
* libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat
|
* libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat
|
||||||
* libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger
|
* libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger
|
||||||
* libpng versions 0.97, January 1998, through 1.5.7beta02 - November 5, 2011: Glenn
|
* libpng versions 0.97, January 1998, through 1.5.7beta02 - November 8, 2011: Glenn
|
||||||
* See also "Contributing Authors", below.
|
* See also "Contributing Authors", below.
|
||||||
*
|
*
|
||||||
* Note about libpng version numbers:
|
* Note about libpng version numbers:
|
||||||
@ -195,7 +195,7 @@
|
|||||||
*
|
*
|
||||||
* This code is released under the libpng license.
|
* This code is released under the libpng license.
|
||||||
*
|
*
|
||||||
* libpng versions 1.2.6, August 15, 2004, through 1.5.7beta02, November 5, 2011, are
|
* libpng versions 1.2.6, August 15, 2004, through 1.5.7beta02, November 8, 2011, are
|
||||||
* Copyright (c) 2004, 2006-2011 Glenn Randers-Pehrson, and are
|
* Copyright (c) 2004, 2006-2011 Glenn Randers-Pehrson, and are
|
||||||
* distributed according to the same disclaimer and license as libpng-1.2.5
|
* distributed according to the same disclaimer and license as libpng-1.2.5
|
||||||
* with the following individual added to the list of Contributing Authors:
|
* with the following individual added to the list of Contributing Authors:
|
||||||
@ -307,7 +307,7 @@
|
|||||||
* Y2K compliance in libpng:
|
* Y2K compliance in libpng:
|
||||||
* =========================
|
* =========================
|
||||||
*
|
*
|
||||||
* November 5, 2011
|
* November 8, 2011
|
||||||
*
|
*
|
||||||
* Since the PNG Development group is an ad-hoc body, we can't make
|
* Since the PNG Development group is an ad-hoc body, we can't make
|
||||||
* an official declaration.
|
* an official declaration.
|
||||||
@ -365,12 +365,15 @@
|
|||||||
* describes how to use libpng, and the file example.c summarizes it
|
* describes how to use libpng, and the file example.c summarizes it
|
||||||
* with some code on which to build. This file is useful for looking
|
* with some code on which to build. This file is useful for looking
|
||||||
* at the actual function definitions and structure components.
|
* at the actual function definitions and structure components.
|
||||||
|
*
|
||||||
|
* If you just need to read a PNG file and don't want to read the documentation
|
||||||
|
* skip to the end of this file and read the section entitled 'simplified API'.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Version information for png.h - this should match the version in png.c */
|
/* Version information for png.h - this should match the version in png.c */
|
||||||
#define PNG_LIBPNG_VER_STRING "1.5.7beta02"
|
#define PNG_LIBPNG_VER_STRING "1.5.7beta02"
|
||||||
#define PNG_HEADER_VERSION_STRING \
|
#define PNG_HEADER_VERSION_STRING \
|
||||||
" libpng version 1.5.7beta02 - November 5, 2011\n"
|
" libpng version 1.5.7beta02 - November 8, 2011\n"
|
||||||
|
|
||||||
#define PNG_LIBPNG_VER_SONUM 15
|
#define PNG_LIBPNG_VER_SONUM 15
|
||||||
#define PNG_LIBPNG_VER_DLLNUM 15
|
#define PNG_LIBPNG_VER_DLLNUM 15
|
||||||
@ -488,6 +491,7 @@ extern "C" {
|
|||||||
* 2. Type definitions (base types are defined in pngconf.h), structure
|
* 2. Type definitions (base types are defined in pngconf.h), structure
|
||||||
* definitions.
|
* definitions.
|
||||||
* 3. Exported library functions.
|
* 3. Exported library functions.
|
||||||
|
* 4. Simplified API.
|
||||||
*
|
*
|
||||||
* The library source code has additional files (principally pngpriv.h) that
|
* The library source code has additional files (principally pngpriv.h) that
|
||||||
* allow configuration of the library.
|
* allow configuration of the library.
|
||||||
@ -1124,6 +1128,11 @@ PNG_EXPORT(31, void, png_set_gray_to_rgb, (png_structp png_ptr));
|
|||||||
|
|
||||||
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
|
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
|
||||||
/* Reduce RGB to grayscale. */
|
/* Reduce RGB to grayscale. */
|
||||||
|
#define PNG_ERROR_ACTION_NONE 1
|
||||||
|
#define PNG_ERROR_ACTION_WARN 2
|
||||||
|
#define PNG_ERROR_ACTION_ERROR 3
|
||||||
|
#define PNG_RGB_TO_GRAY_DEFAULT (-1)/*for red/green coefficients*/
|
||||||
|
|
||||||
PNG_FP_EXPORT(32, void, png_set_rgb_to_gray, (png_structp png_ptr,
|
PNG_FP_EXPORT(32, void, png_set_rgb_to_gray, (png_structp png_ptr,
|
||||||
int error_action, double red, double green));
|
int error_action, double red, double green));
|
||||||
PNG_FIXED_EXPORT(33, void, png_set_rgb_to_gray_fixed, (png_structp png_ptr,
|
PNG_FIXED_EXPORT(33, void, png_set_rgb_to_gray_fixed, (png_structp png_ptr,
|
||||||
@ -2611,6 +2620,268 @@ PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i));
|
|||||||
: (png_int_32)png_get_uint_32(buf)))
|
: (png_int_32)png_get_uint_32(buf)))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* SIMPLIFIED API
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Please read the documentation in libpng-manual.txt if you don't understand
|
||||||
|
* what follows.
|
||||||
|
*
|
||||||
|
* The simplified API hides the details of both libpng and the PNG file format
|
||||||
|
* itself. It allows PNG files to be read into a very limited number of
|
||||||
|
* in-memory bitmap formats or to be written from the same formats. If these
|
||||||
|
* formats do not accomodate your needs then you can, and should, use the more
|
||||||
|
* sophisticated APIs above - these support a wide variety of in-memory formats
|
||||||
|
* and a wide variety of sophisticated transformations to those formats as well
|
||||||
|
* as a wide variety of APIs to manipulate ancilliary information.
|
||||||
|
*
|
||||||
|
* To read a PNG file using the simplified API:
|
||||||
|
*
|
||||||
|
* 1) Declare a 'png_image' structure (see below) on the stack and memset() it
|
||||||
|
* to all zero.
|
||||||
|
* 2) Call the appropriate png_image_begin_read... function.
|
||||||
|
* 3) Set the png_image 'format' member to the required format and allocate a
|
||||||
|
* buffer for the image.
|
||||||
|
* 4) Call png_image_finish_read to read the image into your buffer.
|
||||||
|
*
|
||||||
|
* To write a PNG file using the simplified API:
|
||||||
|
*
|
||||||
|
* 1) Declare a 'png_image' structure on the stack and memset() it to all zero.
|
||||||
|
* 2) Initialize the members of the structure that describe the image, setting
|
||||||
|
* the 'format' member to the format of the image in memory.
|
||||||
|
* 3) Call the appropriate png_image_write... function with a pointer to the
|
||||||
|
* image to write the PNG data.
|
||||||
|
*
|
||||||
|
* png_image is a structure that describes the in-memory formant of an image
|
||||||
|
* when it is being read or define the in-memory format of an image that you
|
||||||
|
* need to write:
|
||||||
|
*/
|
||||||
|
typedef struct png_control *png_controlp;
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
png_uint_32 width; /* Image width in pixels (columns) */
|
||||||
|
png_uint_32 height; /* Image height in pixels (rows) */
|
||||||
|
png_uint_32 format; /* Image format as defined below */
|
||||||
|
png_uint_32 flags; /* A bit mask containing informational flags */
|
||||||
|
png_controlp opaque; /* Initialize to NULL, free with png_image_free */
|
||||||
|
|
||||||
|
/* In the event of an error or warning the following field will be set to a
|
||||||
|
* non-zero value and the 'message' field will contain a '\0' terminated
|
||||||
|
* string with the libpng error message.
|
||||||
|
*/
|
||||||
|
png_uint_32 warning_or_error;
|
||||||
|
char message[64];
|
||||||
|
} png_image, *png_imagep;
|
||||||
|
|
||||||
|
/* The pixels (samples) of the image have one to four channels in the range 0 to
|
||||||
|
* 1.0:
|
||||||
|
*
|
||||||
|
* 1: A single gray or luminance channel (G).
|
||||||
|
* 2: A gray/luminance channel and an alpha channel (GA).
|
||||||
|
* 3: Three red, green, blue color channels (RGB).
|
||||||
|
* 4: Three color channels and an alpha channel (RGBA).
|
||||||
|
*
|
||||||
|
* The channels are encoded in one of two ways:
|
||||||
|
*
|
||||||
|
* a) As a small integer, value 0..255, contained in a (png_byte). For the
|
||||||
|
* alpha channel the original value is simple value/255. For the color or
|
||||||
|
* luminance channels the value is encoded according to the sRGB specification
|
||||||
|
* and matches the 8-bit format expected by typical display devices.
|
||||||
|
*
|
||||||
|
* The color/gray channels are not scaled (pre-multiplied) by the alpha
|
||||||
|
* channel and are suitable for passing to color management software.
|
||||||
|
*
|
||||||
|
* b) As a value in the range 0..65535, contained in a (png_uint_16). All
|
||||||
|
* channels can be converted to the original value by dividing by 65535; all
|
||||||
|
* channels are linear. Color channels use the RGB encoding (RGB end-points) of
|
||||||
|
* the sRGB specification. This encoding is identified by the
|
||||||
|
* PNG_FORMAT_FLAG_LINEAR flag below.
|
||||||
|
*
|
||||||
|
* When an alpha channel is present it is expected to denote pixel coverage
|
||||||
|
* of the color or luminance channels and is returned as an associated alpha
|
||||||
|
* channel: the color/gray channels are scaled (pre-multiplied) the alpha value.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* PNG_FORMAT_*
|
||||||
|
*
|
||||||
|
* #defines to be used in png_image::format. Each #define identifies a
|
||||||
|
* particular layout of channel data and, if present, alpha values. There are
|
||||||
|
* separate defines for each of the two channel encodings.
|
||||||
|
*
|
||||||
|
* A format is built up using single bit flag values. Not all combinations are
|
||||||
|
* valid: use the bit flag values below for testing a format returned by the
|
||||||
|
* read APIs, but set formats from the derived values.
|
||||||
|
*
|
||||||
|
* NOTE: libpng can be built with particular features disabled, if you see
|
||||||
|
* compiler errors because the definition of one of the following flags has been
|
||||||
|
* compiled out it is because libpng does not have the required support. It is
|
||||||
|
* possible, however, for the libpng configuration to enable the format on just
|
||||||
|
* read or just write, in that case you will may see an error at run time. You
|
||||||
|
* can guard against this by checking for the definition of:
|
||||||
|
*
|
||||||
|
* PNG_SIMPLIFIED_{READ,WRITE}_{BGR,AFIRST}_SUPPORTED
|
||||||
|
*/
|
||||||
|
#define PNG_FORMAT_FLAG_ALPHA 0x01 /* format with an alpha channel */
|
||||||
|
#define PNG_FORMAT_FLAG_COLOR 0x02 /* color format: otherwise grayscale */
|
||||||
|
#define PNG_FORMAT_FLAG_LINEAR 0x04 /* png_uint_16 channels else png_byte */
|
||||||
|
|
||||||
|
#ifdef PNG_FORMAT_BGR_SUPPORTED
|
||||||
|
# define PNG_FORMAT_FLAG_BGR 0x08 /* BGR colors, else order is RGB */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef PNG_FORMAT_AFIRST_SUPPORTED
|
||||||
|
# define PNG_FORMAT_FLAG_AFIRST 0x10 /* alpha channel comes first */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Supported formats are as follows. Future versions of libpng may support more
|
||||||
|
* formats, for compatibility with older versions simply check if the format
|
||||||
|
* macro is defined using #ifdef. These defines describe the in-memory layout
|
||||||
|
* of the components of the pixels of the image.
|
||||||
|
*
|
||||||
|
* First the single byte formats:
|
||||||
|
*/
|
||||||
|
#define PNG_FORMAT_GRAY 0
|
||||||
|
#define PNG_FORMAT_GA PNG_FORMAT_FLAG_ALPHA
|
||||||
|
#define PNG_FORMAT_AG (PNG_FORMAT_GA|PNG_FORMAT_AFIRST)
|
||||||
|
#define PNG_FORMAT_RGB PNG_FORMAT_FLAG_COLOR
|
||||||
|
#define PNG_FORMAT_BGR (PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_BGR)
|
||||||
|
#define PNG_FORMAT_RGBA (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_ALPHA)
|
||||||
|
#define PNG_FORMAT_ARGB (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_AFIRST)
|
||||||
|
#define PNG_FORMAT_BGRA (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_ALPHA)
|
||||||
|
#define PNG_FORMAT_ABGR (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_AFIRST)
|
||||||
|
|
||||||
|
/* Then the linear (png_uint_16) formats. When naming these "Y" is used to
|
||||||
|
* indicate a luminance channel. The component order within the pixel is
|
||||||
|
* always the same - there is no provision for swapping the order of the
|
||||||
|
* components in the linear format.
|
||||||
|
*/
|
||||||
|
#define PNG_FORMAT_FP_Y PNG_FORMAT_FLAG_FP
|
||||||
|
#define PNG_FORMAT_FP_Y_ALPHA (PNG_FORMAT_FLAG_FP|PNG_FORMAT_FLAG_ALPHA)
|
||||||
|
#define PNG_FORMAT_FP_RGB (PNG_FORMAT_FLAG_FP|PNG_FORMAT_FLAG_COLOR)
|
||||||
|
#define PNG_FORMAT_FP_RGB_ALPHA \
|
||||||
|
(PNG_FORMAT_FLAG_FP|PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA)
|
||||||
|
|
||||||
|
/* PNG_IMAGE macros
|
||||||
|
*
|
||||||
|
* These are convenience macros to derive information from a png_image structure
|
||||||
|
*/
|
||||||
|
#define PNG_IMAGE_CHANNELS(fmt)\
|
||||||
|
(1+((fmt)&(PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA)))
|
||||||
|
/* Return the total number of channels in a given format: 1..4 */
|
||||||
|
|
||||||
|
#define PNG_IMAGE_COMPONENT_SIZE(fmt)\
|
||||||
|
(((fmt) & PNG_FORMAT_FLAG_LINEAR) ? sizeof (png_uint_16) : sizeof (png_byte))
|
||||||
|
/* Return the size in bytes of a single component of a pixel in the image. */
|
||||||
|
|
||||||
|
#define PNG_IMAGE_PIXEL_SIZE(fmt)\
|
||||||
|
(PNG_IMAGE_CHANNELS(fmt) * PNG_IMAGE_COMPONENT_SIZE(fmt))
|
||||||
|
/* Return the size in bytes of a single pixel in the image. */
|
||||||
|
|
||||||
|
#define PNG_IMAGE_ROW_STRIDE(image)\
|
||||||
|
(PNG_IMAGE_CHANNELS((image).format) * (image).width)
|
||||||
|
/* Return the total number of components in a single row of the image; this
|
||||||
|
* is the minimum 'row stride', the minimum count of components between each
|
||||||
|
* row. */
|
||||||
|
|
||||||
|
#define PNG_IMAGE_BUFFER_SIZE(image, row_stride)\
|
||||||
|
(PNG_IMAGE_COMPONENT_SIZE((image).format) * (image).height * (row_stride))
|
||||||
|
/* Return the size, in bytes, of an image buffer given a png_image and a row
|
||||||
|
* stride - the number of components to leave space for in each row. */
|
||||||
|
|
||||||
|
/* PNG_IMAGE_FLAG_*
|
||||||
|
*
|
||||||
|
* Flags containing additional information about the image are held in the
|
||||||
|
* 'flags' field of png_image.
|
||||||
|
*/
|
||||||
|
#define PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB 1
|
||||||
|
/* This indicates the the RGB values of the in-memory bitmap do not
|
||||||
|
* correspond to the red, green and blue end-points defined by sRGB.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef PNG_SIMPLIFIED_READ_SUPPORTED
|
||||||
|
/* READ APIs
|
||||||
|
* ---------
|
||||||
|
*
|
||||||
|
* The png_image passed to the read APIs must have been initialized by setting
|
||||||
|
* the png_controlp field 'opaque' to NULL (or, better, memset the whole thing.)
|
||||||
|
*/
|
||||||
|
#ifdef PNG_STDIO_SUPPORTED
|
||||||
|
PNG_EXPORT(234, int, png_image_begin_read_from_file, (png_imagep image,
|
||||||
|
const char *file_name));
|
||||||
|
/* The named file is opened for read and the image filled in from the PNG
|
||||||
|
* header in the file. */
|
||||||
|
|
||||||
|
PNG_EXPORT(235, int, png_image_begin_read_from_stdio, (png_imagep image,
|
||||||
|
FILE* file));
|
||||||
|
/* The PNG header is read from the stdio FILE object. */
|
||||||
|
#endif /* PNG_STDIO_SUPPORTED */
|
||||||
|
|
||||||
|
PNG_EXPORT(236, int, png_image_begin_read_from_memory, (png_imagep image,
|
||||||
|
png_const_voidp memory, png_size_t size));
|
||||||
|
/* The PNG header is read from the given memory buffer. */
|
||||||
|
|
||||||
|
PNG_EXPORT(237, int, png_image_finish_read, (png_imagep image,
|
||||||
|
png_colorp background, void *buffer, png_int_32 row_stride));
|
||||||
|
/* Finish reading the image into the supplied buffer and clean up the
|
||||||
|
* png_image structure.
|
||||||
|
*
|
||||||
|
* row_stride is the step, in png_byte or float units as appropriate,
|
||||||
|
* between adjacent rows. A positive stride indicates that the top-most row
|
||||||
|
* is first in the buffer - the normal top-down arrangement. A negative
|
||||||
|
* stride indicates that the bottom-most row is first in the buffer.
|
||||||
|
*
|
||||||
|
* background need only be supplied if an alpha channel must be removed from
|
||||||
|
* a png_byte format and the removal is to be done by compositing on a solid
|
||||||
|
* color; otherwise it may be NULL and any composition will be done directly
|
||||||
|
* onto the buffer. The value is an sRGB color to use for the background,
|
||||||
|
* for grayscale output the green channel is used.
|
||||||
|
*
|
||||||
|
* For linear output removing an alpha channel is always done by compositing
|
||||||
|
* on black.
|
||||||
|
*/
|
||||||
|
|
||||||
|
PNG_EXPORT(238, void, png_image_free, (png_imagep image));
|
||||||
|
/* Free any data allocated by libpng in image->opaque, setting the pointer to
|
||||||
|
* NULL. May be called at any time after the structure is initialized. */
|
||||||
|
#endif /* PNG_SIMPLIFIED_READ_SUPPORTED */
|
||||||
|
|
||||||
|
#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
|
||||||
|
/* WRITE APIS
|
||||||
|
* ----------
|
||||||
|
* For write you must initialize a png_image structure to describe the image to
|
||||||
|
* be written:
|
||||||
|
*
|
||||||
|
* opaque: must be initialized to NULL
|
||||||
|
* width: image width in pixels
|
||||||
|
* height: image height in rows
|
||||||
|
* format: the format of the data you wish to write
|
||||||
|
* flags: set to 0 unless one of the defined flags applies; set
|
||||||
|
* PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB for color format images where the RGB
|
||||||
|
* values do not correspond to the colors in sRGB.
|
||||||
|
*/
|
||||||
|
PNG_EXPORT(239, int, png_image_write_to_file, (png_imagep image,
|
||||||
|
const char *file, int convert_to_8bit, const void *buffer,
|
||||||
|
png_int_32 row_stride));
|
||||||
|
/* Write the image to the named file. */
|
||||||
|
|
||||||
|
PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file,
|
||||||
|
int convert_to_8_bit, const void *buffer, png_int_32 row_stride));
|
||||||
|
/* Write the image to the given (FILE*). */
|
||||||
|
|
||||||
|
/* With all write APIs if image is in one of the linear formats with
|
||||||
|
* (png_uint_16) data then setting convert_to_8_bit will cause the output to be
|
||||||
|
* a (png_byte) PNG gamma encoded according to the sRGB specification, otherwise
|
||||||
|
* a 16-bit linear encoded PNG file is written.
|
||||||
|
*
|
||||||
|
* With all APIs row_stride is handled as in the read APIs - it is the spacing
|
||||||
|
* from one row to the next in component sized units (float) and if negative
|
||||||
|
* indicates a bottom-up row layout in the buffer.
|
||||||
|
*/
|
||||||
|
#endif /* PNG_SIMPLIFIED_WRITE_SUPPORTED */
|
||||||
|
/*******************************************************************************
|
||||||
|
* END OF SIMPLIFIED API
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
/* Maintainer: Put new public prototypes here ^, in libpng.3, and project
|
/* Maintainer: Put new public prototypes here ^, in libpng.3, and project
|
||||||
* defs
|
* defs
|
||||||
*/
|
*/
|
||||||
@ -2620,7 +2891,7 @@ PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i));
|
|||||||
* scripts/symbols.def as well.
|
* scripts/symbols.def as well.
|
||||||
*/
|
*/
|
||||||
#ifdef PNG_EXPORT_LAST_ORDINAL
|
#ifdef PNG_EXPORT_LAST_ORDINAL
|
||||||
PNG_EXPORT_LAST_ORDINAL(233);
|
PNG_EXPORT_LAST_ORDINAL(240);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
80
pngerror.c
80
pngerror.c
@ -673,4 +673,84 @@ png_set_strip_error_numbers(png_structp png_ptr, png_uint_32 strip_mode)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined PNG_SIMPLIFIED_READ_SUPPORTED ||\
|
||||||
|
defined PNG_SIMPLIFIED_WRITE_SUPPORTED
|
||||||
|
/* Currently the above both depend on SETJMP_SUPPORTED, however it would be
|
||||||
|
* possible to implement without setjmp support just so long as there is some
|
||||||
|
* way to handle the error return here:
|
||||||
|
*/
|
||||||
|
PNG_FUNCTION(void /* PRIVATE */,
|
||||||
|
png_safe_error,(png_structp png_ptr, png_const_charp error_message),
|
||||||
|
PNG_NORETURN)
|
||||||
|
{
|
||||||
|
png_imagep image = png_ptr->error_ptr;
|
||||||
|
|
||||||
|
/* An error is always logged here, overwriting anything (typically a warning)
|
||||||
|
* that is already there:
|
||||||
|
*/
|
||||||
|
if (image != NULL)
|
||||||
|
{
|
||||||
|
png_safecat(image->message, sizeof image->message, 0, error_message);
|
||||||
|
image->warning_or_error = 1;
|
||||||
|
|
||||||
|
/* Retrieve the jmp_buf from within the png_control */
|
||||||
|
if (image->opaque != NULL && image->opaque->error_buf != NULL)
|
||||||
|
longjmp(image->opaque->error_buf, 1);
|
||||||
|
|
||||||
|
/* Missing longjmp buffer, the following is to help debugging: */
|
||||||
|
{
|
||||||
|
size_t pos = png_safecat(image->message, sizeof image->message, 0,
|
||||||
|
"bad longjmp: ");
|
||||||
|
png_safecat(image->message, sizeof image->message, pos, error_message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Here on an internal programming error. */
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef PNG_WARNINGS_SUPPORTED
|
||||||
|
void /* PRIVATE */
|
||||||
|
png_safe_warning(png_structp png_ptr, png_const_charp warning_message)
|
||||||
|
{
|
||||||
|
png_imagep image = png_ptr->error_ptr;
|
||||||
|
|
||||||
|
/* A warning is just logged if there is no warning or error. */
|
||||||
|
if (image->warning_or_error == 0)
|
||||||
|
{
|
||||||
|
png_safecat(image->message, sizeof image->message, 0, warning_message);
|
||||||
|
image->warning_or_error = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int /* PRIVATE */
|
||||||
|
png_safe_execute(png_imagep imageIn, int (*function)(png_voidp), png_voidp arg)
|
||||||
|
{
|
||||||
|
volatile png_imagep image = imageIn;
|
||||||
|
volatile int result;
|
||||||
|
volatile png_voidp saved_error_buf;
|
||||||
|
jmp_buf safe_jmpbuf;
|
||||||
|
|
||||||
|
/* Safely execute function(arg) with png_error returning to this function. */
|
||||||
|
saved_error_buf = image->opaque->error_buf;
|
||||||
|
result = setjmp(safe_jmpbuf) == 0;
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
|
||||||
|
image->opaque->error_buf = safe_jmpbuf;
|
||||||
|
result = function(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
image->opaque->error_buf = saved_error_buf;
|
||||||
|
|
||||||
|
/* And do the cleanup prior to any failure return. */
|
||||||
|
if (!result)
|
||||||
|
png_image_free(image);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif /* SIMPLIFIED READ/WRITE */
|
||||||
#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
|
#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
|
||||||
|
|||||||
78
pngpriv.h
78
pngpriv.h
@ -196,6 +196,23 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
|
|||||||
# define PNG_STATIC static
|
# define PNG_STATIC static
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* C99 restrict is used where possible, to do this 'restrict' is defined as
|
||||||
|
* empty if we can't be sure it is supported. configure builds have already
|
||||||
|
* done this work.
|
||||||
|
*/
|
||||||
|
#ifdef PNG_CONFIGURE_LIBPNG
|
||||||
|
# define PNG_RESTRICT restrict
|
||||||
|
#else
|
||||||
|
/* Modern compilers support restrict, but assume not for anything not
|
||||||
|
* recognized here:
|
||||||
|
*/
|
||||||
|
# if defined __GNUC__ || defined _MSC_VER || defined __WATCOMC__
|
||||||
|
# define PNG_RESTRICT restrict
|
||||||
|
# else
|
||||||
|
# define PNG_RESTRICT
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/* If warnings or errors are turned off the code is disabled or redirected here.
|
/* If warnings or errors are turned off the code is disabled or redirected here.
|
||||||
* From 1.5.4 functions have been added to allow very limited formatting of
|
* From 1.5.4 functions have been added to allow very limited formatting of
|
||||||
* error and warning messages - this code will also be disabled here.
|
* error and warning messages - this code will also be disabled here.
|
||||||
@ -498,6 +515,26 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
|
|||||||
abs((int)((c1).green) - (int)((c2).green)) + \
|
abs((int)((c1).green) - (int)((c2).green)) + \
|
||||||
abs((int)((c1).blue) - (int)((c2).blue)))
|
abs((int)((c1).blue) - (int)((c2).blue)))
|
||||||
|
|
||||||
|
/* Added to libpng-1.5.7: sRGB convertion tables */
|
||||||
|
#ifdef PNG_SIMPLIFIED_READ_SUPPORTED
|
||||||
|
PNG_EXTERN /*PRIVATE*/ PNG_CONST png_uint_16 png_sRGB_table[256];
|
||||||
|
/* Convert from an sRGB encoded value 0..255 to a 16-bit linear value,
|
||||||
|
* 0..65535. This table gives the closes 16-bit answers (no errors).
|
||||||
|
*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined PNG_SIMPLIFIED_READ_SUPPORTED ||\
|
||||||
|
defined PNG_SIMPLFIED_WRITE_SUPPORTED
|
||||||
|
PNG_EXTERN /*PRIVATE*/ PNG_CONST png_uint_16 png_sRGB_base[512];
|
||||||
|
PNG_EXTERN /*PRIVATE*/ PNG_CONST png_byte png_sRGB_delta[512];
|
||||||
|
|
||||||
|
#define PNG_sRGB_FROM_LINEAR(linear) ((png_sRGB_base[(linear)>>15] +\
|
||||||
|
((((linear)&0x7fff)*png_sRGB_delta[(linear)>>15])>>12)) >> 8)
|
||||||
|
/* Given a value 'linear' in the range 0..255*65535 calculate the 8-bit sRGB
|
||||||
|
* encoded value with maximum error 0.646365. Note that the input is not a
|
||||||
|
* 16-bit value; it has been multiplied by 255! */
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Added to libpng-1.2.6 JB */
|
/* Added to libpng-1.2.6 JB */
|
||||||
#define PNG_ROWBYTES(pixel_bits, width) \
|
#define PNG_ROWBYTES(pixel_bits, width) \
|
||||||
((pixel_bits) >= 8 ? \
|
((pixel_bits) >= 8 ? \
|
||||||
@ -1588,6 +1625,47 @@ PNG_EXTERN void png_build_gamma_table PNGARG((png_structp png_ptr,
|
|||||||
int bit_depth));
|
int bit_depth));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* SIMPLIFIED READ/WRITE SUPPORT */
|
||||||
|
#if defined PNG_SIMPLIFIED_READ_SUPPORTED ||\
|
||||||
|
defined PNG_SIMPLIFIED_WRITE_SUPPORTED
|
||||||
|
/* The internal structure that png_image::opaque points to. */
|
||||||
|
typedef struct png_control
|
||||||
|
{
|
||||||
|
png_structp png_ptr;
|
||||||
|
png_infop info_ptr;
|
||||||
|
png_voidp error_buf; /* Always a jmp_buf at present. */
|
||||||
|
|
||||||
|
png_const_bytep memory; /* Memory buffer. */
|
||||||
|
png_size_t size; /* Size of the memory buffer. */
|
||||||
|
|
||||||
|
unsigned int for_write :1; /* Otherwise it is a read structure */
|
||||||
|
unsigned int owned_file :1; /* We own the file in io_ptr */
|
||||||
|
} png_control;
|
||||||
|
|
||||||
|
/* Utility to safely execute a piece of libpng code catching and logging any
|
||||||
|
* errors that might occur. Returns true on success, false on failure (either
|
||||||
|
* of the function or as a result of a png_error.)
|
||||||
|
*/
|
||||||
|
PNG_FUNCTION(void, png_safe_error, (png_structp png_ptr,
|
||||||
|
png_const_charp error_message), PNG_NORETURN);
|
||||||
|
|
||||||
|
#ifdef PNG_WARNINGS_SUPPORTED
|
||||||
|
PNG_EXTERN void png_safe_warning(png_structp png_ptr,
|
||||||
|
png_const_charp warning_message);
|
||||||
|
#else
|
||||||
|
# define png_safe_warning 0/*dummy argument*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PNG_EXTERN int png_safe_execute PNGARG((png_imagep image,
|
||||||
|
int (*function)(png_voidp), png_voidp arg));
|
||||||
|
|
||||||
|
/* Utility to log an error, this also cleans up the png_image, the function
|
||||||
|
* always returns 0 (false).
|
||||||
|
*/
|
||||||
|
PNG_EXTERN int png_image_error(png_imagep image, png_const_charp error_message);
|
||||||
|
|
||||||
|
#endif /* SIMPLIFIED READ/WRITE */
|
||||||
|
|
||||||
/* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */
|
/* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
705
pngread.c
705
pngread.c
@ -15,6 +15,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "pngpriv.h"
|
#include "pngpriv.h"
|
||||||
|
#if defined PNG_SIMPLIFIED_READ_SUPPORTED && defined PNG_STDIO_SUPPORTED
|
||||||
|
# include <errno.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef PNG_READ_SUPPORTED
|
#ifdef PNG_READ_SUPPORTED
|
||||||
|
|
||||||
@ -1304,4 +1307,706 @@ png_read_png(png_structp png_ptr, png_infop info_ptr,
|
|||||||
}
|
}
|
||||||
#endif /* PNG_INFO_IMAGE_SUPPORTED */
|
#endif /* PNG_INFO_IMAGE_SUPPORTED */
|
||||||
#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
|
#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
|
||||||
|
|
||||||
|
#ifdef PNG_SIMPLIFIED_READ_SUPPORTED
|
||||||
|
/* SIMPLIFIED READ
|
||||||
|
*
|
||||||
|
* This code currently relies on the sequential reader, though it could easily
|
||||||
|
* be made to work with the progressive one.
|
||||||
|
*/
|
||||||
|
/* Do all the *safe* initialization - 'safe' means that png_error won't be
|
||||||
|
* called, so setting up the jmp_buf is not required.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
png_image_read_init(png_imagep image)
|
||||||
|
{
|
||||||
|
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, image,
|
||||||
|
png_safe_error, png_safe_warning);
|
||||||
|
|
||||||
|
if (png_ptr != NULL)
|
||||||
|
{
|
||||||
|
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||||
|
|
||||||
|
if (info_ptr != NULL)
|
||||||
|
{
|
||||||
|
png_controlp control = png_malloc_warn(png_ptr, sizeof *control);
|
||||||
|
|
||||||
|
if (control != NULL)
|
||||||
|
{
|
||||||
|
memset(control, 0, sizeof *control);
|
||||||
|
|
||||||
|
control->png_ptr = png_ptr;
|
||||||
|
control->info_ptr = info_ptr;
|
||||||
|
control->for_write = 0;
|
||||||
|
|
||||||
|
image->opaque = control;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Error clean up */
|
||||||
|
png_destroy_info_struct(png_ptr, &info_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
png_destroy_read_struct(&png_ptr, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return png_image_error(image, "png_image_read: out of memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Utility to find the base format of a PNG file from a png_struct. */
|
||||||
|
static png_uint_32
|
||||||
|
png_image_format(png_structp png_ptr, png_infop info_ptr)
|
||||||
|
{
|
||||||
|
png_uint_32 format = 0;
|
||||||
|
|
||||||
|
if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
|
||||||
|
format |= PNG_FORMAT_FLAG_COLOR;
|
||||||
|
|
||||||
|
if (png_ptr->color_type & PNG_COLOR_MASK_ALPHA)
|
||||||
|
format |= PNG_FORMAT_FLAG_ALPHA;
|
||||||
|
|
||||||
|
else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
|
||||||
|
format |= PNG_FORMAT_FLAG_ALPHA;
|
||||||
|
|
||||||
|
if (png_ptr->bit_depth == 16)
|
||||||
|
format |= PNG_FORMAT_FLAG_LINEAR;
|
||||||
|
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do the main body of a 'png_image_begin_read' function; read the PNG file
|
||||||
|
* header and fill in all the information. This is executed in a safe context,
|
||||||
|
* unlike the init routine above.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
png_image_read_header(png_voidp argument)
|
||||||
|
{
|
||||||
|
png_imagep image = argument;
|
||||||
|
png_structp png_ptr = image->opaque->png_ptr;
|
||||||
|
png_infop info_ptr = image->opaque->info_ptr;
|
||||||
|
|
||||||
|
png_read_info(png_ptr, info_ptr);
|
||||||
|
|
||||||
|
/* Do this the fast way; just read directly out of png_struct. */
|
||||||
|
image->width = png_ptr->width;
|
||||||
|
image->height = png_ptr->height;
|
||||||
|
|
||||||
|
{
|
||||||
|
png_uint_32 format = png_image_format(png_ptr, info_ptr);
|
||||||
|
|
||||||
|
image->format = format;
|
||||||
|
image->flags = 0;
|
||||||
|
|
||||||
|
/* Now try to work out whether the color data does not match sRGB. */
|
||||||
|
if ((format & PNG_FORMAT_FLAG_COLOR) != 0 &&
|
||||||
|
(info_ptr->valid & PNG_INFO_sRGB) == 0)
|
||||||
|
{
|
||||||
|
/* gamma is irrelevant because libpng does gamma correction, what
|
||||||
|
* matters is if the cHRM chunk doesn't match or, in the absence of
|
||||||
|
* cRHM, if the iCCP profile looks to have different end points.
|
||||||
|
*/
|
||||||
|
if (info_ptr->valid & PNG_INFO_cHRM)
|
||||||
|
{
|
||||||
|
/* TODO: this is a copy'n'paste from pngrutil.c, make a common
|
||||||
|
* checking function. This checks for a 1% error.
|
||||||
|
*/
|
||||||
|
/* The cHRM chunk is used in preference to iCCP */
|
||||||
|
if (PNG_OUT_OF_RANGE(info_ptr->x_white, 31270, 1000) ||
|
||||||
|
PNG_OUT_OF_RANGE(info_ptr->y_white, 32900, 1000) ||
|
||||||
|
PNG_OUT_OF_RANGE(info_ptr->x_red, 64000, 1000) ||
|
||||||
|
PNG_OUT_OF_RANGE(info_ptr->y_red, 33000, 1000) ||
|
||||||
|
PNG_OUT_OF_RANGE(info_ptr->x_green, 30000, 1000) ||
|
||||||
|
PNG_OUT_OF_RANGE(info_ptr->y_green, 60000, 1000) ||
|
||||||
|
PNG_OUT_OF_RANGE(info_ptr->x_blue, 15000, 1000) ||
|
||||||
|
PNG_OUT_OF_RANGE(info_ptr->y_blue, 6000, 1000))
|
||||||
|
image->flags |= PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (info_ptr->valid & PNG_INFO_iCCP)
|
||||||
|
{
|
||||||
|
# if 0 /* TODO: IMPLEMENT THIS! */
|
||||||
|
/* Here if we just have an iCCP chunk. */
|
||||||
|
if (!png_iCCP_is_sRGB(png_ptr, info_ptr))
|
||||||
|
# endif
|
||||||
|
image->flags |= PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef PNG_STDIO_SUPPORTED
|
||||||
|
int PNGAPI
|
||||||
|
png_image_begin_read_from_stdio(png_imagep image, FILE* file)
|
||||||
|
{
|
||||||
|
if (image != NULL)
|
||||||
|
{
|
||||||
|
if (file != NULL)
|
||||||
|
{
|
||||||
|
if (png_image_read_init(image))
|
||||||
|
{
|
||||||
|
/* This is slightly evil, but png_init_io doesn't do anything other
|
||||||
|
* than this and we haven't changed the standard IO functions so
|
||||||
|
* this saves a 'safe' function.
|
||||||
|
*/
|
||||||
|
image->opaque->png_ptr->io_ptr = file;
|
||||||
|
return png_safe_execute(image, png_image_read_header, image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
return png_image_error(image,
|
||||||
|
"png_image_begin_read_from_stdio: invalid argument");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PNGAPI
|
||||||
|
png_image_begin_read_from_file(png_imagep image, const char *file_name)
|
||||||
|
{
|
||||||
|
if (image != NULL)
|
||||||
|
{
|
||||||
|
if (file_name != NULL)
|
||||||
|
{
|
||||||
|
FILE *fp = fopen(file_name, "rb");
|
||||||
|
|
||||||
|
if (fp != NULL)
|
||||||
|
{
|
||||||
|
if (png_image_read_init(image))
|
||||||
|
{
|
||||||
|
image->opaque->png_ptr->io_ptr = fp;
|
||||||
|
image->opaque->owned_file = 1;
|
||||||
|
return png_safe_execute(image, png_image_read_header, image);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clean up: just the opened file. */
|
||||||
|
(void)fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
return png_image_error(image, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
return png_image_error(image,
|
||||||
|
"png_image_begin_read_from_file: invalid argument");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* PNG_STDIO_SUPPORTED */
|
||||||
|
|
||||||
|
static void PNGCBAPI
|
||||||
|
png_image_memory_read(png_structp png_ptr, png_bytep out, png_size_t need)
|
||||||
|
{
|
||||||
|
if (png_ptr != NULL)
|
||||||
|
{
|
||||||
|
png_imagep image = png_ptr->io_ptr;
|
||||||
|
if (image != NULL)
|
||||||
|
{
|
||||||
|
png_controlp cp = image->opaque;
|
||||||
|
if (cp != NULL)
|
||||||
|
{
|
||||||
|
png_const_bytep memory = cp->memory;
|
||||||
|
png_size_t size = cp->size;
|
||||||
|
|
||||||
|
if (memory != NULL && size >= need)
|
||||||
|
{
|
||||||
|
memcpy(out, memory, need);
|
||||||
|
cp->memory = memory + need;
|
||||||
|
cp->size = size - need;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
png_error(png_ptr, "read beyond end of data");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
png_error(png_ptr, "invalid memory read");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int PNGAPI png_image_begin_read_from_memory(png_imagep image,
|
||||||
|
png_const_voidp memory, png_size_t size)
|
||||||
|
{
|
||||||
|
if (image != NULL)
|
||||||
|
{
|
||||||
|
if (memory != NULL && size > 0)
|
||||||
|
{
|
||||||
|
if (png_image_read_init(image))
|
||||||
|
{
|
||||||
|
/* Now set the IO functions to read from the memory buffer and
|
||||||
|
* store it into io_ptr. Again do this in-place to avoid calling a
|
||||||
|
* libpng function that requires error handling.
|
||||||
|
*/
|
||||||
|
image->opaque->memory = memory;
|
||||||
|
image->opaque->size = size;
|
||||||
|
image->opaque->png_ptr->io_ptr = image;
|
||||||
|
image->opaque->png_ptr->read_data_fn = png_image_memory_read;
|
||||||
|
|
||||||
|
return png_safe_execute(image, png_image_read_header, image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
return png_image_error(image,
|
||||||
|
"png_image_begin_read_from_memory: invalid argument");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Arguments to png_image_finish_read: */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
/* Arguments: */
|
||||||
|
png_imagep image;
|
||||||
|
png_voidp buffer;
|
||||||
|
png_int_32 row_stride;
|
||||||
|
png_colorp background;
|
||||||
|
/* Local variables: */
|
||||||
|
png_bytep local_row;
|
||||||
|
png_bytep first_row;
|
||||||
|
ptrdiff_t row_bytes; /* unsigned arithmetic step between rows */
|
||||||
|
} png_image_read_control;
|
||||||
|
|
||||||
|
/* Just the row reading part of png_image_read. */
|
||||||
|
static int
|
||||||
|
png_image_read_composite(png_voidp argument)
|
||||||
|
{
|
||||||
|
png_image_read_control *display = argument;
|
||||||
|
png_imagep image = display->image;
|
||||||
|
png_structp png_ptr = image->opaque->png_ptr;
|
||||||
|
png_byte interlace_type = png_ptr->interlaced;
|
||||||
|
int passes;
|
||||||
|
|
||||||
|
switch (interlace_type)
|
||||||
|
{
|
||||||
|
case PNG_INTERLACE_NONE:
|
||||||
|
passes = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PNG_INTERLACE_ADAM7:
|
||||||
|
passes = PNG_INTERLACE_ADAM7_PASSES;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
png_error(png_ptr, "unknown interlace type");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
png_uint_32 height = image->height;
|
||||||
|
png_uint_32 width = image->width;
|
||||||
|
unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) ? 3 : 1;
|
||||||
|
int pass;
|
||||||
|
|
||||||
|
for (pass = 0; pass < passes; ++pass)
|
||||||
|
{
|
||||||
|
png_bytep row = display->first_row;
|
||||||
|
unsigned int startx, stepx, stepy;
|
||||||
|
png_uint_32 y;
|
||||||
|
|
||||||
|
if (interlace_type == PNG_INTERLACE_ADAM7)
|
||||||
|
{
|
||||||
|
/* The row may be empty for a short image: */
|
||||||
|
if (PNG_PASS_COLS(width, pass) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
startx = PNG_PASS_START_COL(pass);
|
||||||
|
stepx = PNG_PASS_COL_OFFSET(pass);
|
||||||
|
y = PNG_PASS_START_ROW(pass);
|
||||||
|
stepy = PNG_PASS_COL_OFFSET(pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
y = 0;
|
||||||
|
startx = 0;
|
||||||
|
stepx = stepy = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; y<height; y += stepy)
|
||||||
|
if (interlace_type == PNG_INTERLACE_NONE ||
|
||||||
|
PNG_ROW_IN_INTERLACE_PASS(y, pass))
|
||||||
|
{
|
||||||
|
png_bytep inrow = display->local_row;
|
||||||
|
png_bytep outrow = row;
|
||||||
|
png_uint_32 x;
|
||||||
|
|
||||||
|
/* Read the row, which is packed: */
|
||||||
|
png_read_row(png_ptr, inrow, NULL);
|
||||||
|
|
||||||
|
/* Now do the composition on each pixel in this row. */
|
||||||
|
for (x = startx; x<width; x += stepx, outrow += stepx*channels)
|
||||||
|
{
|
||||||
|
png_byte alpha = inrow[channels];
|
||||||
|
|
||||||
|
if (alpha > 0) /* else no change to the output */
|
||||||
|
{
|
||||||
|
unsigned int c;
|
||||||
|
|
||||||
|
for (c=0; c<channels; ++c)
|
||||||
|
{
|
||||||
|
png_uint_32 component = inrow[c];
|
||||||
|
|
||||||
|
if (alpha < 255) /* else just use component */
|
||||||
|
{
|
||||||
|
/* This is PNG_OPTIMIZED_ALPHA, the component value
|
||||||
|
* is a linear 8-bit value. Combine this with the
|
||||||
|
* current outrow[c] value which is sRGB encoded.
|
||||||
|
* Arithmetic here is 16-bits to preserve the output
|
||||||
|
* values correctly.
|
||||||
|
*/
|
||||||
|
component *= 257*255; /* =65535 */
|
||||||
|
component += (255-alpha)*png_sRGB_table[outrow[c]];
|
||||||
|
|
||||||
|
/* So 'component' is scaled by 255*65535 and is
|
||||||
|
* therefore appropriate for the above tables.
|
||||||
|
*/
|
||||||
|
component = PNG_sRGB_FROM_LINEAR(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
outrow[c] = (png_byte)component;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inrow += channels+1; /* components and alpha channel */
|
||||||
|
}
|
||||||
|
|
||||||
|
row += display->row_bytes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The guts of png_image_finish_read as a png_safe_execute callback. */
|
||||||
|
static int
|
||||||
|
png_image_read_end(png_voidp argument)
|
||||||
|
{
|
||||||
|
png_image_read_control *display = argument;
|
||||||
|
png_imagep image = display->image;
|
||||||
|
png_structp png_ptr = image->opaque->png_ptr;
|
||||||
|
png_infop info_ptr = image->opaque->info_ptr;
|
||||||
|
|
||||||
|
png_uint_32 format = image->format;
|
||||||
|
int linear = (format & PNG_FORMAT_FLAG_LINEAR) != 0;
|
||||||
|
int do_local_compose = 0;
|
||||||
|
int passes = 0;
|
||||||
|
|
||||||
|
/* Add transforms to ensure the correct output format is produced then check
|
||||||
|
* that the required implementation support is there. Always expand; always
|
||||||
|
* need 8 bits minimum, no palette and expanded tRNS.
|
||||||
|
*/
|
||||||
|
png_set_expand(png_ptr);
|
||||||
|
|
||||||
|
/* Now check the format to see if it was modified. */
|
||||||
|
{
|
||||||
|
png_uint_32 base_format = png_image_format(png_ptr, info_ptr);
|
||||||
|
png_uint_32 change = format ^ base_format;
|
||||||
|
|
||||||
|
/* Set the gamma appropriately, linear for 16-bit input, sRGB otherwise.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
png_fixed_point input_gamma_default, output_gamma;
|
||||||
|
int mode;
|
||||||
|
|
||||||
|
if (base_format & PNG_FORMAT_FLAG_LINEAR)
|
||||||
|
input_gamma_default = PNG_GAMMA_LINEAR;
|
||||||
|
else
|
||||||
|
input_gamma_default = PNG_DEFAULT_sRGB;
|
||||||
|
|
||||||
|
if (linear)
|
||||||
|
{
|
||||||
|
mode = PNG_ALPHA_STANDARD;
|
||||||
|
output_gamma = PNG_GAMMA_LINEAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mode = PNG_ALPHA_PNG;
|
||||||
|
output_gamma = PNG_DEFAULT_sRGB;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the mode, the default gamma for the file and then, if it
|
||||||
|
* doesn't match the default, the output gamma.
|
||||||
|
*/
|
||||||
|
png_set_alpha_mode_fixed(png_ptr, mode, input_gamma_default);
|
||||||
|
if (input_gamma_default != output_gamma)
|
||||||
|
png_set_alpha_mode(png_ptr, mode, output_gamma);
|
||||||
|
|
||||||
|
/* If the bit-depth changes then handle that here. */
|
||||||
|
if (change & PNG_FORMAT_FLAG_LINEAR)
|
||||||
|
{
|
||||||
|
if (linear /*16-bit output*/)
|
||||||
|
png_set_expand_16(png_ptr);
|
||||||
|
|
||||||
|
else /* 8-bit output */
|
||||||
|
png_set_scale_16(png_ptr);
|
||||||
|
|
||||||
|
change &= ~PNG_FORMAT_FLAG_LINEAR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now the background/alpha channel changes. */
|
||||||
|
if (change & PNG_FORMAT_FLAG_ALPHA)
|
||||||
|
{
|
||||||
|
/* Removing an alpha channel requires composition for the 8-bit
|
||||||
|
* formats; for the 16-bit it is already done, above, by the
|
||||||
|
* pre-multiplication and the channel just needs to be stripped.
|
||||||
|
*/
|
||||||
|
if (base_format & PNG_FORMAT_FLAG_ALPHA)
|
||||||
|
{
|
||||||
|
if (linear) /* compose on black (well, pre-multiply) */
|
||||||
|
png_set_strip_alpha(png_ptr);
|
||||||
|
|
||||||
|
else if (display->background != NULL)
|
||||||
|
{
|
||||||
|
png_color_16 c;
|
||||||
|
|
||||||
|
c.index = 0; /*unused*/
|
||||||
|
c.red = display->background->red;
|
||||||
|
c.green = display->background->green;
|
||||||
|
c.blue = display->background->blue;
|
||||||
|
c.gray = display->background->green;
|
||||||
|
|
||||||
|
/* This is always an 8-bit sRGB value, using the 'green' channel
|
||||||
|
* for gray is much better than calculating the luminance here;
|
||||||
|
* we can get off-by-one errors in that calculation relative to
|
||||||
|
* the app expectations and that will show up in transparent
|
||||||
|
* pixels.
|
||||||
|
*/
|
||||||
|
png_set_background_fixed(png_ptr, &c,
|
||||||
|
PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
|
||||||
|
0/*gamma: not used*/);
|
||||||
|
}
|
||||||
|
|
||||||
|
else /* compose on row: implemented below. */
|
||||||
|
{
|
||||||
|
do_local_compose = 1;
|
||||||
|
/* This leaves the alpha channel in the output, it has to be
|
||||||
|
* removed by the code below. Set the encoding to the 'OPTIMIZE'
|
||||||
|
* one so the code only has to hack on the pixels that require
|
||||||
|
* composition.
|
||||||
|
*/
|
||||||
|
png_set_alpha_mode(png_ptr, PNG_ALPHA_OPTIMIZED,
|
||||||
|
PNG_DEFAULT_sRGB);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else /* output needs an alpha channel */
|
||||||
|
{
|
||||||
|
/* This is tricky because it happens before the swap operation has
|
||||||
|
* been accomplished, so always add the alpha channel after the
|
||||||
|
* component channels.
|
||||||
|
*/
|
||||||
|
png_set_add_alpha(png_ptr, 255/*opaque*/, PNG_FILLER_AFTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
change &= ~PNG_FORMAT_FLAG_ALPHA;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (change & PNG_FORMAT_FLAG_COLOR)
|
||||||
|
{
|
||||||
|
/* gray<->color transformation required. */
|
||||||
|
if (format & PNG_FORMAT_FLAG_COLOR)
|
||||||
|
png_set_gray_to_rgb(png_ptr);
|
||||||
|
|
||||||
|
else
|
||||||
|
png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE,
|
||||||
|
PNG_RGB_TO_GRAY_DEFAULT, PNG_RGB_TO_GRAY_DEFAULT);
|
||||||
|
|
||||||
|
change &= ~PNG_FORMAT_FLAG_COLOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
# ifdef PNG_FORMAT_BGR_SUPPORTED
|
||||||
|
if (format & PNG_FORMAT_FLAG_BGR)
|
||||||
|
{
|
||||||
|
/* Check only the output format; PNG is never BGR, don't do this if
|
||||||
|
* the output is gray, but fix up the 'format' value in that case.
|
||||||
|
*/
|
||||||
|
if (format & PNG_FORMAT_FLAG_COLOR)
|
||||||
|
png_set_bgr(png_ptr);
|
||||||
|
|
||||||
|
else
|
||||||
|
format &= ~PNG_FORMAT_FLAG_BGR;
|
||||||
|
|
||||||
|
change &= ~PNG_FORMAT_FLAG_BGR;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# ifdef PNG_FORMAT_AFIRST_SUPPORTED
|
||||||
|
if (format & PNG_FORMAT_FLAG_AFIRST)
|
||||||
|
{
|
||||||
|
/* Only relevant if there is an alpha channel - it's particularly
|
||||||
|
* important to handle this correctly because do_local_compose may
|
||||||
|
* be set above and then libpng will keep the alpha channel for this
|
||||||
|
* code to remove.
|
||||||
|
*/
|
||||||
|
if (format & PNG_FORMAT_FLAG_ALPHA)
|
||||||
|
png_set_swap_alpha(png_ptr);
|
||||||
|
|
||||||
|
else
|
||||||
|
format &= ~PNG_FORMAT_FLAG_AFIRST;
|
||||||
|
|
||||||
|
change &= ~PNG_FORMAT_FLAG_AFIRST;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* If the *output* is 16-bit then we need to check for a byte-swap on this
|
||||||
|
* architecture.
|
||||||
|
*/
|
||||||
|
if (linear)
|
||||||
|
{
|
||||||
|
PNG_CONST png_uint_16 le = 0x0001;
|
||||||
|
|
||||||
|
if (*(png_const_bytep)&le)
|
||||||
|
png_set_swap(png_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If change is not now 0 some transformation is missing - error out. */
|
||||||
|
if (change)
|
||||||
|
png_error(png_ptr, "png_read_image: unsupported transformation");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update the 'info' structure and make sure the result is as required, first
|
||||||
|
* make sure to turn on the interlace handling if it will be required
|
||||||
|
* (because it can't be turned on *after* the call to png_read_update_info!)
|
||||||
|
*/
|
||||||
|
if (!do_local_compose)
|
||||||
|
passes = png_set_interlace_handling(png_ptr);
|
||||||
|
|
||||||
|
png_read_update_info(png_ptr, info_ptr);
|
||||||
|
|
||||||
|
{
|
||||||
|
png_uint_32 info_format = 0;
|
||||||
|
|
||||||
|
if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
|
||||||
|
info_format |= PNG_FORMAT_FLAG_COLOR;
|
||||||
|
|
||||||
|
if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
|
||||||
|
{
|
||||||
|
/* This channel may be removed below. */
|
||||||
|
if (!do_local_compose)
|
||||||
|
info_format |= PNG_FORMAT_FLAG_ALPHA;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (do_local_compose) /* internal error */
|
||||||
|
png_error(png_ptr, "png_image_read: alpha channel lost");
|
||||||
|
|
||||||
|
if (info_ptr->bit_depth == 16)
|
||||||
|
info_format |= PNG_FORMAT_FLAG_LINEAR;
|
||||||
|
|
||||||
|
# ifdef PNG_FORMAT_BGR_SUPPORTED
|
||||||
|
if (png_ptr->transformations & PNG_BGR)
|
||||||
|
info_format |= PNG_FORMAT_FLAG_BGR;
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# ifdef PNG_FORMAT_AFIRST_SUPPORTED
|
||||||
|
if (png_ptr->transformations & PNG_SWAP_ALPHA)
|
||||||
|
info_format |= PNG_FORMAT_FLAG_AFIRST;
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* This is actually an internal error. */
|
||||||
|
if (info_format != format)
|
||||||
|
png_error(png_ptr, "png_read_image: invalid transformations");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now read the rows. If do_local_compose is set then it is necessary to use
|
||||||
|
* a local row buffer. The output will be GA, RGBA or BGRA and must be
|
||||||
|
* converted to G, RGB or BGR as appropriate. The 'local_row' member of the
|
||||||
|
* display acts as a flag.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
png_bytep first_row = display->buffer;
|
||||||
|
ptrdiff_t row_bytes = display->row_stride;
|
||||||
|
|
||||||
|
if (linear)
|
||||||
|
row_bytes *= sizeof (png_uint_16);
|
||||||
|
|
||||||
|
/* The following expression is designed to work correctly whether it gives
|
||||||
|
* a signed or an unsigned result.
|
||||||
|
*/
|
||||||
|
if (row_bytes < 0)
|
||||||
|
first_row += (image->height-1) * (-row_bytes);
|
||||||
|
|
||||||
|
display->first_row = first_row;
|
||||||
|
display->row_bytes = row_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (do_local_compose)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
png_bytep row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
|
||||||
|
|
||||||
|
display->local_row = row;
|
||||||
|
result = png_safe_execute(image, png_image_read_composite, display);
|
||||||
|
display->local_row = NULL;
|
||||||
|
png_free(png_ptr, row);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
png_alloc_size_t row_bytes = display->row_bytes;
|
||||||
|
|
||||||
|
while (--passes >= 0)
|
||||||
|
{
|
||||||
|
png_uint_32 y = image->height;
|
||||||
|
png_bytep row = display->first_row;
|
||||||
|
|
||||||
|
while (y-- > 0)
|
||||||
|
{
|
||||||
|
png_read_row(png_ptr, row, NULL);
|
||||||
|
row += row_bytes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int PNGAPI
|
||||||
|
png_image_finish_read(png_imagep image, png_colorp background, void *buffer,
|
||||||
|
png_int_32 row_stride)
|
||||||
|
{
|
||||||
|
if (image != NULL)
|
||||||
|
{
|
||||||
|
png_uint_32 check;
|
||||||
|
|
||||||
|
if (row_stride < 0)
|
||||||
|
check = -row_stride;
|
||||||
|
|
||||||
|
else
|
||||||
|
check = row_stride;
|
||||||
|
|
||||||
|
if (buffer != NULL && check >= PNG_IMAGE_ROW_STRIDE(*image))
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
png_image_read_control display;
|
||||||
|
|
||||||
|
memset(&display, 0, sizeof display);
|
||||||
|
display.image = image;
|
||||||
|
display.buffer = buffer;
|
||||||
|
display.row_stride = row_stride;
|
||||||
|
display.background = background;
|
||||||
|
display.local_row = NULL;
|
||||||
|
result = png_safe_execute(image, png_image_read_end, &display);
|
||||||
|
png_image_free(image);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
return png_image_error(image,
|
||||||
|
"png_image_finish_read: invalid argument");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* PNG_SIMPLIFIED_READ_SUPPORTED */
|
||||||
#endif /* PNG_READ_SUPPORTED */
|
#endif /* PNG_READ_SUPPORTED */
|
||||||
|
|||||||
@ -936,15 +936,15 @@ png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
|
|||||||
|
|
||||||
switch(error_action)
|
switch(error_action)
|
||||||
{
|
{
|
||||||
case 1:
|
case PNG_ERROR_ACTION_NONE:
|
||||||
png_ptr->transformations |= PNG_RGB_TO_GRAY;
|
png_ptr->transformations |= PNG_RGB_TO_GRAY;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case PNG_ERROR_ACTION_WARN:
|
||||||
png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
|
png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case PNG_ERROR_ACTION_ERROR:
|
||||||
png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
|
png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
47
pngrutil.c
47
pngrutil.c
@ -2767,18 +2767,13 @@ png_check_chunk_name(png_structp png_ptr, png_uint_32 chunk_name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Combines the row recently read in with the existing pixels in the
|
/* Combines the row recently read in with the existing pixels in the row. This
|
||||||
* row. This routine takes care of alpha and transparency if requested.
|
* routine takes care of alpha and transparency if requested. This routine also
|
||||||
* This routine also handles the two methods of progressive display
|
* handles the two methods of progressive display of interlaced images,
|
||||||
* of interlaced images, depending on the mask value.
|
* depending on the 'display' value; if 'display' is true then the whole row
|
||||||
* The mask value describes which pixels are to be combined with
|
* (dp) is filled from the start by replicating the available pixels. If
|
||||||
* the row. The pattern always repeats every 8 pixels, so just 8
|
* 'display' is false only those pixels present in the pass are filled in.
|
||||||
* bits are needed. A one indicates the pixel is to be combined,
|
|
||||||
* a zero indicates the pixel is to be skipped. This is in addition
|
|
||||||
* to any alpha or transparency value associated with the pixel. If
|
|
||||||
* you want all pixels to be combined, pass 0xff (255) in mask.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void /* PRIVATE */
|
void /* PRIVATE */
|
||||||
png_combine_row(png_structp png_ptr, png_bytep dp, int display)
|
png_combine_row(png_structp png_ptr, png_bytep dp, int display)
|
||||||
{
|
{
|
||||||
@ -2850,7 +2845,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
|
|||||||
|
|
||||||
if (pixel_depth < 8)
|
if (pixel_depth < 8)
|
||||||
{
|
{
|
||||||
/* For pixel depths up to 4-bpp the 8-pixel mask can be expanded to fit
|
/* For pixel depths up to 4 bpp the 8-pixel mask can be expanded to fit
|
||||||
* into 32 bits, then a single loop over the bytes using the four byte
|
* into 32 bits, then a single loop over the bytes using the four byte
|
||||||
* values in the 32-bit mask can be used. For the 'display' option the
|
* values in the 32-bit mask can be used. For the 'display' option the
|
||||||
* expanded mask may also not require any masking within a byte. To
|
* expanded mask may also not require any masking within a byte. To
|
||||||
@ -2859,7 +2854,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
|
|||||||
*
|
*
|
||||||
* The 'regular' case requires a mask for each of the first 6 passes,
|
* The 'regular' case requires a mask for each of the first 6 passes,
|
||||||
* the 'display' case does a copy for the even passes in the range
|
* the 'display' case does a copy for the even passes in the range
|
||||||
* 0..6. This has already been handled in the tst above.
|
* 0..6. This has already been handled in the test above.
|
||||||
*
|
*
|
||||||
* The masks are arranged as four bytes with the first byte to use in
|
* The masks are arranged as four bytes with the first byte to use in
|
||||||
* the lowest bits (little-endian) regardless of the order (PACKSWAP or
|
* the lowest bits (little-endian) regardless of the order (PACKSWAP or
|
||||||
@ -2867,7 +2862,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
|
|||||||
*
|
*
|
||||||
* NOTE: the whole of this logic depends on the caller of this function
|
* NOTE: the whole of this logic depends on the caller of this function
|
||||||
* only calling it on rows appropriate to the pass. This function only
|
* only calling it on rows appropriate to the pass. This function only
|
||||||
* understands the 'x' logic, the 'y' logic is handled by the caller.
|
* understands the 'x' logic; the 'y' logic is handled by the caller.
|
||||||
*
|
*
|
||||||
* The following defines allow generation of compile time constant bit
|
* The following defines allow generation of compile time constant bit
|
||||||
* masks for each pixel depth and each possibility of swapped or not
|
* masks for each pixel depth and each possibility of swapped or not
|
||||||
@ -2885,7 +2880,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
|
|||||||
* the compiler even though it isn't used. Microsoft Visual C (various
|
* the compiler even though it isn't used. Microsoft Visual C (various
|
||||||
* versions) and the Intel C compiler are known to do this. To avoid
|
* versions) and the Intel C compiler are known to do this. To avoid
|
||||||
* this the following macros are used in 1.5.6. This is a temporary
|
* this the following macros are used in 1.5.6. This is a temporary
|
||||||
* solution to avoid destablizing the code during the release process.
|
* solution to avoid destabilizing the code during the release process.
|
||||||
*/
|
*/
|
||||||
# if PNG_USE_COMPILE_TIME_MASKS
|
# if PNG_USE_COMPILE_TIME_MASKS
|
||||||
# define PNG_LSR(x,s) ((x)>>((s) & 0x1f))
|
# define PNG_LSR(x,s) ((x)>>((s) & 0x1f))
|
||||||
@ -2930,7 +2925,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
|
|||||||
#if PNG_USE_COMPILE_TIME_MASKS
|
#if PNG_USE_COMPILE_TIME_MASKS
|
||||||
/* Utility macros to construct all the masks for a depth/swap
|
/* Utility macros to construct all the masks for a depth/swap
|
||||||
* combination. The 's' parameter says whether the format is PNG
|
* combination. The 's' parameter says whether the format is PNG
|
||||||
* (big endian bytes) or not. Only the three odd numbered passes are
|
* (big endian bytes) or not. Only the three odd-numbered passes are
|
||||||
* required for the display/block algorithm.
|
* required for the display/block algorithm.
|
||||||
*/
|
*/
|
||||||
# define S_MASKS(d,s) { S_MASK(0,d,s), S_MASK(1,d,s), S_MASK(2,d,s),\
|
# define S_MASKS(d,s) { S_MASK(0,d,s), S_MASK(1,d,s), S_MASK(2,d,s),\
|
||||||
@ -2943,7 +2938,8 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
|
|||||||
/* Hence the pre-compiled masks indexed by PACKSWAP (or not), depth and
|
/* Hence the pre-compiled masks indexed by PACKSWAP (or not), depth and
|
||||||
* then pass:
|
* then pass:
|
||||||
*/
|
*/
|
||||||
static PNG_CONST png_uint_32 row_mask[2/*PACKSWAP*/][3/*depth*/][6] = {
|
static PNG_CONST png_uint_32 row_mask[2/*PACKSWAP*/][3/*depth*/][6] =
|
||||||
|
{
|
||||||
/* Little-endian byte masks for PACKSWAP */
|
/* Little-endian byte masks for PACKSWAP */
|
||||||
{ S_MASKS(1,0), S_MASKS(2,0), S_MASKS(4,0) },
|
{ S_MASKS(1,0), S_MASKS(2,0), S_MASKS(4,0) },
|
||||||
/* Normal (big-endian byte) masks - PNG format */
|
/* Normal (big-endian byte) masks - PNG format */
|
||||||
@ -2953,7 +2949,8 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
|
|||||||
/* display_mask has only three entries for the odd passes, so index by
|
/* display_mask has only three entries for the odd passes, so index by
|
||||||
* pass>>1.
|
* pass>>1.
|
||||||
*/
|
*/
|
||||||
static PNG_CONST png_uint_32 display_mask[2][3][3] = {
|
static PNG_CONST png_uint_32 display_mask[2][3][3] =
|
||||||
|
{
|
||||||
/* Little-endian byte masks for PACKSWAP */
|
/* Little-endian byte masks for PACKSWAP */
|
||||||
{ B_MASKS(1,0), B_MASKS(2,0), B_MASKS(4,0) },
|
{ B_MASKS(1,0), B_MASKS(2,0), B_MASKS(4,0) },
|
||||||
/* Normal (big-endian byte) masks - PNG format */
|
/* Normal (big-endian byte) masks - PNG format */
|
||||||
@ -3129,7 +3126,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
|
|||||||
/* Check for double byte alignment and, if possible, use a
|
/* Check for double byte alignment and, if possible, use a
|
||||||
* 16-bit copy. Don't attempt this for narrow images - ones that
|
* 16-bit copy. Don't attempt this for narrow images - ones that
|
||||||
* are less than an interlace panel wide. Don't attempt it for
|
* are less than an interlace panel wide. Don't attempt it for
|
||||||
* wide bytes-to-copy either - use the png_memcpy there.
|
* wide bytes_to_copy either - use the png_memcpy there.
|
||||||
*/
|
*/
|
||||||
if (bytes_to_copy < 16 /*else use png_memcpy*/ &&
|
if (bytes_to_copy < 16 /*else use png_memcpy*/ &&
|
||||||
png_isaligned(dp, png_uint_16) &&
|
png_isaligned(dp, png_uint_16) &&
|
||||||
@ -3506,13 +3503,19 @@ png_read_filter_row_sub(png_row_infop row_info, png_bytep row,
|
|||||||
png_size_t istop = row_info->rowbytes;
|
png_size_t istop = row_info->rowbytes;
|
||||||
unsigned int bpp = (row_info->pixel_depth + 7) >> 3;
|
unsigned int bpp = (row_info->pixel_depth + 7) >> 3;
|
||||||
png_bytep rp = row + bpp;
|
png_bytep rp = row + bpp;
|
||||||
|
#if 0
|
||||||
png_bytep lp = row;
|
png_bytep lp = row;
|
||||||
|
#endif
|
||||||
|
|
||||||
PNG_UNUSED(prev_row)
|
PNG_UNUSED(prev_row)
|
||||||
|
|
||||||
for (i = bpp; i < istop; i++)
|
for (i = bpp; i < istop; i++)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
*rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
|
*rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
|
||||||
|
#else
|
||||||
|
*rp = (png_byte)(((int)(*rp) + (int)(*(rp-bpp))) & 0xff);
|
||||||
|
#endif
|
||||||
rp++;
|
rp++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3540,7 +3543,9 @@ png_read_filter_row_avg(png_row_infop row_info, png_bytep row,
|
|||||||
png_size_t i;
|
png_size_t i;
|
||||||
png_bytep rp = row;
|
png_bytep rp = row;
|
||||||
png_const_bytep pp = prev_row;
|
png_const_bytep pp = prev_row;
|
||||||
|
#if 0
|
||||||
png_bytep lp = row;
|
png_bytep lp = row;
|
||||||
|
#endif
|
||||||
unsigned int bpp = (row_info->pixel_depth + 7) >> 3;
|
unsigned int bpp = (row_info->pixel_depth + 7) >> 3;
|
||||||
png_size_t istop = row_info->rowbytes - bpp;
|
png_size_t istop = row_info->rowbytes - bpp;
|
||||||
|
|
||||||
@ -3555,7 +3560,11 @@ png_read_filter_row_avg(png_row_infop row_info, png_bytep row,
|
|||||||
for (i = 0; i < istop; i++)
|
for (i = 0; i < istop; i++)
|
||||||
{
|
{
|
||||||
*rp = (png_byte)(((int)(*rp) +
|
*rp = (png_byte)(((int)(*rp) +
|
||||||
|
#if 0
|
||||||
(int)(*pp++ + *lp++) / 2 ) & 0xff);
|
(int)(*pp++ + *lp++) / 2 ) & 0xff);
|
||||||
|
#else
|
||||||
|
(int)(*pp++ + *(rp-bpp)) / 2 ) & 0xff);
|
||||||
|
#endif
|
||||||
|
|
||||||
rp++;
|
rp++;
|
||||||
}
|
}
|
||||||
|
|||||||
550
pngwrite.c
550
pngwrite.c
@ -12,6 +12,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "pngpriv.h"
|
#include "pngpriv.h"
|
||||||
|
#if defined PNG_SIMPLIFIED_WRITE_SUPPORTED && defined PNG_STDIO_SUPPORTED
|
||||||
|
# include <errno.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef PNG_WRITE_SUPPORTED
|
#ifdef PNG_WRITE_SUPPORTED
|
||||||
|
|
||||||
@ -1651,4 +1654,551 @@ png_write_png(png_structp png_ptr, png_infop info_ptr,
|
|||||||
PNG_UNUSED(params)
|
PNG_UNUSED(params)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
|
||||||
|
#ifdef PNG_STDIO_SUPPORTED /* currently required for png_image_write_* */
|
||||||
|
/* Initialize the write structure - general purpose utility. */
|
||||||
|
static int
|
||||||
|
png_image_write_init(png_imagep image)
|
||||||
|
{
|
||||||
|
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, image,
|
||||||
|
png_safe_error, png_safe_warning);
|
||||||
|
|
||||||
|
if (png_ptr != NULL)
|
||||||
|
{
|
||||||
|
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||||
|
|
||||||
|
if (info_ptr != NULL)
|
||||||
|
{
|
||||||
|
png_controlp control = png_malloc_warn(png_ptr, sizeof *control);
|
||||||
|
|
||||||
|
if (control != NULL)
|
||||||
|
{
|
||||||
|
memset(control, 0, sizeof *control);
|
||||||
|
|
||||||
|
control->png_ptr = png_ptr;
|
||||||
|
control->info_ptr = info_ptr;
|
||||||
|
control->for_write = 1;
|
||||||
|
|
||||||
|
image->opaque = control;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Error clean up */
|
||||||
|
png_destroy_info_struct(png_ptr, &info_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
png_destroy_write_struct(&png_ptr, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return png_image_error(image, "png_image_read: out of memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Arguments to png_image_write_main: */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
/* Arguments: */
|
||||||
|
png_imagep image;
|
||||||
|
png_const_voidp buffer;
|
||||||
|
png_int_32 row_stride;
|
||||||
|
int convert_to_8bit;
|
||||||
|
/* Local variables: */
|
||||||
|
png_const_voidp first_row;
|
||||||
|
ptrdiff_t row_bytes;
|
||||||
|
png_voidp local_row;
|
||||||
|
} png_image_write_control;
|
||||||
|
|
||||||
|
/* Write png_uint_16 input to a 16-bit PNG, the png_ptr has already been set to
|
||||||
|
* do any necssary byte swapped. The component order is defined by the
|
||||||
|
* png_image format value.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
png_write_image_16bit(png_voidp argument)
|
||||||
|
{
|
||||||
|
png_image_write_control *display = argument;
|
||||||
|
png_imagep image = display->image;
|
||||||
|
png_structp png_ptr = image->opaque->png_ptr;
|
||||||
|
|
||||||
|
png_const_uint_16p input_row = display->first_row;
|
||||||
|
png_uint_16p output_row = display->local_row;
|
||||||
|
png_uint_16p row_end;
|
||||||
|
int channels = (image->format & PNG_FORMAT_FLAG_COLOR) ? 3 : 1;
|
||||||
|
int aindex = 0;
|
||||||
|
png_uint_32 y = image->height;
|
||||||
|
|
||||||
|
if (image->format & PNG_FORMAT_FLAG_ALPHA)
|
||||||
|
{
|
||||||
|
if (image->format & PNG_FORMAT_FLAG_AFIRST)
|
||||||
|
{
|
||||||
|
aindex = -1;
|
||||||
|
++input_row; /* To point to the first component */
|
||||||
|
++output_row;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
aindex = channels;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
png_error(png_ptr, "png_write_image: internal call error");
|
||||||
|
|
||||||
|
/* Work out the output row end and count over this, note that the increment
|
||||||
|
* above to 'row' means that row_end can actually be beyond the end of the
|
||||||
|
* row, this is correct.
|
||||||
|
*/
|
||||||
|
row_end = output_row + image->width * (channels+1);
|
||||||
|
|
||||||
|
while (y-- > 0)
|
||||||
|
{
|
||||||
|
png_const_uint_16p in_ptr = input_row;
|
||||||
|
png_uint_16p out_ptr = output_row;
|
||||||
|
|
||||||
|
while (out_ptr < row_end)
|
||||||
|
{
|
||||||
|
png_uint_16 alpha = in_ptr[aindex];
|
||||||
|
png_uint_32 reciprocal = 0;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
out_ptr[aindex] = alpha;
|
||||||
|
|
||||||
|
/* Calculate a reciprocal. The correct calculation is simply
|
||||||
|
* component/alpha*65535 << 15. (I.e. 15 bits of precision), this
|
||||||
|
* allows correct rounding by adding .5 before the shift. 'reciprocal'
|
||||||
|
* is only initialized when required.
|
||||||
|
*/
|
||||||
|
if (alpha > 0 && alpha < 65535)
|
||||||
|
reciprocal = ((0xffff<<15)+(alpha>>1))/alpha;
|
||||||
|
|
||||||
|
c = channels;
|
||||||
|
do /* always at least one channel */
|
||||||
|
{
|
||||||
|
png_uint_16 component = *in_ptr++;
|
||||||
|
|
||||||
|
/* The following gives 65535 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 discontinuity which will probably damage
|
||||||
|
* compression when moving from a fully transparent area to a
|
||||||
|
* nearly transparent one. (The assumption here is that opaque
|
||||||
|
* areas tend not to be 0 intensity.)
|
||||||
|
*/
|
||||||
|
if (component >= alpha)
|
||||||
|
component = 65535;
|
||||||
|
|
||||||
|
/* component<alpha, so component/alpha is less than one and
|
||||||
|
* component*reciprocal is less than 2^31.
|
||||||
|
*/
|
||||||
|
else if (component > 0 && alpha < 65535)
|
||||||
|
{
|
||||||
|
png_uint_32 calc = component * reciprocal;
|
||||||
|
calc += 16384; /* round to nearest */
|
||||||
|
component = (png_uint_16)(calc >> 15);
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_ptr++ = component;
|
||||||
|
}
|
||||||
|
while (--c > 0);
|
||||||
|
|
||||||
|
/* Skip to next component (skip the intervening alpha channel) */
|
||||||
|
++in_ptr;
|
||||||
|
++out_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
png_write_row(png_ptr, (png_bytep)output_row);
|
||||||
|
input_row += display->row_bytes/(sizeof (png_uint_16));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Given 16-bit input (1 to 4 channels) write 8-bit output. If an alpha channel
|
||||||
|
* is present it must be removed from the components, the components are then
|
||||||
|
* written in sRGB encoding. No components are added or removed.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
png_write_image_8bit(png_voidp argument)
|
||||||
|
{
|
||||||
|
png_image_write_control *display = argument;
|
||||||
|
png_imagep image = display->image;
|
||||||
|
png_structp png_ptr = image->opaque->png_ptr;
|
||||||
|
|
||||||
|
png_const_uint_16p input_row = display->first_row;
|
||||||
|
png_bytep output_row = display->local_row;
|
||||||
|
png_uint_32 y = image->height;
|
||||||
|
int channels = (image->format & PNG_FORMAT_FLAG_COLOR) ? 3 : 1;
|
||||||
|
|
||||||
|
if (image->format & PNG_FORMAT_FLAG_ALPHA)
|
||||||
|
{
|
||||||
|
png_bytep row_end;
|
||||||
|
int aindex;
|
||||||
|
|
||||||
|
if (image->format & PNG_FORMAT_FLAG_AFIRST)
|
||||||
|
{
|
||||||
|
aindex = -1;
|
||||||
|
++input_row; /* To point to the first component */
|
||||||
|
++output_row;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
aindex = channels;
|
||||||
|
|
||||||
|
/* Use row_end in place of a loop counter: */
|
||||||
|
row_end = output_row + image->width * (channels+1);
|
||||||
|
|
||||||
|
while (y-- > 0)
|
||||||
|
{
|
||||||
|
png_const_uint_16p in_ptr = input_row;
|
||||||
|
png_bytep out_ptr = output_row;
|
||||||
|
|
||||||
|
if (aindex != 0) while (out_ptr < row_end) /* Alpha channel case */
|
||||||
|
{
|
||||||
|
png_uint_16 alpha = in_ptr[aindex];
|
||||||
|
png_uint_32 reciprocal = 0;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
/* Scale and write the alpha channel. See pngrtran.c
|
||||||
|
* png_do_scale_16_to_8 for a discussion of this calculation. The
|
||||||
|
* code here has machine native values, so use:
|
||||||
|
*
|
||||||
|
* (V * 255 + 32895) >> 16
|
||||||
|
*/
|
||||||
|
out_ptr[aindex] = (png_byte)((alpha * 255 + 32895) >> 16);
|
||||||
|
|
||||||
|
/* Calculate a reciprocal. As above the 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.
|
||||||
|
*/
|
||||||
|
if (alpha > 0 && alpha < 65535)
|
||||||
|
reciprocal = (((0xffff*0xff)<<7)+(alpha>>1))/alpha;
|
||||||
|
|
||||||
|
c = channels;
|
||||||
|
do /* always at least one channel */
|
||||||
|
{
|
||||||
|
/* Need 32 bit accuracy in the sRGB tables */
|
||||||
|
png_uint_32 component = *in_ptr++;
|
||||||
|
|
||||||
|
/* The following gives 65535 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 discontinuity which will probably damage
|
||||||
|
* compression when moving from a fully transparent area to a
|
||||||
|
* nearly transparent one. (The assumption here is that opaque
|
||||||
|
* areas tend not to be 0 intensity.)
|
||||||
|
*/
|
||||||
|
if (component >= alpha)
|
||||||
|
*out_ptr++ = 255;
|
||||||
|
|
||||||
|
/* component<alpha, so component/alpha is less than one and
|
||||||
|
* component*reciprocal is less than 2^31.
|
||||||
|
*/
|
||||||
|
else if (component > 0 && alpha < 65535)
|
||||||
|
{
|
||||||
|
component *= reciprocal;
|
||||||
|
component += 64; /* round to nearest */
|
||||||
|
component >>= 7;
|
||||||
|
|
||||||
|
/* Convert the component to sRGB. */
|
||||||
|
*out_ptr++ = (png_byte)PNG_sRGB_FROM_LINEAR(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
*out_ptr++ = 0;
|
||||||
|
}
|
||||||
|
while (--c > 0);
|
||||||
|
|
||||||
|
/* Skip to next component (skip the intervening alpha channel) */
|
||||||
|
++in_ptr;
|
||||||
|
++out_ptr;
|
||||||
|
} /* while out_ptr < row_end */
|
||||||
|
} /* while y */
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* No alpha channel, so the row_end really is the end of the row and it
|
||||||
|
* is sufficient to loop over the components one by one.
|
||||||
|
*/
|
||||||
|
png_bytep row_end = output_row + image->width * channels;
|
||||||
|
|
||||||
|
while (y-- > 0)
|
||||||
|
{
|
||||||
|
png_const_uint_16p in_ptr = input_row;
|
||||||
|
png_bytep out_ptr = output_row;
|
||||||
|
|
||||||
|
while (out_ptr < row_end)
|
||||||
|
{
|
||||||
|
png_uint_32 component = *in_ptr++;
|
||||||
|
|
||||||
|
component *= 255;
|
||||||
|
*out_ptr++ = (png_byte)PNG_sRGB_FROM_LINEAR(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
png_write_row(png_ptr, output_row);
|
||||||
|
input_row += display->row_bytes/(sizeof (png_uint_16));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
png_image_write_main(png_voidp argument)
|
||||||
|
{
|
||||||
|
png_image_write_control *display = argument;
|
||||||
|
png_imagep image = display->image;
|
||||||
|
png_structp png_ptr = image->opaque->png_ptr;
|
||||||
|
png_infop info_ptr = image->opaque->info_ptr;
|
||||||
|
png_uint_32 format = image->format;
|
||||||
|
|
||||||
|
int linear = (format & PNG_FORMAT_FLAG_LINEAR) != 0; /* input */
|
||||||
|
int alpha = (format & PNG_FORMAT_FLAG_ALPHA) != 0;
|
||||||
|
int write_16bit = linear && !display->convert_to_8bit;
|
||||||
|
|
||||||
|
/* Set the required transforms then write the rows in the correct order. */
|
||||||
|
png_set_IHDR(png_ptr, info_ptr, image->width, image->height,
|
||||||
|
write_16bit ? 16 : 8,
|
||||||
|
((format & PNG_FORMAT_FLAG_COLOR) ? PNG_COLOR_MASK_COLOR : 0) +
|
||||||
|
((format & PNG_FORMAT_FLAG_ALPHA) ? PNG_COLOR_MASK_ALPHA : 0),
|
||||||
|
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
|
||||||
|
|
||||||
|
/* Counter-intuitively the data transformations must be called *after*
|
||||||
|
* png_write_info, not before as in the read code, but the 'set' functions
|
||||||
|
* must still be called before. Just set the color space information, never
|
||||||
|
* write an interlaced image.
|
||||||
|
*/
|
||||||
|
if (write_16bit)
|
||||||
|
{
|
||||||
|
/* 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_cHRM_fixed(png_ptr, info_ptr,
|
||||||
|
/* color x y */
|
||||||
|
/* white */ 31270, 32900,
|
||||||
|
/* red */ 64000, 33000,
|
||||||
|
/* green */ 30000, 60000,
|
||||||
|
/* blue */ 15000, 6000
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
png_set_sRGB(png_ptr, info_ptr, PNG_sRGB_INTENT_PERCEPTUAL);
|
||||||
|
|
||||||
|
/* Write the file header. */
|
||||||
|
png_write_info(png_ptr, info_ptr);
|
||||||
|
|
||||||
|
/* Now set up the data transformations (*after* the header is written),
|
||||||
|
* remove the handled transformations from the 'format' flags for checking.
|
||||||
|
*/
|
||||||
|
format &= ~(PNG_FORMAT_FLAG_COLOR | PNG_FORMAT_FLAG_LINEAR |
|
||||||
|
PNG_FORMAT_FLAG_ALPHA);
|
||||||
|
|
||||||
|
/* Check for a little endian system if writing 16 bit files. */
|
||||||
|
if (write_16bit)
|
||||||
|
{
|
||||||
|
PNG_CONST png_uint_16 le = 0x0001;
|
||||||
|
|
||||||
|
if (*(png_const_bytep)&le)
|
||||||
|
png_set_swap(png_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
# ifdef PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED
|
||||||
|
if (format & PNG_FORMAT_FLAG_BGR)
|
||||||
|
{
|
||||||
|
png_set_bgr(png_ptr);
|
||||||
|
format &= ~PNG_FORMAT_FLAG_BGR;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
|
||||||
|
if (format & PNG_FORMAT_FLAG_AFIRST)
|
||||||
|
{
|
||||||
|
png_set_swap_alpha(png_ptr);
|
||||||
|
format &= ~PNG_FORMAT_FLAG_AFIRST;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* That should have handled all the transforms. */
|
||||||
|
if (format != 0)
|
||||||
|
png_error(png_ptr, "png_write_image: unsupported transformation");
|
||||||
|
|
||||||
|
{
|
||||||
|
png_const_bytep row = display->buffer;
|
||||||
|
ptrdiff_t row_bytes = display->row_stride;
|
||||||
|
|
||||||
|
if (linear)
|
||||||
|
row_bytes *= sizeof (png_uint_16);
|
||||||
|
|
||||||
|
if (row_bytes < 0)
|
||||||
|
row += (image->height-1) * (-row_bytes);
|
||||||
|
|
||||||
|
display->first_row = row;
|
||||||
|
display->row_bytes = row_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
* either there is an alpha channel or it is converted to 8-bit.
|
||||||
|
*/
|
||||||
|
if ((linear && alpha) || display->convert_to_8bit)
|
||||||
|
{
|
||||||
|
png_bytep row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
|
||||||
|
int result;
|
||||||
|
|
||||||
|
display->local_row = row;
|
||||||
|
if (write_16bit)
|
||||||
|
result = png_safe_execute(image, png_write_image_16bit, display);
|
||||||
|
else
|
||||||
|
result = png_safe_execute(image, png_write_image_8bit, display);
|
||||||
|
display->local_row = NULL;
|
||||||
|
|
||||||
|
png_free(png_ptr, row);
|
||||||
|
|
||||||
|
/* Skip the 'write_end' on error: */
|
||||||
|
if (!result)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Otherwise this is the case where the input is in a format currently
|
||||||
|
* supported by the rest of the libpng write code; call it directly.
|
||||||
|
*/
|
||||||
|
else
|
||||||
|
{
|
||||||
|
png_const_bytep row = display->first_row;
|
||||||
|
ptrdiff_t row_bytes = display->row_bytes;
|
||||||
|
png_uint_32 y = image->height;
|
||||||
|
|
||||||
|
while (y-- > 0)
|
||||||
|
{
|
||||||
|
png_write_row(png_ptr, row);
|
||||||
|
row += row_bytes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
png_write_end(png_ptr, info_ptr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PNGAPI
|
||||||
|
png_image_write_to_stdio (png_imagep image, FILE *file, int convert_to_8bit,
|
||||||
|
const void *buffer, png_int_32 row_stride)
|
||||||
|
{
|
||||||
|
/* Write the image to the given (FILE*). */
|
||||||
|
if (image != NULL)
|
||||||
|
{
|
||||||
|
if (file != NULL)
|
||||||
|
{
|
||||||
|
if (png_image_write_init(image))
|
||||||
|
{
|
||||||
|
png_image_write_control display;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
/* This is slightly evil, but png_init_io doesn't do anything other
|
||||||
|
* than this and we haven't changed the standard IO functions so
|
||||||
|
* this saves a 'safe' function.
|
||||||
|
*/
|
||||||
|
image->opaque->png_ptr->io_ptr = file;
|
||||||
|
|
||||||
|
memset(&display, 0, sizeof display);
|
||||||
|
display.image = image;
|
||||||
|
display.buffer = buffer;
|
||||||
|
display.row_stride = row_stride;
|
||||||
|
display.convert_to_8bit = convert_to_8bit;
|
||||||
|
|
||||||
|
result = png_safe_execute(image, png_image_write_main, &display);
|
||||||
|
png_image_free(image);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
return png_image_error(image,
|
||||||
|
"png_image_write_to_stdio: invalid argument");
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PNGAPI
|
||||||
|
png_image_write_to_file (png_imagep image, const char *file_name,
|
||||||
|
int convert_to_8bit, const void *buffer, png_int_32 row_stride)
|
||||||
|
{
|
||||||
|
/* Write the image to the named file. */
|
||||||
|
if (image != NULL)
|
||||||
|
{
|
||||||
|
if (file_name != NULL)
|
||||||
|
{
|
||||||
|
FILE *fp = fopen(file_name, "wb");
|
||||||
|
|
||||||
|
if (fp != NULL)
|
||||||
|
{
|
||||||
|
if (png_image_write_init(image))
|
||||||
|
{
|
||||||
|
png_image_write_control display;
|
||||||
|
|
||||||
|
image->opaque->png_ptr->io_ptr = fp;
|
||||||
|
image->opaque->owned_file = 1;
|
||||||
|
/* No need to close this file now - png_image_free will do that.
|
||||||
|
*/
|
||||||
|
|
||||||
|
memset(&display, 0, sizeof display);
|
||||||
|
display.image = image;
|
||||||
|
display.buffer = buffer;
|
||||||
|
display.row_stride = row_stride;
|
||||||
|
display.convert_to_8bit = convert_to_8bit;
|
||||||
|
|
||||||
|
if (png_safe_execute(image, png_image_write_main, &display))
|
||||||
|
{
|
||||||
|
int error; /* from fflush/fclose */
|
||||||
|
|
||||||
|
/* Make sure the file is flushed correctly. */
|
||||||
|
if (fflush(fp) == 0)
|
||||||
|
{
|
||||||
|
/* Steal the file pointer back to make sure it closes ok.
|
||||||
|
*/
|
||||||
|
image->opaque->png_ptr->io_ptr = NULL;
|
||||||
|
image->opaque->owned_file = 0;
|
||||||
|
|
||||||
|
if (fclose(fp) == 0)
|
||||||
|
{
|
||||||
|
png_image_free(image);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
error = errno;
|
||||||
|
|
||||||
|
return png_image_error(image, strerror(error));
|
||||||
|
}
|
||||||
|
|
||||||
|
else /* else cleanup has already happened */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Clean up: just the opened file. */
|
||||||
|
(void)fclose(fp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
return png_image_error(image, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
return png_image_error(image,
|
||||||
|
"png_image_write_to_file: invalid argument");
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* PNG_STDIO_SUPPORTED */
|
||||||
|
#endif /* SIMPLIFIED_WRITE */
|
||||||
#endif /* PNG_WRITE_SUPPORTED */
|
#endif /* PNG_WRITE_SUPPORTED */
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
#
|
#
|
||||||
com pnglibconf.h - library build configuration
|
com pnglibconf.h - library build configuration
|
||||||
com
|
com
|
||||||
com libpng version 1.5.3 - July 7, 2011
|
version
|
||||||
com
|
com
|
||||||
com Copyright (c) 1998-2011 Glenn Randers-Pehrson
|
com Copyright (c) 1998-2011 Glenn Randers-Pehrson
|
||||||
com
|
com
|
||||||
@ -576,3 +576,31 @@ option WRITE_COMPRESSED_TEXT enables WRITE_TEXT
|
|||||||
# leave the row_pointers member out of the info structure.
|
# leave the row_pointers member out of the info structure.
|
||||||
|
|
||||||
option INFO_IMAGE
|
option INFO_IMAGE
|
||||||
|
|
||||||
|
# Simplified API options
|
||||||
|
# Read:
|
||||||
|
option SIMPLIFIED_READ requires SEQUENTIAL_READ READ_TRANSFORMS SETJMP
|
||||||
|
option SIMPLIFIED_READ enables READ_EXPAND READ_16BIT READ_EXPAND_16
|
||||||
|
option SIMPLIFIED_READ enables READ_SCALE_16_TO_8 READ_RGB_TO_GRAY
|
||||||
|
option SIMPLIFIED_READ enables READ_ALPHA_MODE READ_BACKGROUND READ_STRIP_ALPHA
|
||||||
|
option SIMPLIFIED_READ enables READ_FILLER READ_SWAP
|
||||||
|
|
||||||
|
option SIMPLIFIED_READ_AFIRST requires SIMPLIFIED_READ disabled
|
||||||
|
option READ_SWAP_ALPHA enables SIMPLIFIED_READ_AFIRST
|
||||||
|
|
||||||
|
option SIMPLIFIED_READ_BGR requires SIMPLIFIED_READ disabled
|
||||||
|
option READ_BGR enables SIMPLIFIED_READ_BGR
|
||||||
|
|
||||||
|
# Write:
|
||||||
|
option SIMPLIFIED_WRITE requires WRITE STDIO SETJMP
|
||||||
|
option SIMPLIFIED_WRITE enables WRITE_SWAP WRITE_gAMA WRITE_sRGB WRITE_cHRM
|
||||||
|
|
||||||
|
option SIMPLIFIED_WRITE_AFIRST requires SIMPLIFIED_WRITE disabled
|
||||||
|
option WRITE_SWAP_ALPHA enables SIMPLIFIED_WRITE_AFIRST
|
||||||
|
|
||||||
|
option SIMPLIFIED_WRITE_BGR requires SIMPLIFIED_WRITE disabled
|
||||||
|
option WRITE_BGR enables SIMPLIFIED_WRITE_BGR
|
||||||
|
|
||||||
|
# Formats:
|
||||||
|
option FORMAT_AFIRST if SIMPLIFIED_READ_AFIRST SIMPLIFIED_WRITE_AFIRST
|
||||||
|
option FORMAT_BGR if SIMPLIFIED_READ_BGR SIMPLIFIED_WRITE_BGR
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
/* pnglibconf.h - library build configuration */
|
/* pnglibconf.h - library build configuration */
|
||||||
|
|
||||||
/* libpng version 1.5.7beta02 - November 8, 2011 */
|
/* Libpng 1.5.7beta02 - November 8, 2011 */
|
||||||
|
|
||||||
/* Copyright (c) 1998-2011 Glenn Randers-Pehrson */
|
/* Copyright (c) 1998-2011 Glenn Randers-Pehrson */
|
||||||
|
|
||||||
@ -54,6 +54,8 @@
|
|||||||
#define PNG_FIXED_POINT_SUPPORTED
|
#define PNG_FIXED_POINT_SUPPORTED
|
||||||
#define PNG_FLOATING_ARITHMETIC_SUPPORTED
|
#define PNG_FLOATING_ARITHMETIC_SUPPORTED
|
||||||
#define PNG_FLOATING_POINT_SUPPORTED
|
#define PNG_FLOATING_POINT_SUPPORTED
|
||||||
|
#define PNG_FORMAT_AFIRST_SUPPORTED
|
||||||
|
#define PNG_FORMAT_BGR_SUPPORTED
|
||||||
#define PNG_gAMA_SUPPORTED
|
#define PNG_gAMA_SUPPORTED
|
||||||
#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED
|
#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED
|
||||||
#define PNG_hIST_SUPPORTED
|
#define PNG_hIST_SUPPORTED
|
||||||
@ -126,6 +128,12 @@
|
|||||||
#define PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED
|
#define PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED
|
||||||
#define PNG_SETJMP_SUPPORTED
|
#define PNG_SETJMP_SUPPORTED
|
||||||
#define PNG_SET_USER_LIMITS_SUPPORTED
|
#define PNG_SET_USER_LIMITS_SUPPORTED
|
||||||
|
#define PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED
|
||||||
|
#define PNG_SIMPLIFIED_READ_BGR_SUPPORTED
|
||||||
|
#define PNG_SIMPLIFIED_READ_SUPPORTED
|
||||||
|
#define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
|
||||||
|
#define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED
|
||||||
|
#define PNG_SIMPLIFIED_WRITE_SUPPORTED
|
||||||
#define PNG_sPLT_SUPPORTED
|
#define PNG_sPLT_SUPPORTED
|
||||||
#define PNG_sRGB_SUPPORTED
|
#define PNG_sRGB_SUPPORTED
|
||||||
#define PNG_STDIO_SUPPORTED
|
#define PNG_STDIO_SUPPORTED
|
||||||
|
|||||||
@ -239,3 +239,10 @@ EXPORTS
|
|||||||
png_get_cHRM_XYZ_fixed @231
|
png_get_cHRM_XYZ_fixed @231
|
||||||
png_set_cHRM_XYZ @232
|
png_set_cHRM_XYZ @232
|
||||||
png_set_cHRM_XYZ_fixed @233
|
png_set_cHRM_XYZ_fixed @233
|
||||||
|
png_image_begin_read_from_file @234
|
||||||
|
png_image_begin_read_from_stdio @235
|
||||||
|
png_image_begin_read_from_memory @236
|
||||||
|
png_image_finish_read @237
|
||||||
|
png_image_free @238
|
||||||
|
png_image_write_to_file @239
|
||||||
|
png_image_write_to_stdio @240
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user