diff --git a/Startcode/imageInput.c b/Startcode/imageInput.c index bb30de1..a640b63 100644 --- a/Startcode/imageInput.c +++ b/Startcode/imageInput.c @@ -6,17 +6,145 @@ #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 -// TODO Vervollständigen Sie die Funktion readImages unter Benutzung Ihrer Hilfsfunktionen +/* + * Aufbau der mnist_test.info2 + * + * Offset Inhalt Typ + * ------ ---------------------------- ---------------------------------- + * 0 "__info2_image_file_format__" 26 ASCII-Zeichen + * 26 Anzahl der Bilder unsigned short (2 Bytes) 10 27 -> 27 10 -> 10000 + * 28 Breite eines Bildes unsigned short (2 Bytes) 1C 00 -> 00 1C -> 28 + * 30 Höhe eines Bildes unsigned short (2 Bytes) 1C 00 -> 00 1C -> 28 + * 32 Bild 0: width*height Pixel unsigned char je Pixel (Graustufe 0-255) + * direkt danach: Label 0 unsigned char (Klasse 0-9) + * + * usw... + */ + + +//prüft, ob die Datei mit dem erwarteten Dateitag beginnt +static int checkFileTag(FILE *file) +{ + int isValid = 0; + size_t tagLength = strlen(FILE_HEADER_STRING); + char buffer[BUFFER_SIZE] = {0}; + + if(tagLength < BUFFER_SIZE && fread(buffer, sizeof(char), tagLength, file) == tagLength) + { + isValid = strncmp(buffer, FILE_HEADER_STRING, tagLength) == 0; + } + + return isValid; +} + +//liest Anzahl, Breite und Höhe der Bildserie; Erfolg nur, wenn alle Werte gelesen werden konnten und positiv sind +static int readSeriesHeader(FILE *file, unsigned short *count, unsigned short *width, unsigned short *height) +{ + return fread(count, sizeof(unsigned short), 1, file) == 1 + && fread(width, sizeof(unsigned short), 1, file) == 1 + && fread(height, sizeof(unsigned short), 1, file) == 1 + && *count > 0 && *width > 0 && *height > 0; +} + +//liest die Pixelwerte eines einzelnen Bildes; buffer ist NULL im Fehlerfall +static GrayScaleImage readImage(FILE *file, unsigned int width, unsigned int height) +{ + GrayScaleImage image = {NULL, 0, 0}; + + GrayScalePixelType *buffer = (GrayScalePixelType *)calloc(width * height, sizeof(GrayScalePixelType)); + + if(buffer != NULL && fread(buffer, sizeof(GrayScalePixelType), width * height, file) == width * height) + { + image.buffer = buffer; + image.width = width; + image.height = height; + } + else + { + free(buffer); + } + + return image; +} + +//liest die Klasse (Label) des zuletzt gelesenen Bildes +static int readLabel(FILE *file, unsigned char *label) +{ + return fread(label, sizeof(unsigned char), 1, file) == 1; +} + +static int isValidSeries(const GrayScaleImageSeries *series) +{ + return series->images != NULL && series->labels != NULL && series->count > 0; +} + GrayScaleImageSeries *readImages(const char *path) { GrayScaleImageSeries *series = NULL; - + FILE *file = fopen(path, "rb"); //Binärdatei, daher "rb" + + if(file != NULL) + { + unsigned short count = 0; + unsigned short width = 0; + unsigned short height = 0; + + if(checkFileTag(file) && readSeriesHeader(file, &count, &width, &height)) + { + series = (GrayScaleImageSeries *)malloc(sizeof(GrayScaleImageSeries)); //struct containing *images, *lables and count + + if(series != NULL) + { + series->images = (GrayScaleImage *)calloc(count, sizeof(GrayScaleImage)); //10000 * 784bytes in our example + series->labels = (unsigned char *)calloc(count, sizeof(unsigned char)); //10000bytes 1 for every picture in our example + series->count = count; + + if(isValidSeries(series)) + { + int allRead = 1; + + for(unsigned int i = 0; i < count && allRead; i++) + { + series->images[i] = readImage(file, width, height); + allRead = series->images[i].buffer != NULL && readLabel(file, &series->labels[i]); + } + + if(!allRead) + { + clearSeries(series); + series = NULL; + } + } + else + { + clearSeries(series); + series = NULL; + } + } + } + + fclose(file); + } + return series; } -// TODO Vervollständigen Sie die Funktion clearSeries, welche eine Bildserie vollständig aus dem Speicher freigibt void clearSeries(GrayScaleImageSeries *series) { -} \ No newline at end of file + if(series != NULL) + { + if(series->images != NULL) + { + //erst die Pixelbuffer der einzelnen Bilder, dann das Array selbst + for(unsigned int i = 0; i < series->count; i++) + { + free(series->images[i].buffer); + } + free(series->images); + } + + free(series->labels); + free(series); + } +}