Add top level file open function.

Fimrware will now automatically detect the appropriate file type and read
in that file type correctly.

Working on tying on of this stuff togheter next. It's getting a little
bit too complicated to deal with error cases. Need to add error message
function layer.
This commit is contained in:
Kwabena W. Agyeman 2016-02-23 21:23:36 -05:00
parent c3936f4322
commit 4df0b5044b
4 changed files with 221 additions and 29 deletions

View File

@ -21,7 +21,8 @@ static uint32_t bmp_fmt;
static uint32_t bmp_row_bytes;
// This function inits the geometry values of an image.
int bmp_read_geometry(FIL *fp, image_t *img, const char *path)
int bmp_read_geometry(FIL *fp, image_t *img, const char *path,
bool *w_flipped, bool *h_flipped)
{
FRESULT res = f_open(fp, path, FA_READ|FA_OPEN_EXISTING);
if (res != FR_OK) {
@ -112,6 +113,13 @@ int bmp_read_geometry(FIL *fp, image_t *img, const char *path)
return -1;
}
if (w_flipped) {
*w_flipped = (bmp_w < 0); // Raster scan perspective
}
if (h_flipped) {
*h_flipped = (bmp_h >= 0); // Raster scan perspective
}
return FR_OK;
}
@ -129,8 +137,8 @@ int bmp_read_pixels(FIL *fp, image_t *img, int line_start, int line_end)
uint8_t pixel;
READ_BYTE(fp, &pixel);
if (j < img->w) {
if (bmp_h < 0) { // vertical flip
if (bmp_w < 0) { // horizontal flip
if (bmp_h < 0) { // vertical flip (BMP file perspective)
if (bmp_w < 0) { // horizontal flip (BMP file perspective)
IM_SET_GS_PIXEL(img, (img->w-j-1), i, pixel);
} else {
IM_SET_GS_PIXEL(img, j, i, pixel);
@ -153,8 +161,8 @@ int bmp_read_pixels(FIL *fp, image_t *img, int line_start, int line_end)
READ_WORD(fp, &pixel);
IM_SWAP16(pixel);
if (j < img->w) {
if (bmp_h < 0) { // vertical flip
if (bmp_w < 0) { // horizontal flip
if (bmp_h < 0) { // vertical flip (BMP file perspective)
if (bmp_w < 0) { // horizontal flip (BMP file perspective)
IM_SET_RGB565_PIXEL(img, (img->w-j-1), i, pixel);
} else {
IM_SET_RGB565_PIXEL(img, j, i, pixel);
@ -206,7 +214,7 @@ static int bmp_read_int(image_t *img, const char *path)
{
FIL fp;
int res = bmp_read_geometry(&fp, img, path);
int res = bmp_read_geometry(&fp, img, path, NULL, NULL);
if (res != FR_OK) {
return res;
}

View File

@ -10,9 +10,11 @@
#include <string.h>
#include <arm_math.h>
#include <stm32f4xx.h>
#include <mp.h>
#include "array.h"
#include "imlib.h"
#include "ff.h"
#include "ff_wrapper.h"
#include "mdefs.h"
#include "font.h"
#include "fb_alloc.h"
@ -24,6 +26,76 @@ extern const int8_t lab_table[196608];
/* Grayscale [0..255] to rainbox lookup */
extern const uint16_t rainbow_table[256];
////////////////////////////////////////////////////////////////////////////////
#define IMLIB_READ_FUNCTION_LINE_BUFFER (32)
static enum { PPM_IMAGE, BMP_IMAGE, JPEG_IMAGE } imlib_image_type;
int imlib_read_geometry(FIL *fp, image_t *image, const char *path,
bool *w_flipped, bool *h_flipped, bool disable_jpeg)
{
FRESULT res = f_open(fp, path, FA_READ|FA_OPEN_EXISTING);
if (res != FR_OK) {
return res;
}
char magic[2];
READ_DATA(fp, &magic, 2);
res = f_close(fp);
if (res != FR_OK) {
return res;
}
if ((magic[0]=='P')
&& ((magic[1]=='2') || (magic[1]=='3')
|| (magic[1]=='5') || (magic[1]=='6'))) { // PPM
imlib_image_type = PPM_IMAGE;
*w_flipped = false;
*h_flipped = false;
return ppm_read_geometry(fp, image, path);
} else if ((magic[0]=='B') && (magic[1]=='M')) { // BMP
imlib_image_type = BMP_IMAGE;
return bmp_read_geometry(fp, image, path, w_flipped, h_flipped);
} else if ((magic[0]==0xFF) && (magic[1]==0xD8)) { // JPEG
if (disable_jpeg) {
nlr_jump(mp_obj_new_exception_msg(
&mp_type_OSError,
"Operation not supported on JPEG"));
}
imlib_image_type = JPEG_IMAGE;
*w_flipped = false;
*h_flipped = false;
return jpeg_read_geometry(fp, image, path);
}
return -1;
}
int imlib_read_pixels(FIL *fp, image_t *img, int line_start, int line_end)
{
switch (imlib_image_type) {
case PPM_IMAGE: return ppm_read_pixels(fp, img, line_start, line_end);
case BMP_IMAGE: return bmp_read_pixels(fp, img, line_start, line_end);
default: return jpeg_read_pixels(fp, img);
}
}
/* those just call ppm for now */
int imlib_load_image(image_t *image, const char *path)
{
// needs to be redone still
return ppm_read(image, path);
}
int imlib_save_image(image_t *image, const char *path, rectangle_t *roi)
{
return ppm_write_subimg(image, path, roi);
}
////////////////////////////////////////////////////////////////////////////////
// Get pixel (handles boundary check and image type check).
int imlib_get_pixel(image_t *img, int x, int y)
{
@ -46,16 +118,7 @@ void imlib_set_pixel(image_t *img, int x, int y, int p)
}
}
/* those just call ppm for now */
int imlib_load_image(image_t *image, const char *path)
{
return ppm_read(image, path);
}
int imlib_save_image(image_t *image, const char *path, rectangle_t *roi)
{
return ppm_write_subimg(image, path, roi);
}
////////////////////////////////////////////////////////////////////////////////
void imlib_draw_line(image_t *img, int x0, int y0, int x1, int y1, int c)
{
@ -138,6 +201,8 @@ void imlib_draw_string(image_t *img, int x_off, int y_off, const char *str, int
}
}
////////////////////////////////////////////////////////////////////////////////
void imlib_binary(image_t *img, int num_thresholds, simple_color_t *l_thresholds, simple_color_t *h_thresholds, bool invert)
{
if (IM_IS_GS(img)) {
@ -443,6 +508,8 @@ float imlib_orientation_degrees(image_t *img, int *sum, int *x_center, int *y_ce
return (imlib_orientation_radians(img, sum, x_center, y_center, r) * 180.0) / M_PI;
}
////////////////////////////////////////////////////////////////////////////////
void imlib_negate(image_t *img)
{
if (IM_IS_GS(img)) {
@ -491,6 +558,8 @@ void imlib_difference(image_t *img, const char *file, image_t *other)
}
}
////////////////////////////////////////////////////////////////////////////////
uint32_t imlib_lab_distance(struct color *c0, struct color *c1)
{
uint32_t sum=0;

View File

@ -280,6 +280,27 @@ typedef enum interp {
INTERP_BICUBIC
} interp_t;
/* Image file functions */
int ppm_read_geometry(FIL *fp, image_t *img, const char *path);
int ppm_read_pixels(FIL *fp, image_t *img, int line_start, int line_end);
int ppm_read(image_t *img, const char *path);
int ppm_write_subimg(image_t *img, const char *path, rectangle_t *r);
int bmp_read_geometry(FIL *fp, image_t *img, const char *path,
bool *w_flipped, bool *h_flipped);
int bmp_read_pixels(FIL *fp, image_t *img, int line_start, int line_end);
int bmp_read(image_t *img, const char *path);
int bmp_write_subimg(image_t *img, const char *path, rectangle_t *r);
int jpeg_read_geometry(FIL *fp, image_t *img, const char *path);
int jpeg_read_pixels(FIL *fp, image_t *img);
int jpeg_read(image_t *img, const char *path);
int jpeg_write(image_t *img, const char *path);
int imlib_read_geometry(FIL *fp, image_t *img, const char *path,
bool *w_flipped, bool *h_flipped, bool disable_jpeg);
int imlib_read_pixels(FIL *fp, image_t *img, int line_start, int line_end);
int imlib_load_image(image_t *image, const char *path);
int imlib_save_image(image_t *image, const char *path, rectangle_t *roi);
/* Basic image functions */
int imlib_get_pixel(image_t *img, int x, int y);
void imlib_set_pixel(image_t *img, int x, int y, int p);
@ -288,18 +309,6 @@ point_t *point_alloc(int16_t x, int16_t y);
bool point_equal(point_t *p1, point_t *p2);
float point_distance(point_t *p1, point_t *p2);
/* Image file functions */
int ppm_read_geometry(FIL *fp, image_t *img, const char *path);
int ppm_read_pixels(FIL *fp, image_t *img, int line_start, int line_end);
int ppm_read(image_t *img, const char *path);
int ppm_write_subimg(image_t *img, const char *path, rectangle_t *r);
int bmp_read_geometry(FIL *fp, image_t *img, const char *path);
int bmp_read_pixels(FIL *fp, image_t *img, int line_start, int line_end);
int bmp_read(image_t *img, const char *path);
int bmp_write_subimg(image_t *img, const char *path, rectangle_t *r);
int imlib_load_image(image_t *image, const char *path);
int imlib_save_image(image_t *image, const char *path, rectangle_t *roi);
/* Rectangle functions */
rectangle_t *rectangle_alloc(int16_t x, int16_t y, int16_t w, int16_t h);
bool rectangle_equal(rectangle_t *r1, rectangle_t *r2);
@ -349,7 +358,6 @@ void imlib_histeq(struct image *src);
void imlib_median_filter(image_t *src, int r);
void imlib_erode(image_t *src, int ksize);
void imlib_dilate(image_t *src, int ksize);
void imlib_invert(image_t *src);
void imlib_threshold(image_t *src, image_t *dst, color_t *color, int color_size, int threshold);
void imlib_rainbow(image_t *src, struct image *dst);
array_t *imlib_count_blobs(struct image *image);

View File

@ -11,6 +11,7 @@
#include <arm_math.h>
#include "ff.h"
#include "ff_wrapper.h"
#include "xalloc.h"
#include "imlib.h"
#include "stm32f4xx_hal.h"
@ -632,3 +633,109 @@ void jpeg_compress(image_t *src, image_t *dst, int quality)
printf("time: %lums\n", HAL_GetTick() - start);
#endif
}
// This function inits the geometry values of an image.
int jpeg_read_geometry(FIL *fp, image_t *img, const char *path)
{
FRESULT res = f_open(fp, path, FA_READ|FA_OPEN_EXISTING);
if (res != FR_OK) {
return res;
}
for (;;) {
uint16_t header;
READ_WORD(fp, &header);
IM_SWAP16(header);
if ((0xFFD0 <= header) && (header <= 0xFFD9)) {
continue;
} else if (((0xFFC0 <= header) && (header <= 0xFFCF))
|| ((0xFFDA <= header) && (header <= 0xFFDF))
|| ((0xFFE0 <= header) && (header <= 0xFFEF))
|| ((0xFFF0 <= header) && (header <= 0xFFFE)))
{
uint16_t size;
READ_WORD(fp, &size);
IM_SWAP16(size);
if (((0xFFC0 <= header) && (header <= 0xFFC3))
|| ((0xFFC5 <= header) && (header <= 0xFFC7))
|| ((0xFFC9 <= header) && (header <= 0xFFCB))
|| ((0xFFCD <= header) && (header <= 0xFFCF)))
{
READ_BYTE_IGNORE(fp);
uint16_t width;
READ_WORD(fp, &width);
IM_SWAP16(width);
uint16_t height;
READ_WORD(fp, &height);
IM_SWAP16(height);
img->w = width;
img->h = height;
img->bpp = f_size(fp);
return FR_OK;
}
FRESULT res = f_lseek(fp, f_tell(fp) + size - 2);
if (res != FR_OK) {
f_close(fp);
return res;
}
} else {
f_close(fp);
return -1;
}
}
}
// This function reads the pixel values of an image.
int jpeg_read_pixels(FIL *fp, image_t *img)
{
FRESULT res = f_lseek(fp, 0);
if (res != FR_OK) {
f_close(fp);
return res;
}
READ_DATA(fp, img->pixels, img->bpp);
return FR_OK;
}
static int jpeg_read_int(image_t *img, const char *path)
{
FIL fp;
int res = jpeg_read_geometry(&fp, img, path);
if (res != FR_OK) {
return res;
}
if (!img->pixels) { // don't allocate if already allocated...
img->pixels = xalloc(img->bpp);
}
res = jpeg_read_pixels(&fp, img);
if (res != FR_OK) {
return res;
}
return f_close(&fp);
}
int jpeg_read(image_t *img, const char *path)
{
const uint8_t *backup = img->pixels;
const int res = jpeg_read_int(img, path);
// free image if I didn't start with one...
if ((res != FR_OK) && (!backup) && (img->pixels)) {
xfree(img->pixels);
}
return res;
}
int jpeg_write(image_t *img, const char *path)
{
FIL fp;
FRESULT res = f_open(&fp, path, FA_WRITE|FA_CREATE_ALWAYS);
if (res != FR_OK) {
return res;
}
WRITE_DATA(&fp, img->pixels, img->bpp);
return f_close(&fp);
}