mirror of
https://gitee.com/zlgopen/awtk.git
synced 2024-12-02 03:58:33 +08:00
improve bitmap, image loader and image_gen
This commit is contained in:
parent
5a7a0c3fda
commit
4a860c041a
@ -61,45 +61,6 @@ ret_t bitmap_destroy(bitmap_t* bitmap) {
|
||||
|
||||
#include "base/pixel_pack_unpack.h"
|
||||
|
||||
ret_t bitmap_rgba_to_bgr565(bitmap_t* image, uint16_t* output) {
|
||||
uint32_t i = 0;
|
||||
uint16_t* d = output;
|
||||
uint32_t nr = image->w * image->h;
|
||||
uint32_t* s = (uint32_t*)(image->data);
|
||||
return_value_if_fail(image->format == BITMAP_FMT_RGBA8888, RET_BAD_PARAMS);
|
||||
|
||||
for (i = 0; i < nr; i++, d++, s++) {
|
||||
color_t c;
|
||||
c.color = *s;
|
||||
*d = rgb_to_bgr565(c.rgba.r, c.rgba.g, c.rgba.b);
|
||||
}
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
ret_t bitmap_rgba_to_bgra(bitmap_t* image) {
|
||||
int i = 0;
|
||||
int nr = image->w * image->h;
|
||||
uint8_t* data = (uint8_t*)(image->data);
|
||||
|
||||
/*default format is rgba, some sys need bgra*/
|
||||
for (i = 0; i < nr; i++) {
|
||||
uint8_t r = data[0];
|
||||
uint8_t g = data[1];
|
||||
uint8_t b = data[2];
|
||||
uint8_t a = data[3];
|
||||
data[0] = b;
|
||||
data[1] = g;
|
||||
data[2] = r;
|
||||
data[3] = a;
|
||||
|
||||
data += 4;
|
||||
}
|
||||
image->format = BITMAP_FMT_BGRA8888;
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
uint32_t bitmap_get_bpp(bitmap_t* bmp) {
|
||||
return_value_if_fail(bmp != NULL, 0);
|
||||
|
||||
@ -129,8 +90,8 @@ ret_t bitmap_alloc_data(bitmap_t* bitmap) {
|
||||
|
||||
size = bitmap_get_bpp(bitmap) * bitmap->w * bitmap->h;
|
||||
size = TK_ROUND_TO(size, BITMAP_ALIGN_SIZE) + BITMAP_ALIGN_SIZE;
|
||||
data = (uint8_t*)TKMEM_ALLOC(size);
|
||||
|
||||
data = (uint8_t*)TKMEM_ALLOC(size);
|
||||
if (data != NULL) {
|
||||
memset(data, 0x00, size);
|
||||
bitmap->data_free_ptr = data;
|
||||
@ -236,7 +197,8 @@ ret_t bitmap_get_pixel(bitmap_t* bitmap, uint32_t x, uint32_t y, rgba_t* rgba) {
|
||||
return RET_NOT_IMPL;
|
||||
}
|
||||
|
||||
ret_t bitmap_init_rgba8888(bitmap_t* b, uint32_t w, uint32_t h, uint8_t* data, uint32_t comp) {
|
||||
ret_t bitmap_init_rgba8888(bitmap_t* b, uint32_t w, uint32_t h, const uint8_t* data,
|
||||
uint32_t comp) {
|
||||
uint32_t i = 0;
|
||||
|
||||
if (comp == 4) {
|
||||
@ -244,7 +206,7 @@ ret_t bitmap_init_rgba8888(bitmap_t* b, uint32_t w, uint32_t h, uint8_t* data, u
|
||||
memcpy((uint8_t*)(b->data), data, size);
|
||||
} else {
|
||||
uint32_t n = w * h;
|
||||
uint8_t* s = data;
|
||||
const uint8_t* s = data;
|
||||
uint8_t* d = (uint8_t*)(b->data);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
@ -258,10 +220,11 @@ ret_t bitmap_init_rgba8888(bitmap_t* b, uint32_t w, uint32_t h, uint8_t* data, u
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
ret_t bitmap_init_bgra8888(bitmap_t* b, uint32_t w, uint32_t h, uint8_t* data, uint32_t comp) {
|
||||
ret_t bitmap_init_bgra8888(bitmap_t* b, uint32_t w, uint32_t h, const uint8_t* data,
|
||||
uint32_t comp) {
|
||||
uint32_t i = 0;
|
||||
uint32_t n = w * h;
|
||||
uint8_t* s = data;
|
||||
const uint8_t* s = data;
|
||||
uint8_t* d = (uint8_t*)(b->data);
|
||||
|
||||
/*bgra=rgba*/
|
||||
@ -278,10 +241,10 @@ ret_t bitmap_init_bgra8888(bitmap_t* b, uint32_t w, uint32_t h, uint8_t* data, u
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
ret_t bitmap_init_bgr565(bitmap_t* b, uint32_t w, uint32_t h, uint8_t* data, uint32_t comp) {
|
||||
ret_t bitmap_init_bgr565(bitmap_t* b, uint32_t w, uint32_t h, const uint8_t* data, uint32_t comp) {
|
||||
uint32_t i = 0;
|
||||
uint32_t n = w * h;
|
||||
uint8_t* s = data;
|
||||
const uint8_t* s = data;
|
||||
uint16_t* d = (uint16_t*)(b->data);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
@ -293,9 +256,28 @@ ret_t bitmap_init_bgr565(bitmap_t* b, uint32_t w, uint32_t h, uint8_t* data, uin
|
||||
|
||||
s += comp;
|
||||
}
|
||||
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
ret_t bitmap_init(bitmap_t* b, uint32_t w, uint32_t h, bitmap_format_t format, uint8_t* data,
|
||||
bool_t rgba_data_is_opaque(const uint8_t* data, uint32_t w, uint32_t h, uint8_t comp) {
|
||||
if (comp == 4) {
|
||||
uint32_t i = 0;
|
||||
uint32_t n = w * h;
|
||||
const uint8_t* s = data;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
if (s[3] != 0xff) {
|
||||
return FALSE;
|
||||
}
|
||||
s += 4;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
ret_t bitmap_init(bitmap_t* b, uint32_t w, uint32_t h, bitmap_format_t format, const uint8_t* data,
|
||||
uint32_t comp) {
|
||||
return_value_if_fail(b != NULL && data != NULL && (comp == 3 || comp == 4), RET_BAD_PARAMS);
|
||||
|
||||
@ -307,7 +289,7 @@ ret_t bitmap_init(bitmap_t* b, uint32_t w, uint32_t h, bitmap_format_t format, u
|
||||
b->flags = BITMAP_FLAG_IMMUTABLE;
|
||||
return_value_if_fail(bitmap_alloc_data(b) == RET_OK, RET_OOM);
|
||||
|
||||
if (comp == 3) {
|
||||
if (rgba_data_is_opaque(data, w, h, comp)) {
|
||||
b->flags |= BITMAP_FLAG_OPAQUE;
|
||||
}
|
||||
|
||||
@ -315,7 +297,7 @@ ret_t bitmap_init(bitmap_t* b, uint32_t w, uint32_t h, bitmap_format_t format, u
|
||||
return bitmap_init_bgra8888(b, w, h, data, comp);
|
||||
} else if (format == BITMAP_FMT_RGBA8888) {
|
||||
return bitmap_init_rgba8888(b, w, h, data, comp);
|
||||
} else if (comp == 3) {
|
||||
} else if (format == BITMAP_FMT_BGR565) {
|
||||
return bitmap_init_bgr565(b, w, h, data, comp);
|
||||
} else {
|
||||
return RET_NOT_IMPL;
|
||||
|
@ -166,9 +166,13 @@ struct _bitmap_t {
|
||||
/*data是按cache line对齐,而data_free_ptr是用于释放的指针*/
|
||||
uint8_t* data_free_ptr;
|
||||
|
||||
/*destroy时是否需要释放data指向的内存*/
|
||||
bool_t should_free_data;
|
||||
|
||||
/*destroy时是否需要释放bitmap本身的内存*/
|
||||
bool_t should_free_handle;
|
||||
/* 显示特定的数据,如OpenGL texture ID,picasso/agg中图片等。*/
|
||||
|
||||
/* 显示特定的数据,如OpenGL texture ID,agg/agge中图片等。*/
|
||||
void* specific;
|
||||
/*specific_destroy的上下文*/
|
||||
void* specific_ctx;
|
||||
@ -187,6 +191,55 @@ struct _bitmap_t {
|
||||
*/
|
||||
bitmap_t* bitmap_create(void);
|
||||
|
||||
/**
|
||||
* @method bitmap_create_ex
|
||||
* 创建图片对象。
|
||||
* @annotation ["constructor", "scriptable"]
|
||||
* @param {uint32_t} w 宽度。
|
||||
* @param {uint32_t} h 高度。
|
||||
* @param {bitmap_format_t} format 格式。
|
||||
*
|
||||
* @return {bitmap_t*} 返回bitmap对象。
|
||||
*/
|
||||
bitmap_t* bitmap_create_ex(uint32_t w, uint32_t h, bitmap_format_t format);
|
||||
|
||||
/**
|
||||
* @method bitmap_get_bpp
|
||||
* 获取图片一个像素占用的字节数。
|
||||
* @annotation ["scriptable"]
|
||||
*
|
||||
* @return {uint32_t} 返回一个像素占用的字节数。
|
||||
*/
|
||||
uint32_t bitmap_get_bpp(bitmap_t* bitmap);
|
||||
|
||||
/**
|
||||
* @method bitmap_get_pixel
|
||||
* 获取图片指定像素的rgba颜色值(主要用于测试程序)。
|
||||
* @param {bitmap_t*} bitmap bitmap对象。
|
||||
* @param {uint32_t} x x坐标。
|
||||
* @param {uint32_t} y y坐标。
|
||||
* @param {rgba_t*} rgba 返回颜色值。
|
||||
*
|
||||
* @return {ret_t} 返回RET_OK表示成功,否则表示失败。
|
||||
*/
|
||||
ret_t bitmap_get_pixel(bitmap_t* bitmap, uint32_t x, uint32_t y, rgba_t* rgba);
|
||||
|
||||
/**
|
||||
* @method bitmap_init
|
||||
* 初始化图片。
|
||||
* @param {bitmap_t*} bitmap bitmap对象。
|
||||
* @param {uint32_t} w 宽度。
|
||||
* @param {uint32_t} h 高度。
|
||||
* @param {bitmap_format_t} format 格式。
|
||||
* @param {const uint8_t*} data
|
||||
* 数据。3通道时为RGB888格式,4通道时为RGBA888格式(内部拷贝该数据,不会引用,调用者自行释放)。
|
||||
* @param {uint32_t} comp 颜色通道数(目前支持3(rgb)和4(rgba))。
|
||||
*
|
||||
* @return {ret_t} 返回RET_OK表示成功,否则表示失败。
|
||||
*/
|
||||
ret_t bitmap_init(bitmap_t* b, uint32_t w, uint32_t h, bitmap_format_t format, const uint8_t* data,
|
||||
uint32_t comp);
|
||||
|
||||
/**
|
||||
* @method bitmap_destroy
|
||||
* 销毁图片。
|
||||
@ -302,16 +355,9 @@ typedef enum _image_draw_type_t {
|
||||
#define BITMAP_ALIGN_SIZE 32
|
||||
#endif /*BITMAP_ALIGN_SIZE*/
|
||||
|
||||
uint32_t bitmap_get_bpp(bitmap_t* bitmap);
|
||||
ret_t bitmap_rgba_to_bgra(bitmap_t* image);
|
||||
ret_t bitmap_rgba_to_bgr565(bitmap_t* image, uint16_t* output);
|
||||
bitmap_t* bitmap_create_ex(uint32_t w, uint32_t h, bitmap_format_t format);
|
||||
|
||||
/*private*/
|
||||
ret_t bitmap_alloc_data(bitmap_t* bitmap);
|
||||
ret_t bitmap_get_pixel(bitmap_t* bitmap, uint32_t x, uint32_t y, rgba_t* rgba);
|
||||
|
||||
ret_t bitmap_init(bitmap_t* b, uint32_t w, uint32_t h, bitmap_format_t format, uint8_t* data,
|
||||
uint32_t comp);
|
||||
bool_t rgba_data_is_opaque(const uint8_t* data, uint32_t w, uint32_t h, uint8_t comp);
|
||||
|
||||
END_C_DECLS
|
||||
|
||||
|
@ -20,43 +20,53 @@
|
||||
*/
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
|
||||
#include "base/mem.h"
|
||||
|
||||
#define STBI_FREE TKMEM_FREE
|
||||
#define STBI_MALLOC TKMEM_ALLOC
|
||||
#define STBI_REALLOC(p, s) TKMEM_REALLOC(char, p, s)
|
||||
|
||||
#include "base/mem.h"
|
||||
|
||||
#include "stb/stb_image.h"
|
||||
#include "image_loader/image_loader_stb.h"
|
||||
|
||||
static ret_t image_loader_stb_load(image_loader_t* l, const uint8_t* buff, uint32_t buff_size,
|
||||
bitmap_t* image) {
|
||||
ret_t stb_load_image(const uint8_t* buff, uint32_t buff_size, bitmap_t* image, bool_t require_bgra,
|
||||
bool_t enable_bgr565) {
|
||||
int i = 0;
|
||||
int w = 0;
|
||||
int h = 0;
|
||||
int n = 0;
|
||||
int nr = 0;
|
||||
ret_t ret = RET_FAIL;
|
||||
uint8_t* data = stbi_load_from_memory(buff, buff_size, &w, &h, &n, 0);
|
||||
return_value_if_fail(data != NULL, RET_FAIL);
|
||||
|
||||
if (n == 3) {
|
||||
#ifdef WITH_BITMAP_BGR565
|
||||
if (enable_bgr565 && rgba_data_is_opaque(data, w, h, n)) {
|
||||
ret = bitmap_init(image, w, h, BITMAP_FMT_BGR565, data, n);
|
||||
stbi_image_free((uint8_t*)(data));
|
||||
return ret;
|
||||
#endif /*WITH_BITMAP_BGR565*/
|
||||
} else if (require_bgra) {
|
||||
ret = bitmap_init(image, w, h, BITMAP_FMT_BGRA8888, data, n);
|
||||
} else {
|
||||
ret = bitmap_init(image, w, h, BITMAP_FMT_RGBA8888, data, n);
|
||||
}
|
||||
|
||||
stbi_image_free((uint8_t*)(data));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ret_t image_loader_stb_load(image_loader_t* l, const uint8_t* buff, uint32_t buff_size,
|
||||
bitmap_t* image) {
|
||||
bool_t require_bgra = FALSE;
|
||||
bool_t enable_bgr565 = FALSE;
|
||||
return_value_if_fail(l != NULL && buff != NULL && image != NULL, RET_BAD_PARAMS);
|
||||
|
||||
#ifdef WITH_BITMAP_BGR565
|
||||
enable_bgr565 = TRUE;
|
||||
#endif /*WITH_BITMAP_BGR565*/
|
||||
|
||||
#ifdef WITH_BITMAP_BGRA
|
||||
ret = bitmap_init(image, w, h, BITMAP_FMT_BGRA8888, data, n);
|
||||
#else
|
||||
ret = bitmap_init(image, w, h, BITMAP_FMT_RGBA8888, data, n);
|
||||
require_bgra = TRUE;
|
||||
#endif /*WITH_BITMAP_BGRA*/
|
||||
|
||||
stbi_image_free((uint8_t*)(data));
|
||||
return ret;
|
||||
return stb_load_image(buff, buff_size, image, require_bgra, enable_bgr565);
|
||||
}
|
||||
|
||||
static const image_loader_t stb_loader = {.load = image_loader_stb_load};
|
||||
|
4
src/image_loader/image_loader_stb.h
Executable file → Normal file
4
src/image_loader/image_loader_stb.h
Executable file → Normal file
@ -28,6 +28,10 @@ BEGIN_C_DECLS
|
||||
|
||||
image_loader_t* image_loader_stb(void);
|
||||
|
||||
/*for tool image_gen only*/
|
||||
ret_t stb_load_image(const uint8_t* buff, uint32_t buff_size, bitmap_t* image, bool_t require_bgra,
|
||||
bool_t enable_bgr565);
|
||||
|
||||
END_C_DECLS
|
||||
|
||||
#endif /*TK_IMAGE_LOADER_STB_H*/
|
||||
|
@ -2,9 +2,13 @@
|
||||
|
||||
在嵌入式系统中,RAM比较少,虽然PNG/JPG等文件可以大幅度降低存储空间,但是需要解码到内存中,不太适合直接使用。AWTK提供了imagegen工具,将图片转换成位图数据,直接编译到代码中,放在flash中,不占用内存空间。
|
||||
|
||||
用法说明:
|
||||
|
||||
```
|
||||
./bin/imagegen in_filename out_filename
|
||||
./bin/imagegen in_filename out_filename bgra|bgr565
|
||||
```
|
||||
|
||||
* in_filename png/jpg 文件
|
||||
* out_filename 位图数据文件
|
||||
* in\_filename png/jpg 文件的文件名。
|
||||
* out\_filename 位图数据文件的文件名。
|
||||
* bgra 表示输出BITMAP\_FMT\_BGRA8888格式的图片。
|
||||
* bgr565 表示把不透明的图片转成BITMAP\_FMT\_BGR565格式的图片。
|
||||
|
@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
#include "base/mem.h"
|
||||
#include "base/utils.h"
|
||||
#include "common/utils.h"
|
||||
#include "image_gen/image_gen.h"
|
||||
#include "base/image_manager.h"
|
||||
@ -40,14 +41,13 @@ ret_t image_gen(bitmap_t* image, const char* output_filename) {
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
#include "base/utils.h"
|
||||
|
||||
uint32_t image_gen_buff(bitmap_t* image, uint8_t* output_buff, uint32_t buff_size) {
|
||||
size_t size = 0;
|
||||
uint32_t bpp = bitmap_get_bpp(image);
|
||||
bitmap_header_t* header = (bitmap_header_t*)output_buff;
|
||||
return_value_if_fail(image != NULL && output_buff != NULL, 0);
|
||||
|
||||
size = sizeof(uint32_t) * image->w * image->h;
|
||||
size = bpp * image->w * image->h;
|
||||
return_value_if_fail((size + sizeof(bitmap_header_t)) < buff_size, RET_BAD_PARAMS);
|
||||
|
||||
header->w = image->w;
|
||||
@ -55,25 +55,7 @@ uint32_t image_gen_buff(bitmap_t* image, uint8_t* output_buff, uint32_t buff_siz
|
||||
header->flags = image->flags;
|
||||
header->format = image->format;
|
||||
|
||||
if (image->flags & BITMAP_FLAG_OPAQUE) {
|
||||
if (image->format == BITMAP_FMT_RGBA8888) {
|
||||
if (bitmap_rgba_to_bgr565(image, (uint16_t*)(header->data)) == RET_OK) {
|
||||
header->format = BITMAP_FMT_BGR565;
|
||||
size = sizeof(uint16_t) * image->w * image->h;
|
||||
} else {
|
||||
assert(!"bitmap_rgba_to_bgr565 fail.");
|
||||
}
|
||||
} else if (image->format == BITMAP_FMT_BGR565) {
|
||||
size = sizeof(uint16_t) * image->w * image->h;
|
||||
memcpy(header->data, image->data, size);
|
||||
} else if (image->format == BITMAP_FMT_BGRA8888) {
|
||||
size = sizeof(uint32_t) * image->w * image->h;
|
||||
memcpy(header->data, image->data, size);
|
||||
}
|
||||
} else {
|
||||
size = sizeof(uint32_t) * image->w * image->h;
|
||||
memcpy(header->data, image->data, size);
|
||||
}
|
||||
|
||||
return size + sizeof(bitmap_header_t);
|
||||
}
|
||||
|
@ -29,25 +29,36 @@ int main(int argc, char** argv) {
|
||||
bitmap_t image;
|
||||
uint32_t size = 0;
|
||||
uint8_t* buff = NULL;
|
||||
bool_t require_bgra = FALSE;
|
||||
bool_t enable_bgr565 = FALSE;
|
||||
const char* in_filename = NULL;
|
||||
const char* out_filename = NULL;
|
||||
image_loader_t* loader = NULL;
|
||||
|
||||
TKMEM_INIT(4 * 1024 * 1024);
|
||||
|
||||
if (argc != 3) {
|
||||
printf("Usage: %s in_filename out_filename\n", argv[0]);
|
||||
if (argc < 3) {
|
||||
printf("Usage: %s in_filename out_filename (bgra|bgr565)\n", argv[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argc >= 4) {
|
||||
const char* options = argv[3];
|
||||
|
||||
if (strstr(options, "bgra") != NULL) {
|
||||
require_bgra = TRUE;
|
||||
}
|
||||
|
||||
if (strstr(options, "bgr565") != NULL) {
|
||||
enable_bgr565 = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
in_filename = argv[1];
|
||||
out_filename = argv[2];
|
||||
|
||||
loader = image_loader_stb();
|
||||
buff = (uint8_t*)read_file(in_filename, &size);
|
||||
if (buff != NULL) {
|
||||
if (image_loader_load(loader, buff, size, &image) == RET_OK) {
|
||||
if (stb_load_image(buff, size, &image, require_bgra, enable_bgr565) == RET_OK) {
|
||||
if (image_gen(&image, out_filename) == RET_OK) {
|
||||
printf("done\n");
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user