boards: cxd56_imageproc.c: Add alpha blend API
Add imageproc_alpha_blend() to blend two images in a specified ratio. The blended source image is selectable from the following two types: - Single color image - YUV422 image The blend ratio is selectable from the following three types: - Blend ratio with single value - Blend ratio with 1bpp - Blend ratio with 8bpp
This commit is contained in:
parent
8fec8cccfc
commit
f1f0378d0a
@ -140,6 +140,10 @@
|
||||
#define FIXEDSRC (1 << 14)
|
||||
#define MSBFIRST (1 << 13)
|
||||
|
||||
#ifndef MIN
|
||||
# define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
@ -217,6 +221,7 @@ struct __attribute__ ((aligned(16))) ge2d_abcmd_s
|
||||
static sem_t g_rotwait;
|
||||
static sem_t g_rotexc;
|
||||
static sem_t g_geexc;
|
||||
static sem_t g_abexc;
|
||||
|
||||
static int g_gfd = -1;
|
||||
static char g_gcmdbuf[256] __attribute__ ((aligned(16)));
|
||||
@ -373,6 +378,39 @@ static void *set_rop_cmd(void *cmdbuf,
|
||||
return (void *)((uintptr_t) cmdbuf + sizeof(struct ge2d_ropcmd_s));
|
||||
}
|
||||
|
||||
static void *set_ab_cmd(void *cmdbuf, void *srcaddr, void *destaddr,
|
||||
uint16_t srcwidth, uint16_t srcheight,
|
||||
uint16_t srcpitch, uint16_t destpitch,
|
||||
void *aaddr, uint16_t apitch,
|
||||
int options, uint16_t fixedsrc, uint16_t fixedalpha)
|
||||
{
|
||||
struct ge2d_abcmd_s *ac = (struct ge2d_abcmd_s *)cmdbuf;
|
||||
|
||||
memset(ac, 0, sizeof(struct ge2d_abcmd_s));
|
||||
|
||||
ac->cmd = ABCMD | options;
|
||||
ac->mode = fixedalpha;
|
||||
ac->srch = srcwidth - 1;
|
||||
ac->srcv = srcheight - 1;
|
||||
ac->saddr = (uint32_t)(uintptr_t)srcaddr | MSEL;
|
||||
ac->daddr = (uint32_t)(uintptr_t)destaddr | MSEL;
|
||||
ac->spitch = srcpitch - 1;
|
||||
ac->dpitch = destpitch - 1;
|
||||
ac->fixedsrc = (uint32_t)fixedsrc;
|
||||
if (aaddr)
|
||||
{
|
||||
ac->aaddr = (uint32_t)(uintptr_t)aaddr | MSEL;
|
||||
ac->apitch = apitch - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
ac->aaddr = (uint32_t)(uintptr_t)destaddr | MSEL;
|
||||
ac->apitch = destpitch - 1;
|
||||
}
|
||||
|
||||
return (void *)((uintptr_t)cmdbuf + sizeof(struct ge2d_abcmd_s));
|
||||
}
|
||||
|
||||
static void *set_halt_cmd(void *cmdbuf)
|
||||
{
|
||||
memset(cmdbuf, 0, 16);
|
||||
@ -426,6 +464,77 @@ static void imageproc_convert_(int is_yuv2rgb,
|
||||
ip_semgive(&g_rotexc);
|
||||
}
|
||||
|
||||
static void get_rect_info(imageproc_imginfo_t *imginfo,
|
||||
int *offset, int *w, int *h)
|
||||
{
|
||||
if (imginfo->rect)
|
||||
{
|
||||
*offset = (imginfo->rect->y1 * imginfo->w)
|
||||
+ imginfo->rect->x1;
|
||||
*w = imginfo->rect->x2 - imginfo->rect->x1 + 1;
|
||||
*h = imginfo->rect->y2 - imginfo->rect->y1 + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
*offset = 0;
|
||||
*w = imginfo->w;
|
||||
*h = imginfo->h;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int chk_imgsize(imageproc_imginfo_t *imginfo)
|
||||
{
|
||||
if (!imginfo)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((imginfo->w > HSIZE_MAX) || (imginfo->w < HSIZE_MIN) ||
|
||||
(imginfo->h > VSIZE_MAX) || (imginfo->h < VSIZE_MIN))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (imginfo->rect)
|
||||
{
|
||||
if ((imginfo->rect->x2 <= imginfo->rect->x1) ||
|
||||
(imginfo->rect->y2 <= imginfo->rect->y1))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((imginfo->rect->x2 >= imginfo->w) ||
|
||||
(imginfo->rect->y2 >= imginfo->h))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *get_blendarea(imageproc_imginfo_t *imginfo, int offset)
|
||||
{
|
||||
switch (imginfo->type)
|
||||
{
|
||||
case IMAGEPROC_IMGTYPE_8BPP:
|
||||
return imginfo->img.p_u8 + offset;
|
||||
|
||||
case IMAGEPROC_IMGTYPE_16BPP:
|
||||
return imginfo->img.p_u16 + offset;
|
||||
|
||||
case IMAGEPROC_IMGTYPE_BINARY:
|
||||
return imginfo->img.binary.p_u8 + offset / 8;
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
@ -435,6 +544,7 @@ void imageproc_initialize(void)
|
||||
nxsem_init(&g_rotexc, 0, 1);
|
||||
nxsem_init(&g_rotwait, 0, 0);
|
||||
nxsem_init(&g_geexc, 0, 1);
|
||||
nxsem_init(&g_abexc, 0, 1);
|
||||
nxsem_set_protocol(&g_rotwait, SEM_PRIO_NONE);
|
||||
|
||||
cxd56_ge2dinitialize(GEDEVNAME);
|
||||
@ -465,6 +575,7 @@ void imageproc_finalize(void)
|
||||
nxsem_destroy(&g_rotwait);
|
||||
nxsem_destroy(&g_rotexc);
|
||||
nxsem_destroy(&g_geexc);
|
||||
nxsem_destroy(&g_abexc);
|
||||
}
|
||||
|
||||
void imageproc_convert_yuv2rgb(uint8_t * ibuf,
|
||||
@ -697,3 +808,194 @@ int imageproc_clip_and_resize(uint8_t * ibuf,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int imageproc_alpha_blend(imageproc_imginfo_t *dst,
|
||||
int pos_x,
|
||||
int pos_y,
|
||||
imageproc_imginfo_t *src,
|
||||
imageproc_imginfo_t *alpha)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Graphic engine control */
|
||||
|
||||
void *cmd = g_gcmdbuf;
|
||||
size_t len;
|
||||
|
||||
/* alpha blend options */
|
||||
|
||||
uint16_t fixed_alpha;
|
||||
uint16_t fixed_src;
|
||||
int options;
|
||||
|
||||
/* blended rectangles information */
|
||||
|
||||
void *dst_addr;
|
||||
void *src_addr;
|
||||
void *a_addr;
|
||||
|
||||
int dst_offset;
|
||||
int dst_w;
|
||||
int dst_h;
|
||||
int src_offset;
|
||||
int src_w;
|
||||
int src_h;
|
||||
int a_offset;
|
||||
int a_w;
|
||||
int a_h;
|
||||
|
||||
int blendarea_left;
|
||||
int blendarea_right;
|
||||
int blendarea_top;
|
||||
int blendarea_bottom;
|
||||
|
||||
/* Parameter range check */
|
||||
|
||||
ret = chk_imgsize(dst);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = chk_imgsize(src);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = chk_imgsize(alpha);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Determine alpha blend options */
|
||||
|
||||
fixed_src = 0;
|
||||
fixed_alpha = 0;
|
||||
options = 0;
|
||||
|
||||
switch (alpha->type)
|
||||
{
|
||||
case IMAGEPROC_IMGTYPE_SINGLE:
|
||||
fixed_alpha = 0x0800 | (uint8_t)alpha->img.single;
|
||||
break;
|
||||
|
||||
case IMAGEPROC_IMGTYPE_BINARY:
|
||||
fixed_alpha = (uint8_t)alpha->img.binary.multiplier;
|
||||
options |= ALPHA1BPP;
|
||||
|
||||
break;
|
||||
|
||||
case IMAGEPROC_IMGTYPE_8BPP:
|
||||
|
||||
/* In this case, no option */
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (src->type)
|
||||
{
|
||||
case IMAGEPROC_IMGTYPE_SINGLE:
|
||||
options |= FIXEDSRC;
|
||||
fixed_src = src->img.single;
|
||||
break;
|
||||
|
||||
case IMAGEPROC_IMGTYPE_16BPP:
|
||||
|
||||
/* In this case, no option */
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (dst->type)
|
||||
{
|
||||
case IMAGEPROC_IMGTYPE_16BPP:
|
||||
|
||||
/* In this case, no option */
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Determine offset, width, height of rectangles from IN parameter */
|
||||
|
||||
get_rect_info(dst, &dst_offset, &dst_w, &dst_h);
|
||||
get_rect_info(src, &src_offset, &src_w, &src_h);
|
||||
get_rect_info(alpha, &a_offset, &a_w, &a_h);
|
||||
|
||||
/* Recalculate offset by calculating overlapped area. */
|
||||
|
||||
blendarea_left = - MIN(0, pos_x);
|
||||
blendarea_right = MIN(MIN(a_w, src_w), dst_w - pos_x);
|
||||
blendarea_top = - MIN(0, pos_y);
|
||||
blendarea_bottom = MIN(MIN(a_h, src_h), dst_h - pos_y);
|
||||
|
||||
if ((blendarea_right <= blendarea_left) ||
|
||||
(blendarea_bottom <= blendarea_top))
|
||||
{
|
||||
return 0; /* Not blend due to no overlapped area */
|
||||
}
|
||||
|
||||
dst_offset += ((blendarea_top + pos_y) * dst->w)
|
||||
+ (blendarea_left + pos_x);
|
||||
src_offset += (blendarea_top * src->w) + blendarea_left;
|
||||
a_offset += (blendarea_top * alpha->w) + blendarea_left;
|
||||
|
||||
dst_addr = get_blendarea(dst, dst_offset);
|
||||
src_addr = get_blendarea(src, src_offset);
|
||||
a_addr = get_blendarea(alpha, a_offset);
|
||||
|
||||
ret = ip_semtake(&g_abexc);
|
||||
if (ret)
|
||||
{
|
||||
return ret; /* -EINTR */
|
||||
}
|
||||
|
||||
/* Create descriptor to graphics engine */
|
||||
|
||||
cmd = set_ab_cmd(cmd,
|
||||
src_addr,
|
||||
dst_addr,
|
||||
blendarea_right - blendarea_left, /* width of blended area */
|
||||
blendarea_bottom - blendarea_top, /* height of blended area */
|
||||
src->w, /* pitch of src image */
|
||||
dst->w, /* pitch of dst image */
|
||||
a_addr,
|
||||
alpha->w, /* pitch of alpha plane */
|
||||
options,
|
||||
fixed_src,
|
||||
fixed_alpha);
|
||||
|
||||
if (cmd == NULL)
|
||||
{
|
||||
ip_semgive(&g_abexc);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Terminate command */
|
||||
|
||||
cmd = set_halt_cmd(cmd);
|
||||
|
||||
/* Process alpha blending */
|
||||
|
||||
len = (uintptr_t)cmd - (uintptr_t)g_gcmdbuf;
|
||||
ret = write(g_gfd, g_gcmdbuf, len);
|
||||
if (ret < 0)
|
||||
{
|
||||
ip_semgive(&g_abexc);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
ip_semgive(&g_abexc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -46,6 +46,10 @@ extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/* Structure of rectangle coordinates from left top point to
|
||||
* right bottom point.
|
||||
*/
|
||||
@ -59,6 +63,43 @@ extern "C"
|
||||
};
|
||||
typedef struct imageproc_rect_s imageproc_rect_t;
|
||||
|
||||
/* Enumeration of image type */
|
||||
|
||||
enum imageproc_imginfo_e
|
||||
{
|
||||
IMAGEPROC_IMGTYPE_SINGLE = 0, /* All pixels have the same value */
|
||||
IMAGEPROC_IMGTYPE_BINARY = 1, /* Each pixels have 0 or specific non-zero value */
|
||||
IMAGEPROC_IMGTYPE_8BPP = 2, /* Each pixels have 8bit value */
|
||||
IMAGEPROC_IMGTYPE_16BPP = 3, /* Each pixels have 16bit value */
|
||||
};
|
||||
|
||||
/* Structure of binary image */
|
||||
|
||||
struct imageproc_binary_img_s
|
||||
{
|
||||
uint8_t *p_u8; /* 1bpp image */
|
||||
int multiplier; /* specific non-zero value */
|
||||
};
|
||||
typedef struct imageproc_binary_img_s imageproc_binary_img_t;
|
||||
|
||||
/* Structure of image information. */
|
||||
|
||||
struct imageproc_imginfo_s
|
||||
{
|
||||
enum imageproc_imginfo_e type; /* Type of image data */
|
||||
int w; /* width of total image */
|
||||
int h; /* height of total image */
|
||||
imageproc_rect_t *rect; /* clipped rectangle */
|
||||
union
|
||||
{
|
||||
int single; /* type = IMAGEPROC_IMGTYPE_SINGLE */
|
||||
imageproc_binary_img_t binary; /* type = IMAGEPROC_IMGTYPE_BINARY */
|
||||
uint8_t *p_u8; /* type = IMAGEPROC_IMGTYPE_8BPP */
|
||||
uint16_t *p_u16; /* type = IMAGEPROC_IMGTYPE_16BPP */
|
||||
} img;
|
||||
};
|
||||
typedef struct imageproc_imginfo_s imageproc_imginfo_t;
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions Prototypes
|
||||
****************************************************************************/
|
||||
@ -162,6 +203,34 @@ extern "C"
|
||||
uint16_t ohsize, uint16_t ovsize, int bpp,
|
||||
imageproc_rect_t * clip_rect);
|
||||
|
||||
/* Execute alpha blending
|
||||
*
|
||||
* Execute alpha blending.
|
||||
* dst buffer is overwritten by blended image.
|
||||
*
|
||||
* [in,out] dst: Destination image.
|
||||
* dst->type = IMAGEPROC_IMGTYPE_16BPP.
|
||||
* [in] pos_x: x-coordinate of blended position.
|
||||
* Minus value means
|
||||
* the left of the destination image origin.
|
||||
* [in] pos_y: y-coordinate of blended position.
|
||||
* Minus value means
|
||||
* the upper of the destination image origin.
|
||||
* [in] src: Source image.
|
||||
* src->type = IMAGEPROC_IMGTYPE_16BPP or
|
||||
* IMAGEPROC_IMGTYPE_SINGLE.
|
||||
* [in] alpha: Alpha plane.
|
||||
* alpha->type = IMAGEPROC_IMGTYPE_SINGLE,
|
||||
* IMAGEPROC_IMGTYPE_BINARY,
|
||||
* or IMAGEPROC_IMGTYPE_8BPP.
|
||||
*
|
||||
* return 0 on success, otherwise error code.
|
||||
*/
|
||||
|
||||
int imageproc_alpha_blend(imageproc_imginfo_t *dst, int pos_x, int pos_y,
|
||||
imageproc_imginfo_t *src,
|
||||
imageproc_imginfo_t *alpha);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user