Merge pull request #223 from kwagyeman/master

Improved subscr and get_buffer
This commit is contained in:
Ibrahim Abd Elkader 2017-04-30 02:05:34 +02:00 committed by GitHub
commit 6535b4fcdb
2 changed files with 213 additions and 52 deletions

View File

@ -351,7 +351,7 @@ void image_copy(image_t *dst, image_t *src);
((uint16_t *) _image->data)[(_image->w * _y) + _x]; \ ((uint16_t *) _image->data)[(_image->w * _y) + _x]; \
}) })
#define IMAGE_PUT_RGB565_PIXEL(image, x, y) \ #define IMAGE_PUT_RGB565_PIXEL(image, x, y, v) \
({ \ ({ \
__typeof__ (image) _image = (image); \ __typeof__ (image) _image = (image); \
__typeof__ (x) _x = (x); \ __typeof__ (x) _x = (x); \

View File

@ -141,72 +141,233 @@ static void py_image_print(const mp_print_t *print, mp_obj_t self_in, mp_print_k
static mp_obj_t py_image_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) static mp_obj_t py_image_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value)
{ {
py_image_obj_t *o = self_in; py_image_obj_t *self = self_in;
image_t *arg_img = py_image_cobj(self_in); if (value == MP_OBJ_NULL) { // delete
if (value == MP_OBJ_NULL) { } else if (value == MP_OBJ_SENTINEL) { // load
// delete switch (self->_cobj.bpp) {
// not supported case IMAGE_BPP_BINARY: {
return MP_OBJ_NULL; if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
} else if (value == MP_OBJ_SENTINEL) { mp_bound_slice_t slice;
// load if (!mp_seq_get_fast_slice_indexes(self->_cobj.w * self->_cobj.h, index, &slice)) {
if (IM_IS_GS(arg_img)) { mp_not_implemented("only slices with step=1 (aka None) are supported");
int i = mp_get_index(o->base.type, arg_img->w*arg_img->h, index, false); }
int x = (i % arg_img->w); mp_obj_tuple_t *result = mp_obj_new_tuple(slice.stop - slice.start, NULL);
int y = (i / arg_img->w); for (mp_uint_t i = 0; i < result->len; i++) {
return mp_obj_new_int(IM_GET_GS_PIXEL(arg_img, x, y)); result->items[i] = mp_obj_new_int(IMAGE_GET_BINARY_PIXEL(&(self->_cobj), (slice.start + i) % self->_cobj.w, (slice.start + i) / self->_cobj.w));
} else if (IM_IS_RGB565(arg_img)) { }
int i = mp_get_index(o->base.type, arg_img->w*arg_img->h, index, false); return result;
int x = (i % arg_img->w); }
int y = (i / arg_img->w); mp_uint_t i = mp_get_index(self->base.type, self->_cobj.w * self->_cobj.h, index, false);
return mp_obj_new_int(IM_GET_RGB565_PIXEL(arg_img, x, y)); return mp_obj_new_int(IMAGE_GET_BINARY_PIXEL(&(self->_cobj), i % self->_cobj.w, i / self->_cobj.w));
} else { }
int i = mp_get_index(o->base.type, arg_img->bpp, index, false); case 3: // BAYER
return mp_obj_new_int(arg_img->pixels[i]); // JPEG case IMAGE_BPP_GRAYSCALE: {
if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
mp_bound_slice_t slice;
if (!mp_seq_get_fast_slice_indexes(self->_cobj.w * self->_cobj.h, index, &slice)) {
mp_not_implemented("only slices with step=1 (aka None) are supported");
}
mp_obj_tuple_t *result = mp_obj_new_tuple(slice.stop - slice.start, NULL);
for (mp_uint_t i = 0; i < result->len; i++) {
uint8_t p = IMAGE_GET_GRAYSCALE_PIXEL(&(self->_cobj), (slice.start + i) % self->_cobj.w, (slice.start + i) / self->_cobj.w);
result->items[i] = mp_obj_new_int(p);
}
return result;
}
mp_uint_t i = mp_get_index(self->base.type, self->_cobj.w * self->_cobj.h, index, false);
uint8_t p = IMAGE_GET_GRAYSCALE_PIXEL(&(self->_cobj), i % self->_cobj.w, i / self->_cobj.w);
return mp_obj_new_int(p);
}
case IMAGE_BPP_RGB565: {
if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
mp_bound_slice_t slice;
if (!mp_seq_get_fast_slice_indexes(self->_cobj.w * self->_cobj.h, index, &slice)) {
mp_not_implemented("only slices with step=1 (aka None) are supported");
}
mp_obj_tuple_t *result = mp_obj_new_tuple(slice.stop - slice.start, NULL);
for (mp_uint_t i = 0; i < result->len; i++) {
uint16_t p = IMAGE_GET_RGB565_PIXEL(&(self->_cobj), (slice.start + i) % self->_cobj.w, (slice.start + i) / self->_cobj.w);
result->items[i] = mp_obj_new_tuple(3, (mp_obj_t []) {mp_obj_new_int(COLOR_RGB565_TO_R8(p)),
mp_obj_new_int(COLOR_RGB565_TO_G8(p)),
mp_obj_new_int(COLOR_RGB565_TO_B8(p))});
}
return result;
}
mp_uint_t i = mp_get_index(self->base.type, self->_cobj.w * self->_cobj.h, index, false);
uint16_t p = IMAGE_GET_RGB565_PIXEL(&(self->_cobj), i % self->_cobj.w, i / self->_cobj.w);
return mp_obj_new_tuple(3, (mp_obj_t []) {mp_obj_new_int(COLOR_RGB565_TO_R8(p)),
mp_obj_new_int(COLOR_RGB565_TO_G8(p)),
mp_obj_new_int(COLOR_RGB565_TO_B8(p))});
}
default: {
if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
mp_bound_slice_t slice;
if (!mp_seq_get_fast_slice_indexes(self->_cobj.bpp, index, &slice)) {
mp_not_implemented("only slices with step=1 (aka None) are supported");
}
mp_obj_tuple_t *result = mp_obj_new_tuple(slice.stop - slice.start, NULL);
for (mp_uint_t i = 0; i < result->len; i++) {
result->items[i] = mp_obj_new_int(self->_cobj.data[slice.start + i]);
}
return result;
}
mp_uint_t i = mp_get_index(self->base.type, self->_cobj.bpp, index, false);
return mp_obj_new_int(self->_cobj.data[i]);
}
}
} else { // store
switch (self->_cobj.bpp) {
case IMAGE_BPP_BINARY: {
if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
mp_bound_slice_t slice;
if (!mp_seq_get_fast_slice_indexes(self->_cobj.w * self->_cobj.h, index, &slice)) {
mp_not_implemented("only slices with step=1 (aka None) are supported");
}
if (MP_OBJ_IS_TYPE(value, &mp_type_list)) {
mp_uint_t value_l_len;
mp_obj_t *value_l;
mp_obj_get_array(value, &value_l_len, &value_l);
PY_ASSERT_TRUE_MSG(value_l_len == (slice.stop - slice.start), "cannot grow or shrink image");
for (mp_uint_t i = 0; i < (slice.stop - slice.start); i++) {
IMAGE_PUT_BINARY_PIXEL(&(self->_cobj), (slice.start + i) % self->_cobj.w, (slice.start + i) / self->_cobj.w, mp_obj_get_int(value_l[i]));
} }
} else { } else {
// store mp_int_t v = mp_obj_get_int(value);
if (IM_IS_GS(arg_img)) { for (mp_uint_t i = 0; i < (slice.stop - slice.start); i++) {
int i = mp_get_index(o->base.type, arg_img->w*arg_img->h, index, false); IMAGE_PUT_BINARY_PIXEL(&(self->_cobj), (slice.start + i) % self->_cobj.w, (slice.start + i) / self->_cobj.w, v);
int x = (i % arg_img->w);
int y = (i / arg_img->w);
IM_SET_GS_PIXEL(arg_img, x, y, mp_obj_get_int(value));
} else if (IM_IS_RGB565(arg_img)) {
int i = mp_get_index(o->base.type, arg_img->w*arg_img->h, index, false);
int x = (i % arg_img->w);
int y = (i / arg_img->w);
IM_SET_RGB565_PIXEL(arg_img, x, y, mp_obj_get_int(value));
} else {
int i = mp_get_index(o->base.type, arg_img->bpp, index, false);
arg_img->pixels[i] = mp_obj_get_int(value); // JPEG
} }
} }
return mp_const_none; return mp_const_none;
}
mp_uint_t i = mp_get_index(self->base.type, self->_cobj.w * self->_cobj.h, index, false);
IMAGE_PUT_BINARY_PIXEL(&(self->_cobj), i % self->_cobj.w, i / self->_cobj.w, mp_obj_get_int(value));
return mp_const_none;
}
case 3: // BAYER
case IMAGE_BPP_GRAYSCALE: {
if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
mp_bound_slice_t slice;
if (!mp_seq_get_fast_slice_indexes(self->_cobj.w * self->_cobj.h, index, &slice)) {
mp_not_implemented("only slices with step=1 (aka None) are supported");
}
if (MP_OBJ_IS_TYPE(value, &mp_type_list)) {
mp_uint_t value_l_len;
mp_obj_t *value_l;
mp_obj_get_array(value, &value_l_len, &value_l);
PY_ASSERT_TRUE_MSG(value_l_len == (slice.stop - slice.start), "cannot grow or shrink image");
for (mp_uint_t i = 0; i < (slice.stop - slice.start); i++) {
uint8_t p = mp_obj_get_int(value_l[i]);
IMAGE_PUT_GRAYSCALE_PIXEL(&(self->_cobj), (slice.start + i) % self->_cobj.w, (slice.start + i) / self->_cobj.w, p);
}
} else {
uint8_t p = mp_obj_get_int(value);
for (mp_uint_t i = 0; i < (slice.stop - slice.start); i++) {
IMAGE_PUT_GRAYSCALE_PIXEL(&(self->_cobj), (slice.start + i) % self->_cobj.w, (slice.start + i) / self->_cobj.w, p);
}
}
return mp_const_none;
}
mp_uint_t i = mp_get_index(self->base.type, self->_cobj.w * self->_cobj.h, index, false);
uint8_t p = mp_obj_get_int(value);
IMAGE_PUT_GRAYSCALE_PIXEL(&(self->_cobj), i % self->_cobj.w, i / self->_cobj.w, p);
return mp_const_none;
}
case IMAGE_BPP_RGB565: {
if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
mp_bound_slice_t slice;
if (!mp_seq_get_fast_slice_indexes(self->_cobj.w * self->_cobj.h, index, &slice)) {
mp_not_implemented("only slices with step=1 (aka None) are supported");
}
if (MP_OBJ_IS_TYPE(value, &mp_type_list)) {
mp_uint_t value_l_len;
mp_obj_t *value_l;
mp_obj_get_array(value, &value_l_len, &value_l);
PY_ASSERT_TRUE_MSG(value_l_len == (slice.stop - slice.start), "cannot grow or shrink image");
for (mp_uint_t i = 0; i < (slice.stop - slice.start); i++) {
mp_obj_t *value_2;
mp_obj_get_array_fixed_n(value_l[i], 3, &value_2);
uint16_t p = COLOR_R8_G8_B8_TO_RGB565(mp_obj_get_int(value_2[0]), mp_obj_get_int(value_2[1]), mp_obj_get_int(value_2[2]));
IMAGE_PUT_RGB565_PIXEL(&(self->_cobj), (slice.start + i) % self->_cobj.w, (slice.start + i) / self->_cobj.w, p);
}
} else {
mp_obj_t *value_2;
mp_obj_get_array_fixed_n(value, 3, &value_2);
uint16_t p = COLOR_R8_G8_B8_TO_RGB565(mp_obj_get_int(value_2[0]), mp_obj_get_int(value_2[1]), mp_obj_get_int(value_2[2]));
for (mp_uint_t i = 0; i < (slice.stop - slice.start); i++) {
IMAGE_PUT_RGB565_PIXEL(&(self->_cobj), (slice.start + i) % self->_cobj.w, (slice.start + i) / self->_cobj.w, p);
}
}
return mp_const_none;
}
mp_uint_t i = mp_get_index(self->base.type, self->_cobj.w * self->_cobj.h, index, false);
mp_obj_t *value_2;
mp_obj_get_array_fixed_n(value, 3, &value_2);
uint16_t p = COLOR_R8_G8_B8_TO_RGB565(mp_obj_get_int(value_2[0]), mp_obj_get_int(value_2[1]), mp_obj_get_int(value_2[2]));
IMAGE_PUT_RGB565_PIXEL(&(self->_cobj), i % self->_cobj.w, i / self->_cobj.w, p);
return mp_const_none;
}
default: {
if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
mp_bound_slice_t slice;
if (!mp_seq_get_fast_slice_indexes(self->_cobj.bpp, index, &slice)) {
mp_not_implemented("only slices with step=1 (aka None) are supported");
}
if (MP_OBJ_IS_TYPE(value, &mp_type_list)) {
mp_uint_t value_l_len;
mp_obj_t *value_l;
mp_obj_get_array(value, &value_l_len, &value_l);
PY_ASSERT_TRUE_MSG(value_l_len == (slice.stop - slice.start), "cannot grow or shrink image");
for (mp_uint_t i = 0; i < (slice.stop - slice.start); i++) {
self->_cobj.data[slice.start + i] = mp_obj_get_int(value_l[i]);
}
} else {
mp_int_t v = mp_obj_get_int(value);
for (mp_uint_t i = 0; i < (slice.stop - slice.start); i++) {
self->_cobj.data[slice.start + i] = v;
}
}
return mp_const_none;
}
mp_uint_t i = mp_get_index(self->base.type, self->_cobj.bpp, index, false);
self->_cobj.data[i] = mp_obj_get_int(value);
return mp_const_none;
}
}
}
return MP_OBJ_NULL; // op not supported
} }
static mp_int_t py_image_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) static mp_int_t py_image_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags)
{ {
image_t *arg_img = py_image_cobj(self_in); py_image_obj_t *self = self_in;
if (flags == MP_BUFFER_READ) { if (flags == MP_BUFFER_READ) {
bufinfo->buf = arg_img->pixels; bufinfo->buf = self->_cobj.data;
switch (arg_img->bpp) { switch (self->_cobj.bpp) {
case 1: // GS case IMAGE_BPP_BINARY: {
case 2: // RGB/YUV bufinfo->len = ((self->_cobj.w + UINT32_T_MASK) >> UINT32_T_SHIFT) * self->_cobj.h;
// 1 or 2 BPP
bufinfo->len = arg_img->w * arg_img->h * arg_img->bpp;
break; break;
case 3: // BAYER }
// It's actually 1BPP case IMAGE_BPP_GRAYSCALE: {
bufinfo->len = arg_img->w * arg_img->h * 1; bufinfo->len = (self->_cobj.w * self->_cobj.h) * sizeof(uint8_t);
break; break;
default: // JPEG }
// Size is set in bpp case IMAGE_BPP_RGB565: {
bufinfo->len = arg_img->bpp; bufinfo->len = (self->_cobj.w * self->_cobj.h) * sizeof(uint16_t);
break; break;
} }
case 3: { // BAYER
bufinfo->len = self->_cobj.w * self->_cobj.h;
break;
}
default: { // JPEG
bufinfo->len = self->_cobj.bpp;
break;
}
}
bufinfo->typecode = 'b'; bufinfo->typecode = 'b';
return 0; return 0;
} else { } else {
// not supported // can't write to an image
bufinfo->buf = NULL; bufinfo->buf = NULL;
bufinfo->len = 0; bufinfo->len = 0;
bufinfo->typecode = -1; bufinfo->typecode = -1;