NeuronalesNetz_Team5/imageInput.c
Yannik Baumgärtner cb2c33ff12 Endlich fertig
2025-11-27 14:30:22 +01:00

217 lines
5.4 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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 in der Datei: 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.
}