#include #include #include #include "imageInput.h" #define BUFFER_SIZE 100 #define FILE_HEADER_STRING "__info2_image_file_format__" // ===================================================== // Hilfsfunktion 1 // Datei öffnen + Header prüfen + Metadaten lesen // ===================================================== static FILE *openFileAndReadHeader(const char *path, unsigned short *count, unsigned short *width, unsigned short *height) { // Schritt 1: Datei öffnen FILE *file = fopen(path, "rb"); if (!file) { fprintf(stderr, "Error: Cannot open file '%s'\n", path); return NULL; } // Schritt 2: Header-String prüfen char buffer[BUFFER_SIZE] = {0}; size_t headerLen = strlen(FILE_HEADER_STRING); if (fread(buffer, sizeof(char), headerLen, file) != headerLen) { fprintf(stderr, "Error: Cannot read file header (file too small?)\n"); fclose(file); return NULL; } if (strncmp(buffer, FILE_HEADER_STRING, headerLen) != 0) { fprintf(stderr, "Error: Invalid file header. Expected '%s', got: %.24s\n", FILE_HEADER_STRING, buffer); fclose(file); return NULL; } // Schritt 3: Metadaten lesen (Reihenfolge: count, width, height) // WICHTIG: Diese Reihenfolge (Anzahl, Breite, Höhe) entspricht // der Aufgabenstellung und dem in den Tests verwendeten Format. if (fread(count, sizeof(unsigned short), 1, file) != 1) { fprintf(stderr, "Error: Cannot read image count\n"); fclose(file); return NULL; } if (fread(width, sizeof(unsigned short), 1, file) != 1) { fprintf(stderr, "Error: Cannot read image width\n"); fclose(file); return NULL; } if (fread(height, sizeof(unsigned short), 1, file) != 1) { fprintf(stderr, "Error: Cannot read image height\n"); fclose(file); return NULL; } // Input-Validierung: Prüfe auf ungültige Dimensionen if (*count == 0) { fprintf(stderr, "Error: Image count is 0\n"); fclose(file); return NULL; } if (*width == 0) { fprintf(stderr, "Error: Image width is 0\n"); fclose(file); return NULL; } if (*height == 0) { fprintf(stderr, "Error: Image height is 0\n"); fclose(file); return NULL; } // Erfolg: offene Datei zurückgeben, Position ist nach Metadaten return file; } // ----------------------------------------------------- // Hilfsfunktion 2: Speicher für die gesamte Serie anlegen // ----------------------------------------------------- static GrayScaleImageSeries *allocateSeries(unsigned short count, unsigned short width, unsigned short height) { GrayScaleImageSeries *series = malloc(sizeof(GrayScaleImageSeries)); if (!series) return NULL; series->count = count; series->images = calloc(count, sizeof(GrayScaleImage)); series->labels = calloc(count, sizeof(unsigned char)); if (!series->images || !series->labels) { clearSeries(series); return NULL; } // Bilddimensionen in jedes Struktur-Element übernehmen for (unsigned short i = 0; i < count; i++) { series->images[i].width = width; series->images[i].height = height; } return series; } // ----------------------------------------------------- // Hilfsfunktion 3: EIN BILD + EIN LABEL lesen // ----------------------------------------------------- static int readSingleImage(FILE *file, GrayScaleImage *img, unsigned char *label) { unsigned int pixelCount = img->width * img->height; img->buffer = malloc(pixelCount * sizeof(GrayScalePixelType)); if (!img->buffer) return 0; if (fread(img->buffer, sizeof(GrayScalePixelType), pixelCount, file) != pixelCount) return 0; if (fread(label, sizeof(unsigned char), 1, file) != 1) return 0; return 1; } // ===================================================== // Hauptfunktion: Liest komplette Bilderserie // ===================================================== GrayScaleImageSeries *readImages(const char *path) { unsigned short count = 0, width = 0, height = 0; // Schritt 1-3: Datei öffnen + Header + Metadaten FILE *file = openFileAndReadHeader(path, &count, &width, &height); if (!file) { // Fehler bereits geloggt von openFileAndReadHeader() return NULL; } // Schritt 4: Bilderserie allokieren GrayScaleImageSeries *series = allocateSeries(count, width, height); if (!series) { fprintf(stderr, "Error: Cannot allocate image series\n"); fclose(file); return NULL; } // Schritt 5: Alle Bilder + Labels lesen for (unsigned short i = 0; i < count; i++) { if (!readSingleImage(file, &series->images[i], &series->labels[i])) { fprintf(stderr, "Error: Cannot read image %u\n", i); clearSeries(series); fclose(file); return NULL; } } fclose(file); return series; } // ===================================================== // Speicher-Freigabe // ===================================================== void clearSeries(GrayScaleImageSeries *series) { if (!series) return; if (series->images) { for (unsigned int i = 0; i < series->count; i++) { free(series->images[i].buffer); series->images[i].buffer = NULL; } free(series->images); series->images = NULL; } if (series->labels) { free(series->labels); series->labels = NULL; } free(series); }