Merge pull request #1976 from openmv/ff_refactor

misc: Refactor file management code.
This commit is contained in:
Ibrahim Abdelkader 2023-10-29 11:57:26 +02:00 committed by GitHub
commit fb9379e1e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 914 additions and 1142 deletions

View File

@ -8,9 +8,9 @@
* *
* Framebuffer functions. * Framebuffer functions.
*/ */
#include <ff_wrapper.h>
#include <stdio.h> #include <stdio.h>
#include "fb_alloc.h" #include "fb_alloc.h"
#include "file_utils.h"
#include "programmer/programmer.h" #include "programmer/programmer.h"
#include "spi_flash/include/spi_flash_map.h" #include "spi_flash/include/spi_flash_map.h"
@ -34,7 +34,7 @@ int burn_firmware(const char *path)
int ret = M2M_ERR_FAIL; int ret = M2M_ERR_FAIL;
uint8_t *buf = fb_alloc(FLASH_SECTOR_SZ, FB_ALLOC_NO_HINT); 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; goto error;
} }
@ -44,7 +44,7 @@ int burn_firmware(const char *path)
while (size) { while (size) {
// Read a chuck (max FLASH_SECTOR_SZ bytes). // Read a chuck (max FLASH_SECTOR_SZ bytes).
bytes = MIN(size, FLASH_SECTOR_SZ); 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"); printf("burn_firmware: file read error!\n");
goto error; goto error;
} }
@ -63,7 +63,7 @@ int burn_firmware(const char *path)
error: error:
fb_free(); fb_free();
f_close(&fp); file_ll_close(&fp);
return ret; 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 *file_buf = fb_alloc(FLASH_SECTOR_SZ, FB_ALLOC_NO_HINT);
uint8_t *flash_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; goto error;
} }
@ -92,7 +92,7 @@ int verify_firmware(const char *path)
// Firmware chuck size (max FLASH_SECTOR_SZ bytes). // Firmware chuck size (max FLASH_SECTOR_SZ bytes).
bytes = MIN(size, FLASH_SECTOR_SZ); 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"); printf("verify_firmware: file read error!\n");
goto error; goto error;
} }
@ -118,7 +118,7 @@ int verify_firmware(const char *path)
error: error:
fb_free(); fb_free();
fb_free(); fb_free();
f_close(&fp); file_ll_close(&fp);
return ret; return ret;
} }
@ -135,7 +135,7 @@ int dump_firmware(const char *path)
int ret = M2M_ERR_FAIL; int ret = M2M_ERR_FAIL;
uint8_t *flash_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_WRITE | FA_CREATE_ALWAYS) != FR_OK) { if (file_ll_open(&fp, path, FA_WRITE | FA_CREATE_ALWAYS) != FR_OK) {
goto error; goto error;
} }
@ -151,7 +151,7 @@ int dump_firmware(const char *path)
goto error; 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"); printf("dump_firmware: file write error!\n");
goto error; goto error;
} }
@ -164,6 +164,6 @@ int dump_firmware(const char *path)
error: error:
fb_free(); fb_free();
f_close(&fp); file_ll_close(&fp);
return ret; return ret;
} }

View File

