diff --git a/src/omv/ff_wrapper.c b/src/omv/ff_wrapper.c index 253854c01..d31819caa 100644 --- a/src/omv/ff_wrapper.c +++ b/src/omv/ff_wrapper.c @@ -47,13 +47,15 @@ NORETURN void ff_file_corrupted(FIL *fp) nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "File corrupted!")); } -NORETURN void ff_not_equal() +NORETURN void ff_not_equal(FIL *fp) { + if (fp) f_close(fp); nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Images not equal!")); } -NORETURN void ff_no_intersection() +NORETURN void ff_no_intersection(FIL *fp) { + if (fp) f_close(fp); nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "No intersection!")); } diff --git a/src/omv/ff_wrapper.h b/src/omv/ff_wrapper.h index 380a2b748..f8d452414 100644 --- a/src/omv/ff_wrapper.h +++ b/src/omv/ff_wrapper.h @@ -12,8 +12,8 @@ #include void ff_unsupported_format(FIL *fp); void ff_file_corrupted(FIL *fp); -void ff_not_equal(); -void ff_no_intersection(); +void ff_not_equal(FIL *fp); +void ff_no_intersection(FIL *fp); void file_read_open(FIL *fp, const char *path); void file_write_open(FIL *fp, const char *path); void file_close(FIL *fp); diff --git a/src/omv/img/bmp.c b/src/omv/img/bmp.c index 7863aff1c..819f5ef06 100644 --- a/src/omv/img/bmp.c +++ b/src/omv/img/bmp.c @@ -86,7 +86,7 @@ void bmp_read_pixels(FIL *fp, image_t *img, int line_start, int line_end, bmp_re if ((rs->bmp_h < 0) && (rs->bmp_w >= 0) && (img->w == rs->bmp_row_bytes)) { read_data(fp, // Super Fast - Zoom, Zoom! img->pixels + (line_start * img->w), - (line_end - line_start + 1) * img->w); + (line_end - line_start) * img->w); } else { for (int i = line_start; i < line_end; i++) { for (int j = 0; j < rs->bmp_row_bytes; j++) { @@ -177,7 +177,7 @@ void bmp_read(image_t *img, const char *path) void bmp_write_subimg(image_t *img, const char *path, rectangle_t *r) { rectangle_t rect; - if (!rectangle_subimg(img, r, &rect)) ff_no_intersection(); + if (!rectangle_subimg(img, r, &rect)) ff_no_intersection(NULL); FIL fp; file_write_open(&fp, path); diff --git a/src/omv/img/imlib.c b/src/omv/img/imlib.c index 723848301..dc72fa59f 100644 --- a/src/omv/img/imlib.c +++ b/src/omv/img/imlib.c @@ -87,7 +87,7 @@ static save_image_format_t imblib_parse_extension(image_t *img, const char *path return FORMAT_DONT_CARE; } -bool imlib_read_geometry(FIL *fp, image_t *img, const char *path, img_read_settings_t *rs) +static bool imlib_read_geometry(FIL *fp, image_t *img, const char *path, img_read_settings_t *rs) { file_read_open(fp, path); char magic[2]; @@ -110,7 +110,7 @@ bool imlib_read_geometry(FIL *fp, image_t *img, const char *path, img_read_setti return vflipped; } -void imlib_read_pixels(FIL *fp, image_t *img, int line_start, int line_end, img_read_settings_t *rs) +static void imlib_read_pixels(FIL *fp, image_t *img, int line_start, int line_end, img_read_settings_t *rs) { switch (rs->format) { case FORMAT_DONT_CARE: // won't happen @@ -126,6 +126,79 @@ void imlib_read_pixels(FIL *fp, image_t *img, int line_start, int line_end, img_ } } +// Main Ram = 196,608 bytes +// - +// struct framebuffer = 20 bytes +// FB_JPEG_OFFS_SIZE = 1,024 bytes +// GRAYSCALE 320x240x1 image = 76,800 bytes +// fb_alloc = 4 bytes +// flash cache = 16,384 bytes +// = +// 102,376 bytes +// / +// GRAYSCALE 320x1 lines +// = +// 319 GRAYSCALE 320x1 lines +#define GS_LINE_BUFFER_SIZE (64) // double rgb565 + +// Main Ram = 196,608 bytes +// - +// struct framebuffer = 20 bytes +// FB_JPEG_OFFS_SIZE = 1,024 bytes +// RGB565 320x240x2 image = 153,600 bytes +// fb_alloc = 4 bytes +// flash cache = 16,384 bytes +// = +// 25,576 bytes +// / +// RGB565 320x2 lines +// = +// 39 RGB565 320x2 lines +#define RGB565_LINE_BUFFER_SIZE (32) + +void imlib_image_operation(image_t *img, const char *path, image_t *other, line_op_t op) +{ + if (path) { + FIL fp; + image_t temp; + img_read_settings_t rs; + bool vflipped = imlib_read_geometry(&fp, &temp, path, &rs); + if (!IM_EQUAL(img, &temp)) { + ff_not_equal(&fp); + } + // This code reads a window of an image in at a time and then executes + // the line operation on each line in that window before moving to the + // next window. The vflipped part is here because BMP files can be saved + // vertically flipped resulting in us reading the image backwards. + temp.h = IM_IS_GS(img) ? GS_LINE_BUFFER_SIZE : RGB565_LINE_BUFFER_SIZE; + // When processing vertically flipped images the read function will fill + // the window up from the bottom. The read function assumes that the + // window is equal to an image in size. However, since this is not the + // case we shrink the window size to how many lines we're buffering. + temp.pixels = fb_alloc(temp.w * temp.h * temp.bpp); + for (int i=0; ih; i+=temp.h) { // goes past end + int can_do = IM_MIN(temp.h, img->h-i); + imlib_read_pixels(&fp, &temp, 0, can_do, &rs); + for (int j=0; jh-i-can_do)+j, temp.pixels+(temp.w*temp.bpp*j)); + } + } + } + fb_free(); + file_close(&fp); + } else { + if (!IM_EQUAL(img, other)) { + ff_not_equal(NULL); + } + for (int i=0; ih; i++) { + op(img, i, other->pixels + (img->w * img->bpp * i)); + } + } +} + void imlib_load_image(image_t *img, const char *path) { FIL fp; diff --git a/src/omv/img/imlib.h b/src/omv/img/imlib.h index e44f7b2bb..665839ef8 100644 --- a/src/omv/img/imlib.h +++ b/src/omv/img/imlib.h @@ -311,6 +311,8 @@ typedef struct img_read_settings { save_image_format_t format; } img_read_settings_t; +typedef void (*line_op_t)(image_t*, int, uint8_t*); + /* Image file functions */ void ppm_read_geometry(FIL *fp, image_t *img, const char *path, ppm_read_settings_t *rs); void ppm_read_pixels(FIL *fp, image_t *img, int line_start, int line_end, ppm_read_settings_t *rs); @@ -324,6 +326,7 @@ void jpeg_read_geometry(FIL *fp, image_t *img, const char *path); void jpeg_read_pixels(FIL *fp, image_t *img); void jpeg_read(image_t *img, const char *path); void jpeg_write(image_t *img, const char *path); +void imlib_image_operation(image_t *img, const char *path, image_t *other, line_op_t op); void imlib_load_image(image_t *img, const char *path); void imlib_save_image(image_t *img, const char *path, rectangle_t *roi); diff --git a/src/omv/img/ppm.c b/src/omv/img/ppm.c index a8728d6f1..b8c9d20aa 100644 --- a/src/omv/img/ppm.c +++ b/src/omv/img/ppm.c @@ -93,7 +93,7 @@ void ppm_read_pixels(FIL *fp, image_t *img, int line_start, int line_end, ppm_re } else if (rs->ppm_fmt == '5') { read_data(fp, // Super Fast - Zoom, Zoom! img->pixels + (line_start * img->w), - (line_end - line_start + 1) * img->w); + (line_end - line_start) * img->w); } else if (rs->ppm_fmt == '6') { for (int i = line_start; i < line_end; i++) { for (int j = 0; j < img->w; j++) { @@ -122,7 +122,7 @@ void ppm_read(image_t *img, const char *path) void ppm_write_subimg(image_t *img, const char *path, rectangle_t *r) { rectangle_t rect; - if (!rectangle_subimg(img, r, &rect)) ff_no_intersection(); + if (!rectangle_subimg(img, r, &rect)) ff_no_intersection(NULL); FIL fp; file_write_open(&fp, path);