From 0a0436852830556363253639c0d5688117a68c37 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Sun, 15 Oct 2023 13:54:01 +0200 Subject: [PATCH] misc: Refactor file management code. --- src/drivers/winc1500/src/programmer.c | 20 +- src/omv/Makefile | 2 +- src/omv/common/ff_wrapper.c | 543 ------------------------- src/omv/common/ff_wrapper.h | 57 --- src/omv/common/file_utils.c | 416 +++++++++++++++++++ src/omv/common/file_utils.h | 52 +++ src/omv/common/ini.c | 3 +- src/omv/common/ini.h | 2 +- src/omv/common/usbdbg.c | 1 - src/omv/imlib/bmp.c | 189 ++++----- src/omv/imlib/fft.c | 2 +- src/omv/imlib/gif.c | 72 ++-- src/omv/imlib/haar.c | 31 +- src/omv/imlib/imlib.c | 41 +- src/omv/imlib/imlib.h | 2 +- src/omv/imlib/jpeg.c | 27 +- src/omv/imlib/lbp.c | 6 +- src/omv/imlib/mjpeg.c | 184 ++++----- src/omv/imlib/orb.c | 30 +- src/omv/imlib/png.c | 22 +- src/omv/imlib/ppm.c | 47 +-- src/omv/modules/py_gif.c | 6 +- src/omv/modules/py_image.c | 180 ++++---- src/omv/modules/py_imageio.c | 72 ++-- src/omv/modules/py_mjpeg.c | 4 +- src/omv/modules/py_tf.c | 6 +- src/omv/ports/mimxrt/main.c | 2 +- src/omv/ports/mimxrt/omv_portconfig.mk | 2 +- src/omv/ports/nrf/omv_portconfig.mk | 2 +- src/omv/ports/rp2/omv_portconfig.cmake | 2 +- src/omv/ports/stm32/hash.c | 10 +- src/omv/ports/stm32/main.c | 15 +- src/omv/ports/stm32/modules/py_winc.c | 4 +- src/omv/ports/stm32/omv_portconfig.mk | 2 +- 34 files changed, 914 insertions(+), 1142 deletions(-) delete mode 100644 src/omv/common/ff_wrapper.c delete mode 100644 src/omv/common/ff_wrapper.h create mode 100644 src/omv/common/file_utils.c create mode 100644 src/omv/common/file_utils.h diff --git a/src/drivers/winc1500/src/programmer.c b/src/drivers/winc1500/src/programmer.c index ad7e6936f..463a19f40 100644 --- a/src/drivers/winc1500/src/programmer.c +++ b/src/drivers/winc1500/src/programmer.c @@ -8,9 +8,9 @@ * * Framebuffer functions. */ -#include #include #include "fb_alloc.h" +#include "file_utils.h" #include "programmer/programmer.h" #include "spi_flash/include/spi_flash_map.h" @@ -34,7 +34,7 @@ int burn_firmware(const char *path) int ret = M2M_ERR_FAIL; uint8_t *buf = fb_alloc(FLASH_SECTOR_SZ, FB_ALLOC_NO_HINT); - if (f_open_helper(&fp, path, FA_READ|FA_OPEN_EXISTING) != FR_OK) { + if (file_ll_open(&fp, path, FA_READ|FA_OPEN_EXISTING) != FR_OK) { goto error; } @@ -44,7 +44,7 @@ int burn_firmware(const char *path) while (size) { // Read a chuck (max FLASH_SECTOR_SZ bytes). bytes = MIN(size, FLASH_SECTOR_SZ); - if (f_read(&fp, buf, bytes, &bytes_out) != FR_OK || bytes != bytes_out) { + if (file_ll_read(&fp, buf, bytes, &bytes_out) != FR_OK || bytes != bytes_out) { printf("burn_firmware: file read error!\n"); goto error; } @@ -63,7 +63,7 @@ int burn_firmware(const char *path) error: fb_free(); - f_close(&fp); + file_ll_close(&fp); return ret; } @@ -81,7 +81,7 @@ int verify_firmware(const char *path) uint8_t *file_buf = fb_alloc(FLASH_SECTOR_SZ, FB_ALLOC_NO_HINT); uint8_t *flash_buf = fb_alloc(FLASH_SECTOR_SZ, FB_ALLOC_NO_HINT); - if (f_open_helper(&fp, path, FA_READ|FA_OPEN_EXISTING) != FR_OK) { + if (file_ll_open(&fp, path, FA_READ|FA_OPEN_EXISTING) != FR_OK) { goto error; } @@ -92,7 +92,7 @@ int verify_firmware(const char *path) // Firmware chuck size (max FLASH_SECTOR_SZ bytes). bytes = MIN(size, FLASH_SECTOR_SZ); - if (f_read(&fp, file_buf, bytes, &bytes_out) != FR_OK || bytes_out != bytes) { + if (file_ll_read(&fp, file_buf, bytes, &bytes_out) != FR_OK || bytes_out != bytes) { printf("verify_firmware: file read error!\n"); goto error; } @@ -118,7 +118,7 @@ int verify_firmware(const char *path) error: fb_free(); fb_free(); - f_close(&fp); + file_ll_close(&fp); return ret; } @@ -135,7 +135,7 @@ int dump_firmware(const char *path) int ret = M2M_ERR_FAIL; uint8_t *flash_buf = fb_alloc(FLASH_SECTOR_SZ, FB_ALLOC_NO_HINT); - if (f_open_helper(&fp, path, FA_WRITE | FA_CREATE_ALWAYS) != FR_OK) { + if (file_ll_open(&fp, path, FA_WRITE | FA_CREATE_ALWAYS) != FR_OK) { goto error; } @@ -151,7 +151,7 @@ int dump_firmware(const char *path) goto error; } - if (f_write(&fp, flash_buf, bytes, &bytes_out) != FR_OK || bytes_out != bytes) { + if (file_ll_write(&fp, flash_buf, bytes, &bytes_out) != FR_OK || bytes_out != bytes) { printf("dump_firmware: file write error!\n"); goto error; } @@ -164,6 +164,6 @@ int dump_firmware(const char *path) error: fb_free(); - f_close(&fp); + file_ll_close(&fp); return ret; } diff --git a/src/omv/Makefile b/src/omv/Makefile index 6013e9cf9..245e77ad1 100644 --- a/src/omv/Makefile +++ b/src/omv/Makefile @@ -17,7 +17,7 @@ SRCS += $(addprefix alloc/, \ SRCS += $(addprefix common/, \ array.c \ - ff_wrapper.c \ + file_utils.c \ ini.c \ ringbuf.c \ trace.c \ diff --git a/src/omv/common/ff_wrapper.c b/src/omv/common/ff_wrapper.c deleted file mode 100644 index b976e8bac..000000000 --- a/src/omv/common/ff_wrapper.c +++ /dev/null @@ -1,543 +0,0 @@ -/* - * This file is part of the OpenMV project. - * Copyright (c) 2013-2016 Kwabena W. Agyeman - * This work is licensed under the MIT license, see the file LICENSE for details. - * - * File System Helper Functions - * - */ -#include "imlib_config.h" -#if defined(IMLIB_ENABLE_IMAGE_FILE_IO) - -#include -#include "py/runtime.h" -#include "extmod/vfs.h" -#include "extmod/vfs_fat.h" - -#include "omv_common.h" -#include "fb_alloc.h" -#include "ff_wrapper.h" -#define FF_MIN(x, y) (((x) < (y))?(x):(y)) - -NORETURN static void ff_fail(FIL *fp, FRESULT res) { - if (fp) { - f_close(fp); - } - mp_raise_msg(&mp_type_OSError, (mp_rom_error_text_t) ffs_strerror(res)); -} - -NORETURN static void ff_read_fail(FIL *fp) { - if (fp) { - f_close(fp); - } - mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Failed to read requested bytes!")); -} - -NORETURN static void ff_write_fail(FIL *fp) { - if (fp) { - f_close(fp); - } - mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Failed to write requested bytes!")); -} - -NORETURN static void ff_expect_fail(FIL *fp) { - if (fp) { - f_close(fp); - } - mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Unexpected value read!")); -} - -NORETURN void ff_unsupported_format(FIL *fp) { - if (fp) { - f_close(fp); - } - mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Unsupported format!")); -} - -NORETURN void ff_file_corrupted(FIL *fp) { - if (fp) { - f_close(fp); - } - mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("File corrupted!")); -} - -NORETURN void ff_not_equal(FIL *fp) { - if (fp) { - f_close(fp); - } - mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Images not equal!")); -} - -NORETURN void ff_no_intersection(FIL *fp) { - if (fp) { - f_close(fp); - } - mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("No intersection!")); -} - -void file_read_open(FIL *fp, const char *path) { - FRESULT res = f_open_helper(fp, path, FA_READ | FA_OPEN_EXISTING); - if (res != FR_OK) { - ff_fail(fp, res); - } -} - -void file_write_open(FIL *fp, const char *path) { - FRESULT res = f_open_helper(fp, path, FA_WRITE | FA_CREATE_ALWAYS); - if (res != FR_OK) { - ff_fail(fp, res); - } -} - -void file_read_write_open_existing(FIL *fp, const char *path) { - FRESULT res = f_open_helper(fp, path, FA_READ | FA_WRITE | FA_OPEN_EXISTING); - if (res != FR_OK) { - ff_fail(fp, res); - } -} - -void file_read_write_open_always(FIL *fp, const char *path) { - FRESULT res = f_open_helper(fp, path, FA_READ | FA_WRITE | FA_OPEN_ALWAYS); - if (res != FR_OK) { - ff_fail(fp, res); - } -} - -void file_close(FIL *fp) { - FRESULT res = f_close(fp); - if (res != FR_OK) { - ff_fail(fp, res); - } -} - -void file_seek(FIL *fp, UINT offset) { - FRESULT res = f_lseek(fp, offset); - if (res != FR_OK) { - ff_fail(fp, res); - } -} - -void file_truncate(FIL *fp) { - FRESULT res = f_truncate(fp); - if (res != FR_OK) { - ff_fail(fp, res); - } -} - -void file_sync(FIL *fp) { - FRESULT res = f_sync(fp); - if (res != FR_OK) { - ff_fail(fp, res); - } -} - -// These wrapper functions are used for backward compatibility with -// OpenMV code using vanilla FatFS. Note: Extracted from cc3200 ftp.c - -STATIC FATFS *lookup_path(const TCHAR **path) { - mp_vfs_mount_t *fs = mp_vfs_lookup_path(*path, path); - if (fs == MP_VFS_NONE || fs == MP_VFS_ROOT) { - return NULL; - } - // here we assume that the mounted device is FATFS - return &((fs_user_mount_t *) MP_OBJ_TO_PTR(fs->obj))->fatfs; -} - -FRESULT f_open_helper(FIL *fp, const TCHAR *path, BYTE mode) { - FATFS *fs = lookup_path(&path); - if (fs == NULL) { - return FR_NO_PATH; - } - return f_open(fs, fp, path, mode); -} - -FRESULT f_opendir_helper(FF_DIR *dp, const TCHAR *path) { - FATFS *fs = lookup_path(&path); - if (fs == NULL) { - return FR_NO_PATH; - } - return f_opendir(fs, dp, path); -} - -FRESULT f_stat_helper(const TCHAR *path, FILINFO *fno) { - FATFS *fs = lookup_path(&path); - if (fs == NULL) { - return FR_NO_PATH; - } - return f_stat(fs, path, fno); -} - -FRESULT f_mkdir_helper(const TCHAR *path) { - FATFS *fs = lookup_path(&path); - if (fs == NULL) { - return FR_NO_PATH; - } - return f_mkdir(fs, path); -} - -FRESULT f_unlink_helper(const TCHAR *path) { - FATFS *fs = lookup_path(&path); - if (fs == NULL) { - return FR_NO_PATH; - } - return f_unlink(fs, path); -} - -FRESULT f_rename_helper(const TCHAR *path_old, const TCHAR *path_new) { - FATFS *fs_old = lookup_path(&path_old); - if (fs_old == NULL) { - return FR_NO_PATH; - } - FATFS *fs_new = lookup_path(&path_new); - if (fs_new == NULL) { - return FR_NO_PATH; - } - if (fs_old != fs_new) { - return FR_NO_PATH; - } - return f_rename(fs_new, path_old, path_new); -} - -FRESULT f_touch_helper(const TCHAR *path) { - FIL fp; - FATFS *fs = lookup_path(&path); - if (fs == NULL) { - return FR_NO_PATH; - } - - if (f_stat(fs, path, NULL) != FR_OK) { - f_open(fs, &fp, path, FA_WRITE | FA_CREATE_ALWAYS); - f_close(&fp); - } - - return FR_OK; -} -// When a sector boundary is encountered while writing a file and there are -// more than 512 bytes left to write FatFs will detect that it can bypass -// its internal write buffer and pass the data buffer passed to it directly -// to the disk write function. However, the disk write function needs the -// buffer to be aligned to a 4-byte boundary. FatFs doesn't know this and -// will pass an unaligned buffer if we don't fix the issue. To fix this problem -// we use a temporary buffer to fix the alignment and to speed everything up. - -// We use this temporary buffer for both reads and writes. The buffer allows us -// to do multi-block reads and writes which significantly speed things up. - -static uint32_t file_buffer_offset = 0; -static uint8_t *file_buffer_pointer = 0; -static uint32_t file_buffer_size = 0; -static uint32_t file_buffer_index = 0; - -void file_buffer_init0() { - file_buffer_offset = 0; - file_buffer_pointer = 0; - file_buffer_size = 0; - file_buffer_index = 0; -} - -OMV_ATTR_ALWAYS_INLINE static void file_fill(FIL *fp) { - if (file_buffer_index == file_buffer_size) { - file_buffer_pointer -= file_buffer_offset; - file_buffer_size += file_buffer_offset; - file_buffer_offset = 0; - file_buffer_index = 0; - uint32_t file_remaining = f_size(fp) - f_tell(fp); - uint32_t can_do = FF_MIN(file_buffer_size, file_remaining); - UINT bytes; - FRESULT res = f_read(fp, file_buffer_pointer, can_do, &bytes); - if (res != FR_OK) { - ff_fail(fp, res); - } - if (bytes != can_do) { - ff_read_fail(fp); - } - } -} - -OMV_ATTR_ALWAYS_INLINE static void file_flush(FIL *fp) { - if (file_buffer_index == file_buffer_size) { - UINT bytes; - FRESULT res = f_write(fp, file_buffer_pointer, file_buffer_index, &bytes); - if (res != FR_OK) { - ff_fail(fp, res); - } - if (bytes != file_buffer_index) { - ff_write_fail(fp); - } - file_buffer_pointer -= file_buffer_offset; - file_buffer_size += file_buffer_offset; - file_buffer_offset = 0; - file_buffer_index = 0; - } -} - -uint32_t file_tell_w_buf(FIL *fp) { - if (fp->flag & FA_READ) { - return f_tell(fp) - file_buffer_size + file_buffer_index; - } else { - return f_tell(fp) + file_buffer_index; - } -} - -uint32_t file_size_w_buf(FIL *fp) { - if (fp->flag & FA_READ) { - return f_size(fp); - } else { - return f_size(fp) + file_buffer_index; - } -} - -void file_buffer_on(FIL *fp) { - file_buffer_offset = f_tell(fp) % 4; - file_buffer_pointer = fb_alloc_all(&file_buffer_size, FB_ALLOC_PREFER_SIZE) + file_buffer_offset; - if (!file_buffer_size) { - mp_raise_msg(&mp_type_MemoryError, MP_ERROR_TEXT("No memory!")); - } - file_buffer_size -= file_buffer_offset; - file_buffer_index = 0; - if (fp->flag & FA_READ) { - uint32_t file_remaining = f_size(fp) - f_tell(fp); - uint32_t can_do = FF_MIN(file_buffer_size, file_remaining); - UINT bytes; - FRESULT res = f_read(fp, file_buffer_pointer, can_do, &bytes); - if (res != FR_OK) { - ff_fail(fp, res); - } - if (bytes != can_do) { - ff_read_fail(fp); - } - } -} - -void file_buffer_off(FIL *fp) { - if ((fp->flag & FA_WRITE) && file_buffer_index) { - UINT bytes; - FRESULT res = f_write(fp, file_buffer_pointer, file_buffer_index, &bytes); - if (res != FR_OK) { - ff_fail(fp, res); - } - if (bytes != file_buffer_index) { - ff_write_fail(fp); - } - } - file_buffer_pointer = 0; - fb_free(); -} - -void read_byte(FIL *fp, uint8_t *value) { - if (file_buffer_pointer) { - // We get a massive speed boost by buffering up as much data as possible - // via massive reads. So much so that the time wasted by - // all these operations does not cost us. - for (size_t i = 0; i < sizeof(*value); i++) { - file_fill(fp); - ((uint8_t *) value)[i] = file_buffer_pointer[file_buffer_index++]; - } - } else { - UINT bytes; - FRESULT res = f_read(fp, value, sizeof(*value), &bytes); - if (res != FR_OK) { - ff_fail(fp, res); - } - if (bytes != sizeof(*value)) { - ff_read_fail(fp); - } - } -} - -void read_byte_expect(FIL *fp, uint8_t value) { - uint8_t compare; - read_byte(fp, &compare); - if (value != compare) { - ff_expect_fail(fp); - } -} - -void read_byte_ignore(FIL *fp) { - uint8_t trash; - read_byte(fp, &trash); -} - -void read_word(FIL *fp, uint16_t *value) { - if (file_buffer_pointer) { - // We get a massive speed boost by buffering up as much data as possible - // via massive reads. So much so that the time wasted by - // all these operations does not cost us. - for (size_t i = 0; i < sizeof(*value); i++) { - file_fill(fp); - ((uint8_t *) value)[i] = file_buffer_pointer[file_buffer_index++]; - } - } else { - UINT bytes; - FRESULT res = f_read(fp, value, sizeof(*value), &bytes); - if (res != FR_OK) { - ff_fail(fp, res); - } - if (bytes != sizeof(*value)) { - ff_read_fail(fp); - } - } -} - -void read_word_expect(FIL *fp, uint16_t value) { - uint16_t compare; - read_word(fp, &compare); - if (value != compare) { - ff_expect_fail(fp); - } -} - -void read_word_ignore(FIL *fp) { - uint16_t trash; - read_word(fp, &trash); -} - -void read_long(FIL *fp, uint32_t *value) { - if (file_buffer_pointer) { - // We get a massive speed boost by buffering up as much data as possible - // via massive reads. So much so that the time wasted by - // all these operations does not cost us. - for (size_t i = 0; i < sizeof(*value); i++) { - file_fill(fp); - ((uint8_t *) value)[i] = file_buffer_pointer[file_buffer_index++]; - } - } else { - UINT bytes; - FRESULT res = f_read(fp, value, sizeof(*value), &bytes); - if (res != FR_OK) { - ff_fail(fp, res); - } - if (bytes != sizeof(*value)) { - ff_read_fail(fp); - } - } -} - -void read_long_expect(FIL *fp, uint32_t value) { - uint32_t compare; - read_long(fp, &compare); - if (value != compare) { - ff_expect_fail(fp); - } -} - -void read_long_ignore(FIL *fp) { - uint32_t trash; - read_long(fp, &trash); -} - -void read_data(FIL *fp, void *data, UINT size) { - if (file_buffer_pointer) { - // We get a massive speed boost by buffering up as much data as possible - // via massive reads. So much so that the time wasted by - // all these operations does not cost us. - while (size) { - file_fill(fp); - uint32_t file_buffer_space_left = file_buffer_size - file_buffer_index; - uint32_t can_do = FF_MIN(size, file_buffer_space_left); - memcpy(data, file_buffer_pointer + file_buffer_index, can_do); - file_buffer_index += can_do; - data += can_do; - size -= can_do; - } - } else { - UINT bytes; - FRESULT res = f_read(fp, data, size, &bytes); - if (res != FR_OK) { - ff_fail(fp, res); - } - if (bytes != size) { - ff_read_fail(fp); - } - } -} - -void write_byte(FIL *fp, uint8_t value) { - if (file_buffer_pointer) { - // We get a massive speed boost by buffering up as much data as possible - // before a write to the SD card. So much so that the time wasted by - // all these operations does not cost us. - for (size_t i = 0; i < sizeof(value); i++) { - file_buffer_pointer[file_buffer_index++] = ((uint8_t *) &value)[i]; - file_flush(fp); - } - } else { - UINT bytes; - FRESULT res = f_write(fp, &value, sizeof(value), &bytes); - if (res != FR_OK) { - ff_fail(fp, res); - } - if (bytes != sizeof(value)) { - ff_write_fail(fp); - } - } -} - -void write_word(FIL *fp, uint16_t value) { - if (file_buffer_pointer) { - // We get a massive speed boost by buffering up as much data as possible - // before a write to the SD card. So much so that the time wasted by - // all these operations does not cost us. - for (size_t i = 0; i < sizeof(value); i++) { - file_buffer_pointer[file_buffer_index++] = ((uint8_t *) &value)[i]; - file_flush(fp); - } - } else { - UINT bytes; - FRESULT res = f_write(fp, &value, sizeof(value), &bytes); - if (res != FR_OK) { - ff_fail(fp, res); - } - if (bytes != sizeof(value)) { - ff_write_fail(fp); - } - } -} - -void write_long(FIL *fp, uint32_t value) { - if (file_buffer_pointer) { - // We get a massive speed boost by buffering up as much data as possible - // before a write to the SD card. So much so that the time wasted by - // all these operations does not cost us. - for (size_t i = 0; i < sizeof(value); i++) { - file_buffer_pointer[file_buffer_index++] = ((uint8_t *) &value)[i]; - file_flush(fp); - } - } else { - UINT bytes; - FRESULT res = f_write(fp, &value, sizeof(value), &bytes); - if (res != FR_OK) { - ff_fail(fp, res); - } - if (bytes != sizeof(value)) { - ff_write_fail(fp); - } - } -} - -void write_data(FIL *fp, const void *data, UINT size) { - if (file_buffer_pointer) { - // We get a massive speed boost by buffering up as much data as possible - // before a write to the SD card. So much so that the time wasted by - // all these operations does not cost us. - while (size) { - uint32_t file_buffer_space_left = file_buffer_size - file_buffer_index; - uint32_t can_do = FF_MIN(size, file_buffer_space_left); - memcpy(file_buffer_pointer + file_buffer_index, data, can_do); - file_buffer_index += can_do; - data += can_do; - size -= can_do; - file_flush(fp); - } - } else { - UINT bytes; - FRESULT res = f_write(fp, data, size, &bytes); - if (res != FR_OK) { - ff_fail(fp, res); - } - if (bytes != size) { - ff_write_fail(fp); - } - } -} -#endif //IMLIB_ENABLE_IMAGE_FILE_IO diff --git a/src/omv/common/ff_wrapper.h b/src/omv/common/ff_wrapper.h deleted file mode 100644 index ce3421c20..000000000 --- a/src/omv/common/ff_wrapper.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * This file is part of the OpenMV project. - * Copyright (c) 2013-2016 Kwabena W. Agyeman - * This work is licensed under the MIT license, see the file LICENSE for details. - * - * File System Helper Functions - * - */ -#ifndef __FF_WRAPPER_H__ -#define __FF_WRAPPER_H__ -#include -#include -extern const char *ffs_strerror(FRESULT res); - -//OOFATFS wrappers -FRESULT f_open_helper(FIL *fp, const TCHAR *path, BYTE mode); -FRESULT f_opendir_helper(FF_DIR *dp, const TCHAR *path); -FRESULT f_stat_helper(const TCHAR *path, FILINFO *fno); -FRESULT f_mkdir_helper(const TCHAR *path); -FRESULT f_unlink_helper(const TCHAR *path); -FRESULT f_rename_helper(const TCHAR *path_old, const TCHAR *path_new); -FRESULT f_touch_helper(const TCHAR *path); - -void ff_unsupported_format(FIL *fp); -void ff_file_corrupted(FIL *fp); -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_read_write_open_existing(FIL *fp, const char *path); -void file_read_write_open_always(FIL *fp, const char *path); -void file_close(FIL *fp); -void file_seek(FIL *fp, UINT offset); -void file_truncate(FIL *fp); -void file_sync(FIL *fp); - -// File buffer functions. -void file_buffer_init0(); -void file_buffer_on(FIL *fp); // does fb_alloc_all -uint32_t file_tell_w_buf(FIL *fp); // valid between on and off -uint32_t file_size_w_buf(FIL *fp); // valid between on and off -void file_buffer_off(FIL *fp); // does fb_free -void read_byte(FIL *fp, uint8_t *value); -void read_byte_expect(FIL *fp, uint8_t value); -void read_byte_ignore(FIL *fp); -void read_word(FIL *fp, uint16_t *value); -void read_word_expect(FIL *fp, uint16_t value); -void read_word_ignore(FIL *fp); -void read_long(FIL *fp, uint32_t *value); -void read_long_expect(FIL *fp, uint32_t value); -void read_long_ignore(FIL *fp); -void read_data(FIL *fp, void *data, UINT size); -void write_byte(FIL *fp, uint8_t value); -void write_word(FIL *fp, uint16_t value); -void write_long(FIL *fp, uint32_t value); -void write_data(FIL *fp, const void *data, UINT size); -#endif /* __FF_WRAPPER_H__ */ diff --git a/src/omv/common/file_utils.c b/src/omv/common/file_utils.c new file mode 100644 index 000000000..e4e7b00e4 --- /dev/null +++ b/src/omv/common/file_utils.c @@ -0,0 +1,416 @@ +/* + * This file is part of the OpenMV project. + * Copyright (c) 2013-2023 Kwabena W. Agyeman + * This work is licensed under the MIT license, see the file LICENSE for details. + * + * Filesystem helper functions. + * + */ +#include "imlib_config.h" +#if defined(IMLIB_ENABLE_IMAGE_FILE_IO) + +#include +#include "py/runtime.h" +#include "extmod/vfs.h" +#include "extmod/vfs_fat.h" + +#include "omv_common.h" +#include "fb_alloc.h" +#include "file_utils.h" +#define FF_MIN(x, y) (((x) < (y))?(x):(y)) + +NORETURN static void ff_read_fail(FIL *fp) { + if (fp) { + f_close(fp); + } + mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Failed to read requested bytes!")); +} + +NORETURN static void ff_write_fail(FIL *fp) { + if (fp) { + f_close(fp); + } + mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Failed to write requested bytes!")); +} + +NORETURN static void ff_expect_fail(FIL *fp) { + if (fp) { + f_close(fp); + } + mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Unexpected value read!")); +} + +NORETURN void file_raise_format(FIL *fp) { + if (fp) { + f_close(fp); + } + mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Unsupported format!")); +} + +NORETURN void file_raise_corrupted(FIL *fp) { + if (fp) { + f_close(fp); + } + mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("File corrupted!")); +} + +NORETURN void file_raise_error(FIL *fp, FRESULT res) { + if (fp) { + f_close(fp); + } + mp_raise_msg(&mp_type_OSError, (mp_rom_error_text_t) ffs_strerror(res)); +} + +static FATFS *lookup_path(const TCHAR **path) { + mp_vfs_mount_t *fs = mp_vfs_lookup_path(*path, path); + if (fs == MP_VFS_NONE || fs == MP_VFS_ROOT) { + return NULL; + } + // here we assume that the mounted device is FATFS + return &((fs_user_mount_t *) MP_OBJ_TO_PTR(fs->obj))->fatfs; +} + +FRESULT file_ll_open(FIL *fp, const TCHAR *path, BYTE mode) { + FATFS *fs = lookup_path(&path); + if (fs == NULL) { + return FR_NO_PATH; + } + return f_open(fs, fp, path, mode); +} + +FRESULT file_ll_close(FIL *fp) { + return f_close(fp); +} + +FRESULT file_ll_read(FIL *fp, void *buff, UINT btr, UINT *br) { + return f_read(fp, buff, btr, br); +} + +FRESULT file_ll_write(FIL *fp, const void *buff, UINT btw, UINT *bw) { + return f_write(fp, buff, btw, bw); +} + +FRESULT file_ll_opendir(FF_DIR *dp, const TCHAR *path) { + FATFS *fs = lookup_path(&path); + if (fs == NULL) { + return FR_NO_PATH; + } + return f_opendir(fs, dp, path); +} + +FRESULT file_ll_stat(const TCHAR *path, FILINFO *fno) { + FATFS *fs = lookup_path(&path); + if (fs == NULL) { + return FR_NO_PATH; + } + return f_stat(fs, path, fno); +} + +FRESULT file_ll_mkdir(const TCHAR *path) { + FATFS *fs = lookup_path(&path); + if (fs == NULL) { + return FR_NO_PATH; + } + return f_mkdir(fs, path); +} + +FRESULT file_ll_unlink(const TCHAR *path) { + FATFS *fs = lookup_path(&path); + if (fs == NULL) { + return FR_NO_PATH; + } + return f_unlink(fs, path); +} + +FRESULT file_ll_rename(const TCHAR *path_old, const TCHAR *path_new) { + FATFS *fs_old = lookup_path(&path_old); + if (fs_old == NULL) { + return FR_NO_PATH; + } + FATFS *fs_new = lookup_path(&path_new); + if (fs_new == NULL) { + return FR_NO_PATH; + } + if (fs_old != fs_new) { + return FR_NO_PATH; + } + return f_rename(fs_new, path_old, path_new); +} + +FRESULT file_ll_touch(const TCHAR *path) { + FIL fp; + FATFS *fs = lookup_path(&path); + if (fs == NULL) { + return FR_NO_PATH; + } + + if (f_stat(fs, path, NULL) != FR_OK) { + f_open(fs, &fp, path, FA_WRITE | FA_CREATE_ALWAYS); + f_close(&fp); + } + + return FR_OK; +} + +// When a sector boundary is encountered while writing a file and there are +// more than 512 bytes left to write FatFs will detect that it can bypass +// its internal write buffer and pass the data buffer passed to it directly +// to the disk write function. However, the disk write function needs the +// buffer to be aligned to a 4-byte boundary. FatFs doesn't know this and +// will pass an unaligned buffer if we don't fix the issue. To fix this problem +// we use a temporary buffer to fix the alignment and to speed everything up. +// We use this temporary buffer for both reads and writes. The buffer allows us +// to do multi-block reads and writes which significantly speed things up. + +static uint32_t file_buffer_offset = 0; +static uint8_t *file_buffer_pointer = 0; +static uint32_t file_buffer_size = 0; +static uint32_t file_buffer_index = 0; + +void file_buffer_init0() { + file_buffer_offset = 0; + file_buffer_pointer = 0; + file_buffer_size = 0; + file_buffer_index = 0; +} + +OMV_ATTR_ALWAYS_INLINE static void file_fill(FIL *fp) { + if (file_buffer_index == file_buffer_size) { + file_buffer_pointer -= file_buffer_offset; + file_buffer_size += file_buffer_offset; + file_buffer_offset = 0; + file_buffer_index = 0; + uint32_t file_remaining = f_size(fp) - f_tell(fp); + uint32_t can_do = FF_MIN(file_buffer_size, file_remaining); + UINT bytes; + FRESULT res = f_read(fp, file_buffer_pointer, can_do, &bytes); + if (res != FR_OK) { + file_raise_error(fp, res); + } + if (bytes != can_do) { + ff_read_fail(fp); + } + } +} + +OMV_ATTR_ALWAYS_INLINE static void file_flush(FIL *fp) { + if (file_buffer_index == file_buffer_size) { + UINT bytes; + FRESULT res = f_write(fp, file_buffer_pointer, file_buffer_index, &bytes); + if (res != FR_OK) { + file_raise_error(fp, res); + } + if (bytes != file_buffer_index) { + ff_write_fail(fp); + } + file_buffer_pointer -= file_buffer_offset; + file_buffer_size += file_buffer_offset; + file_buffer_offset = 0; + file_buffer_index = 0; + } +} + +void file_buffer_on(FIL *fp) { + file_buffer_offset = f_tell(fp) % 4; + file_buffer_pointer = fb_alloc_all(&file_buffer_size, FB_ALLOC_PREFER_SIZE) + file_buffer_offset; + if (!file_buffer_size) { + mp_raise_msg(&mp_type_MemoryError, MP_ERROR_TEXT("No memory!")); + } + file_buffer_size -= file_buffer_offset; + file_buffer_index = 0; + if (fp->flag & FA_READ) { + uint32_t file_remaining = f_size(fp) - f_tell(fp); + uint32_t can_do = FF_MIN(file_buffer_size, file_remaining); + UINT bytes; + FRESULT res = f_read(fp, file_buffer_pointer, can_do, &bytes); + if (res != FR_OK) { + file_raise_error(fp, res); + } + if (bytes != can_do) { + ff_read_fail(fp); + } + } +} + +void file_buffer_off(FIL *fp) { + if ((fp->flag & FA_WRITE) && file_buffer_index) { + UINT bytes; + FRESULT res = f_write(fp, file_buffer_pointer, file_buffer_index, &bytes); + if (res != FR_OK) { + file_raise_error(fp, res); + } + if (bytes != file_buffer_index) { + ff_write_fail(fp); + } + } + file_buffer_pointer = 0; + fb_free(); +} + +void file_open(FIL *fp, const char *path, bool buffered, uint32_t flags) { + FRESULT res = file_ll_open(fp, path, flags); + if (res != FR_OK) { + file_raise_error(fp, res); + } + if (buffered) { + file_buffer_on(fp); + } +} + +void file_close(FIL *fp) { + if (file_buffer_pointer) { + file_buffer_off(fp); + } + + FRESULT res = f_close(fp); + if (res != FR_OK) { + file_raise_error(fp, res); + } +} + +void file_seek(FIL *fp, UINT offset) { + FRESULT res = f_lseek(fp, offset); + if (res != FR_OK) { + file_raise_error(fp, res); + } +} + +void file_truncate(FIL *fp) { + FRESULT res = f_truncate(fp); + if (res != FR_OK) { + file_raise_error(fp, res); + } +} + +void file_sync(FIL *fp) { + FRESULT res = f_sync(fp); + if (res != FR_OK) { + file_raise_error(fp, res); + } +} + +uint32_t file_tell(FIL *fp) { + if (file_buffer_pointer) { + if (fp->flag & FA_READ) { + return f_tell(fp) - file_buffer_size + file_buffer_index; + } else { + return f_tell(fp) + file_buffer_index; + } + } + return f_tell(fp); +} + +uint32_t file_size(FIL *fp) { + if (file_buffer_pointer) { + if (fp->flag & FA_READ) { + return f_size(fp); + } else { + return f_size(fp) + file_buffer_index; + } + } + return f_size(fp); +} + +void file_read(FIL *fp, void *data, size_t size) { + if (data == NULL) { + uint8_t byte; + if (file_buffer_pointer) { + for (size_t i = 0; i < size; i++) { + file_fill(fp); + byte = file_buffer_pointer[file_buffer_index++]; + } + } else { + for (size_t i = 0; i < size; i++) { + UINT bytes; + FRESULT res = f_read(fp, &byte, 1, &bytes); + if (res != FR_OK) { + file_raise_error(fp, res); + } + if (bytes != 1) { + ff_read_fail(fp); + } + } + } + return; + } + + if (file_buffer_pointer) { + if (size <= 4) { + for (size_t i = 0; i < size; i++) { + file_fill(fp); + ((uint8_t *) data)[i] = file_buffer_pointer[file_buffer_index++]; + } + } else { + while (size) { + file_fill(fp); + uint32_t file_buffer_space_left = file_buffer_size - file_buffer_index; + uint32_t can_do = FF_MIN(size, file_buffer_space_left); + memcpy(data, file_buffer_pointer + file_buffer_index, can_do); + file_buffer_index += can_do; + data += can_do; + size -= can_do; + } + } + } else { + UINT bytes; + FRESULT res = f_read(fp, data, size, &bytes); + if (res != FR_OK) { + file_raise_error(fp, res); + } + if (bytes != size) { + ff_read_fail(fp); + } + } +} + +void file_write(FIL *fp, const void *data, size_t size) { + if (file_buffer_pointer) { + // We get a massive speed boost by buffering up as much data as possible + // before a write to the SD card. So much so that the time wasted by + // all these operations does not cost us. + while (size) { + uint32_t file_buffer_space_left = file_buffer_size - file_buffer_index; + uint32_t can_do = FF_MIN(size, file_buffer_space_left); + memcpy(file_buffer_pointer + file_buffer_index, data, can_do); + file_buffer_index += can_do; + data += can_do; + size -= can_do; + file_flush(fp); + } + } else { + UINT bytes; + FRESULT res = f_write(fp, data, size, &bytes); + if (res != FR_OK) { + file_raise_error(fp, res); + } + if (bytes != size) { + ff_write_fail(fp); + } + } +} + +void file_write_byte(FIL *fp, uint8_t value) { + file_write(fp, &value, 1); +} + +void file_write_short(FIL *fp, uint16_t value) { + file_write(fp, &value, 2); +} + +void file_write_long(FIL *fp, uint32_t value) { + file_write(fp, &value, 4); +} + +void file_read_check(FIL *fp, const void *data, size_t size) { + uint8_t buf[16]; + while (size) { + size_t len = OMV_MIN(sizeof(buf), size); + file_read(fp, buf, len); + if (memcmp(data, buf, len)) { + ff_expect_fail(fp); + } + size -= len; + data = ((uint8_t *) data) + len; + } +} +#endif //IMLIB_ENABLE_IMAGE_FILE_IO diff --git a/src/omv/common/file_utils.h b/src/omv/common/file_utils.h new file mode 100644 index 000000000..2eed5bfea --- /dev/null +++ b/src/omv/common/file_utils.h @@ -0,0 +1,52 @@ +/* + * This file is part of the OpenMV project. + * Copyright (c) 2013-2023 Kwabena W. Agyeman + * This work is licensed under the MIT license, see the file LICENSE for details. + * + * Filesystem helper functions. + * + */ +#ifndef __FILE_UTILS_H__ +#define __FILE_UTILS_H__ +#include +#include +#include +extern const char *ffs_strerror(FRESULT res); + +void file_raise_format(FIL *fp); +void file_raise_corrupted(FIL *fp); +void file_raise_error(FIL *fp, FRESULT res); + +// These low-level functions/wrappers don't use file buffering, +// and they don't raise any exceptions, so they're safe to call +// from anywhere. +FRESULT file_ll_open(FIL *fp, const TCHAR *path, BYTE mode); +FRESULT file_ll_close(FIL *fp); +FRESULT file_ll_read(FIL *fp, void *buff, UINT btr, UINT *br); +FRESULT file_ll_write(FIL *fp, const void *buff, UINT btw, UINT *bw); +FRESULT file_ll_opendir(FF_DIR *dp, const TCHAR *path); +FRESULT file_ll_stat(const TCHAR *path, FILINFO *fno); +FRESULT file_ll_mkdir(const TCHAR *path); +FRESULT file_ll_unlink(const TCHAR *path); +FRESULT file_ll_rename(const TCHAR *path_old, const TCHAR *path_new); +FRESULT file_ll_touch(const TCHAR *path); + +// File buffer functions. +void file_buffer_init0(); +void file_buffer_on(FIL *fp); // Calls fb_alloc_all() +void file_buffer_off(FIL *fp); // Calls fb_free() + +void file_open(FIL *fp, const char *path, bool buffered, uint32_t flags); +void file_close(FIL *fp); +void file_seek(FIL *fp, UINT offset); +void file_truncate(FIL *fp); +void file_sync(FIL *fp); +uint32_t file_tell(FIL *fp); +uint32_t file_size(FIL *fp); +void file_read(FIL *fp, void *data, size_t size); +void file_write(FIL *fp, const void *data, size_t size); +void file_write_byte(FIL *fp, uint8_t value); +void file_write_short(FIL *fp, uint16_t value); +void file_write_long(FIL *fp, uint32_t value); +void file_read_check(FIL *fp, const void *data, size_t size); +#endif /* __FILE_UTILS_H__ */ diff --git a/src/omv/common/ini.c b/src/omv/common/ini.c index 2ae5326a3..bdf86069e 100644 --- a/src/omv/common/ini.c +++ b/src/omv/common/ini.c @@ -12,6 +12,7 @@ #include #include #include "ini.h" +#include "file_utils.h" /*------------------------------------------------------------------------- _isppace.c - part of ctype.h @@ -190,7 +191,7 @@ int ini_fgetc(FIL *fp) { char c; UINT b; - if (f_read(fp, &c, 1, &b) != FR_OK || b != 1) { + if (file_ll_read(fp, &c, 1, &b) != FR_OK || b != 1) { return (EOF); } return (c); diff --git a/src/omv/common/ini.h b/src/omv/common/ini.h index e802845d0..27fda93dc 100644 --- a/src/omv/common/ini.h +++ b/src/omv/common/ini.h @@ -21,7 +21,7 @@ bool ini_is_true(const char *value); extern "C" { #endif -#include "ff_wrapper.h" +#include "file_utils.h" /* Nonzero if ini_handler callback should accept lineno parameter. */ #ifndef INI_HANDLER_LINENO diff --git a/src/omv/common/usbdbg.c b/src/omv/common/usbdbg.c index cabc0ecf9..c21f777b7 100644 --- a/src/omv/common/usbdbg.c +++ b/src/omv/common/usbdbg.c @@ -24,7 +24,6 @@ #include "sensor.h" #endif #include "framebuffer.h" -#include "ff.h" #include "usbdbg.h" #include "omv_boardconfig.h" #include "py_image.h" diff --git a/src/omv/imlib/bmp.c b/src/omv/imlib/bmp.c index 23b08f504..a0c36ba80 100644 --- a/src/omv/imlib/bmp.c +++ b/src/omv/imlib/bmp.c @@ -16,157 +16,148 @@ #include "py/runtime.h" #include "xalloc.h" -#include "ff_wrapper.h" +#include "file_utils.h" // This function inits the geometry values of an image (opens file). bool bmp_read_geometry(FIL *fp, image_t *img, const char *path, bmp_read_settings_t *rs) { - read_byte_expect(fp, 'B'); - read_byte_expect(fp, 'M'); + file_read_check(fp, "BM", 2); uint32_t file_size; - read_long(fp, &file_size); - read_word_ignore(fp); - read_word_ignore(fp); + file_read(fp, &file_size, 4); + file_read(fp, NULL, 4); uint32_t header_size; - read_long(fp, &header_size); + file_read(fp, &header_size, 4); if (file_size <= header_size) { - ff_file_corrupted(fp); + file_raise_corrupted(fp); } uint32_t data_size = file_size - header_size; if (data_size % 4) { - ff_file_corrupted(fp); + file_raise_corrupted(fp); } uint32_t header_type; - read_long(fp, &header_type); + file_read(fp, &header_type, 4); if ((header_type != 40) // BITMAPINFOHEADER && (header_type != 52) // BITMAPV2INFOHEADER && (header_type != 56) // BITMAPV3INFOHEADER && (header_type != 108) // BITMAPV4HEADER && (header_type != 124)) { - ff_unsupported_format(fp); // BITMAPV5HEADER + file_raise_format(fp); // BITMAPV5HEADER } - read_long(fp, (uint32_t *) &rs->bmp_w); - read_long(fp, (uint32_t *) &rs->bmp_h); + file_read(fp, &rs->bmp_w, 4); + file_read(fp, &rs->bmp_h, 4); if ((rs->bmp_w == 0) || (rs->bmp_h == 0)) { - ff_file_corrupted(fp); + file_raise_corrupted(fp); } img->w = abs(rs->bmp_w); img->h = abs(rs->bmp_h); - read_word_expect(fp, 1); - read_word(fp, &rs->bmp_bpp); + file_read_check(fp, &(uint32_t) {1}, 2); + file_read(fp, &rs->bmp_bpp, 2); if ((rs->bmp_bpp != 8) && (rs->bmp_bpp != 16) && (rs->bmp_bpp != 24)) { - ff_unsupported_format(fp); + file_raise_format(fp); } img->pixfmt = (rs->bmp_bpp == 8) ? PIXFORMAT_GRAYSCALE : PIXFORMAT_RGB565; - read_long(fp, &rs->bmp_fmt); + file_read(fp, &rs->bmp_fmt, 4); if ((rs->bmp_fmt != 0) && (rs->bmp_fmt != 3)) { - ff_unsupported_format(fp); + file_raise_format(fp); } - read_long_expect(fp, data_size); - read_long_ignore(fp); - read_long_ignore(fp); - read_long_ignore(fp); - read_long_ignore(fp); + file_read_check(fp, &data_size, 4); + file_read(fp, NULL, 16); if (rs->bmp_bpp == 8) { if (rs->bmp_fmt != 0) { - ff_unsupported_format(fp); + file_raise_format(fp); } if (header_type >= 52) { // Skip past the remaining BITMAPV2INFOHEADER bytes. for (int i = 0; i < 3; i++) { - read_long_ignore(fp); + file_read(fp, NULL, 4); } } if (header_type >= 56) { // Skip past the remaining BITMAPV3INFOHEADER bytes. for (int i = 0; i < 1; i++) { - read_long_ignore(fp); + file_read(fp, NULL, 4); } } if (header_type >= 108) { // Skip past the remaining BITMAPV4HEADER bytes. for (int i = 0; i < 13; i++) { - read_long_ignore(fp); + file_read(fp, NULL, 4); } } if (header_type >= 124) { // Skip past the remaining BITMAPV5HEADER bytes. for (int i = 0; i < 4; i++) { - read_long_ignore(fp); + file_read(fp, NULL, 4); } } // Color Table (1024 bytes) for (int i = 0; i < 256; i++) { - read_long_expect(fp, ((i) << 16) | ((i) << 8) | i); + file_read_check(fp, &(uint32_t) {((i) << 16) | ((i) << 8) | i}, 4); } } else if (rs->bmp_bpp == 16) { if (rs->bmp_fmt != 3) { - ff_unsupported_format(fp); + file_raise_format(fp); } // Bit Masks (12 bytes) - read_long_expect(fp, 0x1F << 11); - read_long_expect(fp, 0x3F << 5); - read_long_expect(fp, 0x1F); + file_read_check(fp, (uint32_t [3]) {0x1F << 11, 0x3F << 5, 0x1F}, 12); if (header_type >= 56) { // Skip past the remaining BITMAPV3INFOHEADER bytes. for (int i = 0; i < 1; i++) { - read_long_ignore(fp); + file_read(fp, NULL, 4); } } if (header_type >= 108) { // Skip past the remaining BITMAPV4HEADER bytes. for (int i = 0; i < 13; i++) { - read_long_ignore(fp); + file_read(fp, NULL, 4); } } if (header_type >= 124) { // Skip past the remaining BITMAPV5HEADER bytes. for (int i = 0; i < 4; i++) { - read_long_ignore(fp); + file_read(fp, NULL, 4); } } } else if (rs->bmp_bpp == 24) { if (rs->bmp_fmt == 3) { // Bit Masks (12 bytes) - read_long_expect(fp, 0xFF << 16); - read_long_expect(fp, 0xFF << 8); - read_long_expect(fp, 0xFF); + file_read_check(fp, (uint32_t [3]) {0xFF << 16, 0xFF << 8, 0xFF}, 12); } else if (header_type >= 52) { // Skip past the remaining BITMAPV2INFOHEADER bytes. for (int i = 0; i < 3; i++) { - read_long_ignore(fp); + file_read(fp, NULL, 4); } } if (header_type >= 56) { // Skip past the remaining BITMAPV3INFOHEADER bytes. for (int i = 0; i < 1; i++) { - read_long_ignore(fp); + file_read(fp, NULL, 4); } } if (header_type >= 108) { // Skip past the remaining BITMAPV4HEADER bytes. for (int i = 0; i < 13; i++) { - read_long_ignore(fp); + file_read(fp, NULL, 4); } } if (header_type >= 124) { // Skip past the remaining BITMAPV5HEADER bytes. for (int i = 0; i < 4; i++) { - read_long_ignore(fp); + file_read(fp, NULL, 4); } } } rs->bmp_row_bytes = (((img->w * rs->bmp_bpp) + 31) / 32) * 4; if (data_size != (rs->bmp_row_bytes * img->h)) { - ff_file_corrupted(fp); + file_raise_corrupted(fp); } return (rs->bmp_h >= 0); } @@ -175,12 +166,12 @@ bool bmp_read_geometry(FIL *fp, image_t *img, const char *path, bmp_read_setting void bmp_read_pixels(FIL *fp, image_t *img, int n_lines, bmp_read_settings_t *rs) { if (rs->bmp_bpp == 8) { if ((rs->bmp_h < 0) && (rs->bmp_w >= 0) && (img->w == rs->bmp_row_bytes)) { - read_data(fp, img->pixels, n_lines * img->w); + file_read(fp, img->pixels, n_lines * img->w); } else { for (int i = 0; i < n_lines; i++) { for (int j = 0; j < rs->bmp_row_bytes; j++) { uint8_t pixel; - read_byte(fp, &pixel); + file_read(fp, &pixel, 1); if (j < img->w) { if (rs->bmp_h < 0) { // vertical flip (BMP file perspective) @@ -205,7 +196,7 @@ void bmp_read_pixels(FIL *fp, image_t *img, int n_lines, bmp_read_settings_t *rs for (int i = 0; i < n_lines; i++) { for (int j = 0, jj = rs->bmp_row_bytes / 2; j < jj; j++) { uint16_t pixel; - read_word(fp, &pixel); + file_read(fp, &pixel, 2); if (j < img->w) { if (rs->bmp_h < 0) { // vertical flip (BMP file perspective) @@ -229,9 +220,9 @@ void bmp_read_pixels(FIL *fp, image_t *img, int n_lines, bmp_read_settings_t *rs for (int i = 0; i < n_lines; i++) { for (int j = 0, jj = rs->bmp_row_bytes / 3; j < jj; j++) { uint8_t b, g, r; - read_byte(fp, &b); - read_byte(fp, &g); - read_byte(fp, &r); + file_read(fp, &b, 1); + file_read(fp, &g, 1); + file_read(fp, &r, 1); uint16_t pixel = COLOR_R8_G8_B8_TO_RGB565(r, g, b); if (j < img->w) { if (rs->bmp_h < 0) { @@ -252,7 +243,7 @@ void bmp_read_pixels(FIL *fp, image_t *img, int n_lines, bmp_read_settings_t *rs } } for (int j = 0, jj = rs->bmp_row_bytes % 3; j < jj; j++) { - read_byte_ignore(fp); + file_read(fp, NULL, 1); } } } @@ -261,17 +252,33 @@ void bmp_read_pixels(FIL *fp, image_t *img, int n_lines, bmp_read_settings_t *rs void bmp_read(image_t *img, const char *path) { FIL fp; bmp_read_settings_t rs; - file_read_open(&fp, path); - file_buffer_on(&fp); + file_open(&fp, path, true, FA_READ | FA_OPEN_EXISTING); bmp_read_geometry(&fp, img, path, &rs); if (!img->pixels) { img->pixels = xalloc(img->w * img->h * img->bpp); } bmp_read_pixels(&fp, img, img->h, &rs); - file_buffer_off(&fp); file_close(&fp); } +static void bmp_write_header(FIL *fp, uint32_t header_size, uint32_t data_size, + uint32_t bpp, uint32_t ncomp, rectangle_t *r) { + // File Header (14 bytes) + file_write(fp, "BM", 2); + file_write_long(fp, 14 + 40 + header_size + data_size); + file_write_long(fp, 0); + file_write_long(fp, 14 + 40 + header_size); + // Info Header (40 bytes) + file_write_long(fp, 40); + file_write_long(fp, r->w); + file_write_long(fp, -r->h); // store the image flipped (correctly) + file_write_short(fp, 1); + file_write_short(fp, bpp); + file_write_long(fp, ncomp); + file_write_long(fp, data_size); + file_write(fp, (uint8_t [16]) {0}, 16); +} + void bmp_write_subimg(image_t *img, const char *path, rectangle_t *r) { rectangle_t rect; if (!rectangle_subimg(img, r, &rect)) { @@ -279,44 +286,25 @@ void bmp_write_subimg(image_t *img, const char *path, rectangle_t *r) { } FIL fp; - file_write_open(&fp, path); - file_buffer_on(&fp); + file_open(&fp, path, true, FA_WRITE | FA_CREATE_ALWAYS); + if (IM_IS_GS(img)) { const int row_bytes = (((rect.w * 8) + 31) / 32) * 4; const int data_size = (row_bytes * rect.h); const int waste = (row_bytes / sizeof(uint8_t)) - rect.w; - // File Header (14 bytes) - write_byte(&fp, 'B'); - write_byte(&fp, 'M'); - write_long(&fp, 14 + 40 + 1024 + data_size); - write_word(&fp, 0); - write_word(&fp, 0); - write_long(&fp, 14 + 40 + 1024); - // Info Header (40 bytes) - write_long(&fp, 40); - write_long(&fp, rect.w); - write_long(&fp, -rect.h); // store the image flipped (correctly) - write_word(&fp, 1); - write_word(&fp, 8); - write_long(&fp, 0); - write_long(&fp, data_size); - write_long(&fp, 0); - write_long(&fp, 0); - write_long(&fp, 0); - write_long(&fp, 0); - // Color Table (1024 bytes) + // Write BMP file header + bmp_write_header(&fp, 1024, data_size, 8, 0, &rect); + // Write color Table (1024 bytes) for (int i = 0; i < 256; i++) { - write_long(&fp, ((i) << 16) | ((i) << 8) | i); + file_write_long(&fp, ((i) << 16) | ((i) << 8) | i); } if ((rect.x == 0) && (rect.w == img->w) && (img->w == row_bytes)) { - write_data(&fp, // Super Fast - Zoom, Zoom! - img->pixels + (rect.y * img->w), - rect.w * rect.h); + file_write(&fp, img->pixels + (rect.y * img->w), rect.w * rect.h); } else { for (int i = 0; i < rect.h; i++) { - write_data(&fp, img->pixels + ((rect.y + i) * img->w) + rect.x, rect.w); + file_write(&fp, img->pixels + ((rect.y + i) * img->w) + rect.x, rect.w); for (int j = 0; j < waste; j++) { - write_byte(&fp, 0); + file_write_byte(&fp, 0); } } } @@ -324,40 +312,21 @@ void bmp_write_subimg(image_t *img, const char *path, rectangle_t *r) { const int row_bytes = (((rect.w * 16) + 31) / 32) * 4; const int data_size = (row_bytes * rect.h); const int waste = (row_bytes / sizeof(uint16_t)) - rect.w; - // File Header (14 bytes) - write_byte(&fp, 'B'); - write_byte(&fp, 'M'); - write_long(&fp, 14 + 40 + 12 + data_size); - write_word(&fp, 0); - write_word(&fp, 0); - write_long(&fp, 14 + 40 + 12); - // Info Header (40 bytes) - write_long(&fp, 40); - write_long(&fp, rect.w); - write_long(&fp, -rect.h); // store the image flipped (correctly) - write_word(&fp, 1); - write_word(&fp, 16); - write_long(&fp, 3); - write_long(&fp, data_size); - write_long(&fp, 0); - write_long(&fp, 0); - write_long(&fp, 0); - write_long(&fp, 0); - // Bit Masks (12 bytes) - write_long(&fp, 0x1F << 11); - write_long(&fp, 0x3F << 5); - write_long(&fp, 0x1F); + // Write BMP file header + bmp_write_header(&fp, 12, data_size, 16, 3, &rect); + // Write Bit Masks (12 bytes) + file_write_long(&fp, 0x1F << 11); + file_write_long(&fp, 0x3F << 5); + file_write_long(&fp, 0x1F); for (int i = 0; i < rect.h; i++) { for (int j = 0; j < rect.w; j++) { - write_word(&fp, IM_GET_RGB565_PIXEL(img, (rect.x + j), (rect.y + i))); + file_write_short(&fp, IM_GET_RGB565_PIXEL(img, (rect.x + j), (rect.y + i))); } for (int j = 0; j < waste; j++) { - write_word(&fp, 0); + file_write_short(&fp, 0); } } } - file_buffer_off(&fp); - file_close(&fp); } #endif //IMLIB_ENABLE_IMAGE_FILE_IO diff --git a/src/omv/imlib/fft.c b/src/omv/imlib/fft.c index 0aeca21a0..f4fa30f46 100644 --- a/src/omv/imlib/fft.c +++ b/src/omv/imlib/fft.c @@ -10,7 +10,7 @@ #include "py/obj.h" #include #include "fb_alloc.h" -#include "ff_wrapper.h" +#include "file_utils.h" #include "omv_common.h" #include "fft.h" // http://processors.wiki.ti.com/index.php/Efficient_FFT_Computation_of_Real_Input diff --git a/src/omv/imlib/gif.c b/src/omv/imlib/gif.c index c39239da3..f430f2412 100644 --- a/src/omv/imlib/gif.c +++ b/src/omv/imlib/gif.c @@ -12,35 +12,34 @@ #if defined(IMLIB_ENABLE_IMAGE_FILE_IO) #include "fb_alloc.h" -#include "ff_wrapper.h" +#include "file_utils.h" #define BLOCK_SIZE (126) // (2^7) - 2 // (DO NOT CHANGE!) void gif_open(FIL *fp, int width, int height, bool color, bool loop) { file_buffer_on(fp); - write_data(fp, "GIF89a", 6); - write_word(fp, width); - write_word(fp, height); - write_data(fp, (uint8_t []) {0xF6, 0x00, 0x00}, 3); + file_write(fp, "GIF89a", 6); + file_write(fp, (uint16_t []) {width, height}, 4); + file_write(fp, (uint8_t []) {0xF6, 0x00, 0x00}, 3); if (color) { for (int i = 0; i < 128; i++) { int red = ((((i & 0x60) >> 5) * 255) + 1.5) / 3; int green = ((((i & 0x1C) >> 2) * 255) + 3.5) / 7; int blue = (((i & 0x3) * 255) + 1.5) / 3; - write_data(fp, (uint8_t []) {red, green, blue}, 3); + file_write(fp, (uint8_t []) {red, green, blue}, 3); } } else { for (int i = 0; i < 128; i++) { int gray = ((i * 255) + 63.5) / 127; - write_data(fp, (uint8_t []) {gray, gray, gray}, 3); + file_write(fp, (uint8_t []) {gray, gray, gray}, 3); } } if (loop) { - write_data(fp, (uint8_t []) {'!', 0xFF, 0x0B}, 3); - write_data(fp, "NETSCAPE2.0", 11); - write_data(fp, (uint8_t []) {0x03, 0x01, 0x00, 0x00, 0x00}, 5); + file_write(fp, (uint8_t []) {'!', 0xFF, 0x0B}, 3); + file_write(fp, "NETSCAPE2.0", 11); + file_write(fp, (uint8_t []) {0x03, 0x01, 0x00, 0x00, 0x00}, 5); } file_buffer_off(fp); @@ -50,16 +49,15 @@ void gif_add_frame(FIL *fp, image_t *img, uint16_t delay) { file_buffer_on(fp); if (delay) { - write_data(fp, (uint8_t []) {'!', 0xF9, 0x04, 0x04}, 4); - write_word(fp, delay); - write_word(fp, 0); // end + file_write(fp, (uint8_t []) {'!', 0xF9, 0x04, 0x04}, 4); + file_write_short(fp, delay); + file_write_short(fp, 0); // end } - write_byte(fp, 0x2C); - write_long(fp, 0); - write_word(fp, img->w); - write_word(fp, img->h); - write_data(fp, (uint8_t []) {0x00, 0x07}, 2); // 7-bits + file_write_byte(fp, 0x2C); + file_write_long(fp, 0); + file_write(fp, (uint16_t []) {img->w, img->h}, 4); + file_write(fp, (uint8_t []) {0x00, 0x07}, 2); // 7-bits int bytes = img->h * img->w; int blocks = (bytes + BLOCK_SIZE - 1) / BLOCK_SIZE; @@ -67,30 +65,30 @@ void gif_add_frame(FIL *fp, image_t *img, uint16_t delay) { if (IM_IS_GS(img)) { for (int y = 0; y < blocks; y++) { int block_size = IM_MIN(BLOCK_SIZE, bytes - (y * BLOCK_SIZE)); - write_byte(fp, 1 + block_size); - write_byte(fp, 0x80); // clear code + file_write_byte(fp, 1 + block_size); + file_write_byte(fp, 0x80); // clear code for (int x = 0; x < block_size; x++) { - write_byte(fp, img->pixels[(y * BLOCK_SIZE) + x] >> 1); + file_write_byte(fp, img->pixels[(y * BLOCK_SIZE) + x] >> 1); } } } else if (IM_IS_RGB565(img)) { for (int y = 0; y < blocks; y++) { int block_size = IM_MIN(BLOCK_SIZE, bytes - (y * BLOCK_SIZE)); - write_byte(fp, 1 + block_size); - write_byte(fp, 0x80); // clear code + file_write_byte(fp, 1 + block_size); + file_write_byte(fp, 0x80); // clear code for (int x = 0; x < block_size; x++) { - int pixel = ((uint16_t *) img->pixels)[(y * BLOCK_SIZE) + x]; - int red = COLOR_RGB565_TO_R5(pixel) >> 3; - int green = COLOR_RGB565_TO_G6(pixel) >> 3; - int blue = COLOR_RGB565_TO_B5(pixel) >> 3; - write_byte(fp, (red << 5) | (green << 2) | blue); + uint16_t pixel = ((uint16_t *) img->pixels)[(y * BLOCK_SIZE) + x]; + uint16_t r = COLOR_RGB565_TO_R5(pixel) >> 3; + uint16_t g = COLOR_RGB565_TO_G6(pixel) >> 3; + uint16_t b = COLOR_RGB565_TO_B5(pixel) >> 3; + file_write_byte(fp, (r << 5) | (g << 2) | b); } } } else if (img->is_bayer || img->is_yuv) { for (int y = 0; y < blocks; y++) { int block_size = IM_MIN(BLOCK_SIZE, bytes - (y * BLOCK_SIZE)); - write_byte(fp, 1 + block_size); - write_byte(fp, 0x80); // clear code + file_write_byte(fp, 1 + block_size); + file_write_byte(fp, 0x80); // clear code uint16_t pixels[block_size]; if (img->is_bayer) { imlib_debayer_line(0, block_size, y, pixels, PIXFORMAT_RGB565, img); @@ -98,22 +96,22 @@ void gif_add_frame(FIL *fp, image_t *img, uint16_t delay) { imlib_deyuv_line(0, block_size, y, pixels, PIXFORMAT_RGB565, img); } for (int x = 0; x < block_size; x++) { - int r = COLOR_RGB565_TO_R8(pixels[x]); - int g = COLOR_RGB565_TO_G8(pixels[x]); - int b = COLOR_RGB565_TO_B8(pixels[x]); - r >>= 3; g >>= 3; b >>= 3; - write_byte(fp, (r << 5) | (g << 2) | b); + uint16_t pixel = pixels[2]; + uint16_t r = COLOR_RGB565_TO_R5(pixel) >> 3; + uint16_t g = COLOR_RGB565_TO_G6(pixel) >> 3; + uint16_t b = COLOR_RGB565_TO_B5(pixel) >> 3; + file_write_byte(fp, (r << 5) | (g << 2) | b); } } } - write_data(fp, (uint8_t []) {0x01, 0x81, 0x00}, 3); // end code + file_write(fp, (uint8_t []) {0x01, 0x81, 0x00}, 3); // end code file_buffer_off(fp); } void gif_close(FIL *fp) { - write_byte(fp, ';'); + file_write_byte(fp, ';'); file_close(fp); } #endif //IMLIB_ENABLE_IMAGE_FILE_IO diff --git a/src/omv/imlib/haar.c b/src/omv/imlib/haar.c index 5817a9882..ec462cbb5 100644 --- a/src/omv/imlib/haar.c +++ b/src/omv/imlib/haar.c @@ -13,12 +13,11 @@ #include "py/obj.h" #include "py/nlr.h" -#include "ff.h" -#include "ff_wrapper.h" #include "xalloc.h" #include "imlib.h" // built-in cascades #include "cascade.h" +#include "file_utils.h" static int eval_weak_classifier(cascade_t *cascade, point_t pt, int t_idx, int w_idx, int r_idx) { int32_t sumw = 0; @@ -169,14 +168,13 @@ int imlib_load_cascade_from_file(cascade_t *cascade, const char *path) { FIL fp; FRESULT res = FR_OK; - file_read_open(&fp, path); - file_buffer_on(&fp); + file_open(&fp, path, true, FA_READ | FA_OPEN_EXISTING); - /* read detection window size */ - read_data(&fp, &cascade->window, sizeof(cascade->window)); + // Read detection window size + file_read(&fp, &cascade->window, sizeof(cascade->window)); - /* read num stages */ - read_data(&fp, &cascade->n_stages, sizeof(cascade->n_stages)); + // Read num stages + file_read(&fp, &cascade->n_stages, sizeof(cascade->n_stages)); cascade->stages_array = xalloc(sizeof(*cascade->stages_array) * cascade->n_stages); cascade->stages_thresh_array = xalloc(sizeof(*cascade->stages_thresh_array) * cascade->n_stages); @@ -187,7 +185,7 @@ int imlib_load_cascade_from_file(cascade_t *cascade, const char *path) { } /* read num features in each stages */ - read_data(&fp, cascade->stages_array, sizeof(uint8_t) * cascade->n_stages); + file_read(&fp, cascade->stages_array, sizeof(uint8_t) * cascade->n_stages); /* sum num of features in each stages*/ for (i = 0, cascade->n_features = 0; i < cascade->n_stages; i++) { @@ -209,19 +207,19 @@ int imlib_load_cascade_from_file(cascade_t *cascade, const char *path) { } /* read stages thresholds */ - read_data(&fp, cascade->stages_thresh_array, sizeof(int16_t) * cascade->n_stages); + file_read(&fp, cascade->stages_thresh_array, sizeof(int16_t) * cascade->n_stages); /* read features thresholds */ - read_data(&fp, cascade->tree_thresh_array, sizeof(*cascade->tree_thresh_array) * cascade->n_features); + file_read(&fp, cascade->tree_thresh_array, sizeof(*cascade->tree_thresh_array) * cascade->n_features); /* read alpha 1 */ - read_data(&fp, cascade->alpha1_array, sizeof(*cascade->alpha1_array) * cascade->n_features); + file_read(&fp, cascade->alpha1_array, sizeof(*cascade->alpha1_array) * cascade->n_features); /* read alpha 2 */ - read_data(&fp, cascade->alpha2_array, sizeof(*cascade->alpha2_array) * cascade->n_features); + file_read(&fp, cascade->alpha2_array, sizeof(*cascade->alpha2_array) * cascade->n_features); /* read num rectangles per feature*/ - read_data(&fp, cascade->num_rectangles_array, sizeof(*cascade->num_rectangles_array) * cascade->n_features); + file_read(&fp, cascade->num_rectangles_array, sizeof(*cascade->num_rectangles_array) * cascade->n_features); /* sum num of recatngles per feature*/ for (i = 0, cascade->n_rectangles = 0; i < cascade->n_features; i++) { @@ -238,13 +236,12 @@ int imlib_load_cascade_from_file(cascade_t *cascade, const char *path) { } /* read rectangles weights */ - read_data(&fp, cascade->weights_array, sizeof(*cascade->weights_array) * cascade->n_rectangles); + file_read(&fp, cascade->weights_array, sizeof(*cascade->weights_array) * cascade->n_rectangles); /* read rectangles num rectangles * 4 points */ - read_data(&fp, cascade->rectangles_array, sizeof(*cascade->rectangles_array) * cascade->n_rectangles * 4); + file_read(&fp, cascade->rectangles_array, sizeof(*cascade->rectangles_array) * cascade->n_rectangles * 4); error: - file_buffer_off(&fp); file_close(&fp); return res; } diff --git a/src/omv/imlib/imlib.c b/src/omv/imlib/imlib.c index 5feca2dab..c04f72d8b 100644 --- a/src/omv/imlib/imlib.c +++ b/src/omv/imlib/imlib.c @@ -14,7 +14,7 @@ #include "font.h" #include "array.h" -#include "ff_wrapper.h" +#include "file_utils.h" #include "imlib.h" #include "omv_common.h" #include "omv_boardconfig.h" @@ -562,9 +562,9 @@ static save_image_format_t imblib_parse_extension(image_t *img, const char *path } bool imlib_read_geometry(FIL *fp, image_t *img, const char *path, img_read_settings_t *rs) { - file_read_open(fp, path); char magic[4]; - read_data(fp, &magic, 4); + file_open(fp, path, false, FA_READ | FA_OPEN_EXISTING); + file_read(fp, &magic, 4); file_close(fp); bool vflipped = false; @@ -573,31 +573,27 @@ bool imlib_read_geometry(FIL *fp, image_t *img, const char *path, img_read_setti || (magic[1] == '5') || (magic[1] == '6'))) { // PPM rs->format = FORMAT_PNM; - file_read_open(fp, path); - file_buffer_on(fp); // REMEMBER TO TURN THIS OFF LATER! + file_open(fp, path, true, FA_READ | FA_OPEN_EXISTING); ppm_read_geometry(fp, img, path, &rs->ppm_rs); } else if ((magic[0] == 'B') && (magic[1] == 'M')) { // BMP rs->format = FORMAT_BMP; - file_read_open(fp, path); - file_buffer_on(fp); // REMEMBER TO TURN THIS OFF LATER! + file_open(fp, path, true, FA_READ | FA_OPEN_EXISTING); vflipped = bmp_read_geometry(fp, img, path, &rs->bmp_rs); } else if ((magic[0] == 0xFF) && (magic[1] == 0xD8)) { // JPG rs->format = FORMAT_JPG; - file_read_open(fp, path); - // Do not use file_buffer_on() here. + file_open(fp, path, false, FA_READ | FA_OPEN_EXISTING); jpeg_read_geometry(fp, img, path, &rs->jpg_rs); - file_buffer_on(fp); // REMEMBER TO TURN THIS OFF LATER! + file_buffer_on(fp); } else if ((magic[0] == 0x89) && (magic[1] == 0x50) && (magic[2] == 0x4E) && (magic[3] == 0x47)) { // PNG rs->format = FORMAT_PNG; - file_read_open(fp, path); - // Do not use file_buffer_on() here. + file_open(fp, path, false, FA_READ | FA_OPEN_EXISTING); png_read_geometry(fp, img, path, &rs->png_rs); - file_buffer_on(fp); // REMEMBER TO TURN THIS OFF LATER! + file_buffer_on(fp); } else { - ff_unsupported_format(NULL); + file_raise_format(NULL); } imblib_parse_extension(img, path); // Enforce extension! return vflipped; @@ -631,7 +627,7 @@ void imlib_image_operation(image_t *img, const char *path, image_t *other, int s img_read_settings_t rs; bool vflipped = imlib_read_geometry(&fp, &temp, path, &rs); if (!IM_EQUAL(img, &temp)) { - f_close(&fp); + file_close(&fp); mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Images not equal!")); } // When processing vertically flipped images the read function will fill @@ -657,7 +653,6 @@ void imlib_image_operation(image_t *img, const char *path, image_t *other, int s } } } - file_buffer_off(&fp); file_close(&fp); fb_free(); #else @@ -744,9 +739,9 @@ void imlib_image_operation(image_t *img, const char *path, image_t *other, int s #if defined(IMLIB_ENABLE_IMAGE_FILE_IO) void imlib_load_image(image_t *img, const char *path) { FIL fp; - file_read_open(&fp, path); char magic[4]; - read_data(&fp, &magic, 4); + file_open(&fp, path, false, FA_READ | FA_OPEN_EXISTING); + file_read(&fp, &magic, 4); file_close(&fp); if ((magic[0] == 'P') @@ -764,7 +759,7 @@ void imlib_load_image(image_t *img, const char *path) { // PNG png_read(img, path); } else { - ff_unsupported_format(NULL); + file_raise_format(NULL); } imblib_parse_extension(img, path); // Enforce extension! } @@ -779,8 +774,8 @@ void imlib_save_image(image_t *img, const char *path, rectangle_t *roi, int qual break; case FORMAT_RAW: { FIL fp; - file_write_open(&fp, path); - write_data(&fp, img->pixels, img->w * img->h); + file_open(&fp, path, false, FA_WRITE | FA_CREATE_ALWAYS); + file_write(&fp, img->pixels, img->w * img->h); file_close(&fp); break; } @@ -803,8 +798,8 @@ void imlib_save_image(image_t *img, const char *path, rectangle_t *roi, int qual } else if (IM_IS_BAYER(img)) { FIL fp; char *new_path = strcat(strcpy(fb_alloc(strlen(path) + 5, FB_ALLOC_NO_HINT), path), ".raw"); - file_write_open(&fp, new_path); - write_data(&fp, img->pixels, img->w * img->h); + file_open(&fp, new_path, false, FA_WRITE | FA_CREATE_ALWAYS); + file_write(&fp, img->pixels, img->w * img->h); file_close(&fp); fb_free(); } else { diff --git a/src/omv/imlib/imlib.h b/src/omv/imlib/imlib.h index 1f945665b..2ae00327d 100644 --- a/src/omv/imlib/imlib.h +++ b/src/omv/imlib/imlib.h @@ -19,8 +19,8 @@ #include #include #include -#include #include "fb_alloc.h" +#include "file_utils.h" #include "umm_malloc.h" #include "xalloc.h" #include "array.h" diff --git a/src/omv/imlib/jpeg.c b/src/omv/imlib/jpeg.c index 7028f2061..22df93681 100644 --- a/src/omv/imlib/jpeg.c +++ b/src/omv/imlib/jpeg.c @@ -12,7 +12,7 @@ */ #include -#include "ff_wrapper.h" +#include "file_utils.h" #include "imlib.h" #include "omv_boardconfig.h" @@ -2202,7 +2202,7 @@ int jpeg_clean_trailing_bytes(int size, uint8_t *data) { void jpeg_read_geometry(FIL *fp, image_t *img, const char *path, jpg_read_settings_t *rs) { for (;;) { uint16_t header; - read_word(fp, &header); + file_read(fp, &header, 2); header = __REV16(header); if ((0xFFD0 <= header) && (header <= 0xFFD9)) { continue; @@ -2211,19 +2211,19 @@ void jpeg_read_geometry(FIL *fp, image_t *img, const char *path, jpg_read_settin || ((0xFFE0 <= header) && (header <= 0xFFEF)) || ((0xFFF0 <= header) && (header <= 0xFFFE))) { uint16_t size; - read_word(fp, &size); + file_read(fp, &size, 2); size = __REV16(size); if (((0xFFC0 <= header) && (header <= 0xFFC3)) || ((0xFFC5 <= header) && (header <= 0xFFC7)) || ((0xFFC9 <= header) && (header <= 0xFFCB)) || ((0xFFCD <= header) && (header <= 0xFFCF))) { - read_byte_ignore(fp); + file_read(fp, NULL, 1); uint16_t height; - read_word(fp, &height); + file_read(fp, &height, 2); height = __REV16(height); uint16_t width; - read_word(fp, &width); + file_read(fp, &width, 2); width = __REV16(width); rs->jpg_w = width; @@ -2239,7 +2239,7 @@ void jpeg_read_geometry(FIL *fp, image_t *img, const char *path, jpg_read_settin file_seek(fp, f_tell(fp) + size - 2); } } else { - ff_file_corrupted(fp); + file_raise_corrupted(fp); } } } @@ -2247,16 +2247,15 @@ void jpeg_read_geometry(FIL *fp, image_t *img, const char *path, jpg_read_settin // This function reads the pixel values of an image. void jpeg_read_pixels(FIL *fp, image_t *img) { file_seek(fp, 0); - read_data(fp, img->pixels, img->size); + file_read(fp, img->pixels, img->size); } void jpeg_read(image_t *img, const char *path) { FIL fp; jpg_read_settings_t rs; - file_read_open(&fp, path); - - // Do not use file_buffer_on() here. + // Do not use file buffering here. + file_open(&fp, path, false, FA_READ | FA_OPEN_EXISTING); jpeg_read_geometry(&fp, img, path, &rs); if (!img->pixels) { @@ -2269,16 +2268,16 @@ void jpeg_read(image_t *img, const char *path) { void jpeg_write(image_t *img, const char *path, int quality) { FIL fp; - file_write_open(&fp, path); + file_open(&fp, path, false, FA_WRITE | FA_CREATE_ALWAYS); if (IM_IS_JPEG(img)) { - write_data(&fp, img->pixels, img->size); + file_write(&fp, img->pixels, img->size); } else { image_t out = { .w = img->w, .h = img->h, .pixfmt = PIXFORMAT_JPEG, .size = 0, .pixels = NULL }; // alloc in jpeg compress // 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(img, &out, quality, false); - write_data(&fp, out.pixels, out.size); + file_write(&fp, out.pixels, out.size); fb_free(); // frees alloc in jpeg_compress() } file_close(&fp); diff --git a/src/omv/imlib/lbp.c b/src/omv/imlib/lbp.c index 468f95e9f..dc6280048 100644 --- a/src/omv/imlib/lbp.c +++ b/src/omv/imlib/lbp.c @@ -16,7 +16,7 @@ #include "imlib.h" #include "xalloc.h" -#include "ff.h" +#include "file_utils.h" #ifdef IMLIB_ENABLE_FIND_LBP #define LBP_HIST_SIZE (59) //58 uniform hist + 1 @@ -93,7 +93,7 @@ int imlib_lbp_desc_distance(uint8_t *d0, uint8_t *d1) { int imlib_lbp_desc_save(FIL *fp, uint8_t *desc) { UINT bytes; // Write descriptor - return f_write(fp, desc, LBP_DESC_SIZE, &bytes); + return file_ll_write(fp, desc, LBP_DESC_SIZE, &bytes); } int imlib_lbp_desc_load(FIL *fp, uint8_t **desc) { @@ -104,7 +104,7 @@ int imlib_lbp_desc_load(FIL *fp, uint8_t **desc) { uint8_t *hist = xalloc(LBP_DESC_SIZE); // Read descriptor - res = f_read(fp, hist, LBP_DESC_SIZE, &bytes); + res = file_ll_read(fp, hist, LBP_DESC_SIZE, &bytes); if (res != FR_OK || bytes != LBP_DESC_SIZE) { *desc = NULL; xfree(hist); diff --git a/src/omv/imlib/mjpeg.c b/src/omv/imlib/mjpeg.c index 8b0e85212..f501aaf23 100644 --- a/src/omv/imlib/mjpeg.c +++ b/src/omv/imlib/mjpeg.c @@ -11,7 +11,7 @@ #include "imlib.h" #if defined(IMLIB_ENABLE_IMAGE_FILE_IO) -#include "ff_wrapper.h" +#include "file_utils.h" #define SIZE_OFFSET (1 * 4) #define MICROS_OFFSET (8 * 4) @@ -23,72 +23,72 @@ #define MOVI_OFFSET (54 * 4) void mjpeg_open(FIL *fp, int width, int height) { - write_data(fp, "RIFF", 4); // FOURCC fcc; - 0 - write_long(fp, 0); // DWORD cb; size - updated on close - 1 - write_data(fp, "AVI ", 4); // FOURCC fcc; - 2 + file_write(fp, "RIFF", 4); // FOURCC fcc; - 0 + file_write_long(fp, 0); // DWORD cb; size - updated on close - 1 + file_write(fp, "AVI ", 4); // FOURCC fcc; - 2 - write_data(fp, "LIST", 4); // FOURCC fcc; - 3 - write_long(fp, 192); // DWORD cb; - 4 - write_data(fp, "hdrl", 4); // FOURCC fcc; - 5 + file_write(fp, "LIST", 4); // FOURCC fcc; - 3 + file_write_long(fp, 192); // DWORD cb; - 4 + file_write(fp, "hdrl", 4); // FOURCC fcc; - 5 - write_data(fp, "avih", 4); // FOURCC fcc; - 6 - write_long(fp, 56); // DWORD cb; - 7 - write_long(fp, 0); // DWORD dwMicroSecPerFrame; micros - updated on close - 8 - write_long(fp, 0); // DWORD dwMaxBytesPerSec; updated on close - 9 - write_long(fp, 4); // DWORD dwPaddingGranularity; - 10 - write_long(fp, 0); // DWORD dwFlags; - 11 - write_long(fp, 0); // DWORD dwTotalFrames; frames - updated on close - 12 - write_long(fp, 0); // DWORD dwInitialFrames; - 13 - write_long(fp, 1); // DWORD dwStreams; - 14 - write_long(fp, 0); // DWORD dwSuggestedBufferSize; - 15 - write_long(fp, width); // DWORD dwWidth; - 16 - write_long(fp, height); // DWORD dwHeight; - 17 - write_long(fp, 1000); // DWORD dwScale; - 18 - write_long(fp, 0); // DWORD dwRate; rate - updated on close - 19 - write_long(fp, 0); // DWORD dwStart; - 20 - write_long(fp, 0); // DWORD dwLength; length - updated on close - 21 + file_write(fp, "avih", 4); // FOURCC fcc; - 6 + file_write_long(fp, 56); // DWORD cb; - 7 + file_write_long(fp, 0); // DWORD dwMicroSecPerFrame; micros - updated on close - 8 + file_write_long(fp, 0); // DWORD dwMaxBytesPerSec; updated on close - 9 + file_write_long(fp, 4); // DWORD dwPaddingGranularity; - 10 + file_write_long(fp, 0); // DWORD dwFlags; - 11 + file_write_long(fp, 0); // DWORD dwTotalFrames; frames - updated on close - 12 + file_write_long(fp, 0); // DWORD dwInitialFrames; - 13 + file_write_long(fp, 1); // DWORD dwStreams; - 14 + file_write_long(fp, 0); // DWORD dwSuggestedBufferSize; - 15 + file_write_long(fp, width); // DWORD dwWidth; - 16 + file_write_long(fp, height); // DWORD dwHeight; - 17 + file_write_long(fp, 1000); // DWORD dwScale; - 18 + file_write_long(fp, 0); // DWORD dwRate; rate - updated on close - 19 + file_write_long(fp, 0); // DWORD dwStart; - 20 + file_write_long(fp, 0); // DWORD dwLength; length - updated on close - 21 - write_data(fp, "LIST", 4); // FOURCC fcc; - 22 - write_long(fp, 116); // DWORD cb; - 23 - write_data(fp, "strl", 4); // FOURCC fcc; - 24 + file_write(fp, "LIST", 4); // FOURCC fcc; - 22 + file_write_long(fp, 116); // DWORD cb; - 23 + file_write(fp, "strl", 4); // FOURCC fcc; - 24 - write_data(fp, "strh", 4); // FOURCC fcc; - 25 - write_long(fp, 56); // DWORD cb; - 26 - write_data(fp, "vids", 4); // FOURCC fccType; - 27 - write_data(fp, "MJPG", 4); // FOURCC fccHandler; - 28 - write_long(fp, 0); // DWORD dwFlags; - 29 - write_word(fp, 0); // WORD wPriority; - 30 - write_word(fp, 0); // WORD wLanguage; - 30.5 - write_long(fp, 0); // DWORD dwInitialFrames; - 31 - write_long(fp, 1000); // DWORD dwScale; - 32 - write_long(fp, 0); // DWORD dwRate; rate - updated on close - 33 - write_long(fp, 0); // DWORD dwStart; - 34 - write_long(fp, 0); // DWORD dwLength; length - updated on close - 35 - write_long(fp, 0); // DWORD dwSuggestedBufferSize; - 36 - write_long(fp, 10000); // DWORD dwQuality; - 37 - write_long(fp, 0); // DWORD dwSampleSize; - 38 - write_word(fp, 0); // short int left; - 39 - write_word(fp, 0); // short int top; - 39.5 - write_word(fp, 0); // short int right; - 40 - write_word(fp, 0); // short int bottom; - 40.5 + file_write(fp, "strh", 4); // FOURCC fcc; - 25 + file_write_long(fp, 56); // DWORD cb; - 26 + file_write(fp, "vids", 4); // FOURCC fccType; - 27 + file_write(fp, "MJPG", 4); // FOURCC fccHandler; - 28 + file_write_long(fp, 0); // DWORD dwFlags; - 29 + file_write_short(fp, 0); // WORD wPriority; - 30 + file_write_short(fp, 0); // WORD wLanguage; - 30.5 + file_write_long(fp, 0); // DWORD dwInitialFrames; - 31 + file_write_long(fp, 1000); // DWORD dwScale; - 32 + file_write_long(fp, 0); // DWORD dwRate; rate - updated on close - 33 + file_write_long(fp, 0); // DWORD dwStart; - 34 + file_write_long(fp, 0); // DWORD dwLength; length - updated on close - 35 + file_write_long(fp, 0); // DWORD dwSuggestedBufferSize; - 36 + file_write_long(fp, 10000); // DWORD dwQuality; - 37 + file_write_long(fp, 0); // DWORD dwSampleSize; - 38 + file_write_short(fp, 0); // short int left; - 39 + file_write_short(fp, 0); // short int top; - 39.5 + file_write_short(fp, 0); // short int right; - 40 + file_write_short(fp, 0); // short int bottom; - 40.5 - write_data(fp, "strf", 4); // FOURCC fcc; - 41 - write_long(fp, 40); // DWORD cb; - 42 - write_long(fp, 40); // DWORD biSize; - 43 - write_long(fp, width); // LONG biWidth; - 44 - write_long(fp, height); // LONG biHeight; - 45 - write_word(fp, 1); // WORD biPlanes; - 46 - write_word(fp, 24); // WORD biBitCount; - 46.5 - write_data(fp, "MJPG", 4); // DWORD biCompression; - 47 - write_long(fp, 0); // DWORD biSizeImage; - 48 - write_long(fp, 0); // LONG biXPelsPerMeter; - 49 - write_long(fp, 0); // LONG biYPelsPerMeter; - 50 - write_long(fp, 0); // DWORD biClrUsed; - 51 - write_long(fp, 0); // DWORD biClrImportant; - 52 + file_write(fp, "strf", 4); // FOURCC fcc; - 41 + file_write_long(fp, 40); // DWORD cb; - 42 + file_write_long(fp, 40); // DWORD biSize; - 43 + file_write_long(fp, width); // DWORD biWidth; - 44 + file_write_long(fp, height); // DWORD biHeight; - 45 + file_write_short(fp, 1); // WORD biPlanes; - 46 + file_write_short(fp, 24); // WORD biBitCount; - 46.5 + file_write(fp, "MJPG", 4); // DWORD biCompression; - 47 + file_write_long(fp, 0); // DWORD biSizeImage; - 48 + file_write_long(fp, 0); // DWORD biXPelsPerMeter; - 49 + file_write_long(fp, 0); // DWORD biYPelsPerMeter; - 50 + file_write_long(fp, 0); // DWORD biClrUsed; - 51 + file_write_long(fp, 0); // DWORD biClrImportant; - 52 - write_data(fp, "LIST", 4); // FOURCC fcc; - 53 - write_long(fp, 0); // DWORD cb; movi - updated on close - 54 - write_data(fp, "movi", 4); // FOURCC fcc; - 55 + file_write(fp, "LIST", 4); // FOURCC fcc; - 53 + file_write_long(fp, 0); // DWORD cb; movi - updated on close - 54 + file_write(fp, "movi", 4); // FOURCC fcc; - 55 } void mjpeg_write(FIL *fp, int width, int height, uint32_t *frames, uint32_t *bytes, @@ -185,9 +185,9 @@ void mjpeg_write(FIL *fp, int width, int height, uint32_t *frames, uint32_t *byt } uint32_t size_padded = (((dst_img.size + 3) / 4) * 4); - write_data(fp, "00dc", 4); // FOURCC fcc; - write_long(fp, size_padded); // DWORD cb; - write_data(fp, dst_img.data, size_padded); // reading past okay + file_write(fp, "00dc", 4); // FOURCC fcc; + file_write_long(fp, size_padded); // DWORD cb; + file_write(fp, dst_img.data, size_padded); // reading past okay *frames += 1; *bytes += size_padded; @@ -199,67 +199,39 @@ void mjpeg_sync(FIL *fp, uint32_t *frames, uint32_t *bytes, float fps) { uint32_t position = f_tell(fp); // Needed file_seek(fp, SIZE_OFFSET); - write_long(fp, 216 + (*frames * 8) + *bytes); + file_write_long(fp, 216 + (*frames * 8) + *bytes); // Needed file_seek(fp, MICROS_OFFSET); - write_long(fp, (!fast_roundf(fps)) ? 0 : - fast_roundf(1000000 / fps)); - write_long(fp, (!(*frames)) ? 0 : - fast_roundf((((*frames * 8) + *bytes) * fps) / *frames)); + file_write_long(fp, (!fast_roundf(fps)) ? 0 : + fast_roundf(1000000 / fps)); + file_write_long(fp, (!(*frames)) ? 0 : + fast_roundf((((*frames * 8) + *bytes) * fps) / *frames)); // Needed file_seek(fp, FRAMES_OFFSET); - write_long(fp, *frames); + file_write_long(fp, *frames); // Probably not needed but writing it just in case. file_seek(fp, RATE_0_OFFSET); - write_long(fp, fast_roundf(fps * 1000)); + file_write_long(fp, fast_roundf(fps * 1000)); // Probably not needed but writing it just in case. file_seek(fp, LENGTH_0_OFFSET); - write_long(fp, (!fast_roundf(fps)) ? 0 : - fast_roundf((*frames * 1000) / fps)); + file_write_long(fp, (!fast_roundf(fps)) ? 0 : + fast_roundf((*frames * 1000) / fps)); // Probably not needed but writing it just in case. file_seek(fp, RATE_1_OFFSET); - write_long(fp, fast_roundf(fps * 1000)); + file_write_long(fp, fast_roundf(fps * 1000)); // Probably not needed but writing it just in case. file_seek(fp, LENGTH_1_OFFSET); - write_long(fp, (!fast_roundf(fps)) ? 0 : - fast_roundf((*frames * 1000) / fps)); + file_write_long(fp, (!fast_roundf(fps)) ? 0 : + fast_roundf((*frames * 1000) / fps)); // Needed file_seek(fp, MOVI_OFFSET); - write_long(fp, 4 + (*frames * 8) + *bytes); + file_write_long(fp, 4 + (*frames * 8) + *bytes); file_sync(fp); file_seek(fp, position); } void mjpeg_close(FIL *fp, uint32_t *frames, uint32_t *bytes, float fps) { - // Needed - file_seek(fp, SIZE_OFFSET); - write_long(fp, 216 + (*frames * 8) + *bytes); - // Needed - file_seek(fp, MICROS_OFFSET); - write_long(fp, (!fast_roundf(fps)) ? 0 : - fast_roundf(1000000 / fps)); - write_long(fp, (!(*frames)) ? 0 : - fast_roundf((((*frames * 8) + *bytes) * fps) / *frames)); - // Needed - file_seek(fp, FRAMES_OFFSET); - write_long(fp, *frames); - // Probably not needed but writing it just in case. - file_seek(fp, RATE_0_OFFSET); - write_long(fp, fast_roundf(fps * 1000)); - // Probably not needed but writing it just in case. - file_seek(fp, LENGTH_0_OFFSET); - write_long(fp, (!fast_roundf(fps)) ? 0 : - fast_roundf((*frames * 1000) / fps)); - // Probably not needed but writing it just in case. - file_seek(fp, RATE_1_OFFSET); - write_long(fp, fast_roundf(fps * 1000)); - // Probably not needed but writing it just in case. - file_seek(fp, LENGTH_1_OFFSET); - write_long(fp, (!fast_roundf(fps)) ? 0 : - fast_roundf((*frames * 1000) / fps)); - // Needed - file_seek(fp, MOVI_OFFSET); - write_long(fp, 4 + (*frames * 8) + *bytes); + mjpeg_sync(fp, frames, bytes, fps); file_close(fp); } diff --git a/src/omv/imlib/orb.c b/src/omv/imlib/orb.c index db188d75d..2fc01f399 100644 --- a/src/omv/imlib/orb.c +++ b/src/omv/imlib/orb.c @@ -42,10 +42,10 @@ #include #include "fmath.h" #include "arm_math.h" -#include "ff.h" #include "imlib.h" #include "xalloc.h" #include "fb_alloc.h" +#include "file_utils.h" #ifdef IMLIB_ENABLE_FIND_KEYPOINTS #define PATCH_SIZE (31) // 31x31 pixels @@ -719,7 +719,7 @@ int orb_save_descriptor(FIL *fp, array_t *kpts) { int kpts_size = array_length(kpts); // Write the number of keypoints - res = f_write(fp, &kpts_size, sizeof(kpts_size), &bytes); + res = file_ll_write(fp, &kpts_size, sizeof(kpts_size), &bytes); if (res != FR_OK || bytes != sizeof(kpts_size)) { goto error; } @@ -729,37 +729,37 @@ int orb_save_descriptor(FIL *fp, array_t *kpts) { kp_t *kp = array_at(kpts, i); // Write X - res = f_write(fp, &kp->x, sizeof(kp->x), &bytes); + res = file_ll_write(fp, &kp->x, sizeof(kp->x), &bytes); if (res != FR_OK || bytes != sizeof(kp->x)) { goto error; } // Write Y - res = f_write(fp, &kp->y, sizeof(kp->y), &bytes); + res = file_ll_write(fp, &kp->y, sizeof(kp->y), &bytes); if (res != FR_OK || bytes != sizeof(kp->y)) { goto error; } // Write Score - res = f_write(fp, &kp->score, sizeof(kp->score), &bytes); + res = file_ll_write(fp, &kp->score, sizeof(kp->score), &bytes); if (res != FR_OK || bytes != sizeof(kp->score)) { goto error; } // Write Octave - res = f_write(fp, &kp->octave, sizeof(kp->octave), &bytes); + res = file_ll_write(fp, &kp->octave, sizeof(kp->octave), &bytes); if (res != FR_OK || bytes != sizeof(kp->octave)) { goto error; } // Write Angle - res = f_write(fp, &kp->angle, sizeof(kp->angle), &bytes); + res = file_ll_write(fp, &kp->angle, sizeof(kp->angle), &bytes); if (res != FR_OK || bytes != sizeof(kp->angle)) { goto error; } // Write descriptor - res = f_write(fp, kp->desc, KDESC_SIZE, &bytes); + res = file_ll_write(fp, kp->desc, KDESC_SIZE, &bytes); if (res != FR_OK || bytes != KDESC_SIZE) { goto error; } @@ -776,7 +776,7 @@ int orb_load_descriptor(FIL *fp, array_t *kpts) { int kpts_size = 0; // Read number of keypoints - res = f_read(fp, &kpts_size, sizeof(kpts_size), &bytes); + res = file_ll_read(fp, &kpts_size, sizeof(kpts_size), &bytes); if (res != FR_OK || bytes != sizeof(kpts_size)) { goto error; } @@ -787,37 +787,37 @@ int orb_load_descriptor(FIL *fp, array_t *kpts) { kp->matched = 0; // Read X - res = f_read(fp, &kp->x, sizeof(kp->x), &bytes); + res = file_ll_read(fp, &kp->x, sizeof(kp->x), &bytes); if (res != FR_OK || bytes != sizeof(kp->x)) { goto error; } // Read Y - res = f_read(fp, &kp->y, sizeof(kp->y), &bytes); + res = file_ll_read(fp, &kp->y, sizeof(kp->y), &bytes); if (res != FR_OK || bytes != sizeof(kp->y)) { goto error; } // Read Score - res = f_read(fp, &kp->score, sizeof(kp->score), &bytes); + res = file_ll_read(fp, &kp->score, sizeof(kp->score), &bytes); if (res != FR_OK || bytes != sizeof(kp->score)) { goto error; } // Read Octave - res = f_read(fp, &kp->octave, sizeof(kp->octave), &bytes); + res = file_ll_read(fp, &kp->octave, sizeof(kp->octave), &bytes); if (res != FR_OK || bytes != sizeof(kp->octave)) { goto error; } // Read Angle - res = f_read(fp, &kp->angle, sizeof(kp->angle), &bytes); + res = file_ll_read(fp, &kp->angle, sizeof(kp->angle), &bytes); if (res != FR_OK || bytes != sizeof(kp->angle)) { goto error; } // Read descriptor - res = f_read(fp, kp->desc, KDESC_SIZE, &bytes); + res = file_ll_read(fp, kp->desc, KDESC_SIZE, &bytes); if (res != FR_OK || bytes != KDESC_SIZE) { goto error; } diff --git a/src/omv/imlib/png.c b/src/omv/imlib/png.c index 9eb24cfa8..5d104dba9 100644 --- a/src/omv/imlib/png.c +++ b/src/omv/imlib/png.c @@ -12,7 +12,7 @@ #include "imlib.h" #include "py/mphal.h" #include "py/runtime.h" -#include "ff_wrapper.h" +#include "file_utils.h" #if defined(IMLIB_ENABLE_PNG_ENCODER) || defined(IMLIB_ENABLE_PNG_DECODER) #include "lodepng.h" #include "umm_malloc.h" @@ -265,12 +265,12 @@ void png_decompress(image_t *dst, image_t *src) { void png_read_geometry(FIL *fp, image_t *img, const char *path, png_read_settings_t *rs) { uint32_t header; file_seek(fp, 12); // start of IHDR - read_long(fp, &header); + file_read(fp, &header, 4); if (header == 0x52444849) { // IHDR uint32_t width, height; - read_long(fp, &width); - read_long(fp, &height); + file_read(fp, &width, 4); + file_read(fp, &height, 4); width = __builtin_bswap32(width); height = __builtin_bswap32(height); @@ -283,23 +283,23 @@ void png_read_geometry(FIL *fp, image_t *img, const char *path, png_read_setting img->size = rs->png_size; img->pixfmt = PIXFORMAT_PNG; } else { - ff_file_corrupted(fp); + file_raise_corrupted(fp); } } // This function reads the pixel values of an image. void png_read_pixels(FIL *fp, image_t *img) { file_seek(fp, 0); - read_data(fp, img->pixels, img->size); + file_read(fp, img->pixels, img->size); } void png_read(image_t *img, const char *path) { FIL fp; png_read_settings_t rs; - file_read_open(&fp, path); + // Do not use file buferring here. + file_open(&fp, path, false, FA_READ | FA_OPEN_EXISTING); - // Do not use file_buffer_on() here. png_read_geometry(&fp, img, path, &rs); if (!img->pixels) { @@ -312,13 +312,13 @@ void png_read(image_t *img, const char *path) { void png_write(image_t *img, const char *path) { FIL fp; - file_write_open(&fp, path); + file_open(&fp, path, false, FA_WRITE | FA_CREATE_ALWAYS); if (img->pixfmt == PIXFORMAT_PNG) { - write_data(&fp, img->pixels, img->size); + file_write(&fp, img->pixels, img->size); } else { image_t out = { .w = img->w, .h = img->h, .pixfmt = PIXFORMAT_PNG, .size = 0, .pixels = NULL }; // alloc in png compress png_compress(img, &out); - write_data(&fp, out.pixels, out.size); + file_write(&fp, out.pixels, out.size); fb_free(); // frees alloc in png_compress() } file_close(&fp); diff --git a/src/omv/imlib/ppm.c b/src/omv/imlib/ppm.c index aeae3074d..c60793d20 100644 --- a/src/omv/imlib/ppm.c +++ b/src/omv/imlib/ppm.c @@ -18,7 +18,7 @@ #include "xalloc.h" #include "imlib.h" -#include "ff_wrapper.h" +#include "file_utils.h" static void read_int_reset(ppm_read_settings_t *rs) { rs->read_int_c_valid = false; @@ -31,10 +31,10 @@ static void read_int(FIL *fp, uint32_t *i, ppm_read_settings_t *rs) { mode = EAT_WHITESPACE; for (*i = 0;;) { if (!rs->read_int_c_valid) { - if (file_tell_w_buf(fp) == file_size_w_buf(fp)) { + if (file_tell(fp) == file_size(fp)) { return; } - read_byte(fp, &rs->read_int_c); + file_read(fp, &rs->read_int_c, 1); rs->read_int_c_valid = true; } if (mode == EAT_WHITESPACE) { @@ -62,11 +62,11 @@ static void read_int(FIL *fp, uint32_t *i, ppm_read_settings_t *rs) { // This function inits the geometry values of an image. void ppm_read_geometry(FIL *fp, image_t *img, const char *path, ppm_read_settings_t *rs) { read_int_reset(rs); - read_byte_expect(fp, 'P'); - read_byte(fp, &rs->ppm_fmt); + file_read_check(fp, "P", 1); + file_read(fp, &rs->ppm_fmt, 1); if ((rs->ppm_fmt != '2') && (rs->ppm_fmt != '3') && (rs->ppm_fmt != '5') && (rs->ppm_fmt != '6')) { - ff_unsupported_format(fp); + file_raise_format(fp); } img->pixfmt = ((rs->ppm_fmt == '2') || (rs->ppm_fmt == '5')) ? PIXFORMAT_GRAYSCALE : PIXFORMAT_RGB565; @@ -75,13 +75,13 @@ void ppm_read_geometry(FIL *fp, image_t *img, const char *path, ppm_read_setting read_int(fp, (uint32_t *) &img->h, rs); if ((img->w == 0) || (img->h == 0)) { - ff_file_corrupted(fp); + file_raise_corrupted(fp); } uint32_t max; read_int(fp, &max, rs); if (max != 255) { - ff_unsupported_format(fp); + file_raise_format(fp); } } @@ -106,14 +106,14 @@ void ppm_read_pixels(FIL *fp, image_t *img, int n_lines, ppm_read_settings_t *rs } } } else if (rs->ppm_fmt == '5') { - read_data(fp, img->pixels, n_lines * img->w); + file_read(fp, img->pixels, n_lines * img->w); } else if (rs->ppm_fmt == '6') { for (int i = 0; i < n_lines; i++) { for (int j = 0; j < img->w; j++) { uint8_t r, g, b; - read_byte(fp, &r); - read_byte(fp, &g); - read_byte(fp, &b); + file_read(fp, &r, 1); + file_read(fp, &g, 1); + file_read(fp, &b, 1); IM_SET_RGB565_PIXEL(img, j, i, COLOR_R8_G8_B8_TO_RGB565(r, g, b)); } } @@ -124,16 +124,13 @@ void ppm_read(image_t *img, const char *path) { FIL fp; ppm_read_settings_t rs; - file_read_open(&fp, path); - file_buffer_on(&fp); + file_open(&fp, path, true, FA_READ | FA_OPEN_EXISTING); ppm_read_geometry(&fp, img, path, &rs); if (!img->pixels) { img->pixels = xalloc(img->w * img->h * img->bpp); } ppm_read_pixels(&fp, img, img->h, &rs); - - file_buffer_off(&fp); file_close(&fp); } @@ -144,25 +141,23 @@ void ppm_write_subimg(image_t *img, const char *path, rectangle_t *r) { } FIL fp; - file_write_open(&fp, path); - file_buffer_on(&fp); + file_open(&fp, path, true, FA_WRITE | FA_CREATE_ALWAYS); + if (IM_IS_GS(img)) { char buffer[20]; // exactly big enough for 5-digit w/h int len = snprintf(buffer, 20, "P5\n%d %d\n255\n", rect.w, rect.h); - write_data(&fp, buffer, len); + file_write(&fp, buffer, len); if ((rect.x == 0) && (rect.w == img->w)) { - write_data(&fp, // Super Fast - Zoom, Zoom! - img->pixels + (rect.y * img->w), - rect.w * rect.h); + file_write(&fp, img->pixels + (rect.y * img->w), rect.w * rect.h); } else { for (int i = 0; i < rect.h; i++) { - write_data(&fp, img->pixels + ((rect.y + i) * img->w) + rect.x, rect.w); + file_write(&fp, img->pixels + ((rect.y + i) * img->w) + rect.x, rect.w); } } } else { char buffer[20]; // exactly big enough for 5-digit w/h int len = snprintf(buffer, 20, "P6\n%d %d\n255\n", rect.w, rect.h); - write_data(&fp, buffer, len); + file_write(&fp, buffer, len); for (int i = 0; i < rect.h; i++) { for (int j = 0; j < rect.w; j++) { int pixel = IM_GET_RGB565_PIXEL(img, (rect.x + j), (rect.y + i)); @@ -170,12 +165,10 @@ void ppm_write_subimg(image_t *img, const char *path, rectangle_t *r) { buff[0] = COLOR_RGB565_TO_R8(pixel); buff[1] = COLOR_RGB565_TO_G8(pixel); buff[2] = COLOR_RGB565_TO_B8(pixel); - write_data(&fp, buff, 3); + file_write(&fp, buff, 3); } } } - file_buffer_off(&fp); - file_close(&fp); } #endif //IMLIB_ENABLE_IMAGE_FILE_IO diff --git a/src/omv/modules/py_gif.c b/src/omv/modules/py_gif.c index 62bfb3a3c..c08eb3f80 100644 --- a/src/omv/modules/py_gif.c +++ b/src/omv/modules/py_gif.c @@ -11,7 +11,7 @@ #include "py/mphal.h" #include "py/runtime.h" -#include "ff_wrapper.h" +#include "file_utils.h" #include "framebuffer.h" #include "imlib.h" #include "py_assert.h" @@ -40,7 +40,7 @@ static mp_obj_t py_gif_open(uint n_args, const mp_obj_t *args, mp_map_t *kw_args gif->base.type = &py_gif_type; #if defined(IMLIB_ENABLE_IMAGE_FILE_IO) - file_write_open(&gif->fp, mp_obj_str_get_str(args[0])); + file_open(&gif->fp, mp_obj_str_get_str(args[0]), false, FA_WRITE | FA_CREATE_ALWAYS); gif_open(&gif->fp, gif->width, gif->height, gif->color, gif->loop); #else mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Image I/O is not supported")); @@ -66,7 +66,7 @@ static mp_obj_t py_gif_format(mp_obj_t gif_obj) { static mp_obj_t py_gif_size(mp_obj_t gif_obj) { #if defined(IMLIB_ENABLE_IMAGE_FILE_IO) py_gif_obj_t *arg_gif = gif_obj; - return mp_obj_new_int(file_size_w_buf(&arg_gif->fp)); + return mp_obj_new_int(file_size(&arg_gif->fp)); #else return mp_obj_new_int(0); #endif diff --git a/src/omv/modules/py_image.c b/src/omv/modules/py_image.c index 784b05b73..698aa54a6 100644 --- a/src/omv/modules/py_image.c +++ b/src/omv/modules/py_image.c @@ -23,7 +23,7 @@ #include "imlib.h" #include "array.h" -#include "ff_wrapper.h" +#include "file_utils.h" #include "xalloc.h" #include "fb_alloc.h" #include "framebuffer.h" @@ -6892,7 +6892,6 @@ mp_obj_t py_image_load_image(uint n_args, const mp_obj_t *pos_args, mp_map_t *kw fb_alloc_mark(); imlib_read_geometry(&fp, &image, path, &rs); - file_buffer_off(&fp); file_close(&fp); if (args[ARG_copy_to_fb].u_bool) { @@ -6980,59 +6979,54 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_load_cascade_obj, 1, py_image_load_ca #if defined(IMLIB_ENABLE_IMAGE_FILE_IO) mp_obj_t py_image_load_descriptor(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { FIL fp; - UINT bytes; - FRESULT res; + FRESULT res = FR_OK; uint32_t desc_type; mp_obj_t desc = mp_const_none; const char *path = mp_obj_str_get_str(args[0]); - if ((res = f_open_helper(&fp, path, FA_READ | FA_OPEN_EXISTING)) == FR_OK) { - // Read descriptor type - res = f_read(&fp, &desc_type, sizeof(desc_type), &bytes); - if (res != FR_OK || bytes != sizeof(desc_type)) { - goto error; - } + file_open(&fp, path, false, FA_READ | FA_OPEN_EXISTING); - // Load descriptor - switch (desc_type) { - #if defined(IMLIB_ENABLE_FIND_LBP) - case DESC_LBP: { - py_lbp_obj_t *lbp = m_new_obj(py_lbp_obj_t); - lbp->base.type = &py_lbp_type; + // Read descriptor type + file_read(&fp, &desc_type, sizeof(desc_type)); - res = imlib_lbp_desc_load(&fp, &lbp->hist); - if (res == FR_OK) { - desc = lbp; - } - break; + // Load descriptor + switch (desc_type) { + #if defined(IMLIB_ENABLE_FIND_LBP) + case DESC_LBP: { + py_lbp_obj_t *lbp = m_new_obj(py_lbp_obj_t); + lbp->base.type = &py_lbp_type; + + res = imlib_lbp_desc_load(&fp, &lbp->hist); + if (res == FR_OK) { + desc = lbp; } - #endif //IMLIB_ENABLE_FIND_LBP - #if defined(IMLIB_ENABLE_FIND_KEYPOINTS) - case DESC_ORB: { - array_t *kpts = NULL; - array_alloc(&kpts, xfree); - - res = orb_load_descriptor(&fp, kpts); - if (res == FR_OK) { - // Return keypoints MP object - py_kp_obj_t *kp_obj = m_new_obj(py_kp_obj_t); - kp_obj->base.type = &py_kp_type; - kp_obj->kpts = kpts; - kp_obj->threshold = 10; - kp_obj->normalized = false; - desc = kp_obj; - } - break; - } - #endif //IMLIB_ENABLE_FIND_KEYPOINTS + break; } + #endif //IMLIB_ENABLE_FIND_LBP + #if defined(IMLIB_ENABLE_FIND_KEYPOINTS) + case DESC_ORB: { + array_t *kpts = NULL; + array_alloc(&kpts, xfree); - f_close(&fp); + res = orb_load_descriptor(&fp, kpts); + if (res == FR_OK) { + // Return keypoints MP object + py_kp_obj_t *kp_obj = m_new_obj(py_kp_obj_t); + kp_obj->base.type = &py_kp_type; + kp_obj->kpts = kpts; + kp_obj->threshold = 10; + kp_obj->normalized = false; + desc = kp_obj; + } + break; + } + #endif //IMLIB_ENABLE_FIND_KEYPOINTS } -error: - // File open or write error + file_close(&fp); + + // File read error if (res != FR_OK) { mp_raise_msg(&mp_type_OSError, (mp_rom_error_text_t) ffs_strerror(res)); } @@ -7047,58 +7041,54 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_load_descriptor_obj, 1, py_image_load mp_obj_t py_image_save_descriptor(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { FIL fp; - UINT bytes; - FRESULT res; + FRESULT res = FR_OK; uint32_t desc_type; const char *path = mp_obj_str_get_str(args[1]); - if ((res = f_open_helper(&fp, path, FA_WRITE | FA_CREATE_ALWAYS)) == FR_OK) { - // Find descriptor type - const mp_obj_type_t *desc_obj_type = mp_obj_get_type(args[0]); - if (0) { - #if defined(IMLIB_ENABLE_FIND_LBP) - } else if (desc_obj_type == &py_lbp_type) { - desc_type = DESC_LBP; - #endif //IMLIB_ENABLE_FIND_LBP - #if defined(IMLIB_ENABLE_FIND_KEYPOINTS) - } else if (desc_obj_type == &py_kp_type) { - desc_type = DESC_ORB; - #endif //IMLIB_ENABLE_FIND_KEYPOINTS - } else { - (void) desc_obj_type; - mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Descriptor type is not supported")); - } + file_open(&fp, path, false, FA_WRITE | FA_CREATE_ALWAYS); - // Write descriptor type - res = f_write(&fp, &desc_type, sizeof(desc_type), &bytes); - if (res != FR_OK || bytes != sizeof(desc_type)) { - goto error; - } - - // Write descriptor - switch (desc_type) { - #if defined(IMLIB_ENABLE_FIND_LBP) - case DESC_LBP: { - py_lbp_obj_t *lbp = ((py_lbp_obj_t *) args[0]); - res = imlib_lbp_desc_save(&fp, lbp->hist); - break; - } - #endif //IMLIB_ENABLE_FIND_LBP - #if defined(IMLIB_ENABLE_FIND_KEYPOINTS) - case DESC_ORB: { - py_kp_obj_t *kpts = ((py_kp_obj_t *) args[0]); - res = orb_save_descriptor(&fp, kpts->kpts); - break; - } - #endif //IMLIB_ENABLE_FIND_KEYPOINTS - } - // ignore unsupported descriptors when saving - f_close(&fp); + // Find descriptor type + const mp_obj_type_t *desc_obj_type = mp_obj_get_type(args[0]); + if (0) { + #if defined(IMLIB_ENABLE_FIND_LBP) + } else if (desc_obj_type == &py_lbp_type) { + desc_type = DESC_LBP; + #endif //IMLIB_ENABLE_FIND_LBP + #if defined(IMLIB_ENABLE_FIND_KEYPOINTS) + } else if (desc_obj_type == &py_kp_type) { + desc_type = DESC_ORB; + #endif //IMLIB_ENABLE_FIND_KEYPOINTS + } else { + (void) desc_obj_type; + mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Descriptor type is not supported")); } -error: - // File open or read error + // Write descriptor type + file_write(&fp, &desc_type, sizeof(desc_type)); + + // Write descriptor + switch (desc_type) { + #if defined(IMLIB_ENABLE_FIND_LBP) + case DESC_LBP: { + py_lbp_obj_t *lbp = ((py_lbp_obj_t *) args[0]); + res = imlib_lbp_desc_save(&fp, lbp->hist); + break; + } + #endif //IMLIB_ENABLE_FIND_LBP + #if defined(IMLIB_ENABLE_FIND_KEYPOINTS) + case DESC_ORB: { + py_kp_obj_t *kpts = ((py_kp_obj_t *) args[0]); + res = orb_save_descriptor(&fp, kpts->kpts); + break; + } + #endif //IMLIB_ENABLE_FIND_KEYPOINTS + } + + // ignore unsupported descriptors when saving + file_close(&fp); + + // File write error if (res != FR_OK) { mp_raise_msg(&mp_type_OSError, (mp_rom_error_text_t) ffs_strerror(res)); } @@ -7194,18 +7184,12 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(py_image_match_descriptor_obj, 2, py_image_mat #if defined(IMLIB_ENABLE_FIND_KEYPOINTS) && defined(IMLIB_ENABLE_IMAGE_FILE_IO) int py_image_descriptor_from_roi(image_t *img, const char *path, rectangle_t *roi) { FIL fp; - FRESULT res = FR_OK; - - printf("Save Descriptor: ROI(%d %d %d %d)\n", roi->x, roi->y, roi->w, roi->h); array_t *kpts = orb_find_keypoints(img, false, 20, 1.5f, 100, CORNER_AGAST, roi); - printf("Save Descriptor: KPTS(%d)\n", array_length(kpts)); - if (array_length(kpts)) { - if ((res = f_open_helper(&fp, path, FA_WRITE | FA_CREATE_ALWAYS)) == FR_OK) { - res = orb_save_descriptor(&fp, kpts); - f_close(&fp); - } - // File open/write error + file_open(&fp, path, false, FA_WRITE | FA_CREATE_ALWAYS); + FRESULT res = orb_save_descriptor(&fp, kpts); + file_close(&fp); + // File write error if (res != FR_OK) { mp_raise_msg(&mp_type_OSError, (mp_rom_error_text_t) ffs_strerror(res)); } diff --git a/src/omv/modules/py_imageio.c b/src/omv/modules/py_imageio.c index 8e68a9d20..5ad3d204a 100644 --- a/src/omv/modules/py_imageio.c +++ b/src/omv/modules/py_imageio.c @@ -22,7 +22,7 @@ #include "py_imageio.h" #if defined(IMLIB_ENABLE_IMAGE_FILE_IO) -#include "ff_wrapper.h" +#include "file_utils.h" #endif #include "framebuffer.h" #include "omv_boardconfig.h" @@ -182,37 +182,37 @@ STATIC mp_obj_t py_imageio_write(mp_obj_t self, mp_obj_t img_obj) { } else if (stream->type == IMAGE_IO_FILE_STREAM) { FIL *fp = &stream->fp; - write_long(fp, elapsed_ms); - write_long(fp, image->w); - write_long(fp, image->h); + file_write_long(fp, elapsed_ms); + file_write_long(fp, image->w); + file_write_long(fp, image->h); char padding[ALIGN_SIZE] = {}; if (stream->version < NEW_PIXFORMAT_VER) { if (image->pixfmt == PIXFORMAT_BINARY) { - write_long(fp, OLD_BINARY_BPP); + file_write_long(fp, OLD_BINARY_BPP); } else if (image->pixfmt == PIXFORMAT_GRAYSCALE) { - write_long(fp, OLD_GRAYSCALE_BPP); + file_write_long(fp, OLD_GRAYSCALE_BPP); } else if (image->pixfmt == PIXFORMAT_RGB565) { - write_long(fp, OLD_RGB565_BPP); + file_write_long(fp, OLD_RGB565_BPP); } else if (image->pixfmt == PIXFORMAT_BAYER) { - write_long(fp, OLD_BAYER_BPP); + file_write_long(fp, OLD_BAYER_BPP); } else if (image->pixfmt == PIXFORMAT_JPEG) { - write_long(fp, image->size); + file_write_long(fp, image->size); } else { mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("Invalid image stream bpp")); } } else { - write_long(fp, image->pixfmt); - write_long(fp, image->size); - write_data(fp, padding, AFTER_SIZE_PADDING); + file_write_long(fp, image->pixfmt); + file_write_long(fp, image->size); + file_write(fp, padding, AFTER_SIZE_PADDING); } uint32_t size = image_size(image); - write_data(fp, image->data, size); + file_write(fp, image->data, size); if (size % ALIGN_SIZE) { - write_data(fp, padding, ALIGN_SIZE - (size % ALIGN_SIZE)); + file_write(fp, padding, ALIGN_SIZE - (size % ALIGN_SIZE)); } // Seeking to the middle of a file and writing data corrupts the remainder of the file. So, @@ -251,7 +251,7 @@ STATIC void int_py_imageio_pause(py_imageio_obj_t *stream, bool pause) { if (0) { #if defined(IMLIB_ENABLE_IMAGE_FILE_IO) } else if (stream->type == IMAGE_IO_FILE_STREAM) { - read_long(&stream->fp, &elapsed_ms); + file_read(&stream->fp, &elapsed_ms, 4); #endif } else if (stream->type == IMAGE_IO_MEMORY_STREAM) { elapsed_ms = *((uint32_t *) (stream->buffer + (stream->offset * stream->size))); @@ -274,11 +274,11 @@ STATIC void int_py_imageio_read_chunk(py_imageio_obj_t *stream, image_t *image, int_py_imageio_pause(stream, pause); - read_long(fp, (uint32_t *) &image->w); - read_long(fp, (uint32_t *) &image->h); + file_read(fp, &image->w, 4); + file_read(fp, &image->h, 4); uint32_t bpp; - read_long(fp, (uint32_t *) &bpp); + file_read(fp, &bpp, 4); if (stream->version < NEW_PIXFORMAT_VER) { if (bpp < 0) { @@ -300,10 +300,10 @@ STATIC void int_py_imageio_read_chunk(py_imageio_obj_t *stream, image_t *image, } image->pixfmt = bpp; - read_long(fp, (uint32_t *) &image->size); + file_read(fp, &image->size, 4); char ignore[AFTER_SIZE_PADDING]; - read_data(fp, ignore, AFTER_SIZE_PADDING); + file_read(fp, ignore, AFTER_SIZE_PADDING); } } #endif @@ -377,7 +377,7 @@ STATIC mp_obj_t py_imageio_read(uint n_args, const mp_obj_t *args, mp_map_t *kw_ #if defined(IMLIB_ENABLE_IMAGE_FILE_IO) } else if (stream->type == IMAGE_IO_FILE_STREAM) { FIL *fp = &stream->fp; - read_data(fp, image.data, size); + file_read(fp, image.data, size); // Check if original byte reversed data. if ((image.pixfmt == PIXFORMAT_RGB565) && (stream->version == ORIGINAL_VER)) { @@ -395,7 +395,7 @@ STATIC mp_obj_t py_imageio_read(uint n_args, const mp_obj_t *args, mp_map_t *kw_ if (size % ALIGN_SIZE) { char ignore[ALIGN_SIZE]; - read_data(fp, ignore, ALIGN_SIZE - (size % ALIGN_SIZE)); + file_read(fp, ignore, ALIGN_SIZE - (size % ALIGN_SIZE)); } if (stream->offset >= stream->count) { @@ -507,20 +507,20 @@ STATIC mp_obj_t py_imageio_make_new(const mp_obj_type_t *type, size_t n_args, si char mode = mp_obj_str_get_str(args[1])[0]; if ((mode == 'W') || (mode == 'w')) { - file_read_write_open_always(fp, mp_obj_str_get_str(args[0])); + file_open(fp, mp_obj_str_get_str(args[0]), false, FA_READ | FA_WRITE | FA_OPEN_ALWAYS); const char string[] = "OMV IMG STR V2.0"; stream->version = NEW_PIXFORMAT_VER; // Overwrite if file is too small. if (f_size(fp) < MAGIC_SIZE) { - write_data(fp, string, sizeof(string) - 1); // exclude null terminator + file_write(fp, string, sizeof(string) - 1); // exclude null terminator } else { uint8_t version_hi, period, version_lo; char temp[sizeof(string) - 3] = {}; - read_data(fp, temp, sizeof(temp) - 1); - read_byte(fp, &version_hi); - read_byte(fp, &period); - read_byte(fp, &version_lo); + file_read(fp, temp, sizeof(temp) - 1); + file_read(fp, &version_hi, 1); + file_read(fp, &period, 1); + file_read(fp, &version_lo, 1); int version = ((version_hi - '0') * 10) + (version_lo - '0'); // Overwrite if file magic does not match. @@ -530,7 +530,7 @@ STATIC mp_obj_t py_imageio_make_new(const mp_obj_type_t *type, size_t n_args, si || (version != RGB565_FIXED_VER) || (version != NEW_PIXFORMAT_VER)) { file_seek(fp, 0); - write_data(fp, string, sizeof(string) - 1); // exclude null terminator + file_write(fp, string, sizeof(string) - 1); // exclude null terminator } else { file_close(fp); mode = 'R'; @@ -540,14 +540,12 @@ STATIC mp_obj_t py_imageio_make_new(const mp_obj_type_t *type, size_t n_args, si if ((mode == 'R') || (mode == 'r')) { uint8_t version_hi, version_lo; - file_read_write_open_existing(fp, mp_obj_str_get_str(args[0])); - read_long_expect(fp, *((uint32_t *) "OMV ")); // OpenMV - read_long_expect(fp, *((uint32_t *) "IMG ")); // Image - read_long_expect(fp, *((uint32_t *) "STR ")); // Stream - read_byte_expect(fp, 'V'); - read_byte(fp, &version_hi); - read_byte_expect(fp, '.'); - read_byte(fp, &version_lo); + file_open(fp, mp_obj_str_get_str(args[0]), false, FA_READ | FA_WRITE | FA_OPEN_EXISTING); + file_read_check(fp, "OMV IMG STR ", 12); // Magic + file_read_check(fp, "V", 1); + file_read(fp, &version_hi, 1); + file_read_check(fp, ".", 1); + file_read(fp, &version_lo, 1); stream->version = ((version_hi - '0') * 10) + (version_lo - '0'); diff --git a/src/omv/modules/py_mjpeg.c b/src/omv/modules/py_mjpeg.c index 50036028a..c1020315e 100644 --- a/src/omv/modules/py_mjpeg.c +++ b/src/omv/modules/py_mjpeg.c @@ -20,7 +20,7 @@ #include "py_helper.h" #include "py_image.h" -#include "ff_wrapper.h" +#include "file_utils.h" #include "framebuffer.h" #include "omv_boardconfig.h" @@ -144,7 +144,7 @@ STATIC mp_obj_t py_mjpeg_open(uint n_args, const mp_obj_t *args, mp_map_t *kw_ar mjpeg->height = py_helper_keyword_int(n_args, args, 2, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_height), MAIN_FB()->h); mjpeg->frames = 0; mjpeg->bytes = 0; - file_write_open(&mjpeg->fp, mp_obj_str_get_str(args[0])); + file_open(&mjpeg->fp, mp_obj_str_get_str(args[0]), false, FA_WRITE | FA_CREATE_ALWAYS); mjpeg_open(&mjpeg->fp, mjpeg->width, mjpeg->height); return mjpeg; } diff --git a/src/omv/modules/py_tf.c b/src/omv/modules/py_tf.c index e1791e038..209af2e63 100644 --- a/src/omv/modules/py_tf.c +++ b/src/omv/modules/py_tf.c @@ -23,7 +23,7 @@ #ifdef IMLIB_ENABLE_TF #include "py_image.h" -#include "ff_wrapper.h" +#include "file_utils.h" #include "py_tf.h" #include "libtf_builtin_models.h" #define GRAYSCALE_RANGE ((COLOR_GRAYSCALE_MAX) -(COLOR_GRAYSCALE_MIN)) @@ -178,12 +178,12 @@ STATIC mp_obj_t int_py_tf_load(mp_obj_t path_obj, bool alloc_mode, bool helper_m if (tf_model->model_data == NULL) { #if defined(IMLIB_ENABLE_IMAGE_FILE_IO) FIL fp; - file_read_open(&fp, path); + file_open(&fp, path, false, FA_READ | FA_OPEN_EXISTING); tf_model->model_data_len = f_size(&fp); tf_model->model_data = alloc_mode ? fb_alloc(tf_model->model_data_len, FB_ALLOC_PREFER_SIZE) : xalloc(tf_model->model_data_len); - read_data(&fp, tf_model->model_data, tf_model->model_data_len); + file_read(&fp, tf_model->model_data, tf_model->model_data_len); file_close(&fp); #else mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Image I/O is not supported")); diff --git a/src/omv/ports/mimxrt/main.c b/src/omv/ports/mimxrt/main.c index 098299313..c53e99423 100644 --- a/src/omv/ports/mimxrt/main.c +++ b/src/omv/ports/mimxrt/main.c @@ -59,7 +59,7 @@ #include "tinyusb_debug.h" #include "fb_alloc.h" #include "dma_alloc.h" -#include "ff_wrapper.h" +#include "file_utils.h" #include "mimxrt_hal.h" extern uint8_t _sstack, _estack, _heap_start, _heap_end; diff --git a/src/omv/ports/mimxrt/omv_portconfig.mk b/src/omv/ports/mimxrt/omv_portconfig.mk index 88994c355..97d7f5a30 100644 --- a/src/omv/ports/mimxrt/omv_portconfig.mk +++ b/src/omv/ports/mimxrt/omv_portconfig.mk @@ -127,7 +127,7 @@ FIRM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/alloc/, \ FIRM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/common/, \ array.o \ - ff_wrapper.o \ + file_utils.o \ ini.o \ ringbuf.o \ trace.o \ diff --git a/src/omv/ports/nrf/omv_portconfig.mk b/src/omv/ports/nrf/omv_portconfig.mk index 5eb92b7a7..f2b365b6c 100644 --- a/src/omv/ports/nrf/omv_portconfig.mk +++ b/src/omv/ports/nrf/omv_portconfig.mk @@ -100,7 +100,7 @@ FIRM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/alloc/, \ FIRM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/common/, \ array.o \ - ff_wrapper.o \ + file_utils.o \ ini.o \ ringbuf.o \ trace.o \ diff --git a/src/omv/ports/rp2/omv_portconfig.cmake b/src/omv/ports/rp2/omv_portconfig.cmake index 39a160e82..4ddb16770 100644 --- a/src/omv/ports/rp2/omv_portconfig.cmake +++ b/src/omv/ports/rp2/omv_portconfig.cmake @@ -93,7 +93,7 @@ target_sources(${MICROPY_TARGET} PRIVATE ${TOP_DIR}/${OMV_DIR}/alloc/unaligned_memcpy.c ${TOP_DIR}/${OMV_DIR}/common/array.c - ${TOP_DIR}/${OMV_DIR}/common/ff_wrapper.c + ${TOP_DIR}/${OMV_DIR}/common/file_utils.c ${TOP_DIR}/${OMV_DIR}/common/ini.c ${TOP_DIR}/${OMV_DIR}/common/ringbuf.c ${TOP_DIR}/${OMV_DIR}/common/trace.c diff --git a/src/omv/ports/stm32/hash.c b/src/omv/ports/stm32/hash.c index 5459beb79..e9276a504 100644 --- a/src/omv/ports/stm32/hash.c +++ b/src/omv/ports/stm32/hash.c @@ -11,10 +11,10 @@ #if (OMV_ENABLE_HASH == 1) #include STM32_HAL_H #include -#include #include -#include "fb_alloc.h" #include "hash.h" +#include "fb_alloc.h" +#include "file_utils.h" #define BLOCK_SIZE (512) static HASH_HandleTypeDef hhash; @@ -56,7 +56,7 @@ int hash_from_file(const char *path, uint8_t *digest) { int ret = -1; uint8_t *buf = fb_alloc(BLOCK_SIZE, FB_ALLOC_NO_HINT); - if (f_open_helper(&fp, path, FA_READ | FA_OPEN_EXISTING) != FR_OK) { + if (file_ll_open(&fp, path, FA_READ | FA_OPEN_EXISTING) != FR_OK) { goto error; } @@ -66,7 +66,7 @@ int hash_from_file(const char *path, uint8_t *digest) { while (size) { // Read a block. bytes = MIN(size, BLOCK_SIZE); - if (f_read(&fp, buf, bytes, &bytes_out) != FR_OK || bytes != bytes_out) { + if (file_ll_read(&fp, buf, bytes, &bytes_out) != FR_OK || bytes != bytes_out) { printf("hash_from_file: file read error!\n"); goto error; } @@ -92,7 +92,7 @@ int hash_from_file(const char *path, uint8_t *digest) { error: fb_free(); - f_close(&fp); + file_ll_close(&fp); return ret; } #endif //OMV_ENABLE_HASH == 1 diff --git a/src/omv/ports/stm32/main.c b/src/omv/ports/stm32/main.c index 635469a20..b560165e3 100644 --- a/src/omv/ports/stm32/main.c +++ b/src/omv/ports/stm32/main.c @@ -33,7 +33,6 @@ #include "rtc.h" #include "storage.h" #include "sdcard.h" -#include "ff.h" #include "extmod/modnetwork.h" #include "modmachine.h" @@ -59,7 +58,7 @@ #include "sdram.h" #include "fb_alloc.h" #include "dma_alloc.h" -#include "ff_wrapper.h" +#include "file_utils.h" #include "usbd_core.h" #include "usbd_desc.h" @@ -124,9 +123,9 @@ void NORETURN __fatal_error(const char *msg) { FA_WRITE | FA_CREATE_ALWAYS) == FR_OK) { UINT bytes; const char *hdr = "FATAL ERROR:\n"; - f_write(&fp, hdr, strlen(hdr), &bytes); - f_write(&fp, msg, strlen(msg), &bytes); - f_close(&fp); + file_ll_write(&fp, hdr, strlen(hdr), &bytes); + file_ll_write(&fp, msg, strlen(msg), &bytes); + file_ll_close(&fp); storage_flush(); // Initialize the USB device if it's not already initialize to allow // the host to mount the filesystem and access the error log. @@ -234,7 +233,7 @@ FRESULT exec_boot_script(const char *path, bool selftest, bool interruptible, bo // Try to run the frozen module first. if (pyexec_frozen_module(path, true) == false) { // No frozen module, try the filesystem. - f_res = f_stat(&vfs_fat->fatfs, path, NULL); + f_res = file_ll_stat(path, NULL); if (f_res == FR_OK) { // Parse, compile and execute the script. pyexec_file(path, true); @@ -270,7 +269,7 @@ FRESULT exec_boot_script(const char *path, bool selftest, bool interruptible, bo if (selftest && f_res == FR_OK) { // Remove self tests script and flush cache - f_unlink(&vfs_fat->fatfs, path); + file_ll_unlink(path); storage_flush(); #ifdef OMV_SELF_TEST_SWD_ADDR @@ -507,7 +506,7 @@ else { MP_STATE_PORT(vfs_cur) = vfs; // Mark FS as OpenMV disk. - f_touch_helper("/.openmv_disk"); + file_ll_touch("/.openmv_disk"); // Parse OpenMV configuration file. openmv_config_t openmv_config; diff --git a/src/omv/ports/stm32/modules/py_winc.c b/src/omv/ports/stm32/modules/py_winc.c index 246aa61ee..eaaccec47 100644 --- a/src/omv/ports/stm32/modules/py_winc.c +++ b/src/omv/ports/stm32/modules/py_winc.c @@ -24,7 +24,7 @@ #include "genhdr/pins.h" #include "omv_common.h" #include "py_helper.h" -#include "ff_wrapper.h" +#include "file_utils.h" #include "winc.h" #include "socket/include/socket.h" @@ -338,7 +338,7 @@ static mp_obj_t py_winc_fw_update(mp_obj_t self_in, mp_obj_t path_in) { FILINFO fno; const char *path = mp_obj_str_get_str(path_in); - if ((res = f_stat_helper(path, &fno)) != FR_OK) { + if ((res = file_ll_stat(path, &fno)) != FR_OK) { mp_raise_msg(&mp_type_OSError, (mp_rom_error_text_t) ffs_strerror(res)); } diff --git a/src/omv/ports/stm32/omv_portconfig.mk b/src/omv/ports/stm32/omv_portconfig.mk index 4ea420ba6..2d019fd50 100644 --- a/src/omv/ports/stm32/omv_portconfig.mk +++ b/src/omv/ports/stm32/omv_portconfig.mk @@ -144,7 +144,7 @@ FIRM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/alloc/, \ FIRM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/common/, \ array.o \ - ff_wrapper.o \ + file_utils.o \ ini.o \ ringbuf.o \ trace.o \