#include #include #include #include "imageInput.h" // Größe eines temporären Puffers #define BUFFER_SIZE 100 // Fester Header-String, der am Anfang jeder gültigen Bilddatei stehen muss #define FILE_HEADER_STRING "__info2_image_file_format__" /* * Prüft den Dateiheader und liest Bildanzahl, Breite und Höhe aus. * Gibt 1 (true) zurück, wenn alles gültig ist, sonst 0 (false). */ static int checkheader(FILE *path, unsigned short *count, unsigned short *width, unsigned short *height) { unsigned int headerlen = strlen(FILE_HEADER_STRING); unsigned char header[64]; // Prüfen, ob der Header-String in den Puffer passt if (headerlen >= sizeof(header)) { return 0; } // Header aus Datei lesen – muss exakt gleich lang sein if (fread(header, 1, headerlen, path) != headerlen) { return 0; } // Header vergleichen – Datei muss mit FILE_HEADER_STRING beginnen if (strncmp((char *)header, FILE_HEADER_STRING, headerlen) != 0) { return 0; } // Danach folgen im File: count, width, height (je 2 Bytes) if (fread(count, sizeof(unsigned short), 1, path) != 1) return 0; if (fread(width, sizeof(unsigned short), 1, path) != 1) return 0; if (fread(height, sizeof(unsigned short), 1, path) != 1) return 0; return 1; } /* * Reserviert Speicher für eine Serie von Graustufenbildern. * Legt: * - Hauptstruktur * - Array von Bildern * - Array von Labels * - Für jedes Bild einen Pixelpuffer * an. */ static GrayScaleImageSeries *allocateSeries(unsigned short count, unsigned short width, unsigned short height) { // Platz für die Gesamtstruktur anfordern GrayScaleImageSeries *series = malloc(sizeof(GrayScaleImageSeries)); if (series == NULL) { return NULL; } series->count = count; // Arrays für Bilder und Labels anlegen series->images = calloc(count, sizeof(GrayScaleImage)); series->labels = calloc(count, sizeof(unsigned char)); if (series->images == NULL || series->labels == NULL) { return NULL; } // Jedem Bild Höhe, Breite und einen eigenen Pixelpuffer zuweisen for (unsigned int i = 0; i < count; i++) { series->images[i].height = height; series->images[i].width = width; // Für jedes Bild einen Puffer anlegen: width * height Pixel series->images[i].buffer = calloc(height * width, sizeof(GrayScalePixelType)); if (series->images[i].buffer == NULL) { // Falls ein Puffer fehlschlägt → alles bisherige wieder freigeben clearSeries(series); return NULL; } } return series; } /* * Liest die Pixeldaten und Labels aller Bilder aus der Datei. * Reihenfolge in der Datei je Bild: * 1. Pixelwerte (width*height Stück) * 2. 1 Byte Label */ static int loadImageData(FILE *file, GrayScaleImageSeries *series, unsigned short count, unsigned short width, unsigned short height) { for (unsigned int i = 0; i < count; i++) { size_t pixelCount = width * height; // Pixeldaten in den Bildpuffer schreiben if (fread(series->images[i].buffer, sizeof(GrayScalePixelType), pixelCount, file) != pixelCount) { return 0; } // Label lesen (1 Byte) if (fread(&series->labels[i], sizeof(unsigned char), 1, file) != 1) { return 0; } } return 1; } // Schliesst eine Datei, sofern sie geöffnet ist static void closefile(FILE *file) { if (file != NULL) { fclose(file); } } /* * Hauptfunktion zum Einlesen der Bilddaten: * 1. Datei öffnen * 2. Header + Metadaten lesen * 3. Speicher anlegen * 4. Pixeldaten + Labels laden * 5. Datei schließen * 6. Zeiger auf fertige Daten zurückgeben */ GrayScaleImageSeries *readImages(const char *path) { unsigned short count, width, height; GrayScaleImageSeries *series = NULL; // Datei im binären Modus öffnen FILE *file = fopen(path, "rb"); if (file == NULL) { return NULL; } // Header überprüfen und Metadaten lesen if (!checkheader(file, &count, &width, &height)) { closefile(file); return NULL; } // Speicher für Serie anlegen series = allocateSeries(count, width, height); if (series == NULL) { closefile(file); return NULL; } // Bilddaten laden if (!loadImageData(file, series, count, width, height)) { clearSeries(series); closefile(file); return NULL; } // Datei schließen und fertige Struktur zurückgeben closefile(file); return series; } /* * Gibt den gesamten reservierten Speicher der Bildserie wieder frei. * Dazu: * - alle Pixelpuffer * - Bilderarray * - Labelsarray * - Hauptstruktur */ void clearSeries(GrayScaleImageSeries *series) { if (series != NULL) { // Erst alle Bildpuffer freigeben for (unsigned int i = 0; i < series->count; i++) { free(series->images[i].buffer); } // Danach Arrays freigeben free(series->images); free(series->labels); // Am Ende die Struktur selbst free(series); } // count, width, height müssen nicht auf 0 gesetzt werden, // da sie bei einer Neu-Allokation sowieso überschrieben werden. }