PageRenderTime 93ms CodeModel.GetById 20ms app.highlight 41ms RepoModel.GetById 23ms app.codeStats 0ms

/src/canvas/default/ftk_image_png_decoder.c

http://ftk.googlecode.com/
C | 283 lines | 219 code | 34 blank | 30 comment | 41 complexity | cc74fd30e7c9c590347680629d9a8a81 MD5 | raw file
  1/*
  2 * File: ftk_image_png_decoder.c	
  3 * Author:	Li XianJing <xianjimli@hotmail.com>
  4 * Brief:	png format image decoder.
  5 *
  6 * Copyright (c) 2009 - 2010  Li XianJing <xianjimli@hotmail.com>
  7 *
  8 * Licensed under the Academic Free License version 2.1
  9 *
 10 * This program is free software; you can redistribute it and/or modify
 11 * it under the terms of the GNU General Public License as published by
 12 * the Free Software Foundation; either version 2 of the License, or
 13 * (at your option) any later version.
 14 *
 15 * This program is distributed in the hope that it will be useful,
 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 18 * GNU General Public License for more details.
 19 *
 20 * You should have received a copy of the GNU General Public License
 21 * along with this program; if not, write to the Free Software
 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 23 */
 24
 25/*
 26 * History:
 27 * ================================================================
 28 * 2009-10-03 Li XianJing <xianjimli@hotmail.com> created
 29 * 2010-10-02 Jiao JinXing <jiaojinxing1987@gmail.com> add rt-thread support.
 30 *
 31 */
 32
 33#define PNG_SKIP_SETJMP_CHECK
 34#include "ftk_log.h"
 35#include "ftk_image_png_decoder.h"

 36#include <png.h>

 37
 38#ifdef RT_THREAD

 39static void ftk_image_png_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
 40{
 41	int fd = (int)png_ptr->io_ptr;
 42
 43	read(fd, data, length);
 44}
 45
 46static png_voidp ftk_png_malloc(png_structp png_ptr, png_size_t size)
 47{
 48	return malloc(size);
 49}
 50
 51static void ftk_png_free(png_structp png_ptr, png_voidp ptr)
 52{
 53	free(ptr);
 54}
 55#endif

 56
 57static Ret ftk_image_png_decoder_match(FtkImageDecoder* thiz, const char* filename)
 58{
 59	return_val_if_fail(filename != NULL, RET_FAIL);
 60
 61	return (strstr(filename, ".png") != NULL) ? RET_OK : RET_FAIL;
 62}
 63
 64static FtkBitmap* load_png (const char *filename)
 65{
 66	int x = 0;
 67	int y = 0;
 68	int w = 0;
 69	int h = 0;
 70#ifndef RT_THREAD
 71	FILE *fp = NULL;
 72#else

 73	int fd = -1;
 74#endif	

 75
 76	int passes_nr = 0;
 77	FtkColor* dst = NULL;
 78	unsigned char* src = NULL;
 79	FtkBitmap* bitmap = NULL;
 80	FtkColor  bg = {0};
 81	png_structp png_ptr = NULL;
 82	png_infop info_ptr = NULL;
 83	png_bytep * row_pointers = NULL;
 84
 85	bg.a = 0xff;
 86
 87#ifndef RT_THREAD
 88	if ((fp = fopen (filename, "rb")) == NULL)
 89	{
 90		ftk_logd("%s: open %s failed.\n", __func__, filename);
 91		return NULL;
 92	}
 93
 94	if((png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)) == NULL)
 95	{
 96		fclose(fp);
 97		return NULL;
 98	}
 99	
100	if((info_ptr = png_create_info_struct(png_ptr)) == NULL)
101	{
102		fclose(fp);
103		return NULL;
104	}
105#else

106	if ((fd = open (filename, O_RDONLY, 0)) < 0)
107	{
108		ftk_logd("%s: open %s failed.\n", __func__, filename);
109		return NULL;
110	}
111
112	if((png_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL, NULL, ftk_png_malloc, ftk_png_free)) == NULL)
113	{
114		close(fd);
115		return NULL;
116	}
117
118	if((info_ptr = png_create_info_struct(png_ptr)) == NULL)
119	{
120		close(fd);
121		return NULL;
122	}
123#endif

124
125#ifdef PNG_SETJMP_SUPPORTED
126	setjmp(png_jmpbuf(png_ptr));
127#endif

128
129#ifndef RT_THREAD
130	png_init_io(png_ptr, fp);
131#else

132	png_set_read_fn(png_ptr, (void *)fd, ftk_image_png_read_data);
133#endif

