PageRenderTime 285ms CodeModel.GetById 100ms app.highlight 69ms RepoModel.GetById 112ms app.codeStats 1ms

/src/canvas/default/ftk_image_bmp_decoder.c

http://ftk.googlecode.com/
C | 339 lines | 264 code | 43 blank | 32 comment | 40 complexity | 2abb7c6667aecdb0222c0d2708d21846 MD5 | raw file
  1/*
  2 * File: ftk_image_bmp_decoder.h    
  3 * Author:  Li XianJing <xianjimli@hotmail.com>
  4 * Brief:   bmp 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-11-28 Li XianJing <xianjimli@hotmail.com> created
 29 *
 30 */
 31
 32#include "ftk_mmap.h"
 33#include "ftk_image_bmp_decoder.h"
 34
 35/**
 36 * http://atlc.sourceforge.net/bmp.html
 37 */
 38static Ret ftk_image_bmp_decoder_match(FtkImageDecoder* thiz, const char* filename)
 39{
 40	return_val_if_fail(filename != NULL, RET_FAIL);
 41
 42	return (strstr(filename, ".bmp") != NULL) ? RET_OK : RET_FAIL;
 43}
 44
 45static Ret ftk_image_bmp_copy32(FtkBitmap* bitmap, int compress, const unsigned char* data)
 46{
 47	int x = 0;
 48	int y = 0;
 49	const unsigned char* src = data;
 50	int width = ftk_bitmap_width(bitmap);
 51	int height = ftk_bitmap_height(bitmap);
 52	FtkColor* bits = ftk_bitmap_lock(bitmap);
 53
 54	for(y = 0; y < height; y++)
 55	{
 56		for(x = 0; x < width; x++, bits++)
 57		{
 58			bits->r = src[0];
 59			bits->g = src[1];	
 60			bits->b = src[2];	
 61			bits->a = 0xff;//src[3];	
 62			src += 4;
 63		}
 64	}
 65
 66	return RET_OK;
 67}
 68
 69static Ret ftk_image_bmp_copy24(FtkBitmap* bitmap, int compress, const unsigned char* data)
 70{
 71	int x = 0;
 72	int y = 0;
 73	const unsigned char* src = data;
 74	const unsigned char* lsrc = data;
 75	int width = ftk_bitmap_width(bitmap);
 76	int height = ftk_bitmap_height(bitmap);
 77	FtkColor* bits = ftk_bitmap_lock(bitmap);
 78	int line_delta = (width * 3 + 3) & 0xfffffffc;
 79
 80	lsrc += line_delta * (height - 1);
 81	for(y = 0; y < height; y++)
 82	{
 83		src = lsrc;
 84		for(x = 0; x < width; x++, bits++)
 85		{
 86			bits->b = src[0];
 87			bits->g = src[1];	
 88			bits->r = src[2];	
 89			bits->a = 0xff;
 90			src += 3;
 91		}
 92		lsrc -= line_delta;
 93	}
 94
 95	return RET_OK;
 96}
 97
 98static Ret ftk_image_bmp_copy8(FtkBitmap* bitmap, int compress, FtkColor* palette, unsigned char* data)
 99{
100	int x = 0;
101	int y = 0;
102	unsigned char index = 0;
103	const unsigned char* src = data;
104	const unsigned char* lsrc = data;
105	int width = ftk_bitmap_width(bitmap);
106	int height = ftk_bitmap_height(bitmap);
107	FtkColor* bits = ftk_bitmap_lock(bitmap);
108	int line_delta = (width + 3) & 0xfffffffc;
109
110	lsrc +=line_delta * (height - 1);
111	for(y = 0; y < height; y++)
112	{
113		src = lsrc;
114		for(x = 0; x < width; x++, bits++)
115		{
116			index = src[x];
117			bits->r = palette[index].r;
118			bits->g = palette[index].g;
119			bits->b = palette[index].b;
120			bits->a = 0xff;
121		}
122		lsrc -= line_delta;
123	}
124
125	return RET_OK;
126}
127
128static Ret ftk_image_bmp_copy4(FtkBitmap* bitmap, int compress, FtkColor* palette, unsigned char* data)
129{
130	int x = 0;
131	int y = 0;
132	int r = 0;
133	int w = 0;
134	unsigned char index = 0;
135	const unsigned char* src = data;
136	const unsigned char* lsrc = data;
137	int width = ftk_bitmap_width(bitmap);
138	int height = ftk_bitmap_height(bitmap);
139	FtkColor* bits = ftk_bitmap_lock(bitmap);
140	int line_delta = (((width & 0x01) ? (width + 1) : width )/2 + 3) & 0xfffffffc;
141
142	w = width>>1;
143	r = width & 0x01;
144
145	lsrc += line_delta * (height - 1);
146	for(y = 0; y < height; y++)
147	{
148		src = lsrc;
149		for(x = 0; x < w; x++)
150		{
151			index = (src[x] >> 4) & 0x0f;
152			bits->r = palette[index].r;
153			bits->g = palette[index].g;
154			bits->b = palette[index].b;
155			bits->a = 0xff;
156			bits++;
157
158			index = src[x] & 0x0f;
159			bits->r = palette[index].r;
160			bits->g = palette[index].g;
161			bits->b = palette[index].b;
162			bits->a = 0xff;
163			bits++;
164		}
165
166		if(r)
167		{
168			index = (src[x] >> 4) & 0x0f;
169			bits->r = palette[index].r;
170			bits->g = palette[index].g;
171			bits->b = palette[index].b;
172			bits->a = 0xff;
173			bits++;
174		}
175		lsrc -= line_delta;
176	}
177
178	return RET_OK;
179}
180
181#define SET_COLOR_1BIT(bit, color) if(bit) {color->r=color->g=color->b=0xff;color->a=0xff;}\
182	else{color->r=color->g=color->b=0x00;color->a=0xff;}
183
184static Ret ftk_image_bmp_copy1(FtkBitmap* bitmap, int compress, FtkColor* palette, unsigned char* data)
185{
186	int x = 0;
187	int y = 0;
188	int r = 0;
189	int w = 0;
190	unsigned char c = 0;
191	const unsigned char* src = data;
192	const unsigned char* lsrc = data;
193	int width = ftk_bitmap_width(bitmap);
194	int height = ftk_bitmap_height(bitmap);
195	FtkColor* bits = ftk_bitmap_lock(bitmap);
196	int line_delta = (width/8 + 3) & 0xfffffffc;
197
198	w = (width+7)>>3;
199	r = width % 8;
200
201	lsrc += line_delta * (height - 1);
202	for(y = 0; y < height; y++)
203	{
204		src = lsrc;
205		for(x = 0; x < w; x++)
206		{
207			c = src[x];
208			if(x == (w - 1))
209			{
210				SET_COLOR_1BIT(c & 0x80,  bits);bits++; if(r == 1) break;
211				SET_COLOR_1BIT(c & 0x40,  bits);bits++; if(r == 2) break;
212				SET_COLOR_1BIT(c & 0x20,  bits);bits++; if(r == 3) break;
213				SET_COLOR_1BIT(c & 0x10,  bits);bits++; if(r == 4) break;
214				SET_COLOR_1BIT(c & 0x08 , bits);bits++; if(r == 5) break;
215				SET_COLOR_1BIT(c & 0x04,  bits);bits++; if(r == 6) break;
216				SET_COLOR_1BIT(c & 0x02,  bits);bits++; if(r == 7) break;
217				SET_COLOR_1BIT(c & 0x01,  bits);bits++; 
218			}
219			else
220			{
221				SET_COLOR_1BIT(c & 0x80,  bits);bits++; 
222				SET_COLOR_1BIT(c & 0x40,  bits);bits++;
223				SET_COLOR_1BIT(c & 0x20,  bits);bits++;
224				SET_COLOR_1BIT(c & 0x10,  bits);bits++;
225				SET_COLOR_1BIT(c & 0x08 , bits);bits++;
226				SET_COLOR_1BIT(c & 0x04,  bits);bits++;
227				SET_COLOR_1BIT(c & 0x02,  bits);bits++;
228				SET_COLOR_1BIT(c & 0x01,  bits);bits++; 
229			}
230		}
231		lsrc -= line_delta;
232	}
233
234	return RET_OK;
235}
236
237static FtkBitmap* load_bmp (const char *filename)
238{
239	size_t bpp = 0;
240	size_t width = 0;
241	size_t height = 0;
242	size_t doffset = 0;
243	int compress = 0;
244	FtkColor bg = {0};
245	FtkBitmap* bitmap = NULL;
246	FtkColor* palette = NULL;
247	unsigned char* src = NULL;
248	unsigned char* data = NULL;
249	FtkMmap* m = ftk_mmap_create(filename, 0, -1);
250
251	return_val_if_fail(m != NULL, NULL);
252
253	data = (unsigned char*)ftk_mmap_data(m);
254
255	if(data[0] != 'B' || data[1] != 'M')
256	{
257		ftk_mmap_destroy(m);
258
259		return NULL;
260	}
261
262	bg.a = 0xff;
263	doffset  = *(unsigned int*)(data + 0x000a);
264	width    = *(unsigned int*)(data + 0x0012);
265	height   = *(unsigned int*)(data + 0x0016);
266	bpp      = *(unsigned short*)(data + 0x001c);
267	compress = *(unsigned int*)(data + 0x001e);
268	palette  = (FtkColor*)(data + 0x0036);
269	src      = data + doffset;
270
271	bitmap = ftk_bitmap_create(width, height, bg);
272
273	switch(bpp)
274	{
275		case 32:
276		{
277			ftk_image_bmp_copy32(bitmap, compress, src);
278			break;
279		}
280		case 24:
281		{
282			ftk_image_bmp_copy24(bitmap, compress, src);
283			break;
284		}
285		case 8:
286		{
287			ftk_image_bmp_copy8(bitmap, compress, palette, src);
288			break;
289		}
290		case 4:
291		{
292			ftk_image_bmp_copy4(bitmap, compress, palette, src);
293			break;
294		}
295		case 1:
296		{
297			ftk_image_bmp_copy1(bitmap, compress, palette, src);
298			break;
299		}
300		default:break;
301	}
302
303	ftk_mmap_destroy(m);
304
305	return bitmap;
306}
307
308static FtkBitmap* ftk_image_bmp_decoder_decode(FtkImageDecoder* thiz, const char* filename)
309{
310	return_val_if_fail(ftk_image_bmp_decoder_match(thiz, filename) == RET_OK, NULL);
311
312	return load_bmp(filename);
313}
314
315static void ftk_image_bmp_decoder_destroy(FtkImageDecoder* thiz)
316{
317	if(thiz != NULL)
318	{
319		FTK_ZFREE(thiz, sizeof(thiz));
320	}
321
322	return;
323}
324
325FtkImageDecoder* ftk_image_bmp_decoder_create(void)
326{
327	FtkImageDecoder* thiz = (FtkImageDecoder*)FTK_ZALLOC(sizeof(FtkImageDecoder));
328
329	if(thiz != NULL)
330	{
331		thiz->match   = ftk_image_bmp_decoder_match;
332		thiz->decode  = ftk_image_bmp_decoder_decode;
333		thiz->destroy = ftk_image_bmp_decoder_destroy;
334	}
335
336	return thiz;
337}
338
339