Selaa lähdekoodia

add blit functions.

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@842 bbd45198-f89e-11dd-88c7-29a3b14d5316
bernard.xiong@gmail.com 14 vuotta sitten
vanhempi
commit
702f5e81b6

+ 298 - 0
components/rtgui/common/blit.c

@@ -0,0 +1,298 @@
+#include <rtgui/rtgui.h>
+#include <rtgui/blit.h>
+
+/* 2 bpp to 1 bpp */
+static void rtgui_blit_line_2_1(rt_uint8_t* dst_ptr, rt_uint8_t* src_ptr, int line)
+{
+	return;
+}
+
+/* 3 bpp to 1 bpp */
+static void rtgui_blit_line_3_1(rt_uint8_t* dst_ptr, rt_uint8_t* src_ptr, int line)
+{
+	line = line / 3;
+	while (line)
+	{
+		*dst_ptr = (rt_uint8_t)(((*src_ptr & 0x00E00000)>>16)|
+			((*(src_ptr + 1) & 0x0000E000)>>11) |
+			((*(src_ptr + 2) & 0x000000C0)>>6));
+
+		src_ptr += 3;
+		dst_ptr ++;
+		line --;
+	}
+	return;
+}
+
+/* 4 bpp to 1 bpp */
+static void rtgui_blit_line_4_1(rt_uint8_t* dst_ptr, rt_uint8_t* src_ptr, int line)
+{
+	line = line / 4;
+	while (line)
+	{
+		*dst_ptr = (rt_uint8_t)(((*src_ptr & 0x00E00000)>>16)|
+			((*(src_ptr + 1) & 0x0000E000)>>11) |
+			((*(src_ptr + 2) & 0x000000C0)>>6));
+
+		src_ptr += 4;
+		dst_ptr ++;
+		line --;
+	}
+	return;
+}
+
+/* 1 bpp to 2 bpp */
+static void rtgui_blit_line_1_2(rt_uint8_t* dst_ptr, rt_uint8_t* src_ptr, int line)
+{
+	return;
+}
+
+/* 3 bpp to 2 bpp */
+static void rtgui_blit_line_3_2(rt_uint8_t* dst_ptr, rt_uint8_t* src_ptr, int line)
+{
+	rt_uint16_t* dst;
+	rt_uint32_t* src;
+
+	dst = (rt_uint16_t*)dst_ptr;
+	line = line / 3;
+	while (line)
+	{
+		*dst = (((*(src_ptr + 2) << 8) & 0x0000F800) | 
+			((*(src_ptr + 1) << 3) & 0x000007E0)     | 
+			((*src_ptr >> 3) & 0x0000001F)); 
+
+		src_ptr += 3;
+		dst ++;
+		line --;
+	}
+
+	return;
+}
+
+/* 4 bpp to 2 bpp */
+static void rtgui_blit_line_4_2(rt_uint8_t* dst_ptr, rt_uint8_t* src_ptr, int line)
+{
+	rt_uint16_t* dst;
+
+	dst = (rt_uint16_t*)dst_ptr;
+	line = line / 4;
+	while (line)
+	{
+		*dst = (((*(src_ptr + 1) << 8) & 0x0000F800) | 
+			((*(src_ptr + 1) << 3) & 0x000007E0)     | 
+			((*src_ptr >> 3) & 0x0000001F)); 
+
+		src_ptr += 4; /* skip alpha */
+		dst ++;
+		line --;
+	}
+
+	return;
+}
+
+static void rtgui_blit_line_1_3(rt_uint8_t* dst_ptr, rt_uint8_t* src_ptr, int line)
+{
+	return;
+}
+
+#define HI	1
+#define LO	0
+
+/* Special optimized blit for RGB 5-6-5 --> RGBA 8-8-8-8 */
+static const rt_uint32_t RGB565_RGBA8888_LUT[512] =
+{
+	0x000000ff, 0x00000000, 0x000008ff, 0x00200000,
+	0x000010ff, 0x00400000, 0x000018ff, 0x00610000,
+	0x000020ff, 0x00810000, 0x000029ff, 0x00a10000,
+	0x000031ff, 0x00c20000, 0x000039ff, 0x00e20000,
+	0x000041ff, 0x08000000, 0x00004aff, 0x08200000,
+	0x000052ff, 0x08400000, 0x00005aff, 0x08610000,
+	0x000062ff, 0x08810000, 0x00006aff, 0x08a10000,
+	0x000073ff, 0x08c20000, 0x00007bff, 0x08e20000,
+	0x000083ff, 0x10000000, 0x00008bff, 0x10200000,
+	0x000094ff, 0x10400000, 0x00009cff, 0x10610000,
+	0x0000a4ff, 0x10810000, 0x0000acff, 0x10a10000,
+	0x0000b4ff, 0x10c20000, 0x0000bdff, 0x10e20000,
+	0x0000c5ff, 0x18000000, 0x0000cdff, 0x18200000,
+	0x0000d5ff, 0x18400000, 0x0000deff, 0x18610000,
+	0x0000e6ff, 0x18810000, 0x0000eeff, 0x18a10000,
+	0x0000f6ff, 0x18c20000, 0x0000ffff, 0x18e20000,
+	0x000400ff, 0x20000000, 0x000408ff, 0x20200000,
+	0x000410ff, 0x20400000, 0x000418ff, 0x20610000,
+	0x000420ff, 0x20810000, 0x000429ff, 0x20a10000,
+	0x000431ff, 0x20c20000, 0x000439ff, 0x20e20000,
+	0x000441ff, 0x29000000, 0x00044aff, 0x29200000,
+	0x000452ff, 0x29400000, 0x00045aff, 0x29610000,
+	0x000462ff, 0x29810000, 0x00046aff, 0x29a10000,
+	0x000473ff, 0x29c20000, 0x00047bff, 0x29e20000,
+	0x000483ff, 0x31000000, 0x00048bff, 0x31200000,
+	0x000494ff, 0x31400000, 0x00049cff, 0x31610000,
+	0x0004a4ff, 0x31810000, 0x0004acff, 0x31a10000,
+	0x0004b4ff, 0x31c20000, 0x0004bdff, 0x31e20000,
+	0x0004c5ff, 0x39000000, 0x0004cdff, 0x39200000,
+	0x0004d5ff, 0x39400000, 0x0004deff, 0x39610000,
+	0x0004e6ff, 0x39810000, 0x0004eeff, 0x39a10000,
+	0x0004f6ff, 0x39c20000, 0x0004ffff, 0x39e20000,
+	0x000800ff, 0x41000000, 0x000808ff, 0x41200000,
+	0x000810ff, 0x41400000, 0x000818ff, 0x41610000,
+	0x000820ff, 0x41810000, 0x000829ff, 0x41a10000,
+	0x000831ff, 0x41c20000, 0x000839ff, 0x41e20000,
+	0x000841ff, 0x4a000000, 0x00084aff, 0x4a200000,
+	0x000852ff, 0x4a400000, 0x00085aff, 0x4a610000,
+	0x000862ff, 0x4a810000, 0x00086aff, 0x4aa10000,
+	0x000873ff, 0x4ac20000, 0x00087bff, 0x4ae20000,
+	0x000883ff, 0x52000000, 0x00088bff, 0x52200000,
+	0x000894ff, 0x52400000, 0x00089cff, 0x52610000,
+	0x0008a4ff, 0x52810000, 0x0008acff, 0x52a10000,
+	0x0008b4ff, 0x52c20000, 0x0008bdff, 0x52e20000,
+	0x0008c5ff, 0x5a000000, 0x0008cdff, 0x5a200000,
+	0x0008d5ff, 0x5a400000, 0x0008deff, 0x5a610000,
+	0x0008e6ff, 0x5a810000, 0x0008eeff, 0x5aa10000,
+	0x0008f6ff, 0x5ac20000, 0x0008ffff, 0x5ae20000,
+	0x000c00ff, 0x62000000, 0x000c08ff, 0x62200000,
+	0x000c10ff, 0x62400000, 0x000c18ff, 0x62610000,
+	0x000c20ff, 0x62810000, 0x000c29ff, 0x62a10000,
+	0x000c31ff, 0x62c20000, 0x000c39ff, 0x62e20000,
+	0x000c41ff, 0x6a000000, 0x000c4aff, 0x6a200000,
+	0x000c52ff, 0x6a400000, 0x000c5aff, 0x6a610000,
+	0x000c62ff, 0x6a810000, 0x000c6aff, 0x6aa10000,
+	0x000c73ff, 0x6ac20000, 0x000c7bff, 0x6ae20000,
+	0x000c83ff, 0x73000000, 0x000c8bff, 0x73200000,
+	0x000c94ff, 0x73400000, 0x000c9cff, 0x73610000,
+	0x000ca4ff, 0x73810000, 0x000cacff, 0x73a10000,
+	0x000cb4ff, 0x73c20000, 0x000cbdff, 0x73e20000,
+	0x000cc5ff, 0x7b000000, 0x000ccdff, 0x7b200000,
+	0x000cd5ff, 0x7b400000, 0x000cdeff, 0x7b610000,
+	0x000ce6ff, 0x7b810000, 0x000ceeff, 0x7ba10000,
+	0x000cf6ff, 0x7bc20000, 0x000cffff, 0x7be20000,
+	0x001000ff, 0x83000000, 0x001008ff, 0x83200000,
+	0x001010ff, 0x83400000, 0x001018ff, 0x83610000,
+	0x001020ff, 0x83810000, 0x001029ff, 0x83a10000,
+	0x001031ff, 0x83c20000, 0x001039ff, 0x83e20000,
+	0x001041ff, 0x8b000000, 0x00104aff, 0x8b200000,
+	0x001052ff, 0x8b400000, 0x00105aff, 0x8b610000,
+	0x001062ff, 0x8b810000, 0x00106aff, 0x8ba10000,
+	0x001073ff, 0x8bc20000, 0x00107bff, 0x8be20000,
+	0x001083ff, 0x94000000, 0x00108bff, 0x94200000,
+	0x001094ff, 0x94400000, 0x00109cff, 0x94610000,
+	0x0010a4ff, 0x94810000, 0x0010acff, 0x94a10000,
+	0x0010b4ff, 0x94c20000, 0x0010bdff, 0x94e20000,
+	0x0010c5ff, 0x9c000000, 0x0010cdff, 0x9c200000,
+	0x0010d5ff, 0x9c400000, 0x0010deff, 0x9c610000,
+	0x0010e6ff, 0x9c810000, 0x0010eeff, 0x9ca10000,
+	0x0010f6ff, 0x9cc20000, 0x0010ffff, 0x9ce20000,
+	0x001400ff, 0xa4000000, 0x001408ff, 0xa4200000,
+	0x001410ff, 0xa4400000, 0x001418ff, 0xa4610000,
+	0x001420ff, 0xa4810000, 0x001429ff, 0xa4a10000,
+	0x001431ff, 0xa4c20000, 0x001439ff, 0xa4e20000,
+	0x001441ff, 0xac000000, 0x00144aff, 0xac200000,
+	0x001452ff, 0xac400000, 0x00145aff, 0xac610000,
+	0x001462ff, 0xac810000, 0x00146aff, 0xaca10000,
+	0x001473ff, 0xacc20000, 0x00147bff, 0xace20000,
+	0x001483ff, 0xb4000000, 0x00148bff, 0xb4200000,
+	0x001494ff, 0xb4400000, 0x00149cff, 0xb4610000,
+	0x0014a4ff, 0xb4810000, 0x0014acff, 0xb4a10000,
+	0x0014b4ff, 0xb4c20000, 0x0014bdff, 0xb4e20000,
+	0x0014c5ff, 0xbd000000, 0x0014cdff, 0xbd200000,
+	0x0014d5ff, 0xbd400000, 0x0014deff, 0xbd610000,
+	0x0014e6ff, 0xbd810000, 0x0014eeff, 0xbda10000,
+	0x0014f6ff, 0xbdc20000, 0x0014ffff, 0xbde20000,
+	0x001800ff, 0xc5000000, 0x001808ff, 0xc5200000,
+	0x001810ff, 0xc5400000, 0x001818ff, 0xc5610000,
+	0x001820ff, 0xc5810000, 0x001829ff, 0xc5a10000,
+	0x001831ff, 0xc5c20000, 0x001839ff, 0xc5e20000,
+	0x001841ff, 0xcd000000, 0x00184aff, 0xcd200000,
+	0x001852ff, 0xcd400000, 0x00185aff, 0xcd610000,
+	0x001862ff, 0xcd810000, 0x00186aff, 0xcda10000,
+	0x001873ff, 0xcdc20000, 0x00187bff, 0xcde20000,
+	0x001883ff, 0xd5000000, 0x00188bff, 0xd5200000,
+	0x001894ff, 0xd5400000, 0x00189cff, 0xd5610000,
+	0x0018a4ff, 0xd5810000, 0x0018acff, 0xd5a10000,
+	0x0018b4ff, 0xd5c20000, 0x0018bdff, 0xd5e20000,
+	0x0018c5ff, 0xde000000, 0x0018cdff, 0xde200000,
+	0x0018d5ff, 0xde400000, 0x0018deff, 0xde610000,
+	0x0018e6ff, 0xde810000, 0x0018eeff, 0xdea10000,
+	0x0018f6ff, 0xdec20000, 0x0018ffff, 0xdee20000,
+	0x001c00ff, 0xe6000000, 0x001c08ff, 0xe6200000,
+	0x001c10ff, 0xe6400000, 0x001c18ff, 0xe6610000,
+	0x001c20ff, 0xe6810000, 0x001c29ff, 0xe6a10000,
+	0x001c31ff, 0xe6c20000, 0x001c39ff, 0xe6e20000,
+	0x001c41ff, 0xee000000, 0x001c4aff, 0xee200000,
+	0x001c52ff, 0xee400000, 0x001c5aff, 0xee610000,
+	0x001c62ff, 0xee810000, 0x001c6aff, 0xeea10000,
+	0x001c73ff, 0xeec20000, 0x001c7bff, 0xeee20000,
+	0x001c83ff, 0xf6000000, 0x001c8bff, 0xf6200000,
+	0x001c94ff, 0xf6400000, 0x001c9cff, 0xf6610000,
+	0x001ca4ff, 0xf6810000, 0x001cacff, 0xf6a10000,
+	0x001cb4ff, 0xf6c20000, 0x001cbdff, 0xf6e20000,
+	0x001cc5ff, 0xff000000, 0x001ccdff, 0xff200000,
+	0x001cd5ff, 0xff400000, 0x001cdeff, 0xff610000,
+	0x001ce6ff, 0xff810000, 0x001ceeff, 0xffa10000,
+	0x001cf6ff, 0xffc20000, 0x001cffff, 0xffe20000,
+};
+
+static void rtgui_blit_line_2_3(rt_uint8_t* dst_ptr, rt_uint8_t* src_ptr, int line)
+{
+	rt_uint16_t *src;
+	rt_uint32_t *dst;
+
+	src = (rt_uint16_t*)src_ptr;
+	dst = (rt_uint32_t*)dst_ptr;
+
+	line = line / 2;
+	while (line)
+	{
+		*dst++ = RGB565_RGBA8888_LUT[src[LO]*2] + RGB565_RGBA8888_LUT[src[HI]*2+1];
+		line--;
+		src ++;
+	}
+}
+
+void rtgui_blit_line_direct(rt_uint8_t* dst_ptr, rt_uint8_t* src_ptr, int line)
+{
+	rt_memcpy(dst_ptr, src_ptr, line);
+}
+
+static void rtgui_blit_line_4_3(rt_uint8_t* dst_ptr, rt_uint8_t* src_ptr, int line)
+{
+	line = line / 4;
+	while (line)
+	{
+		line --;
+	}
+}
+
+static void rtgui_blit_line_1_4(rt_uint8_t* dst_ptr, rt_uint8_t* src_ptr, int line)
+{
+}
+
+static void rtgui_blit_line_2_4(rt_uint8_t* dst_ptr, rt_uint8_t* src_ptr, int line)
+{
+}
+
+static void rtgui_blit_line_3_4(rt_uint8_t* dst_ptr, rt_uint8_t* src_ptr, int line)
+{
+	line = line / 4;
+}
+
+static const rtgui_blit_line_func _blit_table[5][5] = 
+{
+	/* 0_0, 1_0, 2_0, 3_0, 4_0 */
+	{RT_NULL, RT_NULL, RT_NULL, RT_NULL, RT_NULL }, 
+	/* 0_1, 1_1, 2_1, 3_1, 4_1 */
+	{RT_NULL, rtgui_blit_line_direct, rtgui_blit_line_2_1, rtgui_blit_line_3_1, rtgui_blit_line_4_1 }, 
+	/* 0_2, 1_2, 2_2, 3_2, 4_2 */
+	{RT_NULL, rtgui_blit_line_1_2, rtgui_blit_line_direct, rtgui_blit_line_3_2, rtgui_blit_line_4_2 }, 
+	/* 0_3, 1_3, 2_3, 3_3, 4_3 */
+	{RT_NULL, rtgui_blit_line_1_3, rtgui_blit_line_2_3, rtgui_blit_line_direct, rtgui_blit_line_4_3 }, 
+	/* 0_4, 1_4, 2_4, 3_4, 4_4 */
+	{RT_NULL, rtgui_blit_line_1_4, rtgui_blit_line_2_4, rtgui_blit_line_3_4, rtgui_blit_line_direct }, 
+};
+
+const rtgui_blit_line_func rtgui_blit_line_get(int dst_bpp, int src_bpp)
+{
+	RT_ASSERT(dst_bpp>1 && dst_bpp < 5);
+	RT_ASSERT(src_bpp>1 && src_bpp < 5);
+
+	return _blit_table[dst_bpp][src_bpp];
+}

