diff --git a/components/rtgui/common/blit.c b/components/rtgui/common/blit.c new file mode 100644 index 0000000000..c2a26ec83b --- /dev/null +++ b/components/rtgui/common/blit.c @@ -0,0 +1,298 @@ +#include +#include + +/* 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]; +} diff --git a/components/rtgui/common/image.c b/components/rtgui/common/image.c index 7393856300..b7ffdd38f1 100644 --- a/components/rtgui/common/image.c +++ b/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; +} diff --git a/components/rtgui/common/image_bmp.c b/components/rtgui/common/image_bmp.c index 0dbbe4baa6..69e6d7f501 100644 --- a/components/rtgui/common/image_bmp.c +++ b/components/rtgui/common/image_bmp.c @@ -3,6 +3,7 @@ #include #include #include +#include /* 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 = (struct rtgui_image_bmp*) rtgui_malloc(sizeof(struct rtgui_image_bmp)); - if (bmp == RT_NULL) return RT_FALSE; + 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; - bmp->hw_driver = rtgui_graphic_driver_get_default(); - if (bmp->hw_driver == RT_NULL) { rtgui_free(bmp); 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; + } + } - rtgui_filerw_read(file, (char*)&header, 1, sizeof(header)); + header->bfSize = rtgui_filerw_read32(src); + header->bfReserved1 = rtgui_filerw_read16(src); + header->bfReserved2 = rtgui_filerw_read16(src); + header->bfOffBits = rtgui_filerw_read32(src); + + /* 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; + + } + 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); + + } + + /* 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() diff --git a/components/rtgui/common/image_hdc.c b/components/rtgui/common/image_hdc.c index 70b4c0a178..b1a7562d5b 100644 --- a/components/rtgui/common/image_hdc.c +++ b/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); diff --git a/components/rtgui/include/rtgui/blit.h b/components/rtgui/include/rtgui/blit.h new file mode 100644 index 0000000000..8be0b21949 --- /dev/null +++ b/components/rtgui/include/rtgui/blit.h @@ -0,0 +1,9 @@ +#ifndef __RTGUI_BLIT_H__ +#define __RTGUI_BLIT_H__ + +#include + +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 diff --git a/components/rtgui/include/rtgui/image.h b/components/rtgui/include/rtgui/image.h index e0a6859246..c52d78f61a 100644 --- a/components/rtgui/include/rtgui/image.h +++ b/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 diff --git a/components/rtgui/include/rtgui/rtgui_config.h b/components/rtgui/include/rtgui/rtgui_config.h index 415cfd05c8..eb7ea19b16 100644 --- a/components/rtgui/include/rtgui/rtgui_config.h +++ b/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