generated from freudenreichan/info2Praktikum-NeuronalesNetz
- matrix.c: multiply summiert in MatrixType statt int (Nachkommastellen gingen verloren), clearMatrix gibt Speicher frei, Indexpruefung pro Zeile/Spalte, NULL-Pruefungen in add/multiply - imageInput.c: fseek-Spruenge entfernt, Dateikopf pruefen, Lesefehler behandeln, clearSeries implementiert - neuralNetworkTests.c: prepareNeuralNetworkFile implementiert - neuralNetwork.c: clearModel gibt das Layer-Array frei (Speicherleck) - Zusaetzliche Unittests fuer Matrix und Bildeinlesen - Testartefakte und Testprogramme in .gitignore, testFile.info2 entfernt Alle 33 Tests gruen, keine Warnungen, 87.37 % Genauigkeit (wie Referenz). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
149 lines
4.2 KiB
C
149 lines
4.2 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "imageInput.h"
|
|
|
|
#define BUFFER_SIZE 100
|
|
#define FILE_HEADER_STRING "__info2_image_file_format__"
|
|
|
|
// Liest den Identifikationstag am Dateianfang und vergleicht ihn mit FILE_HEADER_STRING
|
|
static int checkFileHeader(FILE *file)
|
|
{
|
|
int isValid = 0;
|
|
size_t fileHeaderLen = strlen(FILE_HEADER_STRING);
|
|
char buffer[BUFFER_SIZE] = {0};
|
|
|
|
if(fileHeaderLen > BUFFER_SIZE-1)
|
|
fileHeaderLen = BUFFER_SIZE-1;
|
|
|
|
if(fread(buffer, sizeof(char), fileHeaderLen, file) == fileHeaderLen)
|
|
isValid = strcmp(buffer, FILE_HEADER_STRING) == 0;
|
|
|
|
return isValid;
|
|
}
|
|
|
|
// Liest den naechsten unsigned short (Anzahl, Breite bzw. Hoehe); 0 im Fehlerfall.
|
|
// Kein fseek noetig: fread setzt den Dateizeiger automatisch hinter die gelesenen Bytes.
|
|
static unsigned short readUnsignedShort(FILE *file)
|
|
{
|
|
unsigned short value = 0;
|
|
|
|
if(fread(&value, sizeof(unsigned short), 1, file) != 1)
|
|
value = 0;
|
|
|
|
return value;
|
|
}
|
|
|
|
static unsigned short readNumberOfImages(FILE *file)
|
|
{
|
|
return readUnsignedShort(file);
|
|
}
|
|
|
|
static unsigned short readImageWidth(FILE *file)
|
|
{
|
|
return readUnsignedShort(file);
|
|
}
|
|
|
|
static unsigned short readImageHeight(FILE *file)
|
|
{
|
|
return readUnsignedShort(file);
|
|
}
|
|
|
|
// Liest die Pixel eines Bildes in einen neuen Puffer; NULL bei Speicher- oder Lesefehler
|
|
static GrayScalePixelType *readImage(FILE *file, unsigned short imageWidth, unsigned short imageHeight)
|
|
{
|
|
size_t numberOfPixels = (size_t)imageWidth * imageHeight;
|
|
GrayScalePixelType *image = (GrayScalePixelType *)malloc(numberOfPixels * sizeof(GrayScalePixelType));
|
|
|
|
if(image != NULL && fread(image, sizeof(GrayScalePixelType), numberOfPixels, file) != numberOfPixels)
|
|
{
|
|
free(image);
|
|
image = NULL;
|
|
}
|
|
|
|
return image;
|
|
}
|
|
|
|
// Liest das Label, das direkt auf die Pixel eines Bildes folgt; 0 bei Erfolg, sonst -1
|
|
static int readLabel(FILE *file, unsigned char *label)
|
|
{
|
|
return fread(label, sizeof(unsigned char), 1, file) == 1 ? 0 : -1;
|
|
}
|
|
|
|
// Legt eine leere Serie fuer numberOfImages Bilder an (Bildpuffer werden spaeter von readImage geliefert)
|
|
static GrayScaleImageSeries *createSeries(unsigned short numberOfImages)
|
|
{
|
|
GrayScaleImageSeries *series = (GrayScaleImageSeries *)calloc(1, sizeof(GrayScaleImageSeries));
|
|
|
|
if(series != NULL)
|
|
{
|
|
// calloc: alle Bildpuffer starten als NULL, damit clearSeries jederzeit gefahrlos aufraeumen kann
|
|
series->images = (GrayScaleImage *)calloc(numberOfImages, sizeof(GrayScaleImage));
|
|
series->labels = (unsigned char *)calloc(numberOfImages, sizeof(unsigned char));
|
|
|
|
if(series->images == NULL || series->labels == NULL)
|
|
{
|
|
clearSeries(series);
|
|
series = NULL;
|
|
}
|
|
else
|
|
series->count = numberOfImages;
|
|
}
|
|
|
|
return series;
|
|
}
|
|
|
|
GrayScaleImageSeries *readImages(const char *path)
|
|
{
|
|
GrayScaleImageSeries *series = NULL;
|
|
FILE *file = fopen(path, "rb");
|
|
|
|
if(file != NULL)
|
|
{
|
|
if(checkFileHeader(file))
|
|
{
|
|
unsigned short numberOfImages = readNumberOfImages(file);
|
|
unsigned short imageWidth = readImageWidth(file);
|
|
unsigned short imageHeight = readImageHeight(file);
|
|
|
|
if(numberOfImages > 0 && imageWidth > 0 && imageHeight > 0)
|
|
series = createSeries(numberOfImages);
|
|
|
|
for(unsigned int i = 0; series != NULL && i < series->count; i++)
|
|
{
|
|
series->images[i].width = imageWidth;
|
|
series->images[i].height = imageHeight;
|
|
series->images[i].buffer = readImage(file, imageWidth, imageHeight);
|
|
|
|
if(series->images[i].buffer == NULL || readLabel(file, &series->labels[i]) != 0)
|
|
{
|
|
clearSeries(series);
|
|
series = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
fclose(file);
|
|
}
|
|
|
|
return series;
|
|
}
|
|
|
|
void clearSeries(GrayScaleImageSeries *series)
|
|
{
|
|
if(series != NULL)
|
|
{
|
|
if(series->images != NULL)
|
|
{
|
|
for(unsigned int i = 0; i < series->count; i++)
|
|
{
|
|
free(series->images[i].buffer);
|
|
}
|
|
}
|
|
|
|
free(series->images);
|
|
free(series->labels);
|
|
free(series);
|
|
}
|
|
}
|