// #include // #include // #include // #include "imageInput.h" // // #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 // GrayScaleImageSeries *readImages(const char *path) // { // GrayScaleImageSeries *series = NULL; // // return series; // } // // // TODO Vervollständigen Sie die Funktion clearSeries, welche eine Bildserie vollständig aus dem Speicher freigibt // void clearSeries(GrayScaleImageSeries *series) // { // // } #include #include #include #include "imageInput.h" #define FILE_HEADER_STRING "__info2_image_file_format__" // --------------------------------------------------------- // Hilfsfunktionen (static, nur in diesem Modul sichtbar) // --------------------------------------------------------- /** * Prüft, ob die Datei mit dem korrekten Header-String beginnt. * Gibt 1 zurück, wenn korrekt, sonst 0. */ static int checkFileHeader(FILE *file) { const char *expectedHeader = FILE_HEADER_STRING; size_t headerLen = strlen(expectedHeader); char buffer[100]; // Puffer groß genug für den Header // Wir lesen genau so viele Bytes, wie der Header lang ist if (fread(buffer, sizeof(char), headerLen, file) != headerLen) { return 0; // Lesefehler oder Datei zu kurz } // Null-Terminierung sicherstellen für strcmp (obwohl wir auch memcmp nutzen könnten) buffer[headerLen] = '\0'; if (strcmp(buffer, expectedHeader) != 0) { return 0; // Header stimmt nicht überein } return 1; } /** * Reserviert den Speicher für die Basis-Struktur der Bildserie. * Reserviert Arrays für 'images' und 'labels', aber noch nicht die Pixel-Buffer der einzelnen Bilder. */ static GrayScaleImageSeries *allocateSeries(unsigned short count) { GrayScaleImageSeries *series = (GrayScaleImageSeries *)malloc(sizeof(GrayScaleImageSeries)); if (series == NULL) return NULL; series->count = count; // Speicher für das Array der Bild-Strukturen series->images = (GrayScaleImage *)calloc(count, sizeof(GrayScaleImage)); // Speicher für das Array der Labels series->labels = (unsigned char *)calloc(count, sizeof(unsigned char)); if (series->images == NULL || series->labels == NULL) { // Falls eine Allokation fehlschlägt, alles bisherige freigeben free(series->images); free(series->labels); free(series); return NULL; } return series; } /** * Liest ein einzelnes Bild (Pixeldaten) und das zugehörige Label. */ static int readSingleImage(FILE *file, GrayScaleImage *image, unsigned char *label, unsigned short width, unsigned short height) { image->width = width; image->height = height; // Speicher für die Pixelwerte reservieren image->buffer = (GrayScalePixelType *)malloc(width * height * sizeof(GrayScalePixelType)); if (image->buffer == NULL) { return 0; } // Pixelwerte lesen if (fread(image->buffer, sizeof(GrayScalePixelType), width * height, file) != width * height) { return 0; } // Label lesen if (fread(label, sizeof(unsigned char), 1, file) != 1) { return 0; } return 1; } // --------------------------------------------------------- // Hauptfunktionen (öffentliche API) // --------------------------------------------------------- GrayScaleImageSeries *readImages(const char *path) { FILE *file = fopen(path, "rb"); // WICHTIG: "rb" für binary mode if (file == NULL) { return NULL; } // 1. Header prüfen if (!checkFileHeader(file)) { fclose(file); return NULL; } // 2. Dimensionen lesen (Anzahl, Breite, Höhe) unsigned short count, width, height; int readCount = 0; readCount += fread(&count, sizeof(unsigned short), 1, file); readCount += fread(&width, sizeof(unsigned short), 1, file); readCount += fread(&height, sizeof(unsigned short), 1, file); if (readCount != 3) { fclose(file); return NULL; } // 3. Speicherstruktur vorbereiten GrayScaleImageSeries *series = allocateSeries(count); if (series == NULL) { fclose(file); return NULL; } // 4. Jedes Bild einzeln einlesen for (int i = 0; i < count; i++) { if (!readSingleImage(file, &series->images[i], &series->labels[i], width, height)) { // Fehler beim Lesen eines Bildes -> Aufräumen clearSeries(series); fclose(file); return NULL; } } fclose(file); return series; } void clearSeries(GrayScaleImageSeries *series) { if (series == NULL) return; // 1. Pixel-Buffer jedes einzelnen Bildes freigeben if (series->images != NULL) { for (int i = 0; i < series->count; i++) { if (series->images[i].buffer != NULL) { free(series->images[i].buffer); series->images[i].buffer = NULL; } } // 2. Das Array der Bild-Strukturen freigeben free(series->images); } // 3. Das Label-Array freigeben if (series->labels != NULL) { free(series->labels); } // 4. Die Hauptstruktur freigeben free(series); }