@ -17,7 +17,7 @@ SRCS += $(addprefix alloc/, \
SRCS += $(addprefix common/, \ SRCS += $(addprefix common/, \
array.c \ array.c \
ff_wrapper.c \ file_utils.c \
ini.c \ ini.c \
ringbuf.c \ ringbuf.c \
trace.c \ trace.c \

View File

@ -1,543 +0,0 @@
/*
* This file is part of the OpenMV project.
* Copyright (c) 2013-2016 Kwabena W. Agyeman <kwagyeman@openmv.io>
* 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 <string.h>
#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

View File

@ -1,57 +0,0 @@
/*
* This file is part of the OpenMV project.
* Copyright (c) 2013-2016 Kwabena W. Agyeman <kwagyeman@openmv.io>
* 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 <stdint.h>
#include <ff.h>
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__ */

416
src/omv/common/file_utils.c Normal file
View File

@ -0,0 +1,416 @@
/*
* This file is part of the OpenMV project.
* Copyright (c) 2013-2023 Kwabena W. Agyeman <kwagyeman@openmv.io>
* 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 <string.h>
#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

View File

@ -0,0 +1,52 @@
/*
* This file is part of the OpenMV project.
* Copyright (c) 2013-2023 Kwabena W. Agyeman <kwagyeman@openmv.io>
* 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 <stdint.h>
#include <stdbool.h>
#include <ff.h>
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__ */

View File

@ -12,6 +12,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <string.h> #include <string.h>
#include "ini.h" #include "ini.h"
#include "file_utils.h"
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
_isppace.c - part of ctype.h _isppace.c - part of ctype.h
@ -190,7 +191,7 @@ int ini_fgetc(FIL *fp) {
char c; char c;
UINT b; 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 (EOF);
} }
return (c); return (c);

View File

@ -21,7 +21,7 @@ bool ini_is_true(const char *value);
extern "C" { extern "C" {
#endif #endif
#include "ff_wrapper.h" #include "file_utils.h"
/* Nonzero if ini_handler callback should accept lineno parameter. */ /* Nonzero if ini_handler callback should accept lineno parameter. */
#ifndef INI_HANDLER_LINENO #ifndef INI_HANDLER_LINENO

View File

@ -24,7 +24,6 @@
#include "sensor.h" #include "sensor.h"
#endif #endif
#include "framebuffer.h" #include "framebuffer.h"
#include "ff.h"
#include "usbdbg.h" #include "usbdbg.h"
#include "omv_boardconfig.h" #include "omv_boardconfig.h"
#include "py_image.h" #include "py_image.h"

View File

@ -16,157 +16,148 @@
#include "py/runtime.h" #include "py/runtime.h"
#include "xalloc.h" #include "xalloc.h"
#include "ff_wrapper.h" #include "file_utils.h"
// This function inits the geometry values of an image (opens file). // 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) { bool bmp_read_geometry(FIL *fp, image_t *img, const char *path, bmp_read_settings_t *rs) {
read_byte_expect(fp, 'B'); file_read_check(fp, "BM", 2);
read_byte_expect(fp, 'M');
uint32_t file_size; uint32_t file_size;
read_long(fp, &file_size); file_read(fp, &file_size, 4);
read_word_ignore(fp); file_read(fp, NULL, 4);
read_word_ignore(fp);
uint32_t header_size; uint32_t header_size;
read_long(fp, &header_size); file_read(fp, &header_size, 4);
if (file_size <= header_size) { if (file_size <= header_size) {
ff_file_corrupted(fp); file_raise_corrupted(fp);
} }
uint32_t data_size = file_size - header_size; uint32_t data_size = file_size - header_size;
if (data_size % 4) { if (data_size % 4) {
ff_file_corrupted(fp); file_raise_corrupted(fp);
} }
uint32_t header_type; uint32_t header_type;
read_long(fp, &header_type); file_read(fp, &header_type, 4);
if ((header_type != 40) // BITMAPINFOHEADER if ((header_type != 40) // BITMAPINFOHEADER
&& (header_type != 52) // BITMAPV2INFOHEADER && (header_type != 52) // BITMAPV2INFOHEADER
&& (header_type != 56) // BITMAPV3INFOHEADER && (header_type != 56) // BITMAPV3INFOHEADER
&& (header_type != 108) // BITMAPV4HEADER && (header_type != 108) // BITMAPV4HEADER
&& (header_type != 124)) { && (header_type != 124)) {
ff_unsupported_format(fp); // BITMAPV5HEADER file_raise_format(fp); // BITMAPV5HEADER
} }
read_long(fp, (uint32_t *) &rs->bmp_w); file_read(fp, &rs->bmp_w, 4);
read_long(fp, (uint32_t *) &rs->bmp_h); file_read(fp, &rs->bmp_h, 4);
if ((rs->bmp_w == 0) || (rs->bmp_h == 0)) { if ((rs->bmp_w == 0) || (rs->bmp_h == 0)) {
ff_file_corrupted(fp); file_raise_corrupted(fp);
} }
img->w = abs(rs->bmp_w); img->w = abs(rs->bmp_w);
img->h = abs(rs->bmp_h); img->h = abs(rs->bmp_h);
read_word_expect(fp, 1); file_read_check(fp, &(uint32_t) {1}, 2);
read_word(fp, &rs->bmp_bpp); file_read(fp, &rs->bmp_bpp, 2);
if ((rs->bmp_bpp != 8) && (rs->bmp_bpp != 16) && (rs->bmp_bpp != 24)) { 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; 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)) { if ((rs->bmp_fmt != 0) && (rs->bmp_fmt != 3)) {
ff_unsupported_format(fp); file_raise_format(fp);
} }
read_long_expect(fp, data_size); file_read_check(fp, &data_size, 4);
read_long_ignore(fp); file_read(fp, NULL, 16);
read_long_ignore(fp);
read_long_ignore(fp);
read_long_ignore(fp);
if (rs->bmp_bpp == 8) { if (rs->bmp_bpp == 8) {
if (rs->bmp_fmt != 0) { if (rs->bmp_fmt != 0) {
ff_unsupported_format(fp); file_raise_format(fp);
} }
if (header_type >= 52) { if (header_type >= 52) {
// Skip past the remaining BITMAPV2INFOHEADER bytes. // Skip past the remaining BITMAPV2INFOHEADER bytes.
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
read_long_ignore(fp); file_read(fp, NULL, 4);
} }
} }
if (header_type >= 56) { if (header_type >= 56) {
// Skip past the remaining BITMAPV3INFOHEADER bytes. // Skip past the remaining BITMAPV3INFOHEADER bytes.
for (int i = 0; i < 1; i++) { for (int i = 0; i < 1; i++) {
read_long_ignore(fp); file_read(fp, NULL, 4);
} }
} }
if (header_type >= 108) { if (header_type >= 108) {
// Skip past the remaining BITMAPV4HEADER bytes. // Skip past the remaining BITMAPV4HEADER bytes.
for (int i = 0; i < 13; i++) { for (int i = 0; i < 13; i++) {
read_long_ignore(fp); file_read(fp, NULL, 4);
} }
} }
if (header_type >= 124) { if (header_type >= 124) {
// Skip past the remaining BITMAPV5HEADER bytes. // Skip past the remaining BITMAPV5HEADER bytes.
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
read_long_ignore(fp); file_read(fp, NULL, 4);
} }
} }
// Color Table (1024 bytes) // Color Table (1024 bytes)
for (int i = 0; i < 256; i++) { 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) { } else if (rs->bmp_bpp == 16) {
if (rs->bmp_fmt != 3) { if (rs->bmp_fmt != 3) {
ff_unsupported_format(fp); file_raise_format(fp);
} }
// Bit Masks (12 bytes) // Bit Masks (12 bytes)
read_long_expect(fp, 0x1F << 11); file_read_check(fp, (uint32_t [3]) {0x1F << 11, 0x3F << 5, 0x1F}, 12);
read_long_expect(fp, 0x3F << 5);
read_long_expect(fp, 0x1F);
if (header_type >= 56) { if (header_type >= 56) {
// Skip past the remaining BITMAPV3INFOHEADER bytes. // Skip past the remaining BITMAPV3INFOHEADER bytes.
for (int i = 0; i < 1; i++) { for (int i = 0; i < 1; i++) {
read_long_ignore(fp); file_read(fp, NULL, 4);
} }
} }
if (header_type >= 108) { if (header_type >= 108) {
// Skip past the remaining BITMAPV4HEADER bytes. // Skip past the remaining BITMAPV4HEADER bytes.
for (int i = 0; i < 13; i++) { for (int i = 0; i < 13; i++) {
read_long_ignore(fp); file_read(fp, NULL, 4);
} }
} }
if (header_type >= 124) { if (header_type >= 124) {
// Skip past the remaining BITMAPV5HEADER bytes. // Skip past the remaining BITMAPV5HEADER bytes.
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
read_long_ignore(fp); file_read(fp, NULL, 4);
} }
} }
} else if (rs->bmp_bpp == 24) { } else if (rs->bmp_bpp == 24) {
if (rs->bmp_fmt == 3) { if (rs->bmp_fmt == 3) {
// Bit Masks (12 bytes) // Bit Masks (12 bytes)
read_long_expect(fp, 0xFF << 16); file_read_check(fp, (uint32_t [3]) {0xFF << 16, 0xFF << 8, 0xFF}, 12);
read_long_expect(fp, 0xFF << 8);
read_long_expect(fp, 0xFF);
} else if (header_type >= 52) { } else if (header_type >= 52) {
// Skip past the remaining BITMAPV2INFOHEADER bytes. // Skip past the remaining BITMAPV2INFOHEADER bytes.
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
read_long_ignore(fp); file_read(fp, NULL, 4);
} }
} }
if (header_type >= 56) { if (header_type >= 56) {
// Skip past the remaining BITMAPV3INFOHEADER bytes. // Skip past the remaining BITMAPV3INFOHEADER bytes.
for (int i = 0; i < 1; i++) { for (int i = 0; i < 1; i++) {
read_long_ignore(fp); file_read(fp, NULL, 4);
} }
} }
if (header_type >= 108) { if (header_type >= 108) {
// Skip past the remaining BITMAPV4HEADER bytes. // Skip past the remaining BITMAPV4HEADER bytes.
for (int i = 0; i < 13; i++) { for (int i = 0; i < 13; i++) {
read_long_ignore(fp); file_read(fp, NULL, 4);
} }
} }
if (header_type >= 124) { if (header_type >= 124) {
// Skip past the remaining BITMAPV5HEADER bytes. // Skip past the remaining BITMAPV5HEADER bytes.
for (int i = 0; i < 4; i++) { 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; rs->bmp_row_bytes = (((img->w * rs->bmp_bpp) + 31) / 32) * 4;
if (data_size != (rs->bmp_row_bytes * img->h)) { if (data_size != (rs->bmp_row_bytes * img->h)) {
ff_file_corrupted(fp); file_raise_corrupted(fp);
} }
return (rs->bmp_h >= 0); 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) { 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_bpp == 8) {
if ((rs->bmp_h < 0) && (rs->bmp_w >= 0) && (img->w == rs->bmp_row_bytes)) { 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 { } else {
for (int i = 0; i < n_lines; i++) { for (int i = 0; i < n_lines; i++) {
for (int j = 0; j < rs->bmp_row_bytes; j++) { for (int j = 0; j < rs->bmp_row_bytes; j++) {
uint8_t pixel; uint8_t pixel;
read_byte(fp, &pixel); file_read(fp, &pixel, 1);
if (j < img->w) { if (j < img->w) {
if (rs->bmp_h < 0) { if (rs->bmp_h < 0) {
// vertical flip (BMP file perspective) // 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 i = 0; i < n_lines; i++) {
for (int j = 0, jj = rs->bmp_row_bytes / 2; j < jj; j++) { for (int j = 0, jj = rs->bmp_row_bytes / 2; j < jj; j++) {
uint16_t pixel; uint16_t pixel;
read_word(fp, &pixel); file_read(fp, &pixel, 2);
if (j < img->w) { if (j < img->w) {
if (rs->bmp_h < 0) { if (rs->bmp_h < 0) {
// vertical flip (BMP file perspective) // 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 i = 0; i < n_lines; i++) {
for (int j = 0, jj = rs->bmp_row_bytes / 3; j < jj; j++) { for (int j = 0, jj = rs->bmp_row_bytes / 3; j < jj; j++) {
uint8_t b, g, r; uint8_t b, g, r;
read_byte(fp, &b); file_read(fp, &b, 1);
read_byte(fp, &g); file_read(fp, &g, 1);
read_byte(fp, &r); file_read(fp, &r, 1);
uint16_t pixel = COLOR_R8_G8_B8_TO_RGB565(r, g, b); uint16_t pixel = COLOR_R8_G8_B8_TO_RGB565(r, g, b);
if (j < img->w) { if (j < img->w) {
if (rs->bmp_h < 0) { 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++) { 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) { void bmp_read(image_t *img, const char *path) {
FIL fp; FIL fp;
bmp_read_settings_t rs; bmp_read_settings_t rs;
file_read_open(&fp, path); file_open(&fp, path, true, FA_READ | FA_OPEN_EXISTING);
file_buffer_on(&fp);
bmp_read_geometry(&fp, img, path, &rs); bmp_read_geometry(&fp, img, path, &rs);
if (!img->pixels) { if (!img->pixels) {
img->pixels = xalloc(img->w * img->h * img->bpp); img->pixels = xalloc(img->w * img->h * img->bpp);
} }
bmp_read_pixels(&fp, img, img->h, &rs); bmp_read_pixels(&fp, img, img->h, &rs);
file_buffer_off(&fp);
file_close(&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) { void bmp_write_subimg(image_t *img, const char *path, rectangle_t *r) {
rectangle_t rect; rectangle_t rect;
if (!rectangle_subimg(img, r, &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; FIL fp;
file_write_open(&fp, path); file_open(&fp, path, true, FA_WRITE | FA_CREATE_ALWAYS);
file_buffer_on(&fp);
if (IM_IS_GS(img)) { if (IM_IS_GS(img)) {
const int row_bytes = (((rect.w * 8) + 31) / 32) * 4; const int row_bytes = (((rect.w * 8) + 31) / 32) * 4;
const int data_size = (row_bytes * rect.h); const int data_size = (row_bytes * rect.h);
const int waste = (row_bytes / sizeof(uint8_t)) - rect.w; const int waste = (row_bytes / sizeof(uint8_t)) - rect.w;
// File Header (14 bytes) // Write BMP file header
write_byte(&fp, 'B'); bmp_write_header(&fp, 1024, data_size, 8, 0, &rect);
write_byte(&fp, 'M'); // Write color Table (1024 bytes)
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)
for (int i = 0; i < 256; i++) { 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)) { if ((rect.x == 0) && (rect.w == img->w) && (img->w == row_bytes)) {
write_data(&fp, // Super Fast - Zoom, Zoom! file_write(&fp, img->pixels + (rect.y * img->w), rect.w * rect.h);
img->pixels + (rect.y * img->w),
rect.w * rect.h);
} else { } else {
for (int i = 0; i < rect.h; i++) { 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++) { 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 row_bytes = (((rect.w * 16) + 31) / 32) * 4;
const int data_size = (row_bytes * rect.h); const int data_size = (row_bytes * rect.h);
const int waste = (row_bytes / sizeof(uint16_t)) - rect.w; const int waste = (row_bytes / sizeof(uint16_t)) - rect.w;
// File Header (14 bytes) // Write BMP file header
write_byte(&fp, 'B'); bmp_write_header(&fp, 12, data_size, 16, 3, &rect);
write_byte(&fp, 'M'); // Write Bit Masks (12 bytes)
write_long(&fp, 14 + 40 + 12 + data_size); file_write_long(&fp, 0x1F << 11);
write_word(&fp, 0); file_write_long(&fp, 0x3F << 5);
write_word(&fp, 0); file_write_long(&fp, 0x1F);
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);
for (int i = 0; i < rect.h; i++) { for (int i = 0; i < rect.h; i++) {
for (int j = 0; j < rect.w; j++) { 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++) { for (int j = 0; j < waste; j++) {
write_word(&fp, 0); file_write_short(&fp, 0);
} }
} }
} }
file_buffer_off(&fp);
file_close(&fp); file_close(&fp);
} }
#endif //IMLIB_ENABLE_IMAGE_FILE_IO #endif //IMLIB_ENABLE_IMAGE_FILE_IO

View File

@ -10,7 +10,7 @@
#include "py/obj.h" #include "py/obj.h"
#include <arm_math.h> #include <arm_math.h>
#include "fb_alloc.h" #include "fb_alloc.h"
#include "ff_wrapper.h" #include "file_utils.h"
#include "omv_common.h" #include "omv_common.h"
#include "fft.h" #include "fft.h"
// http://processors.wiki.ti.com/index.php/Efficient_FFT_Computation_of_Real_Input // http://processors.wiki.ti.com/index.php/Efficient_FFT_Computation_of_Real_Input

View File

@ -12,35 +12,34 @@
#if defined(IMLIB_ENABLE_IMAGE_FILE_IO) #if defined(IMLIB_ENABLE_IMAGE_FILE_IO)
#include "fb_alloc.h" #include "fb_alloc.h"
#include "ff_wrapper.h" #include "file_utils.h"
#define BLOCK_SIZE (126) // (2^7) - 2 // (DO NOT CHANGE!) #define BLOCK_SIZE (126) // (2^7) - 2 // (DO NOT CHANGE!)
void gif_open(FIL *fp, int width, int height, bool color, bool loop) { void gif_open(FIL *fp, int width, int height, bool color, bool loop) {
file_buffer_on(fp); file_buffer_on(fp);
write_data(fp, "GIF89a", 6); file_write(fp, "GIF89a", 6);
write_word(fp, width); file_write(fp, (uint16_t []) {width, height}, 4);
write_word(fp, height); file_write(fp, (uint8_t []) {0xF6, 0x00, 0x00}, 3);
write_data(fp, (uint8_t []) {0xF6, 0x00, 0x00}, 3);
if (color) { if (color) {
for (int i = 0; i < 128; i++) { for (int i = 0; i < 128; i++) {
int red = ((((i & 0x60) >> 5) * 255) + 1.5) / 3; int red = ((((i & 0x60) >> 5) * 255) + 1.5) / 3;
int green = ((((i & 0x1C) >> 2) * 255) + 3.5) / 7; int green = ((((i & 0x1C) >> 2) * 255) + 3.5) / 7;
int blue = (((i & 0x3) * 255) + 1.5) / 3; 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 { } else {
for (int i = 0; i < 128; i++) { for (int i = 0; i < 128; i++) {
int gray = ((i * 255) + 63.5) / 127; 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) { if (loop) {
write_data(fp, (uint8_t []) {'!', 0xFF, 0x0B}, 3); file_write(fp, (uint8_t []) {'!', 0xFF, 0x0B}, 3);
write_data(fp, "NETSCAPE2.0", 11); file_write(fp, "NETSCAPE2.0", 11);
write_data(fp, (uint8_t []) {0x03, 0x01, 0x00, 0x00, 0x00}, 5); file_write(fp, (uint8_t []) {0x03, 0x01, 0x00, 0x00, 0x00}, 5);
} }
file_buffer_off(fp); file_buffer_off(fp);
@ -50,16 +49,15 @@ void gif_add_frame(FIL *fp, image_t *img, uint16_t delay) {
file_buffer_on(fp); file_buffer_on(fp);
if (delay) { if (delay) {
write_data(fp, (uint8_t []) {'!', 0xF9, 0x04, 0x04}, 4); file_write(fp, (uint8_t []) {'!', 0xF9, 0x04, 0x04}, 4);
write_word(fp, delay); file_write_short(fp, delay);
write_word(fp, 0); // end file_write_short(fp, 0); // end
} }
write_byte(fp, 0x2C); file_write_byte(fp, 0x2C);
write_long(fp, 0); file_write_long(fp, 0);
write_word(fp, img->w); file_write(fp, (uint16_t []) {img->w, img->h}, 4);
write_word(fp, img->h); file_write(fp, (uint8_t []) {0x00, 0x07}, 2); // 7-bits
write_data(fp, (uint8_t []) {0x00, 0x07}, 2); // 7-bits
int bytes = img->h * img->w; int bytes = img->h * img->w;
int blocks = (bytes + BLOCK_SIZE - 1) / BLOCK_SIZE; 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)) { if (IM_IS_GS(img)) {
for (int y = 0; y < blocks; y++) { for (int y = 0; y < blocks; y++) {
int block_size = IM_MIN(BLOCK_SIZE, bytes - (y * BLOCK_SIZE)); int block_size = IM_MIN(BLOCK_SIZE, bytes - (y * BLOCK_SIZE));
write_byte(fp, 1 + block_size); file_write_byte(fp, 1 + block_size);
write_byte(fp, 0x80); // clear code file_write_byte(fp, 0x80); // clear code
for (int x = 0; x < block_size; x++) { 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)) { } else if (IM_IS_RGB565(img)) {
for (int y = 0; y < blocks; y++) { for (int y = 0; y < blocks; y++) {
int block_size = IM_MIN(BLOCK_SIZE, bytes - (y * BLOCK_SIZE)); int block_size = IM_MIN(BLOCK_SIZE, bytes - (y * BLOCK_SIZE));
write_byte(fp, 1 + block_size); file_write_byte(fp, 1 + block_size);
write_byte(fp, 0x80); // clear code file_write_byte(fp, 0x80); // clear code
for (int x = 0; x < block_size; x++) { for (int x = 0; x < block_size; x++) {
int pixel = ((uint16_t *) img->pixels)[(y * BLOCK_SIZE) + x]; uint16_t pixel = ((uint16_t *) img->pixels)[(y * BLOCK_SIZE) + x];
int red = COLOR_RGB565_TO_R5(pixel) >> 3; uint16_t r = COLOR_RGB565_TO_R5(pixel) >> 3;
int green = COLOR_RGB565_TO_G6(pixel) >> 3; uint16_t g = COLOR_RGB565_TO_G6(pixel) >> 3;
int blue = COLOR_RGB565_TO_B5(pixel) >> 3; uint16_t b = COLOR_RGB565_TO_B5(pixel) >> 3;
write_byte(fp, (red << 5) | (green << 2) | blue); file_write_byte(fp, (r << 5) | (g << 2) | b);
} }
} }
} else if (img->is_bayer || img->is_yuv) { } else if (img->is_bayer || img->is_yuv) {
for (int y = 0; y < blocks; y++) { for (int y = 0; y < blocks; y++) {
int block_size = IM_MIN(BLOCK_SIZE, bytes - (y * BLOCK_SIZE)); int block_size = IM_MIN(BLOCK_SIZE, bytes - (y * BLOCK_SIZE));
write_byte(fp, 1 + block_size); file_write_byte(fp, 1 + block_size);
write_byte(fp, 0x80); // clear code file_write_byte(fp, 0x80); // clear code
uint16_t pixels[block_size]; uint16_t pixels[block_size];
if (img->is_bayer) { if (img->is_bayer) {
imlib_debayer_line(0, block_size, y, pixels, PIXFORMAT_RGB565, img); 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); imlib_deyuv_line(0, block_size, y, pixels, PIXFORMAT_RGB565, img);
} }
for (int x = 0; x < block_size; x++) { for (int x = 0; x < block_size; x++) {
int r = COLOR_RGB565_TO_R8(pixels[x]); uint16_t pixel = pixels[2];
int g = COLOR_RGB565_TO_G8(pixels[x]); uint16_t r = COLOR_RGB565_TO_R5(pixel) >> 3;
int b = COLOR_RGB565_TO_B8(pixels[x]); uint16_t g = COLOR_RGB565_TO_G6(pixel) >> 3;
r >>= 3; g >>= 3; b >>= 3; uint16_t b = COLOR_RGB565_TO_B5(pixel) >> 3;
write_byte(fp, (r << 5) | (g << 2) | b); 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); file_buffer_off(fp);
} }
void gif_close(FIL *fp) { void gif_close(FIL *fp) {
write_byte(fp, ';'); file_write_byte(fp, ';');
file_close(fp); file_close(fp);
} }
#endif //IMLIB_ENABLE_IMAGE_FILE_IO #endif //IMLIB_ENABLE_IMAGE_FILE_IO

View File

@ -13,12 +13,11 @@
#include "py/obj.h" #include "py/obj.h"
#include "py/nlr.h" #include "py/nlr.h"
#include "ff.h"
#include "ff_wrapper.h"
#include "xalloc.h" #include "xalloc.h"
#include "imlib.h" #include "imlib.h"
// built-in cascades // built-in cascades
#include "cascade.h" #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) { static int eval_weak_classifier(cascade_t *cascade, point_t pt, int t_idx, int w_idx, int r_idx) {
int32_t sumw = 0; int32_t sumw = 0;
@ -169,14 +168,13 @@ int imlib_load_cascade_from_file(cascade_t *cascade, const char *path) {
FIL fp; FIL fp;
FRESULT res = FR_OK; FRESULT res = FR_OK;
file_read_open(&fp, path); file_open(&fp, path, true, FA_READ | FA_OPEN_EXISTING);
file_buffer_on(&fp);
/* read detection window size */ // Read detection window size
read_data(&fp, &cascade->window, sizeof(cascade->window)); file_read(&fp, &cascade->window, sizeof(cascade->window));
/* read num stages */ // Read num stages
read_data(&fp, &cascade->n_stages, sizeof(cascade->n_stages)); file_read(&fp, &cascade->n_stages, sizeof(cascade->n_stages));
cascade->stages_array = xalloc(sizeof(*cascade->stages_array) * 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); 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 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*/ /* sum num of features in each stages*/
for (i = 0, cascade->n_features = 0; i < cascade->n_stages; i++) { 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 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 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 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 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 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*/ /* sum num of recatngles per feature*/
for (i = 0, cascade->n_rectangles = 0; i < cascade->n_features; i++) { 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 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 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: error:
file_buffer_off(&fp);
file_close(&fp); file_close(&fp);
return res; return res;
} }

View File

@ -14,7 +14,7 @@
#include "font.h" #include "font.h"
#include "array.h" #include "array.h"
#include "ff_wrapper.h" #include "file_utils.h"
#include "imlib.h" #include "imlib.h"
#include "omv_common.h" #include "omv_common.h"
#include "omv_boardconfig.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) { 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]; 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); file_close(fp);
bool vflipped = false; 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'))) { || (magic[1] == '5') || (magic[1] == '6'))) {
// PPM // PPM
rs->format = FORMAT_PNM; rs->format = FORMAT_PNM;
file_read_open(fp, path); file_open(fp, path, true, FA_READ | FA_OPEN_EXISTING);
file_buffer_on(fp); // REMEMBER TO TURN THIS OFF LATER!
ppm_read_geometry(fp, img, path, &rs->ppm_rs); ppm_read_geometry(fp, img, path, &rs->ppm_rs);
} else if ((magic[0] == 'B') && (magic[1] == 'M')) { } else if ((magic[0] == 'B') && (magic[1] == 'M')) {
// BMP // BMP
rs->format = FORMAT_BMP; rs->format = FORMAT_BMP;
file_read_open(fp, path); file_open(fp, path, true, FA_READ | FA_OPEN_EXISTING);
file_buffer_on(fp); // REMEMBER TO TURN THIS OFF LATER!
vflipped = bmp_read_geometry(fp, img, path, &rs->bmp_rs); vflipped = bmp_read_geometry(fp, img, path, &rs->bmp_rs);
} else if ((magic[0] == 0xFF) && (magic[1] == 0xD8)) { } else if ((magic[0] == 0xFF) && (magic[1] == 0xD8)) {
// JPG // JPG
rs->format = FORMAT_JPG; rs->format = FORMAT_JPG;
file_read_open(fp, path); file_open(fp, path, false, FA_READ | FA_OPEN_EXISTING);
// Do not use file_buffer_on() here.
jpeg_read_geometry(fp, img, path, &rs->jpg_rs); 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)) { } else if ((magic[0] == 0x89) && (magic[1] == 0x50) && (magic[2] == 0x4E) && (magic[3] == 0x47)) {
// PNG // PNG
rs->format = FORMAT_PNG; rs->format = FORMAT_PNG;
file_read_open(fp, path); file_open(fp, path, false, FA_READ | FA_OPEN_EXISTING);
// Do not use file_buffer_on() here.
png_read_geometry(fp, img, path, &rs->png_rs); png_read_geometry(fp, img, path, &rs->png_rs);
file_buffer_on(fp); // REMEMBER TO TURN THIS OFF LATER! file_buffer_on(fp);
} else { } else {
ff_unsupported_format(NULL); file_raise_format(NULL);
} }
imblib_parse_extension(img, path); // Enforce extension! imblib_parse_extension(img, path); // Enforce extension!
return vflipped; 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; img_read_settings_t rs;
bool vflipped = imlib_read_geometry(&fp, &temp, path, &rs); bool vflipped = imlib_read_geometry(&fp, &temp, path, &rs);
if (!IM_EQUAL(img, &temp)) { if (!IM_EQUAL(img, &temp)) {
f_close(&fp); file_close(&fp);
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Images not equal!")); mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Images not equal!"));
} }
// When processing vertically flipped images the read function will fill // 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); file_close(&fp);
fb_free(); fb_free();
#else #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) #if defined(IMLIB_ENABLE_IMAGE_FILE_IO)
void imlib_load_image(image_t *img, const char *path) { void imlib_load_image(image_t *img, const char *path) {
FIL fp; FIL fp;
file_read_open(&fp, path);
char magic[4]; 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); file_close(&fp);
if ((magic[0] == 'P') if ((magic[0] == 'P')
@ -764,7 +759,7 @@ void imlib_load_image(image_t *img, const char *path) {
// PNG // PNG
png_read(img, path); png_read(img, path);
} else { } else {
ff_unsupported_format(NULL); file_raise_format(NULL);
} }
imblib_parse_extension(img, path); // Enforce extension! 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; break;
case FORMAT_RAW: { case FORMAT_RAW: {
FIL fp; FIL fp;
file_write_open(&fp, path); file_open(&fp, path, false, FA_WRITE | FA_CREATE_ALWAYS);
write_data(&fp, img->pixels, img->w * img->h); file_write(&fp, img->pixels, img->w * img->h);
file_close(&fp); file_close(&fp);
break; 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)) { } else if (IM_IS_BAYER(img)) {
FIL fp; FIL fp;
char *new_path = strcat(strcpy(fb_alloc(strlen(path) + 5, FB_ALLOC_NO_HINT), path), ".raw"); char *new_path = strcat(strcpy(fb_alloc(strlen(path) + 5, FB_ALLOC_NO_HINT), path), ".raw");
file_write_open(&fp, new_path); file_open(&fp, new_path, false, FA_WRITE | FA_CREATE_ALWAYS);
write_data(&fp, img->pixels, img->w * img->h); file_write(&fp, img->pixels, img->w * img->h);
file_close(&fp); file_close(&fp);
fb_free(); fb_free();
} else { } else {

View File

@ -19,8 +19,8 @@
#include <float.h> #include <float.h>
#include <math.h> #include <math.h>
#include <arm_math.h> #include <arm_math.h>
#include <ff.h>
#include "fb_alloc.h" #include "fb_alloc.h"
#include "file_utils.h"
#include "umm_malloc.h" #include "umm_malloc.h"
#include "xalloc.h" #include "xalloc.h"
#include "array.h" #include "array.h"

View File

@ -12,7 +12,7 @@
*/ */
#include <stdio.h> #include <stdio.h>
#include "ff_wrapper.h" #include "file_utils.h"
#include "imlib.h" #include "imlib.h"
#include "omv_boardconfig.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) { void jpeg_read_geometry(FIL *fp, image_t *img, const char *path, jpg_read_settings_t *rs) {
for (;;) { for (;;) {
uint16_t header; uint16_t header;
read_word(fp, &header); file_read(fp, &header, 2);
header = __REV16(header); header = __REV16(header);
if ((0xFFD0 <= header) && (header <= 0xFFD9)) { if ((0xFFD0 <= header) && (header <= 0xFFD9)) {
continue; continue;
@ -2211,19 +2211,19 @@ void jpeg_read_geometry(FIL *fp, image_t *img, const char *path, jpg_read_settin
|| ((0xFFE0 <= header) && (header <= 0xFFEF)) || ((0xFFE0 <= header) && (header <= 0xFFEF))
|| ((0xFFF0 <= header) && (header <= 0xFFFE))) { || ((0xFFF0 <= header) && (header <= 0xFFFE))) {
uint16_t size; uint16_t size;
read_word(fp, &size); file_read(fp, &size, 2);
size = __REV16(size); size = __REV16(size);
if (((0xFFC0 <= header) && (header <= 0xFFC3)) if (((0xFFC0 <= header) && (header <= 0xFFC3))
|| ((0xFFC5 <= header) && (header <= 0xFFC7)) || ((0xFFC5 <= header) && (header <= 0xFFC7))
|| ((0xFFC9 <= header) && (header <= 0xFFCB)) || ((0xFFC9 <= header) && (header <= 0xFFCB))
|| ((0xFFCD <= header) && (header <= 0xFFCF))) { || ((0xFFCD <= header) && (header <= 0xFFCF))) {
read_byte_ignore(fp); file_read(fp, NULL, 1);
uint16_t height; uint16_t height;
read_word(fp, &height); file_read(fp, &height, 2);
height = __REV16(height); height = __REV16(height);
uint16_t width; uint16_t width;
read_word(fp, &width); file_read(fp, &width, 2);
width = __REV16(width); width = __REV16(width);
rs->jpg_w = 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); file_seek(fp, f_tell(fp) + size - 2);
} }
} else { } 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. // This function reads the pixel values of an image.
void jpeg_read_pixels(FIL *fp, image_t *img) { void jpeg_read_pixels(FIL *fp, image_t *img) {
file_seek(fp, 0); 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) { void jpeg_read(image_t *img, const char *path) {
FIL fp; FIL fp;
jpg_read_settings_t rs; jpg_read_settings_t rs;
file_read_open(&fp, path); // Do not use file buffering here.
file_open(&fp, path, false, FA_READ | FA_OPEN_EXISTING);
// Do not use file_buffer_on() here.
jpeg_read_geometry(&fp, img, path, &rs); jpeg_read_geometry(&fp, img, path, &rs);
if (!img->pixels) { 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) { void jpeg_write(image_t *img, const char *path, int quality) {
FIL fp; FIL fp;
file_write_open(&fp, path); file_open(&fp, path, false, FA_WRITE | FA_CREATE_ALWAYS);
if (IM_IS_JPEG(img)) { if (IM_IS_JPEG(img)) {
write_data(&fp, img->pixels, img->size); file_write(&fp, img->pixels, img->size);
} else { } else {
image_t out = { .w = img->w, .h = img->h, .pixfmt = PIXFORMAT_JPEG, .size = 0, .pixels = NULL }; // alloc in jpeg compress 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 // When jpeg_compress needs more memory than in currently allocated it
// will try to realloc. MP will detect that the pointer is outside of // 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. // the heap and return NULL which will cause an out of memory error.
jpeg_compress(img, &out, quality, false); 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() fb_free(); // frees alloc in jpeg_compress()
} }
file_close(&fp); file_close(&fp);

View File

@ -16,7 +16,7 @@
#include "imlib.h" #include "imlib.h"
#include "xalloc.h" #include "xalloc.h"
#include "ff.h" #include "file_utils.h"
#ifdef IMLIB_ENABLE_FIND_LBP #ifdef IMLIB_ENABLE_FIND_LBP
#define LBP_HIST_SIZE (59) //58 uniform hist + 1 #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) { int imlib_lbp_desc_save(FIL *fp, uint8_t *desc) {
UINT bytes; UINT bytes;
// Write descriptor // 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) { 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); uint8_t *hist = xalloc(LBP_DESC_SIZE);
// Read descriptor // 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) { if (res != FR_OK || bytes != LBP_DESC_SIZE) {
*desc = NULL; *desc = NULL;
xfree(hist); xfree(hist);

View File

@ -11,7 +11,7 @@
#include "imlib.h" #include "imlib.h"
#if defined(IMLIB_ENABLE_IMAGE_FILE_IO) #if defined(IMLIB_ENABLE_IMAGE_FILE_IO)
#include "ff_wrapper.h" #include "file_utils.h"
#define SIZE_OFFSET (1 * 4) #define SIZE_OFFSET (1 * 4)
#define MICROS_OFFSET (8 * 4) #define MICROS_OFFSET (8 * 4)
@ -23,72 +23,72 @@
#define MOVI_OFFSET (54 * 4) #define MOVI_OFFSET (54 * 4)
void mjpeg_open(FIL *fp, int width, int height) { void mjpeg_open(FIL *fp, int width, int height) {
write_data(fp, "RIFF", 4); // FOURCC fcc; - 0 file_write(fp, "RIFF", 4); // FOURCC fcc; - 0
write_long(fp, 0); // DWORD cb; size - updated on close - 1 file_write_long(fp, 0); // DWORD cb; size - updated on close - 1
write_data(fp, "AVI ", 4); // FOURCC fcc; - 2 file_write(fp, "AVI ", 4); // FOURCC fcc; - 2
write_data(fp, "LIST", 4); // FOURCC fcc; - 3 file_write(fp, "LIST", 4); // FOURCC fcc; - 3
write_long(fp, 192); // DWORD cb; - 4 file_write_long(fp, 192); // DWORD cb; - 4
write_data(fp, "hdrl", 4); // FOURCC fcc; - 5 file_write(fp, "hdrl", 4); // FOURCC fcc; - 5
write_data(fp, "avih", 4); // FOURCC fcc; - 6 file_write(fp, "avih", 4); // FOURCC fcc; - 6
write_long(fp, 56); // DWORD cb; - 7 file_write_long(fp, 56); // DWORD cb; - 7
write_long(fp, 0); // DWORD dwMicroSecPerFrame; micros - updated on close - 8 file_write_long(fp, 0); // DWORD dwMicroSecPerFrame; micros - updated on close - 8
write_long(fp, 0); // DWORD dwMaxBytesPerSec; updated on close - 9 file_write_long(fp, 0); // DWORD dwMaxBytesPerSec; updated on close - 9
write_long(fp, 4); // DWORD dwPaddingGranularity; - 10 file_write_long(fp, 4); // DWORD dwPaddingGranularity; - 10
write_long(fp, 0); // DWORD dwFlags; - 11 file_write_long(fp, 0); // DWORD dwFlags; - 11
write_long(fp, 0); // DWORD dwTotalFrames; frames - updated on close - 12 file_write_long(fp, 0); // DWORD dwTotalFrames; frames - updated on close - 12
write_long(fp, 0); // DWORD dwInitialFrames; - 13 file_write_long(fp, 0); // DWORD dwInitialFrames; - 13
write_long(fp, 1); // DWORD dwStreams; - 14 file_write_long(fp, 1); // DWORD dwStreams; - 14
write_long(fp, 0); // DWORD dwSuggestedBufferSize; - 15 file_write_long(fp, 0); // DWORD dwSuggestedBufferSize; - 15
write_long(fp, width); // DWORD dwWidth; - 16 file_write_long(fp, width); // DWORD dwWidth; - 16
write_long(fp, height); // DWORD dwHeight; - 17 file_write_long(fp, height); // DWORD dwHeight; - 17
write_long(fp, 1000); // DWORD dwScale; - 18 file_write_long(fp, 1000); // DWORD dwScale; - 18
write_long(fp, 0); // DWORD dwRate; rate - updated on close - 19 file_write_long(fp, 0); // DWORD dwRate; rate - updated on close - 19
write_long(fp, 0); // DWORD dwStart; - 20 file_write_long(fp, 0); // DWORD dwStart; - 20
write_long(fp, 0); // DWORD dwLength; length - updated on close - 21 file_write_long(fp, 0); // DWORD dwLength; length - updated on close - 21
write_data(fp, "LIST", 4); // FOURCC fcc; - 22 file_write(fp, "LIST", 4); // FOURCC fcc; - 22
write_long(fp, 116); // DWORD cb; - 23 file_write_long(fp, 116); // DWORD cb; - 23
write_data(fp, "strl", 4); // FOURCC fcc; - 24 file_write(fp, "strl", 4); // FOURCC fcc; - 24
write_data(fp, "strh", 4); // FOURCC fcc; - 25 file_write(fp, "strh", 4); // FOURCC fcc; - 25
write_long(fp, 56); // DWORD cb; - 26 file_write_long(fp, 56); // DWORD cb; - 26
write_data(fp, "vids", 4); // FOURCC fccType; - 27 file_write(fp, "vids", 4); // FOURCC fccType; - 27
write_data(fp, "MJPG", 4); // FOURCC fccHandler; - 28 file_write(fp, "MJPG", 4); // FOURCC fccHandler; - 28
write_long(fp, 0); // DWORD dwFlags; - 29 file_write_long(fp, 0); // DWORD dwFlags; - 29
write_word(fp, 0); // WORD wPriority; - 30 file_write_short(fp, 0); // WORD wPriority; - 30
write_word(fp, 0); // WORD wLanguage; - 30.5 file_write_short(fp, 0); // WORD wLanguage; - 30.5
write_long(fp, 0); // DWORD dwInitialFrames; - 31 file_write_long(fp, 0); // DWORD dwInitialFrames; - 31
write_long(fp, 1000); // DWORD dwScale; - 32 file_write_long(fp, 1000); // DWORD dwScale; - 32
write_long(fp, 0); // DWORD dwRate; rate - updated on close - 33 file_write_long(fp, 0); // DWORD dwRate; rate - updated on close - 33
write_long(fp, 0); // DWORD dwStart; - 34 file_write_long(fp, 0); // DWORD dwStart; - 34
write_long(fp, 0); // DWORD dwLength; length - updated on close - 35 file_write_long(fp, 0); // DWORD dwLength; length - updated on close - 35
write_long(fp, 0); // DWORD dwSuggestedBufferSize; - 36 file_write_long(fp, 0); // DWORD dwSuggestedBufferSize; - 36
write_long(fp, 10000); // DWORD dwQuality; - 37 file_write_long(fp, 10000); // DWORD dwQuality; - 37
write_long(fp, 0); // DWORD dwSampleSize; - 38 file_write_long(fp, 0); // DWORD dwSampleSize; - 38
write_word(fp, 0); // short int left; - 39 file_write_short(fp, 0); // short int left; - 39
write_word(fp, 0); // short int top; - 39.5 file_write_short(fp, 0); // short int top; - 39.5
write_word(fp, 0); // short int right; - 40 file_write_short(fp, 0); // short int right; - 40
write_word(fp, 0); // short int bottom; - 40.5 file_write_short(fp, 0); // short int bottom; - 40.5
write_data(fp, "strf", 4); // FOURCC fcc; - 41 file_write(fp, "strf", 4); // FOURCC fcc; - 41
write_long(fp, 40); // DWORD cb; - 42 file_write_long(fp, 40); // DWORD cb; - 42
write_long(fp, 40); // DWORD biSize; - 43 file_write_long(fp, 40); // DWORD biSize; - 43
write_long(fp, width); // LONG biWidth; - 44 file_write_long(fp, width); // DWORD biWidth; - 44
write_long(fp, height); // LONG biHeight; - 45 file_write_long(fp, height); // DWORD biHeight; - 45
write_word(fp, 1); // WORD biPlanes; - 46 file_write_short(fp, 1); // WORD biPlanes; - 46
write_word(fp, 24); // WORD biBitCount; - 46.5 file_write_short(fp, 24); // WORD biBitCount; - 46.5
write_data(fp, "MJPG", 4); // DWORD biCompression; - 47 file_write(fp, "MJPG", 4); // DWORD biCompression; - 47
write_long(fp, 0); // DWORD biSizeImage; - 48 file_write_long(fp, 0); // DWORD biSizeImage; - 48
write_long(fp, 0); // LONG biXPelsPerMeter; - 49 file_write_long(fp, 0); // DWORD biXPelsPerMeter; - 49
write_long(fp, 0); // LONG biYPelsPerMeter; - 50 file_write_long(fp, 0); // DWORD biYPelsPerMeter; - 50
write_long(fp, 0); // DWORD biClrUsed; - 51 file_write_long(fp, 0); // DWORD biClrUsed; - 51
write_long(fp, 0); // DWORD biClrImportant; - 52 file_write_long(fp, 0); // DWORD biClrImportant; - 52
write_data(fp, "LIST", 4); // FOURCC fcc; - 53 file_write(fp, "LIST", 4); // FOURCC fcc; - 53
write_long(fp, 0); // DWORD cb; movi - updated on close - 54 file_write_long(fp, 0); // DWORD cb; movi - updated on close - 54
write_data(fp, "movi", 4); // FOURCC fcc; - 55 file_write(fp, "movi", 4); // FOURCC fcc; - 55
} }
void mjpeg_write(FIL *fp, int width, int height, uint32_t *frames, uint32_t *bytes, 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); uint32_t size_padded = (((dst_img.size + 3) / 4) * 4);
write_data(fp, "00dc", 4); // FOURCC fcc; file_write(fp, "00dc", 4); // FOURCC fcc;
write_long(fp, size_padded); // DWORD cb; file_write_long(fp, size_padded); // DWORD cb;
write_data(fp, dst_img.data, size_padded); // reading past okay file_write(fp, dst_img.data, size_padded); // reading past okay
*frames += 1; *frames += 1;
*bytes += size_padded; *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); uint32_t position = f_tell(fp);
// Needed // Needed
file_seek(fp, SIZE_OFFSET); file_seek(fp, SIZE_OFFSET);
write_long(fp, 216 + (*frames * 8) + *bytes); file_write_long(fp, 216 + (*frames * 8) + *bytes);
// Needed // Needed
file_seek(fp, MICROS_OFFSET); file_seek(fp, MICROS_OFFSET);
write_long(fp, (!fast_roundf(fps)) ? 0 : file_write_long(fp, (!fast_roundf(fps)) ? 0 :
fast_roundf(1000000 / fps)); fast_roundf(1000000 / fps));
write_long(fp, (!(*frames)) ? 0 : file_write_long(fp, (!(*frames)) ? 0 :
fast_roundf((((*frames * 8) + *bytes) * fps) / *frames)); fast_roundf((((*frames * 8) + *bytes) * fps) / *frames));
// Needed // Needed
file_seek(fp, FRAMES_OFFSET); file_seek(fp, FRAMES_OFFSET);
write_long(fp, *frames); file_write_long(fp, *frames);
// Probably not needed but writing it just in case. // Probably not needed but writing it just in case.
file_seek(fp, RATE_0_OFFSET); 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. // Probably not needed but writing it just in case.
file_seek(fp, LENGTH_0_OFFSET); file_seek(fp, LENGTH_0_OFFSET);
write_long(fp, (!fast_roundf(fps)) ? 0 : file_write_long(fp, (!fast_roundf(fps)) ? 0 :
fast_roundf((*frames * 1000) / fps)); fast_roundf((*frames * 1000) / fps));
// Probably not needed but writing it just in case. // Probably not needed but writing it just in case.
file_seek(fp, RATE_1_OFFSET); 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. // Probably not needed but writing it just in case.
file_seek(fp, LENGTH_1_OFFSET); file_seek(fp, LENGTH_1_OFFSET);
write_long(fp, (!fast_roundf(fps)) ? 0 : file_write_long(fp, (!fast_roundf(fps)) ? 0 :
fast_roundf((*frames * 1000) / fps)); fast_roundf((*frames * 1000) / fps));
// Needed // Needed
file_seek(fp, MOVI_OFFSET); file_seek(fp, MOVI_OFFSET);
write_long(fp, 4 + (*frames * 8) + *bytes); file_write_long(fp, 4 + (*frames * 8) + *bytes);
file_sync(fp); file_sync(fp);
file_seek(fp, position); file_seek(fp, position);
} }
void mjpeg_close(FIL *fp, uint32_t *frames, uint32_t *bytes, float fps) { void mjpeg_close(FIL *fp, uint32_t *frames, uint32_t *bytes, float fps) {
// Needed mjpeg_sync(fp, frames, bytes, fps);
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);
file_close(fp); file_close(fp);
} }

View File

@ -42,10 +42,10 @@
#include <stdbool.h> #include <stdbool.h>
#include "fmath.h" #include "fmath.h"
#include "arm_math.h" #include "arm_math.h"
#include "ff.h"
#include "imlib.h" #include "imlib.h"
#include "xalloc.h" #include "xalloc.h"
#include "fb_alloc.h" #include "fb_alloc.h"
#include "file_utils.h"
#ifdef IMLIB_ENABLE_FIND_KEYPOINTS #ifdef IMLIB_ENABLE_FIND_KEYPOINTS
#define PATCH_SIZE (31) // 31x31 pixels #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); int kpts_size = array_length(kpts);
// Write the number of keypoints // 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)) { if (res != FR_OK || bytes != sizeof(kpts_size)) {
goto error; goto error;
} }
@ -729,37 +729,37 @@ int orb_save_descriptor(FIL *fp, array_t *kpts) {
kp_t *kp = array_at(kpts, i); kp_t *kp = array_at(kpts, i);
// Write X // 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)) { if (res != FR_OK || bytes != sizeof(kp->x)) {
goto error; goto error;
} }
// Write Y // 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)) { if (res != FR_OK || bytes != sizeof(kp->y)) {
goto error; goto error;
} }
// Write Score // 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)) { if (res != FR_OK || bytes != sizeof(kp->score)) {
goto error; goto error;
} }
// Write Octave // 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)) { if (res != FR_OK || bytes != sizeof(kp->octave)) {
goto error; goto error;
} }
// Write Angle // 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)) { if (res != FR_OK || bytes != sizeof(kp->angle)) {
goto error; goto error;
} }
// Write descriptor // 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) { if (res != FR_OK || bytes != KDESC_SIZE) {
goto error; goto error;
} }
@ -776,7 +776,7 @@ int orb_load_descriptor(FIL *fp, array_t *kpts) {
int kpts_size = 0; int kpts_size = 0;
// Read number of keypoints // 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)) { if (res != FR_OK || bytes != sizeof(kpts_size)) {
goto error; goto error;
} }
@ -787,37 +787,37 @@ int orb_load_descriptor(FIL *fp, array_t *kpts) {
kp->matched = 0; kp->matched = 0;
// Read X // 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)) { if (res != FR_OK || bytes != sizeof(kp->x)) {
goto error; goto error;
} }
// Read Y // 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)) { if (res != FR_OK || bytes != sizeof(kp->y)) {
goto error; goto error;
} }
// Read Score // 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)) { if (res != FR_OK || bytes != sizeof(kp->score)) {
goto error; goto error;
} }
// Read Octave // 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)) { if (res != FR_OK || bytes != sizeof(kp->octave)) {
goto error; goto error;
} }
// Read Angle // 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)) { if (res != FR_OK || bytes != sizeof(kp->angle)) {
goto error; goto error;
} }
// Read descriptor // 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) { if (res != FR_OK || bytes != KDESC_SIZE) {
goto error; goto error;
} }

View File

@ -12,7 +12,7 @@
#include "imlib.h" #include "imlib.h"
#include "py/mphal.h" #include "py/mphal.h"
#include "py/runtime.h" #include "py/runtime.h"
#include "ff_wrapper.h" #include "file_utils.h"
#if defined(IMLIB_ENABLE_PNG_ENCODER) || defined(IMLIB_ENABLE_PNG_DECODER) #if defined(IMLIB_ENABLE_PNG_ENCODER) || defined(IMLIB_ENABLE_PNG_DECODER)
#include "lodepng.h" #include "lodepng.h"
#include "umm_malloc.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) { void png_read_geometry(FIL *fp, image_t *img, const char *path, png_read_settings_t *rs) {
uint32_t header; uint32_t header;
file_seek(fp, 12); // start of IHDR file_seek(fp, 12); // start of IHDR
read_long(fp, &header); file_read(fp, &header, 4);
if (header == 0x52444849) { if (header == 0x52444849) {
// IHDR // IHDR
uint32_t width, height; uint32_t width, height;
read_long(fp, &width); file_read(fp, &width, 4);
read_long(fp, &height); file_read(fp, &height, 4);
width = __builtin_bswap32(width); width = __builtin_bswap32(width);
height = __builtin_bswap32(height); 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->size = rs->png_size;
img->pixfmt = PIXFORMAT_PNG; img->pixfmt = PIXFORMAT_PNG;
} else { } else {
ff_file_corrupted(fp); file_raise_corrupted(fp);
} }
} }
// This function reads the pixel values of an image. // This function reads the pixel values of an image.
void png_read_pixels(FIL *fp, image_t *img) { void png_read_pixels(FIL *fp, image_t *img) {
file_seek(fp, 0); 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) { void png_read(image_t *img, const char *path) {
FIL fp; FIL fp;
png_read_settings_t rs; 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); png_read_geometry(&fp, img, path, &rs);
if (!img->pixels) { 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) { void png_write(image_t *img, const char *path) {
FIL fp; FIL fp;
file_write_open(&fp, path); file_open(&fp, path, false, FA_WRITE | FA_CREATE_ALWAYS);
if (img->pixfmt == PIXFORMAT_PNG) { if (img->pixfmt == PIXFORMAT_PNG) {
write_data(&fp, img->pixels, img->size); file_write(&fp, img->pixels, img->size);
} else { } else {
image_t out = { .w = img->w, .h = img->h, .pixfmt = PIXFORMAT_PNG, .size = 0, .pixels = NULL }; // alloc in png compress image_t out = { .w = img->w, .h = img->h, .pixfmt = PIXFORMAT_PNG, .size = 0, .pixels = NULL }; // alloc in png compress
png_compress(img, &out); 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() fb_free(); // frees alloc in png_compress()
} }
file_close(&fp); file_close(&fp);

View File

@ -18,7 +18,7 @@
#include "xalloc.h" #include "xalloc.h"
#include "imlib.h" #include "imlib.h"
#include "ff_wrapper.h" #include "file_utils.h"
static void read_int_reset(ppm_read_settings_t *rs) { static void read_int_reset(ppm_read_settings_t *rs) {
rs->read_int_c_valid = false; 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; mode = EAT_WHITESPACE;
for (*i = 0;;) { for (*i = 0;;) {
if (!rs->read_int_c_valid) { 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; return;
} }
read_byte(fp, &rs->read_int_c); file_read(fp, &rs->read_int_c, 1);
rs->read_int_c_valid = true; rs->read_int_c_valid = true;
} }
if (mode == EAT_WHITESPACE) { 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. // 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) { void ppm_read_geometry(FIL *fp, image_t *img, const char *path, ppm_read_settings_t *rs) {
read_int_reset(rs); read_int_reset(rs);
read_byte_expect(fp, 'P'); file_read_check(fp, "P", 1);
read_byte(fp, &rs->ppm_fmt); file_read(fp, &rs->ppm_fmt, 1);
if ((rs->ppm_fmt != '2') && (rs->ppm_fmt != '3') && (rs->ppm_fmt != '5') && (rs->ppm_fmt != '6')) { 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; 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); read_int(fp, (uint32_t *) &img->h, rs);
if ((img->w == 0) || (img->h == 0)) { if ((img->w == 0) || (img->h == 0)) {
ff_file_corrupted(fp); file_raise_corrupted(fp);
} }
uint32_t max; uint32_t max;
read_int(fp, &max, rs); read_int(fp, &max, rs);
if (max != 255) { 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') { } 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') { } else if (rs->ppm_fmt == '6') {
for (int i = 0; i < n_lines; i++) { for (int i = 0; i < n_lines; i++) {
for (int j = 0; j < img->w; j++) { for (int j = 0; j < img->w; j++) {
uint8_t r, g, b; uint8_t r, g, b;
read_byte(fp, &r); file_read(fp, &r, 1);
read_byte(fp, &g); file_read(fp, &g, 1);
read_byte(fp, &b); file_read(fp, &b, 1);
IM_SET_RGB565_PIXEL(img, j, i, COLOR_R8_G8_B8_TO_RGB565(r, g, b)); 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; FIL fp;
ppm_read_settings_t rs; ppm_read_settings_t rs;
file_read_open(&fp, path); file_open(&fp, path, true, FA_READ | FA_OPEN_EXISTING);
file_buffer_on(&fp);
ppm_read_geometry(&fp, img, path, &rs); ppm_read_geometry(&fp, img, path, &rs);
if (!img->pixels) { if (!img->pixels) {
img->pixels = xalloc(img->w * img->h * img->bpp); img->pixels = xalloc(img->w * img->h * img->bpp);
} }
ppm_read_pixels(&fp, img, img->h, &rs); ppm_read_pixels(&fp, img, img->h, &rs);
file_buffer_off(&fp);
file_close(&fp); file_close(&fp);
} }
@ -144,25 +141,23 @@ void ppm_write_subimg(image_t *img, const char *path, rectangle_t *r) {
} }
FIL fp; FIL fp;
file_write_open(&fp, path); file_open(&fp, path, true, FA_WRITE | FA_CREATE_ALWAYS);
file_buffer_on(&fp);
if (IM_IS_GS(img)) { if (IM_IS_GS(img)) {
char buffer[20]; // exactly big enough for 5-digit w/h 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); 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)) { if ((rect.x == 0) && (rect.w == img->w)) {
write_data(&fp, // Super Fast - Zoom, Zoom! file_write(&fp, img->pixels + (rect.y * img->w), rect.w * rect.h);
img->pixels + (rect.y * img->w),
rect.w * rect.h);
} else { } else {
for (int i = 0; i < rect.h; i++) { 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 { } else {
char buffer[20]; // exactly big enough for 5-digit w/h 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); 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 i = 0; i < rect.h; i++) {
for (int j = 0; j < rect.w; j++) { for (int j = 0; j < rect.w; j++) {
int pixel = IM_GET_RGB565_PIXEL(img, (rect.x + j), (rect.y + i)); 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[0] = COLOR_RGB565_TO_R8(pixel);
buff[1] = COLOR_RGB565_TO_G8(pixel); buff[1] = COLOR_RGB565_TO_G8(pixel);
buff[2] = COLOR_RGB565_TO_B8(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); file_close(&fp);
} }
#endif //IMLIB_ENABLE_IMAGE_FILE_IO #endif //IMLIB_ENABLE_IMAGE_FILE_IO

View File

@ -11,7 +11,7 @@
#include "py/mphal.h" #include "py/mphal.h"
#include "py/runtime.h" #include "py/runtime.h"
#include "ff_wrapper.h" #include "file_utils.h"
#include "framebuffer.h" #include "framebuffer.h"
#include "imlib.h" #include "imlib.h"
#include "py_assert.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; gif->base.type = &py_gif_type;
#if defined(IMLIB_ENABLE_IMAGE_FILE_IO) #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); gif_open(&gif->fp, gif->width, gif->height, gif->color, gif->loop);
#else #else
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Image I/O is not supported")); 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) { static mp_obj_t py_gif_size(mp_obj_t gif_obj) {
#if defined(IMLIB_ENABLE_IMAGE_FILE_IO) #if defined(IMLIB_ENABLE_IMAGE_FILE_IO)
py_gif_obj_t *arg_gif = gif_obj; 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 #else
return mp_obj_new_int(0); return mp_obj_new_int(0);
#endif #endif

View File

@ -23,7 +23,7 @@
#include "imlib.h" #include "imlib.h"
#include "array.h" #include "array.h"
#include "ff_wrapper.h" #include "file_utils.h"
#include "xalloc.h" #include "xalloc.h"
#include "fb_alloc.h" #include "fb_alloc.h"
#include "framebuffer.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(); fb_alloc_mark();
imlib_read_geometry(&fp, &image, path, &rs); imlib_read_geometry(&fp, &image, path, &rs);
file_buffer_off(&fp);
file_close(&fp); file_close(&fp);
if (args[ARG_copy_to_fb].u_bool) { 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) #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) { mp_obj_t py_image_load_descriptor(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
FIL fp; FIL fp;
UINT bytes; FRESULT res = FR_OK;
FRESULT res;
uint32_t desc_type; uint32_t desc_type;
mp_obj_t desc = mp_const_none; mp_obj_t desc = mp_const_none;
const char *path = mp_obj_str_get_str(args[0]); const char *path = mp_obj_str_get_str(args[0]);
if ((res = f_open_helper(&fp, path, FA_READ | FA_OPEN_EXISTING)) == FR_OK) { file_open(&fp, path, false, FA_READ | FA_OPEN_EXISTING);
// Read descriptor type
res = f_read(&fp, &desc_type, sizeof(desc_type), &bytes);
if (res != FR_OK || bytes != sizeof(desc_type)) {
goto error;
}
// Load descriptor // Read descriptor type
switch (desc_type) { file_read(&fp, &desc_type, sizeof(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); // Load descriptor
if (res == FR_OK) { switch (desc_type) {
desc = lbp; #if defined(IMLIB_ENABLE_FIND_LBP)
} case DESC_LBP: {
break; 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 break;
#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
} }
#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_close(&fp);
// File open or write error
// File read error
if (res != FR_OK) { if (res != FR_OK) {
mp_raise_msg(&mp_type_OSError, (mp_rom_error_text_t) ffs_strerror(res)); 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) { mp_obj_t py_image_save_descriptor(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
FIL fp; FIL fp;
UINT bytes; FRESULT res = FR_OK;
FRESULT res;
uint32_t desc_type; uint32_t desc_type;
const char *path = mp_obj_str_get_str(args[1]); const char *path = mp_obj_str_get_str(args[1]);
if ((res = f_open_helper(&fp, path, FA_WRITE | FA_CREATE_ALWAYS)) == FR_OK) { file_open(&fp, path, false, FA_WRITE | FA_CREATE_ALWAYS);
// 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"));
}
// Write descriptor type // Find descriptor type
res = f_write(&fp, &desc_type, sizeof(desc_type), &bytes); const mp_obj_type_t *desc_obj_type = mp_obj_get_type(args[0]);
if (res != FR_OK || bytes != sizeof(desc_type)) { if (0) {
goto error; #if defined(IMLIB_ENABLE_FIND_LBP)
} } else if (desc_obj_type == &py_lbp_type) {
desc_type = DESC_LBP;
// Write descriptor #endif //IMLIB_ENABLE_FIND_LBP
switch (desc_type) { #if defined(IMLIB_ENABLE_FIND_KEYPOINTS)
#if defined(IMLIB_ENABLE_FIND_LBP) } else if (desc_obj_type == &py_kp_type) {
case DESC_LBP: { desc_type = DESC_ORB;
py_lbp_obj_t *lbp = ((py_lbp_obj_t *) args[0]); #endif //IMLIB_ENABLE_FIND_KEYPOINTS
res = imlib_lbp_desc_save(&fp, lbp->hist); } else {
break; (void) desc_obj_type;
} mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Descriptor type is not supported"));
#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);
} }
error: // Write descriptor type
// File open or read error 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) { if (res != FR_OK) {
mp_raise_msg(&mp_type_OSError, (mp_rom_error_text_t) ffs_strerror(res)); 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) #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) { int py_image_descriptor_from_roi(image_t *img, const char *path, rectangle_t *roi) {
FIL fp; 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); 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 (array_length(kpts)) {
if ((res = f_open_helper(&fp, path, FA_WRITE | FA_CREATE_ALWAYS)) == FR_OK) { file_open(&fp, path, false, FA_WRITE | FA_CREATE_ALWAYS);
res = orb_save_descriptor(&fp, kpts); FRESULT res = orb_save_descriptor(&fp, kpts);
f_close(&fp); file_close(&fp);
} // File write error
// File open/write error
if (res != FR_OK) { if (res != FR_OK) {
mp_raise_msg(&mp_type_OSError, (mp_rom_error_text_t) ffs_strerror(res)); mp_raise_msg(&mp_type_OSError, (mp_rom_error_text_t) ffs_strerror(res));
} }

View File

@ -22,7 +22,7 @@
#include "py_imageio.h" #include "py_imageio.h"
#if defined(IMLIB_ENABLE_IMAGE_FILE_IO) #if defined(IMLIB_ENABLE_IMAGE_FILE_IO)
#include "ff_wrapper.h" #include "file_utils.h"
#endif #endif
#include "framebuffer.h" #include "framebuffer.h"
#include "omv_boardconfig.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) { } else if (stream->type == IMAGE_IO_FILE_STREAM) {
FIL *fp = &stream->fp; FIL *fp = &stream->fp;
write_long(fp, elapsed_ms); file_write_long(fp, elapsed_ms);
write_long(fp, image->w); file_write_long(fp, image->w);
write_long(fp, image->h); file_write_long(fp, image->h);
char padding[ALIGN_SIZE] = {}; char padding[ALIGN_SIZE] = {};
if (stream->version < NEW_PIXFORMAT_VER) { if (stream->version < NEW_PIXFORMAT_VER) {
if (image->pixfmt == PIXFORMAT_BINARY) { if (image->pixfmt == PIXFORMAT_BINARY) {
write_long(fp, OLD_BINARY_BPP); file_write_long(fp, OLD_BINARY_BPP);
} else if (image->pixfmt == PIXFORMAT_GRAYSCALE) { } 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) { } 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) { } 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) { } else if (image->pixfmt == PIXFORMAT_JPEG) {
write_long(fp, image->size); file_write_long(fp, image->size);
} else { } else {
mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("Invalid image stream bpp")); mp_raise_msg(&mp_type_ValueError, MP_ERROR_TEXT("Invalid image stream bpp"));
} }
} else { } else {
write_long(fp, image->pixfmt); file_write_long(fp, image->pixfmt);
write_long(fp, image->size); file_write_long(fp, image->size);
write_data(fp, padding, AFTER_SIZE_PADDING); file_write(fp, padding, AFTER_SIZE_PADDING);
} }
uint32_t size = image_size(image); uint32_t size = image_size(image);
write_data(fp, image->data, size); file_write(fp, image->data, size);
if (size % ALIGN_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, // 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 (0) {
#if defined(IMLIB_ENABLE_IMAGE_FILE_IO) #if defined(IMLIB_ENABLE_IMAGE_FILE_IO)
} else if (stream->type == IMAGE_IO_FILE_STREAM) { } else if (stream->type == IMAGE_IO_FILE_STREAM) {
read_long(&stream->fp, &elapsed_ms); file_read(&stream->fp, &elapsed_ms, 4);
#endif #endif
} else if (stream->type == IMAGE_IO_MEMORY_STREAM) { } else if (stream->type == IMAGE_IO_MEMORY_STREAM) {
elapsed_ms = *((uint32_t *) (stream->buffer + (stream->offset * stream->size))); 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); int_py_imageio_pause(stream, pause);
read_long(fp, (uint32_t *) &image->w); file_read(fp, &image->w, 4);
read_long(fp, (uint32_t *) &image->h); file_read(fp, &image->h, 4);
uint32_t bpp; uint32_t bpp;
read_long(fp, (uint32_t *) &bpp); file_read(fp, &bpp, 4);
if (stream->version < NEW_PIXFORMAT_VER) { if (stream->version < NEW_PIXFORMAT_VER) {
if (bpp < 0) { 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; image->pixfmt = bpp;
read_long(fp, (uint32_t *) &image->size); file_read(fp, &image->size, 4);
char ignore[AFTER_SIZE_PADDING]; char ignore[AFTER_SIZE_PADDING];
read_data(fp, ignore, AFTER_SIZE_PADDING); file_read(fp, ignore, AFTER_SIZE_PADDING);
} }
} }
#endif #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) #if defined(IMLIB_ENABLE_IMAGE_FILE_IO)
} else if (stream->type == IMAGE_IO_FILE_STREAM) { } else if (stream->type == IMAGE_IO_FILE_STREAM) {
FIL *fp = &stream->fp; FIL *fp = &stream->fp;
read_data(fp, image.data, size); file_read(fp, image.data, size);
// Check if original byte reversed data. // Check if original byte reversed data.
if ((image.pixfmt == PIXFORMAT_RGB565) && (stream->version == ORIGINAL_VER)) { 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) { if (size % ALIGN_SIZE) {
char ignore[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) { 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]; char mode = mp_obj_str_get_str(args[1])[0];
if ((mode == 'W') || (mode == 'w')) { 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"; const char string[] = "OMV IMG STR V2.0";
stream->version = NEW_PIXFORMAT_VER; stream->version = NEW_PIXFORMAT_VER;
// Overwrite if file is too small. // Overwrite if file is too small.
if (f_size(fp) < MAGIC_SIZE) { 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 { } else {
uint8_t version_hi, period, version_lo; uint8_t version_hi, period, version_lo;
char temp[sizeof(string) - 3] = {}; char temp[sizeof(string) - 3] = {};
read_data(fp, temp, sizeof(temp) - 1); file_read(fp, temp, sizeof(temp) - 1);
read_byte(fp, &version_hi); file_read(fp, &version_hi, 1);
read_byte(fp, &period); file_read(fp, &period, 1);
read_byte(fp, &version_lo); file_read(fp, &version_lo, 1);
int version = ((version_hi - '0') * 10) + (version_lo - '0'); int version = ((version_hi - '0') * 10) + (version_lo - '0');
// Overwrite if file magic does not match. // 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 != RGB565_FIXED_VER)
|| (version != NEW_PIXFORMAT_VER)) { || (version != NEW_PIXFORMAT_VER)) {
file_seek(fp, 0); 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 { } else {
file_close(fp); file_close(fp);
mode = 'R'; 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')) { if ((mode == 'R') || (mode == 'r')) {
uint8_t version_hi, version_lo; uint8_t version_hi, version_lo;
file_read_write_open_existing(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_EXISTING);
read_long_expect(fp, *((uint32_t *) "OMV ")); // OpenMV file_read_check(fp, "OMV IMG STR ", 12); // Magic
read_long_expect(fp, *((uint32_t *) "IMG ")); // Image file_read_check(fp, "V", 1);
read_long_expect(fp, *((uint32_t *) "STR ")); // Stream file_read(fp, &version_hi, 1);
read_byte_expect(fp, 'V'); file_read_check(fp, ".", 1);
read_byte(fp, &version_hi); file_read(fp, &version_lo, 1);
read_byte_expect(fp, '.');
read_byte(fp, &version_lo);
stream->version = ((version_hi - '0') * 10) + (version_lo - '0'); stream->version = ((version_hi - '0') * 10) + (version_lo - '0');

View File

@ -20,7 +20,7 @@
#include "py_helper.h" #include "py_helper.h"
#include "py_image.h" #include "py_image.h"
#include "ff_wrapper.h" #include "file_utils.h"
#include "framebuffer.h" #include "framebuffer.h"
#include "omv_boardconfig.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->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->frames = 0;
mjpeg->bytes = 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); mjpeg_open(&mjpeg->fp, mjpeg->width, mjpeg->height);
return mjpeg; return mjpeg;
} }

View File

@ -23,7 +23,7 @@
#ifdef IMLIB_ENABLE_TF #ifdef IMLIB_ENABLE_TF
#include "py_image.h" #include "py_image.h"
#include "ff_wrapper.h" #include "file_utils.h"
#include "py_tf.h" #include "py_tf.h"
#include "libtf_builtin_models.h" #include "libtf_builtin_models.h"
#define GRAYSCALE_RANGE ((COLOR_GRAYSCALE_MAX) -(COLOR_GRAYSCALE_MIN)) #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 (tf_model->model_data == NULL) {
#if defined(IMLIB_ENABLE_IMAGE_FILE_IO) #if defined(IMLIB_ENABLE_IMAGE_FILE_IO)
FIL fp; 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_len = f_size(&fp);
tf_model->model_data = alloc_mode tf_model->model_data = alloc_mode
? fb_alloc(tf_model->model_data_len, FB_ALLOC_PREFER_SIZE) ? fb_alloc(tf_model->model_data_len, FB_ALLOC_PREFER_SIZE)
: xalloc(tf_model->model_data_len); : 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); file_close(&fp);
#else #else
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Image I/O is not supported")); mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("Image I/O is not supported"));

View File

@ -59,7 +59,7 @@
#include "tinyusb_debug.h" #include "tinyusb_debug.h"
#include "fb_alloc.h" #include "fb_alloc.h"
#include "dma_alloc.h" #include "dma_alloc.h"
#include "ff_wrapper.h" #include "file_utils.h"
#include "mimxrt_hal.h" #include "mimxrt_hal.h"
extern uint8_t _sstack, _estack, _heap_start, _heap_end; extern uint8_t _sstack, _estack, _heap_start, _heap_end;

View File

@ -127,7 +127,7 @@ FIRM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/alloc/, \
FIRM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/common/, \ FIRM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/common/, \
array.o \ array.o \
ff_wrapper.o \ file_utils.o \
ini.o \ ini.o \
ringbuf.o \ ringbuf.o \
trace.o \ trace.o \

View File

@ -100,7 +100,7 @@ FIRM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/alloc/, \
FIRM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/common/, \ FIRM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/common/, \
array.o \ array.o \
ff_wrapper.o \ file_utils.o \
ini.o \ ini.o \
ringbuf.o \ ringbuf.o \
trace.o \ trace.o \

View File

@ -93,7 +93,7 @@ target_sources(${MICROPY_TARGET} PRIVATE
${TOP_DIR}/${OMV_DIR}/alloc/unaligned_memcpy.c ${TOP_DIR}/${OMV_DIR}/alloc/unaligned_memcpy.c
${TOP_DIR}/${OMV_DIR}/common/array.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/ini.c
${TOP_DIR}/${OMV_DIR}/common/ringbuf.c ${TOP_DIR}/${OMV_DIR}/common/ringbuf.c
${TOP_DIR}/${OMV_DIR}/common/trace.c ${TOP_DIR}/${OMV_DIR}/common/trace.c

View File

@ -11,10 +11,10 @@
#if (OMV_ENABLE_HASH == 1) #if (OMV_ENABLE_HASH == 1)
#include STM32_HAL_H #include STM32_HAL_H
#include <stdbool.h> #include <stdbool.h>
#include <ff_wrapper.h>
#include <stdio.h> #include <stdio.h>
#include "fb_alloc.h"
#include "hash.h" #include "hash.h"
#include "fb_alloc.h"
#include "file_utils.h"
#define BLOCK_SIZE (512) #define BLOCK_SIZE (512)
static HASH_HandleTypeDef hhash; static HASH_HandleTypeDef hhash;
@ -56,7 +56,7 @@ int hash_from_file(const char *path, uint8_t *digest) {
int ret = -1; int ret = -1;
uint8_t *buf = fb_alloc(BLOCK_SIZE, FB_ALLOC_NO_HINT); 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; goto error;
} }
@ -66,7 +66,7 @@ int hash_from_file(const char *path, uint8_t *digest) {
while (size) { while (size) {
// Read a block. // Read a block.
bytes = MIN(size, BLOCK_SIZE); 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"); printf("hash_from_file: file read error!\n");
goto error; goto error;
} }
@ -92,7 +92,7 @@ int hash_from_file(const char *path, uint8_t *digest) {
error: error:
fb_free(); fb_free();
f_close(&fp); file_ll_close(&fp);
return ret; return ret;
} }
#endif //OMV_ENABLE_HASH == 1 #endif //OMV_ENABLE_HASH == 1

View File

@ -33,7 +33,6 @@
#include "rtc.h" #include "rtc.h"
#include "storage.h" #include "storage.h"
#include "sdcard.h" #include "sdcard.h"
#include "ff.h"
#include "extmod/modnetwork.h" #include "extmod/modnetwork.h"
#include "modmachine.h" #include "modmachine.h"
@ -59,7 +58,7 @@
#include "sdram.h" #include "sdram.h"
#include "fb_alloc.h" #include "fb_alloc.h"
#include "dma_alloc.h" #include "dma_alloc.h"
#include "ff_wrapper.h" #include "file_utils.h"
#include "usbd_core.h" #include "usbd_core.h"
#include "usbd_desc.h" #include "usbd_desc.h"
@ -124,9 +123,9 @@ void NORETURN __fatal_error(const char *msg) {
FA_WRITE | FA_CREATE_ALWAYS) == FR_OK) { FA_WRITE | FA_CREATE_ALWAYS) == FR_OK) {
UINT bytes; UINT bytes;
const char *hdr = "FATAL ERROR:\n"; const char *hdr = "FATAL ERROR:\n";
f_write(&fp, hdr, strlen(hdr), &bytes); file_ll_write(&fp, hdr, strlen(hdr), &bytes);
f_write(&fp, msg, strlen(msg), &bytes); file_ll_write(&fp, msg, strlen(msg), &bytes);
f_close(&fp); file_ll_close(&fp);
storage_flush(); storage_flush();
// Initialize the USB device if it's not already initialize to allow // Initialize the USB device if it's not already initialize to allow
// the host to mount the filesystem and access the error log. // 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. // Try to run the frozen module first.
if (pyexec_frozen_module(path, true) == false) { if (pyexec_frozen_module(path, true) == false) {
// No frozen module, try the filesystem. // 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) { if (f_res == FR_OK) {
// Parse, compile and execute the script. // Parse, compile and execute the script.
pyexec_file(path, true); 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) { if (selftest && f_res == FR_OK) {
// Remove self tests script and flush cache // Remove self tests script and flush cache
f_unlink(&vfs_fat->fatfs, path); file_ll_unlink(path);
storage_flush(); storage_flush();
#ifdef OMV_SELF_TEST_SWD_ADDR #ifdef OMV_SELF_TEST_SWD_ADDR
@ -507,7 +506,7 @@ else {
MP_STATE_PORT(vfs_cur) = vfs; MP_STATE_PORT(vfs_cur) = vfs;
// Mark FS as OpenMV disk. // Mark FS as OpenMV disk.
f_touch_helper("/.openmv_disk"); file_ll_touch("/.openmv_disk");
// Parse OpenMV configuration file. // Parse OpenMV configuration file.
openmv_config_t openmv_config; openmv_config_t openmv_config;

View File

@ -24,7 +24,7 @@
#include "genhdr/pins.h" #include "genhdr/pins.h"
#include "omv_common.h" #include "omv_common.h"
#include "py_helper.h" #include "py_helper.h"
#include "ff_wrapper.h" #include "file_utils.h"
#include "winc.h" #include "winc.h"
#include "socket/include/socket.h" #include "socket/include/socket.h"
@ -325,7 +325,7 @@ static mp_obj_t py_winc_fw_update(mp_obj_t self_in, mp_obj_t path_in) {
FILINFO fno; FILINFO fno;
const char *path = mp_obj_str_get_str(path_in); 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)); mp_raise_msg(&mp_type_OSError, (mp_rom_error_text_t) ffs_strerror(res));
} }

View File

@ -144,7 +144,7 @@ FIRM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/alloc/, \
FIRM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/common/, \ FIRM_OBJ += $(addprefix $(BUILD)/$(OMV_DIR)/common/, \
array.o \ array.o \
ff_wrapper.o \ file_utils.o \
ini.o \ ini.o \
ringbuf.o \ ringbuf.o \
trace.o \ trace.o \