diff --git a/components/rtgui/SConscript b/components/rtgui/SConscript index 9c210bcd10..aa55d2ecd4 100644 --- a/components/rtgui/SConscript +++ b/components/rtgui/SConscript @@ -18,6 +18,8 @@ common/image.c common/image_xpm.c common/image_hdc.c common/image_bmp.c +common/image_png.c +common/image_jpg.c common/image_container.c common/font.c common/font_bmp.c diff --git a/components/rtgui/common/image_bmp.c b/components/rtgui/common/image_bmp.c index 838a2f9915..f68dd507e6 100644 --- a/components/rtgui/common/image_bmp.c +++ b/components/rtgui/common/image_bmp.c @@ -1,553 +1,554 @@ -#include -#include -#include -#include -#include -#include - -/* Compression encodings for BMP files */ -#ifndef BI_RGB -#define BI_RGB 0 -#define BI_RLE8 1 -#define BI_RLE4 2 -#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_uint8_t *line_pixels; - rt_uint32_t pitch; - - struct rtgui_filerw* filerw; -}; - -struct rtgui_image_bmp_header -{ - /* The Win32 BMP file header (14 bytes) */ - char magic[2]; - rt_uint32_t bfSize; - rt_uint16_t bfReserved1; - rt_uint16_t bfReserved2; - rt_uint32_t bfOffBits; - - /* The Win32 BITMAPINFOHEADER struct (40 bytes) */ - rt_uint32_t biSize; - rt_int32_t biWidth; - rt_int32_t biHeight; - rt_uint16_t biPlanes; - rt_uint16_t biBitCount; - rt_uint32_t biCompression; - rt_uint32_t biSizeImage; - rt_int32_t biXPelsPerMeter; - rt_int32_t biYPelsPerMeter; - rt_uint32_t biClrUsed; - rt_uint32_t biClrImportant; -}; - -static rt_bool_t rtgui_image_bmp_check(struct rtgui_filerw* file); -static rt_bool_t rtgui_image_bmp_load(struct rtgui_image* image, struct rtgui_filerw* file, rt_bool_t load); -static void rtgui_image_bmp_unload(struct rtgui_image* image); -static void rtgui_image_bmp_blit(struct rtgui_image* image, struct rtgui_dc* dc, struct rtgui_rect* rect); - -struct rtgui_image_engine rtgui_image_bmp_engine = -{ - "bmp", - { RT_NULL }, - rtgui_image_bmp_check, - rtgui_image_bmp_load, - rtgui_image_bmp_unload, - 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; - - start = rtgui_filerw_tell(file); - - /* move to the beginning of file */ - rtgui_filerw_seek(file, 0, RTGUI_FILE_SEEK_SET); - - is_bmp = RT_FALSE; - if ( rtgui_filerw_read(file, magic, 1, sizeof(magic)) == sizeof(magic) ) - { - if (magic[0] == 'B' && - magic[1] == 'M') - { - is_bmp = RT_TRUE; - } - } - - rtgui_filerw_seek(file, start, RTGUI_FILE_SEEK_SET); - - return(is_bmp); -} - -static struct rtgui_image_palette* rtgui_image_bmp_load_palette(struct rtgui_image_bmp_header* header, struct rtgui_filerw* src) -{ - /* Load the palette, if any */ - rt_size_t i; - struct rtgui_image_palette* palette; - - if (header->biClrUsed == 0) - header->biClrUsed = 1 << header->biBitCount; - - palette = rtgui_image_palette_create(header->biClrUsed); - if (palette == RT_NULL) return RT_NULL; - - if ( header->biSize == 12 ) - { - rt_uint8_t r, g, b; - for ( i = 0; i < (int)header->biClrUsed; ++i ) - { - rtgui_filerw_read(src, &b, 1, 1); - rtgui_filerw_read(src, &g, 1, 1); - rtgui_filerw_read(src, &r, 1, 1); - palette->colors[i] = RTGUI_RGB(r, g, b); - } - } - else - { - rt_uint8_t r, g, b, a; - for ( i = 0; i < (int)header->biClrUsed; ++i ) - { - rtgui_filerw_read(src, &b, 1, 1); - rtgui_filerw_read(src, &g, 1, 1); - rtgui_filerw_read(src, &r, 1, 1); - rtgui_filerw_read(src, &a, 1, 1); - palette->colors[i] = RTGUI_ARGB(a, r, g, b); - } - } - - return palette; -} - -static rt_bool_t rtgui_image_bmp_load(struct rtgui_image* image, struct rtgui_filerw* src, rt_bool_t load) -{ - rt_uint32_t Rmask; - rt_uint32_t Gmask; - rt_uint32_t Bmask; - int ExpandBMP, bmpPitch; - struct rtgui_image_bmp* bmp; - struct rtgui_image_bmp_header* header; - struct rtgui_image_palette* palette; - - bmp = RT_NULL; - header = RT_NULL; - palette = 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); - - /* 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); - - } - - /* allocate palette and expand 1 and 4 bit bitmaps to 8 bits per pixel */ - switch (header->biBitCount) - { - case 1: - ExpandBMP = header->biBitCount; - palette = rtgui_image_bmp_load_palette(header, src); - header->biBitCount = 8; - break; - - case 4: - ExpandBMP = header->biBitCount; - palette = rtgui_image_bmp_load_palette(header, src); - header->biBitCount = 8; - break; - - case 8: - palette = rtgui_image_bmp_load_palette(header, src); - ExpandBMP = 0; - 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 = header->biWidth; - image->h = header->biHeight; - image->engine = &rtgui_image_bmp_engine; - image->data = bmp; - bmp->filerw = src; - bmp->byte_per_pixel = header->biBitCount/8; - bmp->pitch = image->w * bmp->byte_per_pixel; - bmp->pixel_offset = header->bfOffBits; - bmp->Rmask = Rmask; bmp->Gmask = Gmask; bmp->Bmask = Bmask; - bmp->ExpandBMP = ExpandBMP; - if (palette != RT_NULL) image->palette = palette; - - /* 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 ) - { - 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_close(bmp->filerw); - bmp->line_pixels = RT_NULL; - bmp->filerw = RT_NULL; - bmp->pixel_offset = 0; - } - else - { - bmp->pixels = RT_NULL; - bmp->line_pixels = rtgui_malloc(bmp->pitch); - } - - return RT_TRUE; - -__exit: - rtgui_free(header); - if (palette != RT_NULL) - { - rtgui_free(palette); - image->palette = RT_NULL; - } - - if (bmp != RT_NULL) - rtgui_free(bmp->pixels); - rtgui_free(bmp); - return RT_FALSE; -} - -static void rtgui_image_bmp_unload(struct rtgui_image* image) -{ - struct rtgui_image_bmp* bmp; - - if (image != RT_NULL) - { - bmp = (struct rtgui_image_bmp*) image->data; - - if (bmp->pixels != RT_NULL) rtgui_free(bmp->pixels); - if (bmp->line_pixels != RT_NULL) rtgui_free(bmp->line_pixels); - if (bmp->filerw != RT_NULL) - { - rtgui_filerw_close(bmp->filerw); - bmp->filerw = RT_NULL; - } - - /* release data */ - rtgui_free(bmp); - } -} - -static void rtgui_image_bmp_blit(struct rtgui_image* image, struct rtgui_dc* dc, struct rtgui_rect* dst_rect) -{ - int y; - rt_uint16_t w, h; - struct rtgui_image_bmp* bmp; - - 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) return; - - bmp = (struct rtgui_image_bmp*) image->data; - RT_ASSERT(bmp != RT_NULL); - - /* 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 (bmp->pixels != RT_NULL) - { - rt_uint8_t* ptr; - - /* get pixel pointer */ - ptr = bmp->pixels; - if (bmp->byte_per_pixel == hw_driver->byte_per_pixel) - { - for (y = 0; y < h; y ++) - { - dc->engine->blit_line(dc, - dst_rect->x1, dst_rect->x1 + w, - dst_rect->y1 + y, - ptr); - ptr += bmp->pitch; - } - } - else - { - rt_size_t pitch; - rt_uint8_t *line_ptr; - - if (image->palette == RT_NULL) - { - rtgui_blit_line_func blit_line; - 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); - dc->engine->blit_line(dc, - dst_rect->x1, dst_rect->x1 + w, - dst_rect->y1 + y, - line_ptr); - ptr += bmp->pitch; - } - } - rtgui_free(line_ptr); - } - else - { - int x; - rtgui_color_t color; - - /* use palette */ - for (y = 0; y < h; y ++) - { - ptr = bmp->pixels + (y * bmp->pitch); - for (x = 0; x < w; x ++) - { - color = image->palette->colors[*ptr]; ptr ++; - rtgui_dc_draw_color_point(dc, dst_rect->x1 + x, dst_rect->y1 + y, color); - } - } - } - } - } - else - { - int offset; +#include +#include +#include +#include +#include +#include + +#ifdef RTGUI_IMAGE_BMP +/* Compression encodings for BMP files */ +#ifndef BI_RGB +#define BI_RGB 0 +#define BI_RLE8 1 +#define BI_RLE4 2 +#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_uint8_t *line_pixels; + rt_uint32_t pitch; + + struct rtgui_filerw* filerw; +}; + +struct rtgui_image_bmp_header +{ + /* The Win32 BMP file header (14 bytes) */ + char magic[2]; + rt_uint32_t bfSize; + rt_uint16_t bfReserved1; + rt_uint16_t bfReserved2; + rt_uint32_t bfOffBits; + + /* The Win32 BITMAPINFOHEADER struct (40 bytes) */ + rt_uint32_t biSize; + rt_int32_t biWidth; + rt_int32_t biHeight; + rt_uint16_t biPlanes; + rt_uint16_t biBitCount; + rt_uint32_t biCompression; + rt_uint32_t biSizeImage; + rt_int32_t biXPelsPerMeter; + rt_int32_t biYPelsPerMeter; + rt_uint32_t biClrUsed; + rt_uint32_t biClrImportant; +}; + +static rt_bool_t rtgui_image_bmp_check(struct rtgui_filerw* file); +static rt_bool_t rtgui_image_bmp_load(struct rtgui_image* image, struct rtgui_filerw* file, rt_bool_t load); +static void rtgui_image_bmp_unload(struct rtgui_image* image); +static void rtgui_image_bmp_blit(struct rtgui_image* image, struct rtgui_dc* dc, struct rtgui_rect* rect); + +struct rtgui_image_engine rtgui_image_bmp_engine = +{ + "bmp", + { RT_NULL }, + rtgui_image_bmp_check, + rtgui_image_bmp_load, + rtgui_image_bmp_unload, + 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; + + start = rtgui_filerw_tell(file); + + /* move to the beginning of file */ + rtgui_filerw_seek(file, 0, RTGUI_FILE_SEEK_SET); + + is_bmp = RT_FALSE; + if ( rtgui_filerw_read(file, magic, 1, sizeof(magic)) == sizeof(magic) ) + { + if (magic[0] == 'B' && + magic[1] == 'M') + { + is_bmp = RT_TRUE; + } + } + + rtgui_filerw_seek(file, start, RTGUI_FILE_SEEK_SET); + + return(is_bmp); +} + +static struct rtgui_image_palette* rtgui_image_bmp_load_palette(struct rtgui_image_bmp_header* header, struct rtgui_filerw* src) +{ + /* Load the palette, if any */ + rt_size_t i; + struct rtgui_image_palette* palette; + + if (header->biClrUsed == 0) + header->biClrUsed = 1 << header->biBitCount; + + palette = rtgui_image_palette_create(header->biClrUsed); + if (palette == RT_NULL) return RT_NULL; + + if ( header->biSize == 12 ) + { + rt_uint8_t r, g, b; + for ( i = 0; i < (int)header->biClrUsed; ++i ) + { + rtgui_filerw_read(src, &b, 1, 1); + rtgui_filerw_read(src, &g, 1, 1); + rtgui_filerw_read(src, &r, 1, 1); + palette->colors[i] = RTGUI_RGB(r, g, b); + } + } + else + { + rt_uint8_t r, g, b, a; + for ( i = 0; i < (int)header->biClrUsed; ++i ) + { + rtgui_filerw_read(src, &b, 1, 1); + rtgui_filerw_read(src, &g, 1, 1); + rtgui_filerw_read(src, &r, 1, 1); + rtgui_filerw_read(src, &a, 1, 1); + palette->colors[i] = RTGUI_ARGB(a, r, g, b); + } + } + + return palette; +} + +static rt_bool_t rtgui_image_bmp_load(struct rtgui_image* image, struct rtgui_filerw* src, rt_bool_t load) +{ + rt_uint32_t Rmask; + rt_uint32_t Gmask; + rt_uint32_t Bmask; + int ExpandBMP, bmpPitch; + struct rtgui_image_bmp* bmp; + struct rtgui_image_bmp_header* header; + struct rtgui_image_palette* palette; + + bmp = RT_NULL; + header = RT_NULL; + palette = 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); + + /* 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); + + } + + /* allocate palette and expand 1 and 4 bit bitmaps to 8 bits per pixel */ + switch (header->biBitCount) + { + case 1: + ExpandBMP = header->biBitCount; + palette = rtgui_image_bmp_load_palette(header, src); + header->biBitCount = 8; + break; + + case 4: + ExpandBMP = header->biBitCount; + palette = rtgui_image_bmp_load_palette(header, src); + header->biBitCount = 8; + break; + + case 8: + palette = rtgui_image_bmp_load_palette(header, src); + ExpandBMP = 0; + 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 = header->biWidth; + image->h = header->biHeight; + image->engine = &rtgui_image_bmp_engine; + image->data = bmp; + bmp->filerw = src; + bmp->byte_per_pixel = header->biBitCount/8; + bmp->pitch = image->w * bmp->byte_per_pixel; + bmp->pixel_offset = header->bfOffBits; + bmp->Rmask = Rmask; bmp->Gmask = Gmask; bmp->Bmask = Bmask; + bmp->ExpandBMP = ExpandBMP; + if (palette != RT_NULL) image->palette = palette; + + /* 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; - - /* calculate offset */ - switch (bmp->ExpandBMP) - { - case 1: - offset = (image->h - h) * (image->w/8) * bmp->byte_per_pixel; - break; - - case 4: - offset = (image->h - h) * (image->w/2) * bmp->byte_per_pixel; - break; - - default: - offset = (image->h - h) * image->w * bmp->byte_per_pixel; - break; - } - /* seek to the begin of pixel data */ - rtgui_filerw_seek(bmp->filerw, bmp->pixel_offset + offset, RTGUI_FILE_SEEK_SET); - - if (bmp->ExpandBMP == 1 || bmp->ExpandBMP == 4) - { + 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 ) + { + 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_close(bmp->filerw); + bmp->line_pixels = RT_NULL; + bmp->filerw = RT_NULL; + bmp->pixel_offset = 0; + } + else + { + bmp->pixels = RT_NULL; + bmp->line_pixels = rtgui_malloc(bmp->pitch); + } + + return RT_TRUE; + +__exit: + rtgui_free(header); + if (palette != RT_NULL) + { + rtgui_free(palette); + image->palette = RT_NULL; + } + + if (bmp != RT_NULL) + rtgui_free(bmp->pixels); + rtgui_free(bmp); + return RT_FALSE; +} + +static void rtgui_image_bmp_unload(struct rtgui_image* image) +{ + struct rtgui_image_bmp* bmp; + + if (image != RT_NULL) + { + bmp = (struct rtgui_image_bmp*) image->data; + + if (bmp->pixels != RT_NULL) rtgui_free(bmp->pixels); + if (bmp->line_pixels != RT_NULL) rtgui_free(bmp->line_pixels); + if (bmp->filerw != RT_NULL) + { + rtgui_filerw_close(bmp->filerw); + bmp->filerw = RT_NULL; + } + + /* release data */ + rtgui_free(bmp); + } +} + +static void rtgui_image_bmp_blit(struct rtgui_image* image, struct rtgui_dc* dc, struct rtgui_rect* dst_rect) +{ + int y; + rt_uint16_t w, h; + struct rtgui_image_bmp* bmp; + + 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) return; + + bmp = (struct rtgui_image_bmp*) image->data; + RT_ASSERT(bmp != RT_NULL); + + /* 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 (bmp->pixels != RT_NULL) + { + rt_uint8_t* ptr; + + /* get pixel pointer */ + ptr = bmp->pixels; + if (bmp->byte_per_pixel == hw_driver->byte_per_pixel) + { + for (y = 0; y < h; y ++) + { + dc->engine->blit_line(dc, + dst_rect->x1, dst_rect->x1 + w, + dst_rect->y1 + y, + ptr); + ptr += bmp->pitch; + } + } + else + { + rt_size_t pitch; + rt_uint8_t *line_ptr; + + if (image->palette == RT_NULL) + { + rtgui_blit_line_func blit_line; + 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); + dc->engine->blit_line(dc, + dst_rect->x1, dst_rect->x1 + w, + dst_rect->y1 + y, + line_ptr); + ptr += bmp->pitch; + } + } + rtgui_free(line_ptr); + } + else + { + int x; + rtgui_color_t color; + + /* use palette */ + for (y = 0; y < h; y ++) + { + ptr = bmp->pixels + (y * bmp->pitch); + for (x = 0; x < w; x ++) + { + color = image->palette->colors[*ptr]; ptr ++; + rtgui_dc_draw_color_point(dc, dst_rect->x1 + x, dst_rect->y1 + y, color); + } + } + } + } + } + else + { + int offset; + rt_uint8_t *bits; + + /* calculate offset */ + switch (bmp->ExpandBMP) + { + case 1: + offset = (image->h - h) * (image->w/8) * bmp->byte_per_pixel; + break; + + case 4: + offset = (image->h - h) * (image->w/2) * bmp->byte_per_pixel; + break; + + default: + offset = (image->h - h) * image->w * bmp->byte_per_pixel; + break; + } + /* seek to the begin of pixel data */ + rtgui_filerw_seek(bmp->filerw, bmp->pixel_offset + offset, RTGUI_FILE_SEEK_SET); + + if (bmp->ExpandBMP == 1 || bmp->ExpandBMP == 4) + { int x; rtgui_color_t color; - /* 1, 4 bit per pixels */ - - /* draw each line */ - for (y = h - 1; y >= 0; y --) - { - /* read pixel data */ + /* 1, 4 bit per pixels */ + + /* draw each line */ + for (y = h - 1; y >= 0; y --) + { + /* read pixel data */ rt_uint8_t pixel = 0; int shift = (8 - bmp->ExpandBMP); int i; @@ -581,17 +582,17 @@ static void rtgui_image_bmp_blit(struct rtgui_image* image, struct rtgui_dc* dc, rtgui_dc_draw_color_point(dc, dst_rect->x1 + x, dst_rect->y1 + y, color); } } - } - else - { + } + else + { rt_uint8_t *line_ptr = (rt_uint8_t*) rtgui_malloc(hw_driver->byte_per_pixel * w); if (line_ptr == RT_NULL) return; - /* draw each line */ - for (y = h - 1; y >= 0; y --) - { - /* read line pixels */ - rtgui_filerw_read(bmp->filerw, bmp->line_pixels, 1, bmp->pitch); + /* draw each line */ + for (y = h - 1; y >= 0; y --) + { + /* read line pixels */ + rtgui_filerw_read(bmp->filerw, bmp->line_pixels, 1, bmp->pitch); /* Skip padding bytes */ if (bmp->pad) @@ -601,10 +602,10 @@ static void rtgui_image_bmp_blit(struct rtgui_image* image, struct rtgui_dc* dc, for ( i=0; i < bmp->pad; ++i ) rtgui_filerw_read(bmp->filerw, &padbyte, 1, 1); } - - if (image->palette == RT_NULL) - { - int pitch; + + if (image->palette == RT_NULL) + { + int pitch; rtgui_blit_line_func blit_line; blit_line = rtgui_blit_line_get(hw_driver->byte_per_pixel , bmp->byte_per_pixel); pitch = w * bmp->byte_per_pixel; @@ -616,9 +617,9 @@ static void rtgui_image_bmp_blit(struct rtgui_image* image, struct rtgui_dc* dc, dst_rect->y1 + y, line_ptr); } - } - else - { + } + else + { int x; rtgui_color_t color; @@ -628,16 +629,17 @@ static void rtgui_image_bmp_blit(struct rtgui_image* image, struct rtgui_dc* dc, { color = image->palette->colors[*bits]; bits ++; rtgui_dc_draw_color_point(dc, dst_rect->x1 + x, dst_rect->y1 + y, color); - } - } - } - if (line_ptr != RT_NULL) rtgui_free(line_ptr); - } - } -} - -void rtgui_image_bmp_init() -{ - /* register bmp on image system */ - rtgui_image_register_engine(&rtgui_image_bmp_engine); -} + } + } + } + if (line_ptr != RT_NULL) rtgui_free(line_ptr); + } + } +} + +void rtgui_image_bmp_init() +{ + /* register bmp on image system */ + rtgui_image_register_engine(&rtgui_image_bmp_engine); +} +#endif diff --git a/components/rtgui/common/image_jpg.c b/components/rtgui/common/image_jpg.c index 9146559230..c445c6a14f 100644 --- a/components/rtgui/common/image_jpg.c +++ b/components/rtgui/common/image_jpg.c @@ -1,7 +1,7 @@ #include #include -#ifdef RTGUI_USING_JPEG +#ifdef RTGUI_IMAGE_JPEG #include #include #include "jpeg/jpeglib.h" diff --git a/components/rtgui/common/image_png.c b/components/rtgui/common/image_png.c index bb6e1b4bf8..0c63e80cf8 100644 --- a/components/rtgui/common/image_png.c +++ b/components/rtgui/common/image_png.c @@ -1,7 +1,7 @@ #include #include -#ifdef RTGUI_USING_PNG +#ifdef RTGUI_IMAGE_PNG #include "libpng/png.h" #include diff --git a/components/rtgui/common/jpeg/SConscript b/components/rtgui/common/jpeg/SConscript new file mode 100644 index 0000000000..72ead4f3d0 --- /dev/null +++ b/components/rtgui/common/jpeg/SConscript @@ -0,0 +1,38 @@ +Import('RTT_ROOT') +Import('rtconfig') +from building import * + +src = Split(''' +jaricom.c +jcomapi.c +jutils.c +jerror.c +jmemmgr.c +jdapimin.c +jdapistd.c +jdarith.c +jdtrans.c +jdatasrc.c +jdmaster.c +jdinput.c +jdmarker.c +jdhuff.c +jdmainct.c +jdcoefct.c +jdpostct.c +jddctmgr.c +jidctfst.c +jidctflt.c +jidctint.c +jdsample.c +jdcolor.c +jquant1.c +jquant2.c +jdmerge.c +jmemnobs.c +''') +CPPPATH = [RTT_ROOT + '/components/rtgui/common/jpeg'] + +group = DefineGroup('jpeg', src, depend = ['RTGUI_IMAGE_JPEG'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/rtgui/common/libpng/SConscript b/components/rtgui/common/libpng/SConscript new file mode 100644 index 0000000000..74c369c071 --- /dev/null +++ b/components/rtgui/common/libpng/SConscript @@ -0,0 +1,28 @@ +Import('RTT_ROOT') +Import('rtconfig') +from building import * + +src = Split(''' +png.c +pngerror.c +pnggccrd.c +pngget.c +pngmem.c +pngpread.c +pngread.c +pngrio.c +pngrtran.c +pngrutil.c +pngset.c +pngtrans.c +pngvcrd.c +pngwio.c +pngwrite.c +pngwtran.c +pngwutil.c +''') +CPPPATH = [RTT_ROOT + '/components/rtgui/common/libpng'] + +group = DefineGroup('libpng', src, depend = ['RTGUI_IMAGE_PNG'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/rtgui/common/libz/SConscript b/components/rtgui/common/libz/SConscript new file mode 100644 index 0000000000..4c763df343 --- /dev/null +++ b/components/rtgui/common/libz/SConscript @@ -0,0 +1,23 @@ +Import('RTT_ROOT') +Import('rtconfig') +from building import * + +src = Split(''' +adler32.c +compress.c +crc32.c +deflate.c +gzio.c +infback.c +inffast.c +inflate.c +inftrees.c +trees.c +uncompr.c +zutil.c +''') +CPPPATH = [RTT_ROOT + '/components/rtgui/common/libz'] + +group = DefineGroup('libz', src, depend = ['RTGUI_IMAGE_PNG'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/rtgui/include/rtgui/rtgui_config.h b/components/rtgui/include/rtgui/rtgui_config.h index 84c9c819f5..2bd82a7b74 100644 --- a/components/rtgui/include/rtgui/rtgui_config.h +++ b/components/rtgui/include/rtgui/rtgui_config.h @@ -38,8 +38,8 @@ #define RTGUI_IMAGE_CONTAINER #define RTGUI_IMAGE_XPM #define RTGUI_IMAGE_BMP - // #define RTGUI_IMAGE_PNG - // #define RTGUI_IMAGE_JPEG + #define RTGUI_IMAGE_PNG + #define RTGUI_IMAGE_JPEG #define RTGUI_USING_FONT12 #define RTGUI_USING_HZ_BMP #define RTGUI_MEM_TRACE