Add scale, blit and blend functions

* Add scale, blit, blend and rainbow
* Update imlib header
* Export new functions to MP
This commit is contained in:
iabdalkader 2014-08-18 12:36:47 +02:00
parent d151388e73
commit f1861a332a
5 changed files with 295 additions and 38 deletions

@ -1 +1 @@
Subproject commit 6f78a8b2b3a96f1faa0261f7b044992aa65a39bb
Subproject commit 44c005220f8d01e008f4c5c606c70e5868c19635

View File

@ -27,6 +27,22 @@
__typeof__ (y) _y = (y); \
src->data[_y*src->w+_x]=c; })
#define R565(p) \
(uint8_t)((p>>3)&0x1F)
#define G565(p) \
(uint8_t)(((p&0x07)<<3)|(p>>13))
#define B565(p) \
(uint8_t)((p>>8)&0x1F)
#define RGB565(r, g, b)\
(uint16_t)(((r&0x1F)<<3)|((g&0x3F)>>3)|(g<<13)|((b&0x1F)<<8))
#define SWAP(x)\
({ uint16_t _x = (x); \
(((_x & 0xff)<<8 |(_x & 0xff00) >> 8));})
#define MAX_GRAY_LEVEL (255)
/* RGB565->LAB lookup */
@ -214,10 +230,6 @@ void imlib_erosion_filter(struct image *src, uint8_t *kernel, int k_size)
xfree(dst);
}
#define SWAP(x)\
({ uint16_t _x = (x); \
(((_x & 0xff)<<8 |(_x & 0xff00) >> 8));})
void imlib_threshold(image_t *src, image_t *dst, struct color *color, int threshold)
{
color_t lab1,lab2;
@ -288,46 +300,191 @@ void imlib_subimage(struct image *src_img, struct image *dst_img, int x_off, int
}
}
void imlib_blit(struct image *dst_img, struct image *src_img, int x_off, int y_off)
void imlib_blit(struct image *src, struct image *dst, int x_off, int y_off)
{
int x, y;
typeof(*src_img->data) *src = src_img->data;
typeof(*dst_img->data) *dst = dst_img->data;
typeof(*src->data) *srcp = src->data;
typeof(*dst->data) *dstp = dst->data;
for (y=y_off; y<src_img->h+y_off; y++) {
for (x=x_off; x<src_img->w+x_off; x++) {
dst[y*dst_img->w+x]=*src++;
for (y=y_off; y<src->h+y_off; y++) {
for (x=x_off; x<src->w+x_off; x++) {
dstp[y*dst->w+x]=*srcp++;
}
}
}
void imlib_scale_image(struct image *src, struct image *dst)
void imlib_blend(struct image *src, struct image *dst, int x_off, int y_off, uint8_t alpha)
{
uint16_t i,r, g, b;
uint16_t spix, dpix;
uint16_t *srcp = (uint16_t *)src->pixels;
uint16_t *dstp = (uint16_t *)dst->pixels;
for (int y=y_off; y<src->h+y_off; y++) {
i=y*dst->w;
for (int x=x_off; x<src->w+x_off; x++) {
spix = *srcp++;
dpix = dstp[i+x];
r=(alpha*R565(spix)+(100-alpha)*R565(dpix))/100;
g=(alpha*G565(spix)+(100-alpha)*G565(dpix))/100;
b=(alpha*B565(spix)+(100-alpha)*B565(dpix))/100;
dstp[i+x]= RGB565(r, g, b);
}
}
}
void imlib_scale_nearest(struct image *src, struct image *dst)
{
int x, y, i, j;
uint8_t *t, *p;
int w1 = src->w;
int h1 = src->h;
int w2 = dst->w;
int h2 = dst->h;
int rat = 0;
if (src->bpp ==1) {
uint8_t *t, *p;
uint8_t *src_data = src->pixels;
uint8_t *dst_data = dst->pixels;
int x_ratio = (int)((w1<<16)/w2) +1;
int y_ratio = (int)((h1<<16)/h2) +1;
uint8_t *src_data = src->pixels;
uint8_t *dst_data = dst->pixels;
int x_ratio = (int)((w1<<16)/w2) +1;
int y_ratio = (int)((h1<<16)/h2) +1;
for (i=0;i<h2;i++){
t = dst_data + i*w2;
y = ((i*y_ratio)>>16);
p = src_data + y*w1;
rat = 0;
for (j=0;j<w2;j++) {
x = (rat>>16);
*t++ = p[x];
rat += x_ratio;
for (i=0; i<h2; i++) {
t = dst_data + i*w2;
y = ((i*y_ratio)>>16);
p = src_data + y*w1;
rat = 0;
for (j=0; j<w2; j++) {
x = (rat>>16);
*t++ = p[x];
rat += x_ratio;
}
}
} else if (src->bpp==2) {
uint16_t *t, *p;
uint16_t *src_data = (uint16_t *)src->pixels;
uint16_t *dst_data = (uint16_t *)dst->pixels;
int x_ratio = (int)((w1<<16)/w2) +1;
int y_ratio = (int)((h1<<16)/h2) +1;
for (i=0; i<h2; i++) {
t = dst_data + i*w2;
y = ((i*y_ratio)>>16);
p = src_data + y*w1;
rat = 0;
for (j=0; j<w2; j++) {
x = (rat>>16);
*t++ = p[x];
rat += x_ratio;
}
}
}
}
void imlib_scale_bilinear(struct image *src, struct image *dst)
{
int w1 = src->w;
int h1 = src->h;
int w2 = dst->w;
int h2 = dst->h;
int offset = 0 ;
int x, y, index;
int r, g, b;
uint16_t A, B, C, D;
float x_diff, y_diff;
float x_ratio = ((float)(w1-1))/w2 ;
float y_ratio = ((float)(h1-1))/h2 ;
uint16_t *srcp = (uint16_t *)src->pixels;
uint16_t *dstp = (uint16_t *)dst->pixels;
for (int i=0;i<h2;i++) {
for (int j=0;j<w2;j++) {
x = (int)(x_ratio * j) ;
y = (int)(y_ratio * i) ;
x_diff = (x_ratio * j) - x ;
y_diff = (y_ratio * i) - y ;
index = y*w1+x ;
A = srcp[index];
B = srcp[index+1];
C = srcp[index+w1];
D = srcp[index+w1+1];
// Yb = Ar(1-w)(1-h) + Br(w)(1-h) + Cr(h)(1-w) + Dr(wh)
r = (int)(R565(A)*(1-x_diff)*(1-y_diff) + R565(B)*(x_diff)*(1-y_diff) +
R565(C)*(y_diff)*(1-x_diff) + R565(D)*(x_diff*y_diff));
// Yb = Ag(1-w)(1-h) + Bg(w)(1-h) + Cg(h)(1-w) + Dg(wh)
g = (int)(G565(A)*(1-x_diff)*(1-y_diff) + G565(B)*(x_diff)*(1-y_diff) +
G565(C)*(y_diff)*(1-x_diff) + G565(D)*(x_diff*y_diff));
// Yb = Ab(1-w)(1-h) + Bb(w)(1-h) + Cb(h)(1-w) + Db(wh)
b =(int)(B565(A)*(1-x_diff)*(1-y_diff) + B565(B)*(x_diff)*(1-y_diff) +
B565(C)*(y_diff)*(1-x_diff) + B565(D)*(x_diff*y_diff));
dstp[offset++] = RGB565(r, g, b);
}
}
}
void imlib_scale_bilinear_gray(struct image *src, struct image *dst)
{
int w1 = src->w;
int h1 = src->h;
int w2 = dst->w;
int h2 = dst->h;
int offset = 0 ;
int A, B, C, D, x, y, index, gray ;
float x_diff, y_diff;
float x_ratio = ((float)(w1-1))/w2 ;
float y_ratio = ((float)(h1-1))/h2 ;
uint8_t *srcp = src->pixels;
uint8_t *dstp = dst->pixels;
for (int i=0;i<h2;i++) {
for (int j=0;j<w2;j++) {
x = (int)(x_ratio * j) ;
y = (int)(y_ratio * i) ;
x_diff = (x_ratio * j) - x ;
y_diff = (y_ratio * i) - y ;
index = y*w1+x;
A = srcp[index];
B = srcp[index+1];
C = srcp[index+w1];
D = srcp[index+w1+1];
// Y = A(1-w)(1-h) + B(w)(1-h) + C(h)(1-w) + Dwh
gray = (int)(A*(1-x_diff)*(1-y_diff) + B*(x_diff)*(1-y_diff) +
C*(y_diff)*(1-x_diff) + D*(x_diff*y_diff));
dstp[offset++] = gray ;
}
}
}
void imlib_scale(struct image *src, struct image *dst, interp_t interp)
{
switch (interp) {
case INTERP_NEAREST:
imlib_scale_nearest(src, dst);
break;
case INTERP_BILINEAR:
if (src->bpp==2) {
imlib_scale_bilinear(src, dst);
} else {
imlib_scale_bilinear_gray(src, dst);
}
break;
case INTERP_BICUBIC:
//NOT implemented
break;
}
}

View File

@ -153,6 +153,12 @@ typedef struct cascade {
int8_t *rectangles_array;
} cascade_t;
typedef enum interp {
INTERP_NEAREST,
INTERP_BILINEAR,
INTERP_BICUBIC
} interp_t;
/* Point functions */
point_t *point_alloc(int x, int y);
int point_equal(point_t *p1, point_t *p2);
@ -179,6 +185,7 @@ void imlib_rgb_to_lab(struct color *rgb, struct color *lab);
void imlib_rgb_to_hsv(struct color *rgb, struct color *hsv);
/* Image filtering functions */
int imlib_image_mean(struct image *src);
void imlib_histeq(struct image *src);
void imlib_median_filter(image_t *src, int r);
void imlib_erosion_filter(struct image *src, uint8_t *kernel, int k_size);
@ -204,12 +211,15 @@ array_t *surf_match(surf_t *surf1, surf_t *surf2);
void surf_draw_ipts(image_t *image, array_t *ipts);
void surf_dump_ipts(array_t *ipts);
void imlib_scale_image(struct image *src, struct image *dst);
/* Drawing functions */
void imlib_draw_rectangle(struct image *image, struct rectangle *r);
void imlib_draw_circle(struct image *image, int cx, int cy, int r);
int imlib_image_mean(struct image *src);
void imlib_subimage(struct image *src_img, struct image *dst_img, int x_off, int y_off);
void imlib_blit(struct image *dst_img, struct image *src_img, int x_off, int y_off);
/* Misc */
void imlib_scale(struct image *src, struct image *dst, interp_t interp);
void imlib_blit(struct image *src, struct image *dst, int x_off, int y_off);
void imlib_blend(struct image *src, struct image *dst, int x_off, int y_off, uint8_t alpha);
void imlib_subimage(struct image *src, struct image *dst, int x_off, int y_off);
/* Image file functions */
int ppm_read(image_t *img, const char *path);

View File

@ -2,6 +2,7 @@
#include "imlib.h"
#include "array.h"
#include "sensor.h"
#include "xalloc.h"
#include "py_assert.h"
#include "py_image.h"
#include "py_file.h"
@ -139,16 +140,39 @@ static mp_obj_t py_image_save(uint n_args, const mp_obj_t *args, mp_map_t *kw_ar
return mp_const_true;
}
static mp_obj_t py_image_blit(mp_obj_t dst_image_obj, mp_obj_t offset_obj, mp_obj_t src_image_obj)
static mp_obj_t py_image_scale(mp_obj_t image_obj, mp_obj_t size_obj)
{
int w,h;
mp_obj_t *array;
image_t *src_image = NULL;
/* get C image pointer */
src_image = py_image_cobj(image_obj);
/* get x,y */
mp_obj_get_array_fixed_n(size_obj, 2, &array);
w = mp_obj_get_int(array[0]);
h = mp_obj_get_int(array[1]);
image_t dst_image = {
.w=w,
.h=h,
.bpp=src_image->bpp,
.pixels=xalloc(w*h*src_image->bpp)
};
imlib_scale(src_image, &dst_image, INTERP_BILINEAR);
*src_image = dst_image;
return image_obj;
}
static mp_obj_t py_image_blit(mp_obj_t dst_image_obj, mp_obj_t src_image_obj, mp_obj_t offset_obj)
{
int x,y;
image_t *src_image = NULL;
image_t *dst_image = NULL;
/* sanity checks */
PY_ASSERT_TRUE(sensor.framesize <= FRAMESIZE_QQVGA);
PY_ASSERT_TRUE(sensor.pixformat == PIXFORMAT_GRAYSCALE);
/* get C image pointer */
src_image = py_image_cobj(src_image_obj);
dst_image = py_image_cobj(dst_image_obj);
@ -165,7 +189,36 @@ static mp_obj_t py_image_blit(mp_obj_t dst_image_obj, mp_obj_t offset_obj, mp_ob
return mp_const_none;
}
imlib_blit(dst_image, src_image, x, y);
imlib_blit(src_image, dst_image, x, y);
return mp_const_true;
}
static mp_obj_t py_image_blend(mp_obj_t dst_image_obj,
mp_obj_t src_image_obj, mp_obj_t param_obj)
{
int x,y;
float alpha;
image_t *src_image = NULL;
image_t *dst_image = NULL;
/* get C image pointer */
src_image = py_image_cobj(src_image_obj);
dst_image = py_image_cobj(dst_image_obj);
/* get x,y,alpha */
mp_obj_t *array;
mp_obj_get_array_fixed_n(param_obj, 3, &array);
x = mp_obj_get_int(array[0]);
y = mp_obj_get_int(array[1]);
alpha = mp_obj_get_float(array[2]);
if ((src_image->w+x)>dst_image->w ||
(src_image->h+y)>dst_image->h) {
printf("src image > dst image\n");
return mp_const_none;
}
imlib_blend(src_image, dst_image, x, y, (uint8_t)(alpha*100.0f));
return mp_const_true;
}
@ -226,6 +279,27 @@ static mp_obj_t py_image_threshold(mp_obj_t image_obj, mp_obj_t color_obj, mp_ob
return bimage_obj;
}
static mp_obj_t py_image_rainbow(mp_obj_t src_image_obj)
{
image_t *src_image = NULL;
/* get C image pointer */
src_image = py_image_cobj(src_image_obj);
/* sanity checks */
PY_ASSERT_TRUE(src_image->bpp==1);
image_t dst_image = {
.w=src_image->w,
.h=src_image->h,
.bpp=2,
.pixels=xalloc(src_image->w*src_image->h*2)
};
imlib_rainbow(src_image, &dst_image);
*src_image = dst_image;
return src_image_obj;
}
static mp_obj_t py_image_draw_circle(mp_obj_t image_obj, mp_obj_t c_obj, mp_obj_t r_obj)
{
int cx, cy, r;
@ -498,10 +572,13 @@ mp_obj_t py_image_load_cascade(mp_obj_t path_obj)
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_size_obj, py_image_size);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_save_obj, 2, py_image_save);
STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_scale_obj, py_image_scale);
STATIC MP_DEFINE_CONST_FUN_OBJ_3(py_image_blit_obj, py_image_blit);
STATIC MP_DEFINE_CONST_FUN_OBJ_3(py_image_blend_obj, py_image_blend);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_histeq_obj, py_image_histeq);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_median_obj, 1, py_image_median);
STATIC MP_DEFINE_CONST_FUN_OBJ_3(py_image_threshold_obj, py_image_threshold);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_image_rainbow_obj, py_image_rainbow);
STATIC MP_DEFINE_CONST_FUN_OBJ_3(py_image_draw_circle_obj, py_image_draw_circle);
STATIC MP_DEFINE_CONST_FUN_OBJ_2(py_image_draw_rectangle_obj, py_image_draw_rectangle);
@ -518,10 +595,13 @@ static const mp_map_elem_t locals_dict_table[] = {
/* basic image functions */
{MP_OBJ_NEW_QSTR(MP_QSTR_save), (mp_obj_t)&py_image_save_obj},
{MP_OBJ_NEW_QSTR(MP_QSTR_scale), (mp_obj_t)&py_image_scale_obj},
{MP_OBJ_NEW_QSTR(MP_QSTR_blit), (mp_obj_t)&py_image_blit_obj},
{MP_OBJ_NEW_QSTR(MP_QSTR_blend), (mp_obj_t)&py_image_blend_obj},
{MP_OBJ_NEW_QSTR(MP_QSTR_histeq), (mp_obj_t)&py_image_histeq_obj},
{MP_OBJ_NEW_QSTR(MP_QSTR_median), (mp_obj_t)&py_image_median_obj},
{MP_OBJ_NEW_QSTR(MP_QSTR_threshold), (mp_obj_t)&py_image_threshold_obj},
{MP_OBJ_NEW_QSTR(MP_QSTR_rainbow), (mp_obj_t)&py_image_rainbow_obj},
/* drawing functions */
{MP_OBJ_NEW_QSTR(MP_QSTR_draw_circle), (mp_obj_t)&py_image_draw_circle_obj},
@ -560,6 +640,14 @@ mp_obj_t py_image(int w, int h, int bpp, void *pixels)
return o;
}
mp_obj_t py_image_from_struct(image_t *image)
{
py_image_obj_t *o = m_new_obj(py_image_obj_t);
o->base.type = &py_image_type;
o->_cobj =*image;
return o;
}
#if 0
typedef struct _mp_obj_array_it_t {
mp_obj_base_t base;

View File

@ -1,8 +1,10 @@
#ifndef __PY_IMAGE_H__
#define __PY_IMAGE_H__
#include "imlib.h"
mp_obj_t py_image_load_image(mp_obj_t path_obj);
mp_obj_t py_image_load_cascade(mp_obj_t path_obj);
mp_obj_t py_image(int width, int height, int bpp, void *pixels);
mp_obj_t py_image_from_struct(image_t *image);
void *py_image_cobj(mp_obj_t image);
#endif /* __PY_IMAGE_H__ */