Merge pull request #170 from kwagyeman/fix_compress

Fix compress and compressed.
This commit is contained in:
Ibrahim Abd Elkader 2017-01-12 04:47:36 +02:00 committed by GitHub
commit e82e3ab785
2 changed files with 50 additions and 43 deletions

View File

@ -225,45 +225,44 @@ static mp_obj_t py_image_save(uint n_args, const mp_obj_t *args, mp_map_t *kw_ar
return mp_const_none; 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) 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]); image_t *arg_img = py_image_cobj(args[0]);
PY_ASSERT_FALSE_MSG(IM_IS_JPEG(arg_img), "Operation not supported on JPEG"); 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); 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... // TODO: Need to set fb_alloc trap here to recover from any exception...
if (fb->pixels == arg_img->pixels) {
// We do not allow shallow copies so this is okay... uint32_t size;
image_t src = {.w=fb->w, .h=fb->h, .bpp=fb->bpp, .pixels=fb->pixels}; uint8_t *buffer = fb_alloc_all(&size);
image_t dst = {.w=fb->w, .h=fb->h, .bpp=128*1024, .pixels=fb->pixels+FB_JPEG_OFFS_SIZE}; image_t out = { .w=arg_img->w, .h=arg_img->h, .bpp=size, .data=buffer };
jpeg_compress(&src, &dst, arg_q, false); PY_ASSERT_FALSE_MSG(jpeg_compress(arg_img, &out, arg_q, false), "Out of Memory!");
fb->bpp = dst.bpp;
arg_img->bpp = dst.bpp; switch(arg_img->bpp) {
arg_img->pixels = dst.pixels; case IMAGE_BPP_BINARY: {
} else { PY_ASSERT_TRUE_MSG(out.bpp <= (((arg_img->w * arg_img->h) + UINT32_T_MASK) >> UINT32_T_SHIFT), "Can't compress in place!");
// Use fb_alloc to compress and then copy image over into old image... break;
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!"));
} }
fb_free(); case IMAGE_BPP_GRAYSCALE: {
// Double check this was not the fb. PY_ASSERT_TRUE_MSG(out.bpp <= ((arg_img->w * arg_img->h) * sizeof(uint8_t)), "Can't compress in place!");
// (happens in non-JPEG mode)... break;
if (fb->pixels == arg_img->pixels) {
fb->bpp = arg_img->bpp;
} }
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; return mp_const_none;
@ -273,24 +272,18 @@ static mp_obj_t py_image_compressed(uint n_args, const mp_obj_t *args, mp_map_t
{ {
image_t *arg_img = py_image_cobj(args[0]); image_t *arg_img = py_image_cobj(args[0]);
PY_ASSERT_FALSE_MSG(IM_IS_JPEG(arg_img), "Operation not supported on JPEG"); 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); 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 // TODO: Need to set fb_alloc trap here to recover from any exception...
// 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...
uint32_t size; uint32_t size;
uint8_t *buffer = fb_alloc_all(&size); uint8_t *buffer = fb_alloc_all(&size);
image_t out = { .w=arg_img->w, .h=arg_img->h, .bpp=size, .pixels=buffer }; image_t out = { .w=arg_img->w, .h=arg_img->h, .bpp=size, .data=buffer };
// When jpeg_compress needs more memory than in currently allocated it PY_ASSERT_FALSE_MSG(jpeg_compress(arg_img, &out, arg_q, false), "Out of Memory!");
// 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);
uint8_t *temp = xalloc(out.bpp); uint8_t *temp = xalloc(out.bpp);
memcpy(temp, out.pixels, out.bpp); memcpy(temp, out.data, out.bpp);
out.pixels = temp; out.data = temp;
fb_free(); fb_free();
return py_image_from_struct(&out); return py_image_from_struct(&out);

View File

@ -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; 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 // Unlock the framebuffer mutex
mutex_unlock(&JPEG_FB()->lock, MUTEX_TID_OMV); mutex_unlock(&JPEG_FB()->lock, MUTEX_TID_OMV);
} }