diff --git a/imageInput.c b/imageInput.c index bb30de1..5408f64 100644 --- a/imageInput.c +++ b/imageInput.c @@ -6,17 +6,156 @@ #define BUFFER_SIZE 100 #define FILE_HEADER_STRING "__info2_image_file_format__" -// TODO Implementieren Sie geeignete Hilfsfunktionen für das Lesen der Bildserie aus einer Datei +typedef enum +{ + IMG_SUCCESS = 0, + IMG_ERR_INVALID_HEADER, // Header did not match + IMG_ERR_READ, // Failed to read from file, maybe it's too short + IMG_ERR, // General Error +} ImageError; + +static ImageError checkHeader(FILE *file); +static ImageError readPictureParams(unsigned short *number, unsigned short *width, unsigned short *height, FILE *file); +static ImageError readImage(size_t numPixels, GrayScalePixelType *pixelBuffer, unsigned char *label, FILE *file); +static ImageError parseImageFile(FILE *file, GrayScaleImageSeries *series); -// TODO Vervollständigen Sie die Funktion readImages unter Benutzung Ihrer Hilfsfunktionen GrayScaleImageSeries *readImages(const char *path) { - GrayScaleImageSeries *series = NULL; - + GrayScaleImageSeries *series = calloc(1, sizeof(GrayScaleImageSeries)); + if (series == NULL) + { + return NULL; + } + + FILE *file = fopen(path, "rb"); + if (file == NULL) + { + clearSeries(series); + series = NULL; + return NULL; // fopen failed + } + + if (parseImageFile(file, series)) + { + clearSeries(series); + series = NULL; + } + + fclose(file); return series; } -// TODO Vervollständigen Sie die Funktion clearSeries, welche eine Bildserie vollständig aus dem Speicher freigibt +static ImageError parseImageFile(FILE *file, GrayScaleImageSeries *series) +{ + if (checkHeader(file)) + { + return IMG_ERR; // header check failed + } + + unsigned short number, width, height; + if (readPictureParams(&number, &width, &height, file)) + { + return IMG_ERR; // read failed + } + size_t pixels = width * height; + + // now setup the image series + series->images = calloc(number, sizeof(GrayScaleImage)); + if (series->images == NULL) + { + return IMG_ERR; + } + + series->labels = malloc(number * sizeof(unsigned char)); + if (series->labels == NULL) + { + return IMG_ERR; + } + + series->count = number; + for (size_t imageIdx = 0; imageIdx < number; imageIdx++) + { + GrayScaleImage *curImage = &series->images[imageIdx]; + + curImage->buffer = malloc(sizeof(GrayScalePixelType) * pixels); + if (curImage->buffer == NULL) + { + return IMG_ERR; + } + + curImage->width = width; + curImage->height = height; + + if (readImage(pixels, curImage->buffer, &series->labels[imageIdx], file)) + { + return IMG_ERR; + } + } + return IMG_SUCCESS; +} + +static ImageError checkHeader(FILE *file) +{ + size_t len = strlen(FILE_HEADER_STRING); + char headerBuf[len + 1]; + size_t charsRead = fread(headerBuf, 1, len, file); + if (charsRead < len) + { + return IMG_ERR_READ; + } + headerBuf[len] = '\0'; + return strcmp(headerBuf, FILE_HEADER_STRING) == 0 ? IMG_SUCCESS : IMG_ERR_INVALID_HEADER; +} + +static ImageError readPictureParams(unsigned short *number, unsigned short *width, unsigned short *height, FILE *file) +{ + if (1 != fread(number, sizeof(unsigned short), 1, file)) + { + return IMG_ERR_READ; + } + + if (1 != fread(width, sizeof(unsigned short), 1, file)) + { + return IMG_ERR_READ; + } + + if (1 != fread(height, sizeof(unsigned short), 1, file)) + { + return IMG_ERR_READ; + } + + return IMG_SUCCESS; +} + +static ImageError readImage(size_t numPixels, GrayScalePixelType *pixelBuffer, unsigned char *label, FILE *file) +{ + if (numPixels > fread(pixelBuffer, sizeof(GrayScalePixelType), numPixels, file)) + { + return IMG_ERR_READ; + } + + if (1 != fread(label, sizeof(unsigned char), 1, file)) + { + return IMG_ERR_READ; + } + + return IMG_SUCCESS; +} + +// frees memory for each image buffer, image, label and finally series void clearSeries(GrayScaleImageSeries *series) { + if (series) + { + + int seriesLen = series->count; + for (size_t imageIdx = 0; imageIdx < seriesLen; imageIdx++) + { + free(series->images[imageIdx].buffer); + } + + free(series->images); + free(series->labels); + free(series); + } } \ No newline at end of file