GadgetSeed  0.9.6
pngdec.c
[詳解]
1 /** @file
2  @brief PNGデコード
3 
4  libpng を使用
5  http://www.libpng.org/
6 
7  @date 2018.01.03
8  @author Takashi SHUDO
9 */
10 
11 #include "file.h"
12 #include "pngdec.h"
13 #include "str.h"
14 #include "memory.h"
15 #include "graphics.h"
16 #include "png.h"
17 
18 //#define DEBUGTBITS 0x01
19 #include "dtprintf.h"
20 
21 
22 static png_structp png_ptr = 0;
23 static png_infop info_ptr = 0;
24 
25 /*
26  * ファイル上データデコード
27  */
28 typedef struct my_png_file_ {
29  int fd;
30 } my_png_file;
31 
32 
33 static void png_fileread_func(png_structp png_sp, png_bytep buf, png_size_t size)
34 {
35  my_png_file *png_file;
36 
37  DTFPRINTF(0x02, "size = %d\n", size);
38 
39  png_file = (my_png_file *)png_get_io_ptr(png_sp);
40 
41  read_file(png_file->fd, buf, size);
42 
43  XDUMP(0x02, buf, size);
44 }
45 
46 static my_png_file png_file;
47 
48 int get_png_file_info(int fd, short *png_width, short *png_height)
49 {
50  int res = 0;
51 #if 0 // png_read_info()で同様の処理は行っているので
52  unsigned char png_sig[8];
53  int rt;
54  rt = read_file(fd, png_sig, 8);
55  seek_file(fd, 0, SEEK_SET);
56  if(rt != 8) {
57  DTPRINTF(0x01, "PNG file read error\n");
58  return -1;
59  }
60 
61  rt = png_check_sig(png_sig, 8);
62  if(rt == 0) {
63  DTPRINTF(0x01, "png_check_sig() error\n");
64  return -1;
65  }
66 #endif
67 
68  png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
69  if(png_ptr == 0) {
70  DTFPRINTF(0x01, "png_create_read_struct() error\n");
71  res = -1;
72  goto error;
73  }
74 
75  info_ptr = png_create_info_struct(png_ptr);
76  if(info_ptr == NULL) {
77  DTFPRINTF(0x01, "png_create_info_struct() error\n");
78  res = -1;
79  goto error;
80  }
81 
82  if(setjmp(png_jmpbuf(png_ptr))) {
83  DTFPRINTF(0x01, "decode error\n");
84  res = -1;
85  goto error;
86  }
87 
88  png_file.fd = fd;
89  png_set_read_fn(png_ptr, (png_voidp)&png_file, (png_rw_ptr)png_fileread_func);
90 
91  png_uint_32 width, height;
92  int bit_depth, color_type, interlace_type;
93  int compression_type, filter_type;
94 
95  png_read_info(png_ptr, info_ptr);
96  png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth,&color_type,
97  &interlace_type, &compression_type, &filter_type);
98  DTPRINTF(0x01, "width = %u, height = %u, bpp = %d, color_type = %d\n",
99  width, height, bit_depth, color_type);
100 
101  *png_width = width;
102  *png_height = height;
103 
104  return res;
105 
106 error:
107  png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
108 
109  return res;
110 }
111 
112 
113 /*
114  * メモリ上データデコード
115  */
116 struct my_png_data {
117  unsigned char *data_ptr;
118 };
119 
120 
121 static void png_dataread_func(png_structp png_ptr, png_bytep buf, png_size_t size)
122 {
123  DTFPRINTF(0x02, "size = %d\n", size);
124 
125  struct my_png_data *png_data = (struct my_png_data *)png_get_io_ptr(png_ptr);
126 
127  memorycopy(buf, png_data->data_ptr, size);
128  png_data->data_ptr += size;
129 
130  XDUMP(0x02, buf, size);
131 }
132 
133 static struct my_png_data png_data;
134 
135 int get_png_data_info(unsigned char *data, short *png_width, short *png_height)
136 {
137  int res = 0;
138 #if 0 // png_read_info()で同様の処理は行っているので
139  unsigned char png_sig[8];
140  int rt;
141  rt = read_file(fd, png_sig, 8);
142  seek_file(fd, 0, SEEK_SET);
143  if(rt != 8) {
144  DTPRINTF(0x01, "PNG file read error\n");
145  return -1;
146  }
147 
148  rt = png_check_sig(png_sig, 8);
149  if(rt == 0) {
150  DTPRINTF(0x01, "png_check_sig() error\n");
151  return -1;
152  }
153 #endif
154 
155  png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
156  if(png_ptr == 0) {
157  DTFPRINTF(0x01, "png_create_read_struct() error\n");
158  res = -1;
159  goto error;
160  }
161 
162  info_ptr = png_create_info_struct(png_ptr);
163  if(info_ptr == NULL) {
164  DTFPRINTF(0x01, "png_create_info_struct() error\n");
165  res = -1;
166  goto error;
167  }
168 
169  if(setjmp(png_jmpbuf(png_ptr))) {
170  DTFPRINTF(0x01, "decode error\n");
171  res = -1;
172  goto error;
173  }
174 
175  png_data.data_ptr = data;
176  png_set_read_fn(png_ptr, (png_voidp)&png_data, (png_rw_ptr)png_dataread_func);
177 
178  png_uint_32 width, height;
179  int bit_depth, color_type, interlace_type;
180  int compression_type, filter_type;
181 
182  png_read_info(png_ptr, info_ptr);
183  png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth,&color_type,
184  &interlace_type, &compression_type, &filter_type);
185  DTPRINTF(0x01, "width = %u, height = %u bpp = %d color_type = %d\n",
186  width, height, bit_depth, color_type);
187 
188  *png_width = width;
189  *png_height = height;
190 
191  return res;
192 
193 error:
194  png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
195 
196  return res;
197 }
198 
199 
200 int decode_png(void *image)
201 {
202  int res = 0;
203  unsigned char **rowimage;
204  int i, j;
205  int rowbytes;
206  png_uint_32 width, height;
207  int bit_depth, color_type, interlace_type;
208  int compression_type, filter_type;
209  PIXEL_DATA *pixel_p = image;
210 
211  png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
212  &interlace_type, &compression_type, &filter_type);
213 
214  switch(color_type) {
215  case PNG_COLOR_TYPE_PALETTE: // インデックスカラー
216  DTPRINTF(0x01, "PNG_COLOR_TYPE_PALETTE not supported\n");
217  res = -1;
218  goto end;
219  break;
220 
221  case PNG_COLOR_TYPE_GRAY: // グレースケール
222  DTPRINTF(0x01, "PNG_COLOR_TYPE_GRAY not supported\n");
223  res = -1;
224  break;
225 
226  case PNG_COLOR_TYPE_GRAY_ALPHA: // グレースケール+α
227  DTPRINTF(0x01, "PNG_COLOR_TYPE_GRAY_ALPHA not supported\n");
228  res = -1;
229  goto end;
230  break;
231 
232  case PNG_COLOR_TYPE_RGB: // RGB
233  DTPRINTF(0x01, "PNG_COLOR_TYPE_RGB\n");
234  break;
235 
236  case PNG_COLOR_TYPE_RGB_ALPHA: // RGBA
237  DTPRINTF(0x01, "PNG_COLOR_TYPE_RGB_ALPHA\n");
238  break;
239 
240  default:
241  DTPRINTF(0x01, "Unknown type(%d)\n", color_type);
242  res = -1;
243  goto end;
244  break;
245  }
246 
247  if(setjmp(png_jmpbuf(png_ptr))) {
248  DTFPRINTF(0x01, "decode error\n");
249  res = -1;
250  goto error;
251  }
252 
253  rowimage = (png_bytepp)alloc_memory(height * sizeof(png_bytep));
254  rowbytes = png_get_rowbytes(png_ptr, info_ptr);
255  DTPRINTF(0x01, "rowbytes = %d\n", rowbytes);
256  for(i=0; i<height; i++) {
257  rowimage[i] = (png_bytep)alloc_memory(rowbytes);
258  }
259 
260  png_read_image(png_ptr, rowimage);
261 
262  for(i=0; i<height; i++) {
263  XDUMP(0x02, rowimage[i], width);
264  for(j=0; j<width; j++) {
265  switch(color_type) {
266  case PNG_COLOR_TYPE_RGB_ALPHA:
267  pixel_p[width*i + j] = RGB(rowimage[i][j*4+0], rowimage[i][j*4+1], rowimage[i][j*4+2]);
268  break;
269 
270  case PNG_COLOR_TYPE_RGB:
271  pixel_p[width*i + j] = RGB(rowimage[i][j*3+0], rowimage[i][j*3+1], rowimage[i][j*3+2]);
272  break;
273 
274  default:
275  break;
276  }
277  }
278  }
279  //draw_image(px, py, width, height, image, width);
280 
281 error:
282  for(i=0; i<height; i++) {
283  free_memory(rowimage[i]);
284  }
285  free_memory(rowimage);
286 
287 end:
288  png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
289 
290  return res;
291 }
292 
293 
294 void dispose_png_info(void)
295 {
296  png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
297 }
PNGデコード
メモリ管理
t_ssize seek_file(int fd, t_ssize offset, int whence)
ファイルアクセス位置の設定
Definition: file.c:244
void free_memory(void *ptr)
確保したメモリを開放する
Definition: memory.c:195
アプリケーション(タスク)デバッグ用マクロ
文字列処理
ファイル
void * alloc_memory(unsigned int size)
メモリを確保する
Definition: memory.c:138
void * memorycopy(void *dest, const void *src, unsigned int count)
メモリコピー
Definition: str.c:760
#define SEEK_SET
設定
Definition: device.h:21
t_ssize read_file(int fd, void *buf, t_size count)
ファイルからデータを読み出す
Definition: file.c:188
グラフィックライブラリ
unsigned short PIXEL_DATA
$gsc グラフィックデバイスは24ビットカラー
Definition: graphics.h:17