diff --git a/src/draw/lv_draw_buf.c b/src/draw/lv_draw_buf.c index 7a0fd5fb1..778a07a55 100644 --- a/src/draw/lv_draw_buf.c +++ b/src/draw/lv_draw_buf.c @@ -115,6 +115,108 @@ void lv_draw_buf_copy(void * dest_buf, uint32_t dest_w, uint32_t dest_h, const l color_format); } +lv_draw_buf_t * lv_draw_buf_create(uint32_t w, uint32_t h, lv_color_format_t cf, uint32_t stride) +{ + uint32_t size; + lv_draw_buf_t * draw_buf = lv_malloc_zeroed(sizeof(lv_draw_buf_t)); + LV_ASSERT_MALLOC(draw_buf); + if(draw_buf == NULL) return NULL; + if(stride == 0) stride = lv_draw_buf_width_to_stride(w, cf); + + size = stride * h; + if(cf == LV_COLOR_FORMAT_RGB565A8) { + size += (stride / 2) * h; /*A8 mask*/ + } + else if(LV_COLOR_FORMAT_IS_INDEXED(cf)) { + /*@todo we have to include palette right before image data*/ + size += LV_COLOR_INDEXED_PALETTE_SIZE(cf) * 4; + } + + /*RLE decompression operates on pixel unit, thus add padding to make sure memory is enough*/ + uint8_t bpp = lv_color_format_get_bpp(cf); + bpp = (bpp + 7) >> 3; + size += bpp; + + void * buf = lv_draw_buf_malloc(size, cf); + LV_ASSERT_MALLOC(buf); + if(buf == NULL) { + lv_free(draw_buf); + return NULL; + } + + draw_buf->header.w = w; + draw_buf->header.h = h; + draw_buf->header.cf = cf; + draw_buf->header.flags = LV_IMAGE_FLAGS_MODIFIABLE; + draw_buf->header.stride = stride; + draw_buf->data = lv_draw_buf_align(buf, cf); + draw_buf->_unaligned = buf; + draw_buf->data_size = size; + return draw_buf; +} + +void lv_draw_buf_destroy(lv_draw_buf_t * buf) +{ + LV_ASSERT_NULL(buf); + if(buf == NULL) return; + if(buf->header.flags & LV_IMAGE_FLAGS_MODIFIABLE) + lv_draw_buf_free(buf->_unaligned); + + lv_free(buf); +} + +void * lv_draw_buf_goto_xy(lv_draw_buf_t * buf, uint32_t x, uint32_t y) +{ + LV_ASSERT_NULL(buf); + if(buf == NULL) return NULL; + + uint8_t * data = buf->data; + data += buf->header.stride * y; + + if(x == 0) + return data; + + return data + x * lv_color_format_get_size(buf->header.cf); +} + +/** + * Convert draw buffer stride and color format. + * @param src source draw buffer + * @param stride new stride + * @return converted draw buffer + */ +lv_draw_buf_t * lv_draw_buf_adjust_stride(const lv_draw_buf_t * src, uint32_t stride) +{ + LV_ASSERT_NULL(src); + LV_ASSERT_NULL(src->data); + if(src == NULL) return NULL; + if(src->data == NULL) return NULL; + + /*Check if stride already match*/ + if(src->header.stride == stride) return NULL; + + /*Calculate the minimal stride allowed from bpp*/ + uint32_t bpp = lv_color_format_get_bpp(src->header.cf); + uint32_t min_stride = (src->header.w * bpp + 7) >> 3; + if(stride < min_stride) { + LV_LOG_WARN("New stride is too small. min: %" LV_PRId32, min_stride); + return NULL; + } + + lv_draw_buf_t * dst = lv_draw_buf_create(src->header.w, src->header.h, src->header.cf, stride); + if(dst == NULL) return NULL; + + uint8_t * dst_data = dst->data; + const uint8_t * src_data = src->data; + for(int32_t y = 0; y < src->header.h; y++) { + lv_memcpy(dst_data, src_data, min_stride); + src_data += src->header.stride; + dst_data += dst->header.stride; + } + + return dst; +} + /********************** * STATIC FUNCTIONS **********************/ diff --git a/src/draw/lv_draw_buf.h b/src/draw/lv_draw_buf.h index f9e8b95fe..3c7fb08a3 100644 --- a/src/draw/lv_draw_buf.h +++ b/src/draw/lv_draw_buf.h @@ -15,6 +15,7 @@ extern "C" { *********************/ #include "../misc/lv_area.h" #include "../misc/lv_color.h" +#include "lv_image_buf.h" /********************* * DEFINES @@ -24,6 +25,13 @@ extern "C" { * TYPEDEFS **********************/ +typedef struct { + lv_image_header_t header; + uint32_t data_size; /*Total buf size in bytes*/ + void * data; + void * _unaligned; /*Unaligned address of data*/ +} lv_draw_buf_t; + typedef void * (*lv_draw_buf_malloc_cb)(size_t size, lv_color_format_t color_format); typedef void (*lv_draw_buf_free_cb)(void * draw_buf); @@ -152,6 +160,54 @@ void lv_draw_buf_clear(void * buf, uint32_t w, uint32_t h, lv_color_format_t col void lv_draw_buf_copy(void * dest_buf, uint32_t dest_w, uint32_t dest_h, const lv_area_t * dest_area_to_copy, void * src_buf, uint32_t src_w, uint32_t src_h, const lv_area_t * src_area_to_copy, lv_color_format_t color_format); + +/** + * Note: Eventually, lv_draw_buf_malloc/free will be kept as private. + * For now, we use `create` to distinguish with malloc. + * + * Create an draw buf by allocating struct for `lv_draw_buf_t` and allocating a buffer for it + * that meets specified requirements. + * + * @param w the buffer width in pixels + * @param h + * @param cf the color format for image + * @param stride the stride in bytes for image. Use 0 for automatic calculation based on + * w, cf, and global stride alignment configuration. + */ +lv_draw_buf_t * lv_draw_buf_create(uint32_t w, uint32_t h, lv_color_format_t cf, uint32_t stride); + +/** + * Destroy a draw buf by free the actual buffer if it's marked as LV_IMAGE_FLAGS_MODIFIABLE in header. + * Then free the lv_draw_buf_t struct. + */ +void lv_draw_buf_destroy(lv_draw_buf_t * buf); + +/** + * @todo, need to replace lv_draw_buf_go_to_xy. + * Return pointer to the buffer at the given coordinates + */ +void * lv_draw_buf_goto_xy(lv_draw_buf_t * buf, uint32_t x, uint32_t y); + +/** + * Adjust the stride of a draw buf. + */ +lv_draw_buf_t * lv_draw_buf_adjust_stride(const lv_draw_buf_t * src, uint32_t stride); + +/** + * As of now, draw buf share same definition as `lv_image_dsc_t`. + * And is interchangeable with `lv_image_dsc_t`. + */ + +static inline void lv_draw_buf_from_image(lv_draw_buf_t * buf, const lv_image_dsc_t * img) +{ + lv_memcpy(buf, img, sizeof(lv_image_dsc_t)); +} + +static inline void lv_draw_buf_to_image(const lv_draw_buf_t * buf, lv_image_dsc_t * img) +{ + lv_memcpy(img, buf, sizeof(lv_image_dsc_t)); +} + /********************** * MACROS **********************/ diff --git a/src/draw/lv_image_buf.h b/src/draw/lv_image_buf.h index e148d121c..79e5199a4 100644 --- a/src/draw/lv_image_buf.h +++ b/src/draw/lv_image_buf.h @@ -16,6 +16,7 @@ extern "C" { #include #include "../misc/lv_color.h" #include "../misc/lv_area.h" +#include "../stdlib/lv_string.h" /********************* * DEFINES @@ -122,8 +123,13 @@ typedef struct { } lv_image_header_t; #endif -/** Image header it is compatible with - * the result from image converter utility*/ +/** + * Struct to describe an image. Both decoded and raw image can share + * the same struct. + * + * Image is also identical to lv_draw_buf_t for now. + * Ideally, decoded image should be lv_draw_buf_t. + */ typedef struct { lv_image_header_t header; /**< A header describing the basics of the image*/ uint32_t data_size; /**< Size of the image in bytes*/ @@ -166,6 +172,17 @@ void _lv_image_buf_get_transformed_area(lv_area_t * res, int32_t w, int32_t h, i uint16_t scale_y, const lv_point_t * pivot); +static inline void lv_image_header_init(lv_image_header_t * header, uint32_t w, uint32_t h, lv_color_format_t cf, + uint32_t stride, lv_image_flags_t flags) +{ + LV_ASSERT(header); + lv_memzero(header, sizeof(*header)); + header->w = w; + header->h = h; + header->cf = cf; + header->stride = stride; + header->flags = flags; +} /********************** * MACROS **********************/