1
/****************************************************************************
2
png.c - read and write png images using libpng routines.
3
Distributed with Xplanet.
4
Copyright (C) 2002 Hari Nair <hari@alumni.caltech.edu>
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or
9
(at your option) any later version.
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
GNU General Public License for more details.
16
You should have received a copy of the GNU General Public License
17
along with this program; if not, write to the Free Software
18
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
****************************************************************************/
27
read_png(const char *filename, int *width, int *height, unsigned char **rgb,
28
unsigned char **alpha)
30
FILE *infile = fopen(filename, "rb");
34
png_bytepp row_pointers;
36
unsigned char *ptr = NULL;
38
int bit_depth, color_type, interlace_type;
41
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
44
(png_error_ptr) NULL);
51
info_ptr = png_create_info_struct(png_ptr);
54
png_destroy_read_struct(&png_ptr, (png_infopp) NULL,
60
if (setjmp(png_ptr->jmpbuf))
62
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
67
png_init_io(png_ptr, infile);
68
png_read_info(png_ptr, info_ptr);
70
png_get_IHDR(png_ptr, info_ptr, &w, &h, &bit_depth, &color_type,
71
&interlace_type, (int *) NULL, (int *) NULL);
76
if (color_type == PNG_COLOR_TYPE_RGB_ALPHA
77
|| color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
79
alpha[0] = malloc(*width * *height);
82
fprintf(stderr, "Can't allocate memory for alpha channel in PNG file.\n");
87
/* Change a paletted/grayscale image to RGB */
88
if (color_type == PNG_COLOR_TYPE_PALETTE && bit_depth <= 8)
89
png_set_expand(png_ptr);
91
/* Change a grayscale image to RGB */
92
if (color_type == PNG_COLOR_TYPE_GRAY
93
|| color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
94
png_set_gray_to_rgb(png_ptr);
96
/* If the PNG file has 16 bits per channel, strip them down to 8 */
97
if (bit_depth == 16) png_set_strip_16(png_ptr);
99
/* use 1 byte per pixel */
100
png_set_packing(png_ptr);
102
row_pointers = malloc(*height * sizeof(png_bytep));
103
if (row_pointers == NULL)
105
fprintf(stderr, "Can't allocate memory for PNG file.\n");
109
for (i = 0; i < *height; i++)
111
row_pointers[i] = malloc(4 * *width);
112
if (row_pointers == NULL)
114
fprintf(stderr, "Can't allocate memory for PNG line.\n");
119
png_read_image(png_ptr, row_pointers);
121
rgb[0] = malloc(3 * *width * *height);
124
fprintf(stderr, "Can't allocate memory for PNG file.\n");
128
if (alpha[0] == NULL)
131
for (i = 0; i < *height; i++)
133
memcpy(ptr, row_pointers[i], 3 * *width);
141
for (i = 0; i < *height; i++)
144
for (j = 0; j < *width; j++)
146
*ptr++ = row_pointers[i][ipos++];
147
*ptr++ = row_pointers[i][ipos++];
148
*ptr++ = row_pointers[i][ipos++];
149
alpha[0][i * *width + j] = row_pointers[i][ipos++];
154
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
156
for (i = 0; i < *height; i++) free(row_pointers[i]);
164
write_png(FILE *outfile, int width, int height, unsigned char *rgb,
165
unsigned char *alpha)
173
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
175
(png_error_ptr) NULL,
176
(png_error_ptr) NULL);
178
if (!png_ptr) return(0);
180
info_ptr = png_create_info_struct(png_ptr);
183
png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
187
png_init_io(png_ptr, outfile);
191
png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB,
192
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
193
PNG_FILTER_TYPE_DEFAULT);
195
png_write_info(png_ptr, info_ptr);
197
for (i = 0; i < height; i++)
199
row_ptr = rgb + 3 * i * width;
200
png_write_rows(png_ptr, &row_ptr, 1);
208
int area = width * height;
209
unsigned char *rgba = malloc(4 * area);
211
png_set_IHDR(png_ptr, info_ptr, width, height, 8,
212
PNG_COLOR_TYPE_RGB_ALPHA,
213
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
214
PNG_FILTER_TYPE_DEFAULT);
216
png_write_info(png_ptr, info_ptr);
218
for (i = 0; i < area; i++)
220
rgba[irgba++] = rgb[irgb++];
221
rgba[irgba++] = rgb[irgb++];
222
rgba[irgba++] = rgb[irgb++];
223
rgba[irgba++] = alpha[i];
226
for (i = 0; i < height; i++)
228
row_ptr = rgba + 4 * i * width;
229
png_write_rows(png_ptr, &row_ptr, 1);
235
png_write_end(png_ptr, info_ptr);
236
png_destroy_write_struct(&png_ptr, &info_ptr);