1 /* input-png.c: PNG loader for autotrace
2
3 Copyright (C) 2000 MenTaLguY <mental@rydia.net>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public License
7 as published by the Free Software Foundation; either version 2.1 of
8 the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18 USA. */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif /* Def: HAVE_CONFIG_H */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "types.h"
29 #include "bitmap.h"
30 #include "message.h"
31 #include "xstd.h"
32 #include <png.h>
33 #include "input-png.h"
34
35 static volatile char rcsid[]="$Id: input-png.c,v 1.16 2002/10/05 19:38:25 masata-y Exp $";
36 static png_bytep * read_png(png_structp png_ptr, png_infop info_ptr, at_input_opts_type * opts);
37
38 /* for pre-1.0.6 versions of libpng */
39 #ifndef png_jmpbuf
40 # define png_jmpbuf(png_ptr) (png_ptr)->jmpbuf
41 #endif
42
handle_warning(png_structp png,const at_string message)43 static void handle_warning(png_structp png, const at_string message) {
44 LOG1("PNG warning: %s", message);
45 at_exception_warning((at_exception_type *)png_get_error_ptr(png),
46 message);
47 /* at_exception_fatal((at_exception_type *)png_get_error_ptr(at_png),
48 "PNG warning"); */
49 }
50
handle_error(png_structp png,const at_string message)51 static void handle_error(png_structp png, const at_string message) {
52 LOG1("PNG error: %s", message);
53 at_exception_fatal((at_exception_type *)png_get_error_ptr(png),
54 message);
55 /* at_exception_fatal((at_exception_type *)png_get_error_ptr(at_png),
56 "PNG error"); */
57
58 }
59
finalize_structs(png_structp png,png_infop info,png_infop end_info)60 static void finalize_structs(png_structp png, png_infop info,
61 png_infop end_info)
62 {
63 png_destroy_read_struct(png ? &png : NULL,
64 info ? &info : NULL,
65 end_info ? &end_info : NULL);
66 }
67
init_structs(png_structp * png,png_infop * info,png_infop * end_info,at_exception_type * exp)68 static int init_structs(png_structp *png, png_infop *info,
69 png_infop *end_info, at_exception_type * exp)
70 {
71 *png = NULL;
72 *info = *end_info = NULL;
73
74 *png = png_create_read_struct(PNG_LIBPNG_VER_STRING, exp,
75 (png_error_ptr)handle_error, (png_error_ptr)handle_warning);
76
77 if (*png) {
78 *info = png_create_info_struct(*png);
79 if (*info) {
80 *end_info = png_create_info_struct(*png);
81 if (*end_info) return 1;
82 }
83 finalize_structs(*png, *info, *end_info);
84 }
85 return 0;
86 }
87
88 #define CHECK_ERROR() do { if (at_exception_got_fatal(exp)) \
89 { \
90 result = 0; \
91 goto cleanup; \
92 } } while (0)
93
load_image(at_bitmap_type * image,FILE * stream,at_input_opts_type * opts,at_exception_type * exp)94 static int load_image(at_bitmap_type *image, FILE *stream, at_input_opts_type * opts, at_exception_type * exp)
95 {
96 png_structp png;
97 png_infop info, end_info;
98 png_bytep *rows;
99 unsigned short width, height, row;
100 int pixel_size;
101 int result = 1;
102
103 if (!init_structs(&png, &info, &end_info, exp))
104 return 0;
105
106 png_init_io(png, stream);
107 CHECK_ERROR();
108
109 png_read_png(png, info, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND, 0);
110 rows = png_get_rows(png, info);
111
112 width = (unsigned short)png_get_image_width(png, info);
113 height = (unsigned short)png_get_image_height(png, info);
114 if ( png_get_color_type(png, info) == PNG_COLOR_TYPE_GRAY ) {
115 pixel_size = 1;
116 } else {
117 pixel_size = 3;
118 }
119
120 *image = at_bitmap_init(NULL, width, height, pixel_size);
121 for ( row = 0 ; row < height ; row++, rows++ ) {
122 memcpy(AT_BITMAP_PIXEL(*image, row, 0), *rows,
123 width * pixel_size * sizeof(unsigned char));
124 }
125 cleanup:
126 finalize_structs(png, info, end_info);
127 return result;
128 }
129
input_png_reader(at_string filename,at_input_opts_type * opts,at_msg_func msg_func,at_address msg_data)130 at_bitmap_type input_png_reader(at_string filename, at_input_opts_type * opts,
131 at_msg_func msg_func, at_address msg_data) {
132 FILE *stream;
133 at_bitmap_type image = at_bitmap_init(0, 0, 0, 1);
134 at_exception_type exp = at_exception_new(msg_func, msg_data);
135
136 stream = fopen(filename, "rb");
137 if (!stream)
138 {
139 LOG1("Can't open \"%s\"\n", filename);
140 at_exception_fatal(&exp, "Cannot open input png file");
141 return image;
142 }
143
144 load_image(&image, stream, opts, &exp);
145 fclose(stream);
146
147 return image;
148 }
149