+ 17 - 0
components/rtgui/common/image.c

@@ -98,6 +98,7 @@ struct rtgui_image* rtgui_image_create_from_file(const char* type, const char* f
 			return RT_NULL;
 		}
 
+		image->palette = RT_NULL;
 		if (engine->image_load(image, filerw, load) != RT_TRUE)
 		{
 			/* close filerw context */
@@ -146,6 +147,7 @@ struct rtgui_image* rtgui_image_create_from_mem(const char* type, const rt_uint8
 			return RT_NULL;
 		}
 
+		image->palette = RT_NULL;
 		if (engine->image_load(image, filerw, load) != RT_TRUE)
 		{
 			/* close filerw context */
@@ -169,6 +171,8 @@ void rtgui_image_destroy(struct rtgui_image* image)
 	RT_ASSERT(image != RT_NULL);
 
 	image->engine->image_unload(image);
+	if (image->palette != RT_NULL)
+		rtgui_free(image->palette);
 	rtgui_free(image);
 }
 
@@ -194,3 +198,16 @@ void rtgui_image_blit(struct rtgui_image* image, struct rtgui_dc* dc, struct rtg
 	}
 }
 
+struct rtgui_image_palette* rtgui_image_palette_create(rt_uint32_t ncolors)
+{
+	struct rtgui_image_palette* palette = RT_NULL;
+
+	if (ncolors > 0)
+	{
+		palette = (struct rtgui_image_palette*) rtgui_malloc(sizeof(struct rtgui_image_palette) + 
+			sizeof(rtgui_color_t) * ncolors);
+		if (palette != RT_NULL) palette->colors = (rtgui_color_t*)(palette + 1);
+	}
+
+	return palette;
+}