134
135	memset(info_ptr, 0x00, sizeof(*info_ptr));
136	png_read_info(png_ptr, info_ptr);
137
138	w = info_ptr->width;
139	h = info_ptr->height;
140
141	passes_nr = png_set_interlace_handling(png_ptr);
142	png_read_update_info(png_ptr, info_ptr);
143
144#ifdef PNG_SETJMP_SUPPORTED
145	setjmp(png_jmpbuf(png_ptr));
146#endif

147
148	row_pointers = (png_bytep*) FTK_ZALLOC(h * sizeof(png_bytep));
149	for (y=0; y< h; y++)
150	{
151		row_pointers[y] = (png_byte*) FTK_ZALLOC(info_ptr->rowbytes);
152	}
153	png_read_image(png_ptr, row_pointers);
154
155	bitmap = ftk_bitmap_create(w, h, bg);
156	dst = ftk_bitmap_lock(bitmap);
157	if (info_ptr->color_type == PNG_COLOR_TYPE_RGBA)
158	{
159		for(y = 0; y < h; y++)
160		{
161			src = row_pointers[y];
162			for(x = 0; x < w; x++)
163			{
164				if(src[3])
165				{
166					dst->r = src[0];
167					dst->g = src[1];
168					dst->b = src[2];
169					dst->a = src[3];
170				}
171				else
172				{
173					dst->r = 0xff;
174					dst->g = 0xff;
175					dst->b = 0xff;
176					dst->a = 0;
177				}
178				src +=4;
179				dst++;
180			}
181		}
182	}
183	else if(info_ptr->color_type == PNG_COLOR_TYPE_RGB)
184	{
185		if(0 == info_ptr->num_trans)
186		{
187			for(y = 0; y < h; y++)
188			{
189				src = row_pointers[y];
190				for(x = 0; x < w; x++)
191				{
192					dst->r = src[0];
193					dst->g = src[1];
194					dst->b = src[2];
195					dst->a = 0xff;
196					src += 3;
197					dst++;
198				}
199			}
200		}
201		else 
202		{
203#if PNG_LIBPNG_VER > 10399

204			png_byte red = png_ptr->trans_color.red & 0xff;
205			png_byte green = png_ptr->trans_color.green & 0xff;
206			png_byte blue = png_ptr->trans_color.blue & 0xff;
207#else
208			png_byte red = png_ptr->trans_values.red & 0xff;
209			png_byte green = png_ptr->trans_values.green & 0xff;
210			png_byte blue = png_ptr->trans_values.blue & 0xff;
211#endif
212			for(y = 0; y < h; y++)
213			{
214				src = row_pointers[y];
215				for(x = 0; x < w; x++)
216				{
217					if(src[0] == red && src[1] == green && src[2] == blue)
218					{
219						dst->a = 0;
220					}
221					else
222					{
223						dst->a = 0xff;
224					}
225					dst->r = src[0];
226					dst->g = src[1];
227					dst->b = src[2];
228					src += 3;
229					dst++;
230				}
231			}
232		}
233	}
234	else
235	{
236		assert(!"not supported.");
237	}
238
239	for(y = 0; y < h; y++)
240	{
241		FTK_FREE(row_pointers[y]);
242	}
243	FTK_FREE(row_pointers);
244	png_destroy_read_struct(&png_ptr, &info_ptr, NULL); 
245
246#ifndef RT_THREAD
247	fclose(fp);
248#else

249	close(fd);
250#endif	
251
252	return bitmap;
253}
254
255static FtkBitmap* ftk_image_png_decoder_decode(FtkImageDecoder* thiz, const char* filename)
256{
257	return_val_if_fail(ftk_image_png_decoder_match(thiz, filename) == RET_OK, NULL);
258
259	return load_png(filename);
260}
261
262static void ftk_image_png_decoder_destroy(FtkImageDecoder* thiz)
263{
264	if(thiz != NULL)
265	{
266		FTK_ZFREE(thiz, sizeof(thiz));
267	}
268}
269
270FtkImageDecoder* ftk_image_png_decoder_create(void)
271{
272	FtkImageDecoder* thiz = (FtkImageDecoder*)FTK_ZALLOC(sizeof(FtkImageDecoder));
273
274	if(thiz != NULL)
275	{
276		thiz->match   = ftk_image_png_decoder_match;
277		thiz->decode  = ftk_image_png_decoder_decode;
278		thiz->destroy = ftk_image_png_decoder_destroy;
279	}
280
281	return thiz;
282}
283