improve bitmap, image loader and image_gen

This commit is contained in:
xianjimli 2018-10-17 09:57:36 +08:00
parent 5a7a0c3fda
commit 4a860c041a
7 changed files with 145 additions and 106 deletions

View File

@ -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;

View File

@ -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 IDpicasso/agg中图片等。*/
/* 显示特定的数据如OpenGL texture IDagg/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
* 3RGB888格式4RGBA888格式()
* @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

View File

@ -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
View 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*/

View File

@ -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格式的图片。

View File

@ -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);
}
memcpy(header->data, image->data, size);
return size + sizeof(bitmap_header_t);
}

View File

@ -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 {