+ 314 - 31
components/rtgui/common/image_bmp.c

@@ -3,6 +3,7 @@
 #include <rtgui/image.h>
 #include <rtgui/rtgui_system.h>
 #include <rtgui/image_bmp.h>
+#include <rtgui/blit.h>
 
 /* Compression encodings for BMP files */
 #ifndef BI_RGB
@@ -12,12 +13,24 @@
 #define BI_BITFIELDS	3
 #endif
 
+#define hw_driver				(rtgui_graphic_driver_get_default())
+
 struct rtgui_image_bmp
 {
 	rt_bool_t is_loaded;
 
+	rt_uint32_t Rmask;
+	rt_uint32_t Gmask;
+	rt_uint32_t Bmask;
+
 	rt_size_t   pixel_offset;
+
+	rt_uint8_t  byte_per_pixel;
+	rt_uint8_t  pad;
+	rt_uint8_t  ExpandBMP;
+
 	rt_uint8_t *pixels;
+	rt_uint32_t pitch;
 
 	struct rtgui_filerw* filerw;
 };
@@ -60,10 +73,26 @@ struct rtgui_image_engine rtgui_image_bmp_engine =
 	rtgui_image_bmp_blit
 };
 
+rt_inline rt_uint32_t rtgui_filerw_read32(struct rtgui_filerw* src)
+{
+	rt_uint32_t value;
+	rtgui_filerw_read(src, &value, (sizeof value), 1);
+	return value;
+}
+
+rt_inline rt_uint16_t rtgui_filerw_read16(struct rtgui_filerw* src)
+{
+	rt_uint16_t value;
+	rtgui_filerw_read(src, &value, (sizeof value), 1);
+	return value;
+
+}
+
 static rt_bool_t rtgui_image_bmp_check(struct rtgui_filerw* file)
 {
 	char magic[2];
 	rt_bool_t is_bmp;
+	rt_off_t start;
 
 	if ( !file ) return 0;
 
@@ -76,7 +105,7 @@ static rt_bool_t rtgui_image_bmp_check(struct rtgui_filerw* file)
 	if ( rtgui_filerw_read(file, magic, 1, sizeof(magic)) == sizeof(magic) )
 	{
 		if (magic[0] == 'B' &&
-			magic[1] == 'M')
+				magic[1] == 'M')
 		{
 			is_bmp = RT_TRUE;
 		}
@@ -87,39 +116,256 @@ static rt_bool_t rtgui_image_bmp_check(struct rtgui_filerw* file)
 	return(is_bmp);
 }
 
