#include #include #include #include "imageInput.h" #define FILE_HEADER_STRING "__info2_image_file_format__" #define FILE_HEADER_LENGTH (sizeof(FILE_HEADER_STRING) - 1U) // Reads an entire image series file and returns a heap-allocated descriptor. GrayScaleImageSeries *readImages(const char *path) { FILE *file = fopen(path, "rb"); if(file == NULL) { return NULL; } if(!checkFileHeader(file)) { fclose(file); return NULL; } unsigned int numberOfImages = readDimension(file); unsigned short width = readDimension(file); unsigned short height = readDimension(file); GrayScaleImageSeries *series = (GrayScaleImageSeries *)malloc(sizeof(GrayScaleImageSeries)); if(series == NULL) { fclose(file); return NULL; } series->images = (GrayScaleImage *)calloc(numberOfImages, sizeof(GrayScaleImage)); series->labels = (unsigned char *)calloc(numberOfImages, sizeof(unsigned char)); series->count = numberOfImages; if(series->images == NULL || series->labels == NULL) { clearSeries(series); fclose(file); return NULL; } for(unsigned int i = 0; i < numberOfImages; i++) { series->images[i] = readImage(file, width, height); series->labels[i] = readLabel(file); } fclose(file); return series; } // Validates and consumes the file header tag that identifies the custom format. bool checkFileHeader(FILE *file) { char buffer[FILE_HEADER_LENGTH + 1] = {0}; size_t bytesRead = fread(buffer, sizeof(char), FILE_HEADER_LENGTH, file); if(bytesRead != FILE_HEADER_LENGTH) { return false; } return strncmp(buffer, FILE_HEADER_STRING, FILE_HEADER_LENGTH) == 0; } // Reads a single 16-bit dimension (width, height or count of Images) from the file. unsigned short int readDimension(FILE *file) { unsigned short int dimension = 0; fread(&dimension, sizeof(unsigned short int), 1, file); return dimension; } // Reads a single grayscale image of the provided dimensions from the file. GrayScaleImage readImage(FILE *file, unsigned short width, unsigned short height) { GrayScaleImage image = {0}; image.width = width; image.height = height; unsigned int pixelCount = (unsigned int)width * (unsigned int)height; image.buffer = (GrayScalePixelType *)malloc(pixelCount * sizeof(GrayScalePixelType)); if(image.buffer != NULL) { fread(image.buffer, sizeof(GrayScalePixelType), pixelCount, file); } return image; } // Reads one byte label that belongs to the preceding image. unsigned char readLabel(FILE *file) { unsigned char label = 0; fread(&label, sizeof(unsigned char), 1, file); return label; } // Releases all heap allocations associated with a GrayScaleImageSeries. void clearSeries(GrayScaleImageSeries *series) { if (series != NULL) { if (series->images != NULL) { // Free each image's buffer for (unsigned int i = 0; i < series->count; i++) { if (series->images[i].buffer != NULL) free(series->images[i].buffer); } free(series->images); } if (series->labels != NULL) free(series->labels); free(series); } }