|
1 /* |
|
2 * GUI PNG files processing |
|
3 * |
|
4 * Copyright (c) 2009 CodeSourcery |
|
5 * |
|
6 * Permission is hereby granted, free of charge, to any person obtaining a copy |
|
7 * of this software and associated documentation files (the "Software"), to deal |
|
8 * in the Software without restriction, including without limitation the rights |
|
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
10 * copies of the Software, and to permit persons to whom the Software is |
|
11 * furnished to do so, subject to the following conditions: |
|
12 * |
|
13 * The above copyright notice and this permission notice shall be included in |
|
14 * all copies or substantial portions of the Software. |
|
15 * |
|
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
|
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|
22 * THE SOFTWARE. |
|
23 */ |
|
24 |
|
25 #include "png.h" |
|
26 #include "qemu-common.h" |
|
27 #include "gui_common.h" |
|
28 #include "gui_png.h" |
|
29 |
|
30 /* |
|
31 int x, y; |
|
32 |
|
33 int width, height; |
|
34 png_byte color_type; |
|
35 png_byte bit_depth; |
|
36 */ |
|
37 |
|
38 typedef struct |
|
39 { |
|
40 int width; |
|
41 int height; |
|
42 void* image4c; /* in 4 channels */ |
|
43 } png_image_data_t; |
|
44 |
|
45 static void abort_(const char * s, ...) |
|
46 { |
|
47 va_list args; |
|
48 va_start(args, s); |
|
49 vfprintf(stderr, s, args); |
|
50 fprintf(stderr, "\n"); |
|
51 va_end(args); |
|
52 abort(); |
|
53 } |
|
54 |
|
55 #if 0 |
|
56 static void read_png_file_low(const char* file_name, png_image_data_t *png_image_data) |
|
57 { |
|
58 png_structp png_ptr; |
|
59 int number_of_passes; |
|
60 char header[8]; // 8 is the maximum size that can be checked |
|
61 int y; |
|
62 |
|
63 /* open file and test for it being a png */ |
|
64 FILE *fp = fopen(file_name, "rb"); |
|
65 if (!fp) |
|
66 abort_("[read_png_file] File %s could not be opened for reading", file_name); |
|
67 fread(header, 1, 8, fp); |
|
68 if (png_sig_cmp(header, 0, 8)) |
|
69 abort_("[read_png_file] File %s is not recognized as a PNG file", file_name); |
|
70 |
|
71 |
|
72 /* initialize stuff */ |
|
73 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); |
|
74 |
|
75 if (!png_ptr) |
|
76 abort_("[read_png_file] png_create_read_struct failed"); |
|
77 |
|
78 png_image_data->info_ptr = png_create_info_struct(png_ptr); |
|
79 if (!png_image_data->info_ptr) |
|
80 abort_("[read_png_file] png_create_info_struct failed"); |
|
81 |
|
82 if (setjmp(png_jmpbuf(png_ptr))) |
|
83 abort_("[read_png_file] Error during init_io"); |
|
84 png_init_io(png_ptr, fp); |
|
85 |
|
86 png_set_sig_bytes(png_ptr, 8); /* 8 == sig_read ? */ |
|
87 |
|
88 png_read_info(png_ptr, png_image_data->info_ptr); |
|
89 |
|
90 /* set transformations */ |
|
91 /* |
|
92 if ((png_image_data->info_ptr->color_type & PNG_COLOR_TYPE_RGB) == 0) |
|
93 transforms |= PNG_TRANSFORM_BGR; |
|
94 */ |
|
95 if (png_get_valid(png_ptr, png_image_data->info_ptr, PNG_INFO_sBIT)) |
|
96 { |
|
97 png_color_8p sig_bit; |
|
98 |
|
99 png_get_sBIT(png_ptr, png_image_data->info_ptr, &sig_bit); |
|
100 printf("sig_bit: %d\n", sig_bit); |
|
101 png_set_shift(png_ptr, sig_bit); |
|
102 } |
|
103 |
|
104 /* TODO DFG: is this needed? */ |
|
105 number_of_passes = png_set_interlace_handling(png_ptr); |
|
106 png_read_update_info(png_ptr, png_image_data->info_ptr); |
|
107 |
|
108 |
|
109 |
|
110 |
|
111 |
|
112 /* read file */ |
|
113 if (setjmp(png_jmpbuf(png_ptr))) |
|
114 abort_("[read_png_file] Error during read_image"); |
|
115 |
|
116 #if 1 |
|
117 png_image_data->row_pointers = (png_bytep*) qemu_malloc(sizeof(png_bytep) * png_image_data->info_ptr->height); |
|
118 for (y=0; y < png_image_data->info_ptr->height; y++) |
|
119 png_image_data->row_pointers[y] = (png_byte*) qemu_malloc(png_image_data->info_ptr->rowbytes); |
|
120 |
|
121 png_read_image(png_ptr, png_image_data->row_pointers); |
|
122 #endif |
|
123 /* DFG TODO: Cleanup */ |
|
124 |
|
125 /* png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); */ |
|
126 |
|
127 fclose(fp); |
|
128 } |
|
129 #endif |
|
130 |
|
131 static void read_png_file(const char* file_name, png_image_data_t *png_image_data, int max_width, int max_height) |
|
132 { |
|
133 png_structp png_ptr; |
|
134 png_infop info_ptr; |
|
135 png_bytep *row_pointers; |
|
136 char header[8]; // 8 is the maximum size that can be checked |
|
137 int y; |
|
138 char* dest; |
|
139 |
|
140 /* open file and test for it being a png */ |
|
141 FILE *fp = fopen(file_name, "rb"); |
|
142 if (!fp) |
|
143 abort_("[read_png_file] File %s could not be opened for reading", file_name); |
|
144 fread(header, 1, 8, fp); |
|
145 if (png_sig_cmp(header, 0, 8)) |
|
146 abort_("[read_png_file] File %s is not recognized as a PNG file", file_name); |
|
147 |
|
148 |
|
149 /* initialize stuff */ |
|
150 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); |
|
151 |
|
152 if (!png_ptr) |
|
153 abort_("[read_png_file] png_create_read_struct failed"); |
|
154 |
|
155 if (max_width > 0 && max_height > 0) |
|
156 png_set_user_limits(png_ptr, max_width, max_height); |
|
157 |
|
158 info_ptr = png_create_info_struct(png_ptr); |
|
159 |
|
160 if (setjmp(png_jmpbuf(png_ptr))) |
|
161 abort_("[read_png_file] Error during init_io"); |
|
162 png_init_io(png_ptr, fp); |
|
163 |
|
164 if (setjmp(png_jmpbuf(png_ptr))) |
|
165 abort_("[read_png_file] Error during init_io"); |
|
166 png_set_sig_bytes(png_ptr, sizeof(header)); |
|
167 |
|
168 if (setjmp(png_jmpbuf(png_ptr))) |
|
169 abort_("[read_png_file] Error during init_io"); |
|
170 png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_ALPHA, png_voidp_NULL); |
|
171 |
|
172 if (setjmp(png_jmpbuf(png_ptr))) |
|
173 abort_("[read_png_file] Error during init_io"); |
|
174 |
|
175 row_pointers = png_get_rows(png_ptr, info_ptr); |
|
176 |
|
177 png_image_data->height = png_get_image_height(png_ptr, info_ptr); |
|
178 png_image_data->width = png_get_image_width(png_ptr, info_ptr); |
|
179 |
|
180 png_image_data->image4c = (void*)qemu_malloc(png_image_data->width * png_image_data->height * 4); |
|
181 |
|
182 dest = (char*)png_image_data->image4c; |
|
183 |
|
184 /* transform this from 3 channels to a (fake for now) 4 channels */ |
|
185 for (y=0; y < png_image_data->height; y++) { |
|
186 char* src = row_pointers[y]; |
|
187 int x; |
|
188 for (x = 0; x < png_image_data->width; x++) { |
|
189 *dest = *src; dest++, src++; |
|
190 *dest = *src; dest++, src++; |
|
191 *dest = *src; dest++, src++; |
|
192 *dest = 0; dest++; /* alpha channel ignored */ |
|
193 } |
|
194 } |
|
195 |
|
196 png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); |
|
197 |
|
198 fclose(fp); |
|
199 } |
|
200 |
|
201 |
|
202 |
|
203 void gui_load_image_png(const char *filename, gui_image_t *image_data) |
|
204 { |
|
205 const int area_height = GET_GUI_AREA_HEIGHT(&image_data->area); |
|
206 const int area_width = GET_GUI_AREA_WIDTH(&image_data->area); |
|
207 png_image_data_t png_image_data; |
|
208 |
|
209 read_png_file(filename, &png_image_data, area_width, area_height); |
|
210 |
|
211 /* see if area has to be resized, because of any of these reasons: |
|
212 a) the image is smaller than the area |
|
213 b) the area is 0 (auto size for the background) |
|
214 */ |
|
215 if (area_height > png_image_data.height || area_height <= 0) |
|
216 SET_GUI_AREA_HEIGHT(&image_data->area, png_image_data.height); |
|
217 if (area_width > png_image_data.width || area_width <= 0) |
|
218 SET_GUI_AREA_WIDTH(&image_data->area, png_image_data.width); |
|
219 |
|
220 image_data->image = png_image_data.image4c; |
|
221 } |
|
222 |