-static rt_bool_t rtgui_image_bmp_load(struct rtgui_image* image, struct rtgui_filerw* file, rt_bool_t load)
+static rt_bool_t rtgui_image_bmp_load(struct rtgui_image* image, struct rtgui_filerw* src, rt_bool_t load)
 {
-    struct rtgui_image_bmp* bmp;
+	struct rtgui_image_bmp* bmp;
+	struct rtgui_image_bmp_header* header;
+	int ExpandBMP, bmpPitch;
+	rt_uint32_t Rmask;
+	rt_uint32_t Gmask;
+	rt_uint32_t Bmask;
+
+	bmp = RT_NULL;
+	header = RT_NULL;
+	header = (struct rtgui_image_bmp_header*) rtgui_malloc(sizeof(struct rtgui_image_bmp_header));
+	if (header == RT_NULL) return RT_FALSE;
+
+	if ( rtgui_filerw_read(src, header->magic, 1, sizeof(header->magic)) ==
+		sizeof(sizeof(header->magic)) )
+	{
+		if (header->magic[0] != 'B' ||
+			header->magic[1] != 'M')
+		{
+			goto __exit;
+		}
+	}
+
+	header->bfSize		= rtgui_filerw_read32(src);
+	header->bfReserved1	= rtgui_filerw_read16(src);
+	header->bfReserved2	= rtgui_filerw_read16(src);
+	header->bfOffBits	= rtgui_filerw_read32(src);
 
-    bmp = (struct rtgui_image_bmp*) rtgui_malloc(sizeof(struct rtgui_image_bmp));
-    if (bmp == RT_NULL) return RT_FALSE;
+	/* Read the Win32 BITMAPINFOHEADER */
+	header->biSize		= rtgui_filerw_read32(src);
+	if ( header->biSize == 12 )
+	{
+		header->biWidth		= (rt_uint32_t)rtgui_filerw_read16(src);
+		header->biHeight	= (rt_uint32_t)rtgui_filerw_read16(src);
+		header->biPlanes	= rtgui_filerw_read16(src);
+		header->biBitCount	= rtgui_filerw_read16(src);
+		header->biCompression	= BI_RGB;
+		header->biSizeImage	= 0;
+		header->biXPelsPerMeter	= 0;
+		header->biYPelsPerMeter	= 0;
+		header->biClrUsed	= 0;
+
+		header->biClrImportant	= 0;
 
-	bmp->hw_driver = rtgui_graphic_driver_get_default();
-	if (bmp->hw_driver == RT_NULL) { rtgui_free(bmp); return RT_FALSE; }
+	}
+	else
+	{
+		header->biWidth		= rtgui_filerw_read32(src);
+		header->biHeight	= rtgui_filerw_read32(src);
+		header->biPlanes	= rtgui_filerw_read16(src);
+		header->biBitCount	= rtgui_filerw_read16(src);
+		header->biCompression	= rtgui_filerw_read32(src);
+		header->biSizeImage	= rtgui_filerw_read32(src);
+		header->biXPelsPerMeter	= rtgui_filerw_read32(src);
+		header->biYPelsPerMeter	= rtgui_filerw_read32(src);
+		header->biClrUsed	= rtgui_filerw_read32(src);
+		header->biClrImportant	= rtgui_filerw_read32(src);
 
-    rtgui_filerw_read(file, (char*)&header, 1, sizeof(header));
+	}
+
+	/* Expand 1 and 4 bit bitmaps to 8 bits per pixel */
+	switch (header->biBitCount)
+	{
+	case 1:
+	case 4:
+		ExpandBMP = header->biBitCount;
+		header->biBitCount = 8;
+		break;
+
+	default:
+		ExpandBMP = 0;
+		break;
+	}
+
+	/* We don't support any BMP compression right now */
+	Rmask = Gmask = Bmask = 0;
+	switch (header->biCompression)
+	{
+	case BI_RGB:
+		/* If there are no masks, use the defaults */
+		if ( header->bfOffBits == (14 + header->biSize) )
+		{
+			/* Default values for the BMP format */
+			switch (header->biBitCount)
+			{
+			case 15:
+			case 16:
+				Rmask = 0x7C00;
+				Gmask = 0x03E0;
+				Bmask = 0x001F;
+				break;
+
+			case 24:
+			case 32:
+				Rmask = 0x00FF0000;
+				Gmask = 0x0000FF00;
+				Bmask = 0x000000FF;
+				break;
+
+			default:
+				break;
+			}
+			break;
+		}
+		/* Fall through -- read the RGB masks */
+
+	case BI_BITFIELDS:
+		switch (header->biBitCount)
+		{
+		case 15:
+		case 16:
+		case 32:
+			Rmask = rtgui_filerw_read32(src);
+			Gmask = rtgui_filerw_read32(src);
+			Bmask = rtgui_filerw_read32(src);
+			break;
+
+		default:
+			break;
+		}
+		break;
+
+	default:
+		rt_kprintf("Compressed BMP files not supported\n");
+		goto __exit;
+	}
+
+	bmp = (struct rtgui_image_bmp*) rtgui_malloc(sizeof(struct rtgui_image_bmp));
+	if (bmp == RT_NULL)
+		goto __exit;
 
 	/* set image information */
-	image->w = (rt_uint16_t)header[1]; image->h = (rt_uint16_t)header[2];
+	image->w = header->biWidth;
+	image->h = header->biHeight;
 	image->engine = &rtgui_image_bmp_engine;
 	image->data = bmp;
-	bmp->filerw = file;
-	bmp->byte_per_pixel = bmp->hw_driver->byte_per_pixel;
+	bmp->filerw = src;
+	bmp->byte_per_pixel = header->biBitCount/8;
 	bmp->pitch = image->w * bmp->byte_per_pixel;
-	bmp->pixel_offset = rtgui_filerw_tell(file);
+	bmp->pixel_offset = header->bfOffBits;
+	bmp->Rmask = Rmask; bmp->Gmask = Gmask; bmp->Bmask = Bmask;
+	bmp->ExpandBMP = ExpandBMP;
+
+	/* Load the palette, if any */
+#if 0
+	if ( palette )
+	{
+		rt_size_t i;
+
+		if (header->biClrUsed == 0)
+			header->biClrUsed = 1 << header->biBitCount;
+
+		image->palette = rtgui_image_palette_create(header->biClrUsed);
+		if ( header->biSize == 12 )
+		{
+			for ( i = 0; i < (int)header->biClrUsed; ++i )
+			{
+				rtgui_filerw_read(src, &RTGUI_RGB_R(image->palette->colors[i]), 1, 1);
+				rtgui_filerw_read(src, &RTGUI_RGB_G(image->palette->colors[i]), 1, 1);
+				rtgui_filerw_read(src, &RTGUI_RGB_B(image->palette->colors[i]), 1, 1);
+				RTGUI_RGB_A(image->palette->colors[i]) = 0;
+			}
+		}
+		else
+		{
+			for ( i = 0; i < (int)header->biClrUsed; ++i )
+			{
+				rtgui_filerw_read(src, &RTGUI_RGB_R(image->palette->colors[i]), 1, 1);
+				rtgui_filerw_read(src, &RTGUI_RGB_G(image->palette->colors[i]), 1, 1);
+				rtgui_filerw_read(src, &RTGUI_RGB_B(image->palette->colors[i]), 1, 1);
+				rtgui_filerw_read(src, &RTGUI_RGB_A(image->palette->colors[i]), 1, 1);
+			}
+		}
+	}
+#endif
+
+	/* get padding */
+	switch (ExpandBMP)
+	{
+	case 1:
+		bmpPitch = (header->biWidth + 7) >> 3;
+		bmp->pad  = (((bmpPitch)%4) ? (4-((bmpPitch)%4)) : 0);
+		break;
+
+	case 4:
+		bmpPitch = (header->biWidth + 1) >> 1;
+		bmp->pad  = (((bmpPitch)%4) ? (4-((bmpPitch)%4)) : 0);
+		break;
+
+	default:
+		bmp->pad  = ((bmp->pitch%4) ? (4-(bmp->pitch%4)) : 0);
+		break;
+	}
 
 	if (load == RT_TRUE)
 	{
+		rt_uint8_t *bits;
+		rt_uint32_t i;
+
 		/* load all pixels */
 		bmp->pixels = rtgui_malloc(image->h * bmp->pitch);
 		if (bmp->pixels == RT_NULL)
+			goto __exit;
+
+		/* Read the pixels.  Note that the bmp image is upside down */
+		if ( rtgui_filerw_seek(src, bmp->pixel_offset, RTGUI_FILE_SEEK_SET) < 0)
+			goto __exit;
+
+		bits = bmp->pixels + image->h * bmp->pitch;
+		while ( bits > bmp->pixels )
 		{
-            /* release data */
-            rtgui_free(bmp);
-            return RT_FALSE;
+			bits -= bmp->pitch;
+			switch (ExpandBMP)
+			{
+			case 1:
+			case 4:
+				{
+					rt_uint8_t pixel = 0;
+					int   shift = (8 - ExpandBMP);
+					for ( i=0; i < image->w; ++i )
+					{
+						if ( i % (8/ExpandBMP) == 0 )
+						{
+							if ( !rtgui_filerw_read(src, &pixel, 1, 1) )
+								goto __exit;
+
+						}
+						*(bits+i) = (pixel>>shift);
+						pixel <<= ExpandBMP;
+					}
+				}
+				break;
+
+			default:
+				if ( rtgui_filerw_read(src, bits, 1, bmp->pitch) != bmp->pitch ) goto __exit;
+				break;
+			}
+
+			/* Skip padding bytes  */
+			if ( bmp->pad )
+			{
+				rt_uint8_t padbyte;
+				for ( i=0; i < bmp->pad; ++i )
+				{
+					rtgui_filerw_read(src, &padbyte, 1, 1);
+				}
+			}
 		}
 
-		rtgui_filerw_read(bmp->filerw, bmp->pixels, 1, image->h * bmp->pitch);
 		rtgui_filerw_close(bmp->filerw);
 		bmp->filerw = RT_NULL;
 		bmp->pixel_offset = 0;
@@ -130,6 +376,13 @@ static rt_bool_t rtgui_image_bmp_load(struct rtgui_image* image, struct rtgui_fi
 	}
 
 	return RT_TRUE;
+
+__exit:
+	rtgui_free(header);
+	if (bmp != RT_NULL)
+		rtgui_free(bmp->pixels);
+	rtgui_free(bmp);
+	return RT_FALSE;
 }
 
 static void rtgui_image_bmp_unload(struct rtgui_image* image)
@@ -165,29 +418,59 @@ static void rtgui_image_bmp_blit(struct rtgui_image* image, struct rtgui_dc* dc,
 	bmp = (struct rtgui_image_bmp*) image->data;
 	RT_ASSERT(bmp != RT_NULL);
 
-	if ((dc->type != RTGUI_DC_HW) || (dc->type != RTGUI_DC_CLIENT)) return;
+	if ((dc->type != RTGUI_DC_HW) && (dc->type != RTGUI_DC_CLIENT)) return;
 
 	/* the minimum rect */
-    if (image->w < rtgui_rect_width(*dst_rect)) w = image->w;
-    else w = rtgui_rect_width(*dst_rect);
-    if (image->h < rtgui_rect_height(*dst_rect)) h = image->h;
-    else h = rtgui_rect_height(*dst_rect);
+	if (image->w < rtgui_rect_width(*dst_rect)) w = image->w;
+	else w = rtgui_rect_width(*dst_rect);
+	if (image->h < rtgui_rect_height(*dst_rect)) h = image->h;
+	else h = rtgui_rect_height(*dst_rect);
 
-    if (bmp->pixels != RT_NULL)
-    {
+	if (bmp->pixels != RT_NULL)
+	{
 		rt_uint8_t* ptr;
 
 		/* get pixel pointer */
 		ptr = bmp->pixels;
-
-		for (y = 0; y < h; y ++)
+		if ((dc->type == RTGUI_DC_HW) || (dc->type == RTGUI_DC_CLIENT))
 		{
-			rtgui_dc_client_draw_raw_hline(dc, ptr, dst_rect->x1, dst_rect->x1 + w, dst_rect->y1 + y);
-			ptr += bmp->pitch;
+			if (bmp->byte_per_pixel == hw_driver->byte_per_pixel)
+			{
+				for (y = 0; y < h; y ++)
+				{
+					rtgui_dc_hw_draw_raw_hline(dc, ptr, 
+						dst_rect->x1, dst_rect->x1 + w,
+						dst_rect->y1 + y);
+					ptr += bmp->pitch;
+				}
+			}
+			else
+			{
+				rt_uint8_t *line_ptr;
+				rtgui_blit_line_func blit_line;
+				rt_size_t pitch;
+
+				line_ptr = (rt_uint8_t*) rtgui_malloc(hw_driver->byte_per_pixel * w);
+				blit_line = rtgui_blit_line_get(hw_driver->byte_per_pixel , bmp->byte_per_pixel);
+				pitch = w * bmp->byte_per_pixel;
+				if (line_ptr != RT_NULL)
+				{
+					for (y = 0; y < h; y ++)
+					{
+						blit_line(line_ptr, ptr, pitch);
+						rtgui_dc_hw_draw_raw_hline(dc, line_ptr, 
+							dst_rect->x1, dst_rect->x1 + w,
+							dst_rect->y1 + y);
+						ptr += bmp->pitch;
+					}
+				}
+
+				rtgui_free(line_ptr);
+			}
 		}
-    }
-    else
-    {
+	}
+	else
+	{
 		rt_uint8_t* ptr;
 		ptr = rtgui_malloc(bmp->pitch);
 		if (ptr == RT_NULL) return; /* no memory */
@@ -205,7 +488,7 @@ static void rtgui_image_bmp_blit(struct rtgui_image* image, struct rtgui_dc* dc,
 		}
 
 		rtgui_free(ptr);
-    }
+	}
 }
 
 void rtgui_image_bmp_init()

+ 2 - 2
components/rtgui/common/image_hdc.c

@@ -155,7 +155,7 @@ static void rtgui_image_hdc_blit(struct rtgui_image* image, struct rtgui_dc* dc,
 	hdc = (struct rtgui_image_hdc*) image->data;
 	RT_ASSERT(hdc != RT_NULL);
 
-	if ((dc->type != RTGUI_DC_HW) || (dc->type != RTGUI_DC_CLIENT)) return;
+	if ((dc->type != RTGUI_DC_HW) && (dc->type != RTGUI_DC_CLIENT)) return;
 
 	/* the minimum rect */
     if (image->w < rtgui_rect_width(*dst_rect)) w = image->w;
@@ -207,7 +207,7 @@ static void rtgui_image_hdcmm_blit(struct rtgui_image* image, struct rtgui_dc* d
 	RT_ASSERT(image != RT_NULL || dc != RT_NULL || dst_rect != RT_NULL);
 
 	/* this dc is not visible */
-	if (rtgui_dc_get_visible(dc) != RT_TRUE || (dc->type != RTGUI_DC_HW) || (dc->type != RTGUI_DC_CLIENT)) return;
+	if (rtgui_dc_get_visible(dc) != RT_TRUE || ((dc->type != RTGUI_DC_HW) && (dc->type != RTGUI_DC_CLIENT))) return;
 
 	hdc = (struct rtgui_image_hdcmm*) image;
 	RT_ASSERT(hdc != RT_NULL);

+ 9 - 0
components/rtgui/include/rtgui/blit.h

@@ -0,0 +1,9 @@
+#ifndef __RTGUI_BLIT_H__
+#define __RTGUI_BLIT_H__
+
+#include <rtgui/rtgui.h>
+
+typedef void (*rtgui_blit_line_func)(rt_uint8_t* dst, rt_uint8_t* src, int line);
+const rtgui_blit_line_func rtgui_blit_line_get(int dst_bpp, int src_bpp);
+
+#endif

+ 11 - 0
components/rtgui/include/rtgui/image.h

@@ -33,6 +33,13 @@ struct rtgui_image_engine
 	void (*image_blit)(struct rtgui_image* image, struct rtgui_dc* dc, struct rtgui_rect* rect);
 };
 
+struct rtgui_image_palette
+{
+	rtgui_color_t* colors;
+	rt_uint32_t ncolors;
+};
+typedef struct rtgui_image_palette rtgui_image_palette_t;
+
 struct rtgui_image
 {
 	/* image metrics */
@@ -41,6 +48,9 @@ struct rtgui_image
 	/* image engine */
 	const struct rtgui_image_engine* engine;
 
+	/* image palette */
+	rtgui_image_palette_t* palette;
+
 	/* image private data */
 	void* data;
 };
@@ -60,6 +70,7 @@ void rtgui_image_register_engine(struct rtgui_image_engine* engine);
 
 /* blit an image on DC */
 void rtgui_image_blit(struct rtgui_image* image, struct rtgui_dc* dc, struct rtgui_rect* rect);
+struct rtgui_image_palette* rtgui_image_palette_create(rt_uint32_t ncolors);
 
 
 #endif

+ 1 - 0
components/rtgui/include/rtgui/rtgui_config.h

@@ -33,6 +33,7 @@
 	#define RTGUI_DEFAULT_FONT_SIZE	12
 
 	#define RTGUI_USING_STDIO_FILERW
+	#define RTGUI_IMAGE_BMP
 	#define RTGUI_IMAGE_PNG
 	#define RTGUI_IMAGE_JPEG
 	#define RTGUI_USING_FONT12