1 /* png.c - load PNG image from file
3 * Raster graphics library
5 * Copyright (c) 1997 Alfredo K. Kojima
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 /* AIX requires this to be the first thing in the file. */
26 # define alloca __builtin_alloca
34 # ifndef alloca /* predefined by HP cc +Olibcalls */
50 #if PNG_LIBPNG_VER < 96
51 #error libpng_must_be_more_at_least_0_96
58 RLoadPNG(RContext
*context
, char *file
, int index
)
64 png_infop pinfo
, einfo
;
65 png_color_16p bkcolor
;
69 png_uint_32 width
, height
;
70 int depth
, junk
, color_type
;
72 unsigned char *r
, *g
, *b
, *a
;
76 sprintf(RErrorString
, "could not open file \"%s\"", file
);
79 png
= png_create_read_struct(PNG_LIBPNG_VER_STRING
, NULL
,
80 (png_error_ptr
)NULL
, (png_error_ptr
)NULL
);
82 sprintf(RErrorString
, "error loading PNG file \"%s\"", file
);
87 pinfo
= png_create_info_struct(png
);
89 sprintf(RErrorString
, "error loading PNG file \"%s\"", file
);
91 png_destroy_read_struct(&png
, NULL
, NULL
);
95 einfo
= png_create_info_struct(png
);
97 sprintf(RErrorString
, "error loading PNG file \"%s\"", file
);
99 png_destroy_read_struct(&png
, &pinfo
, NULL
);
103 if (setjmp(png
->jmpbuf
)) {
104 sprintf(RErrorString
, "error loading PNG file \"%s\"", file
);
106 png_destroy_read_struct(&png
, &pinfo
, &einfo
);
108 RDestroyImage(image
);
114 png_read_info(png
, pinfo
);
116 png_get_IHDR(png
, pinfo
, &width
, &height
, &depth
, &color_type
,
117 &junk
, &junk
, &junk
);
120 /* check for an alpha channel */
121 if (png_get_valid(png
, pinfo
, PNG_INFO_tRNS
))
124 alpha
= (color_type
& PNG_COLOR_MASK_ALPHA
);
126 /* allocate RImage */
127 image
= RCreateImage(width
, height
, alpha
);
129 sprintf(RErrorString
, "could not create RImage");
131 png_destroy_read_struct(&png
, &pinfo
, &einfo
);
135 /* normalize to 8bpp with alpha channel */
136 if (color_type
== PNG_COLOR_TYPE_PALETTE
&& depth
< 8)
139 if (color_type
== PNG_COLOR_TYPE_GRAY
&& depth
< 8)
142 if (png_get_valid(png
, pinfo
, PNG_INFO_tRNS
))
146 png_set_strip_16(png
);
148 if (color_type
== PNG_COLOR_TYPE_GRAY
||
149 color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
150 png_set_gray_to_rgb(png
);
152 /* set gamma correction */
153 if ((context
->attribs
->flags
& RC_GammaCorrection
)
154 && context
->depth
!= 8) {
155 sgamma
= (context
->attribs
->rgamma
+ context
->attribs
->ggamma
+
156 context
->attribs
->bgamma
) / 3;
157 } else if ((tmp
= getenv("DISPLAY_GAMMA")) != NULL
) {
165 if (png_get_gAMA(png
, pinfo
, &gamma
))
166 png_set_gamma(png
, sgamma
, gamma
);
168 png_set_gamma(png
, sgamma
, 0.45);
170 /* do the transforms */
171 png_read_update_info(png
, pinfo
);
173 /* set background color */
174 if (png_get_bKGD(png
, pinfo
, &bkcolor
)) {
175 image
->background
.red
= bkcolor
->red
>> 8;
176 image
->background
.green
= bkcolor
->green
>> 8;
177 image
->background
.blue
= bkcolor
->blue
>> 8;
180 png_rows
= alloca(sizeof(char*)*height
);
182 sprintf(RErrorString
, "out of memory loading \"%s\"", file
);
184 RDestroyImage(image
);
185 png_destroy_read_struct(&png
, &pinfo
, &einfo
);
191 for (y
=0; y
<height
; y
++) {
192 png_rows
[y
] = alloca(png_get_rowbytes(png
, pinfo
));
194 sprintf(RErrorString
, "out of memory loading \"%s\"", file
);
196 RDestroyImage(image
);
197 png_destroy_read_struct(&png
, &pinfo
, &einfo
);
205 png_read_image(png
, png_rows
);
207 png_read_end(png
, einfo
);
209 png_destroy_read_struct(&png
, &pinfo
, &einfo
);
218 /* convert to RImage */
220 for (y
=0; y
<height
; y
++) {
221 for (x
=0, i
=0; x
<width
; x
++) {
222 *(r
++) = *(png_rows
[y
]+i
++);
223 *(g
++) = *(png_rows
[y
]+i
++);
224 *(b
++) = *(png_rows
[y
]+i
++);
225 *(a
++) = *(png_rows
[y
]+i
++);
229 for (y
=0; y
<height
; y
++) {
230 for (x
=0, i
=0; x
<width
; x
++) {
231 *(r
++) = *(png_rows
[y
]+i
++);
232 *(g
++) = *(png_rows
[y
]+i
++);
233 *(b
++) = *(png_rows
[y
]+i
++);