1 /* png.c - load PNG image from file
3 * Raster graphics library
5 * Copyright (c) 1997-2003 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., 51 Franklin St, Fifth Floor, Boston,
32 #include "imgformat.h"
36 RImage
*RLoadPNG(RContext
*context
, const char *file
)
42 png_infop pinfo
, einfo
;
43 png_color_16p bkcolor
;
47 png_uint_32 width
, height
;
48 int depth
, junk
, color_type
;
52 f
= fopen(file
, "rb");
54 RErrorCode
= RERR_OPEN
;
57 png
= png_create_read_struct(PNG_LIBPNG_VER_STRING
, NULL
, (png_error_ptr
) NULL
, (png_error_ptr
) NULL
);
59 RErrorCode
= RERR_NOMEMORY
;
64 pinfo
= png_create_info_struct(png
);
66 RErrorCode
= RERR_NOMEMORY
;
68 png_destroy_read_struct(&png
, NULL
, NULL
);
72 einfo
= png_create_info_struct(png
);
74 RErrorCode
= RERR_NOMEMORY
;
76 png_destroy_read_struct(&png
, &pinfo
, NULL
);
80 RErrorCode
= RERR_INTERNAL
;
81 #if PNG_LIBPNG_VER - 0 < 10400
82 if (setjmp(png
->jmpbuf
)) {
84 if (setjmp(png_jmpbuf(png
))) {
87 png_destroy_read_struct(&png
, &pinfo
, &einfo
);
95 png_read_info(png
, pinfo
);
97 png_get_IHDR(png
, pinfo
, &width
, &height
, &depth
, &color_type
, &junk
, &junk
, &junk
);
100 if (width
< 1 || height
< 1) {
102 png_destroy_read_struct(&png
, &pinfo
, &einfo
);
103 RErrorCode
= RERR_BADIMAGEFILE
;
107 /* check for an alpha channel */
108 if (png_get_valid(png
, pinfo
, PNG_INFO_tRNS
))
111 alpha
= (color_type
& PNG_COLOR_MASK_ALPHA
);
113 /* allocate RImage */
114 image
= RCreateImage(width
, height
, alpha
);
117 png_destroy_read_struct(&png
, &pinfo
, &einfo
);
121 /* normalize to 8bpp with alpha channel */
122 if (color_type
== PNG_COLOR_TYPE_PALETTE
&& depth
<= 8)
125 if (color_type
== PNG_COLOR_TYPE_GRAY
&& depth
<= 8)
128 if (png_get_valid(png
, pinfo
, PNG_INFO_tRNS
))
132 png_set_strip_16(png
);
134 if (color_type
== PNG_COLOR_TYPE_GRAY
|| color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
135 png_set_gray_to_rgb(png
);
137 /* set gamma correction */
138 if ((context
->attribs
->flags
& RC_GammaCorrection
)
139 && context
->depth
!= 8) {
140 sgamma
= (context
->attribs
->rgamma
+ context
->attribs
->ggamma
+ context
->attribs
->bgamma
) / 3;
141 } else if ((tmp
= getenv("DISPLAY_GAMMA")) != NULL
) {
150 if (png_get_gAMA(png
, pinfo
, &gamma
))
151 png_set_gamma(png
, sgamma
, gamma
);
153 png_set_gamma(png
, sgamma
, 0.45);
155 /* do not remove, required for png_read_update_info */
156 png_set_interlace_handling(png
);
158 /* do the transforms */
159 png_read_update_info(png
, pinfo
);
161 /* set background color */
162 if (png_get_bKGD(png
, pinfo
, &bkcolor
)) {
163 image
->background
.red
= bkcolor
->red
>> 8;
164 image
->background
.green
= bkcolor
->green
>> 8;
165 image
->background
.blue
= bkcolor
->blue
>> 8;
168 png_rows
= calloc(height
, sizeof(png_bytep
));
170 RErrorCode
= RERR_NOMEMORY
;
172 RReleaseImage(image
);
173 png_destroy_read_struct(&png
, &pinfo
, &einfo
);
176 for (y
= 0; y
< height
; y
++) {
177 png_rows
[y
] = malloc(png_get_rowbytes(png
, pinfo
));
179 RErrorCode
= RERR_NOMEMORY
;
181 RReleaseImage(image
);
182 png_destroy_read_struct(&png
, &pinfo
, &einfo
);
191 png_read_image(png
, png_rows
);
193 png_read_end(png
, einfo
);
195 png_destroy_read_struct(&png
, &pinfo
, &einfo
);
201 /* convert to RImage */
203 for (y
= 0; y
< height
; y
++) {
204 for (x
= 0, i
= width
* 4; x
< i
; x
++, ptr
++) {
205 *ptr
= *(png_rows
[y
] + x
);
209 for (y
= 0; y
< height
; y
++) {
210 for (x
= 0, i
= width
* 3; x
< i
; x
++, ptr
++) {
211 *ptr
= *(png_rows
[y
] + x
);
215 for (y
= 0; y
< height
; y
++)