Skip to content

Commit

Permalink
Merge pull request #170 from kwagyeman/fix_compress
Browse files Browse the repository at this point in the history
Fix compress and compressed.
  • Loading branch information
iabdalkader committed Jan 12, 2017
2 parents 819e95d + 9efd747 commit e82e3ab
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 43 deletions.
79 changes: 36 additions & 43 deletions src/omv/py/py_image.c
Expand Up @@ -225,72 +225,65 @@ static mp_obj_t py_image_save(uint n_args, const mp_obj_t *args, mp_map_t *kw_ar
return mp_const_none;
}

// TODO fix FB_JPEG_OFFS_SIZE
static mp_obj_t py_image_compress(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
{
image_t *arg_img = py_image_cobj(args[0]);
PY_ASSERT_FALSE_MSG(IM_IS_JPEG(arg_img), "Operation not supported on JPEG");

int arg_q = py_helper_lookup_int(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_quality), 50);
arg_q = IM_MIN(IM_MAX(arg_q, 1), 100);
PY_ASSERT_TRUE_MSG((1 <= arg_q) && (arg_q <= 100), " 1 <= quality <= 100");

// Check if this image is the one in the frame buffer...
if (fb->pixels == arg_img->pixels) {
// We do not allow shallow copies so this is okay...
image_t src = {.w=fb->w, .h=fb->h, .bpp=fb->bpp, .pixels=fb->pixels};
image_t dst = {.w=fb->w, .h=fb->h, .bpp=128*1024, .pixels=fb->pixels+FB_JPEG_OFFS_SIZE};
jpeg_compress(&src, &dst, arg_q, false);
fb->bpp = dst.bpp;
arg_img->bpp = dst.bpp;
arg_img->pixels = dst.pixels;
} else {
// Use fb_alloc to compress and then copy image over into old image...
uint32_t size;
uint8_t *buffer = fb_alloc_all(&size);
image_t out = { .w=arg_img->w, .h=arg_img->h, .bpp=size, .pixels=buffer };
// When jpeg_compress needs more memory than in currently allocated it
// will try to realloc. MP will detect that the pointer is outside of
// the heap and return NULL which will cause an out of memory error.
jpeg_compress(arg_img, &out, arg_q, true);
if (out.bpp <= (arg_img->w * arg_img->h * arg_img->bpp)) {
memcpy(arg_img->pixels, out.pixels, out.bpp);
arg_img->bpp = out.bpp;
} else {
nlr_raise(mp_obj_new_exception_msg(&mp_type_MemoryError, "Won't fit!"));
// TODO: Need to set fb_alloc trap here to recover from any exception...

uint32_t size;
uint8_t *buffer = fb_alloc_all(&size);
image_t out = { .w=arg_img->w, .h=arg_img->h, .bpp=size, .data=buffer };
PY_ASSERT_FALSE_MSG(jpeg_compress(arg_img, &out, arg_q, false), "Out of Memory!");

switch(arg_img->bpp) {
case IMAGE_BPP_BINARY: {
PY_ASSERT_TRUE_MSG(out.bpp <= (((arg_img->w * arg_img->h) + UINT32_T_MASK) >> UINT32_T_SHIFT), "Can't compress in place!");
break;
}
fb_free();
// Double check this was not the fb.
// (happens in non-JPEG mode)...
if (fb->pixels == arg_img->pixels) {
fb->bpp = arg_img->bpp;
case IMAGE_BPP_GRAYSCALE: {
PY_ASSERT_TRUE_MSG(out.bpp <= ((arg_img->w * arg_img->h) * sizeof(uint8_t)), "Can't compress in place!");
break;
}
case IMAGE_BPP_RGB565: {
PY_ASSERT_TRUE_MSG(out.bpp <= ((arg_img->w * arg_img->h) * sizeof(uint16_t)), "Can't compress in place!");
break;
}
default: {
break;
}
}

memcpy(arg_img->data, out.data, out.bpp);
arg_img->bpp = out.bpp;
fb_free();

if (fb->pixels == arg_img->data) {
fb->bpp = arg_img->bpp;
}

return mp_const_none;
}

static mp_obj_t py_image_compressed(uint n_args, const mp_obj_t *args, mp_map_t *kw_args)
{
image_t *arg_img = py_image_cobj(args[0]);
PY_ASSERT_FALSE_MSG(IM_IS_JPEG(arg_img), "Operation not supported on JPEG");

int arg_q = py_helper_lookup_int(kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_quality), 50);
arg_q = IM_MIN(IM_MAX(arg_q, 1), 100);
PY_ASSERT_TRUE_MSG((1 <= arg_q) && (arg_q <= 100), " 1 <= quality <= 100");

// We use fb_alloc here versus xalloc to avoid huge memory hole issues while
// JPEG compression is running. We don't want to try to compress using the
// heap because of the massive memory requirement until we are done...
// TODO: Need to set fb_alloc trap here to recover from any exception...

uint32_t size;
uint8_t *buffer = fb_alloc_all(&size);
image_t out = { .w=arg_img->w, .h=arg_img->h, .bpp=size, .pixels=buffer };
// When jpeg_compress needs more memory than in currently allocated it
// will try to realloc. MP will detect that the pointer is outside of
// the heap and return NULL which will cause an out of memory error.
jpeg_compress(arg_img, &out, arg_q, false);
image_t out = { .w=arg_img->w, .h=arg_img->h, .bpp=size, .data=buffer };
PY_ASSERT_FALSE_MSG(jpeg_compress(arg_img, &out, arg_q, false), "Out of Memory!");
uint8_t *temp = xalloc(out.bpp);
memcpy(temp, out.pixels, out.bpp);
out.pixels = temp;
memcpy(temp, out.data, out.bpp);
out.data = temp;
fb_free();

return py_image_from_struct(&out);
Expand Down
14 changes: 14 additions & 0 deletions src/omv/sensor.c
Expand Up @@ -661,6 +661,20 @@ int sensor_snapshot(image_t *image, line_filter_t line_filter_func, void *line_f
JPEG_FB()->w = dst.w; JPEG_FB()->h = dst.h; JPEG_FB()->size = dst.bpp;
}

// Unlock the framebuffer mutex
mutex_unlock(&JPEG_FB()->lock, MUTEX_TID_OMV);
}
} else if ((fb->bpp >= 3) && JPEG_FB()->enabled && sensor.pixformat != PIXFORMAT_JPEG) {
// Lock FB
if (mutex_try_lock(&JPEG_FB()->lock, MUTEX_TID_OMV)) {
if(OMV_JPEG_BUF_SIZE < fb->bpp) {
// image won't fit. so don't copy.
JPEG_FB()->w = 0; JPEG_FB()->h = 0; JPEG_FB()->size = 0;
} else {
memcpy(JPEG_FB()->pixels, fb->pixels, fb->bpp);
JPEG_FB()->w = fb->w; JPEG_FB()->h = fb->h; JPEG_FB()->size = fb->bpp;
}

// Unlock the framebuffer mutex
mutex_unlock(&JPEG_FB()->lock, MUTEX_TID_OMV);
}
Expand Down

0 comments on commit e82e3ab

Please sign in to comment.