generated from freudenreichan/info2Praktikum-NeuronalesNetz
151 lines
4.6 KiB
C
151 lines
4.6 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__"
|
|
|
|
|
|
/*
|
|
* Aufbau der mnist_test.info2
|
|
*
|
|
* Offset Inhalt Typ
|
|
* ------ ---------------------------- ----------------------------------
|
|
* 0 "__info2_image_file_format__" 26 ASCII-Zeichen
|
|
* 26 Anzahl der Bilder unsigned short (2 Bytes) 10 27 -> 27 10 -> 10000
|
|
* 28 Breite eines Bildes unsigned short (2 Bytes) 1C 00 -> 00 1C -> 28
|
|
* 30 Höhe eines Bildes unsigned short (2 Bytes) 1C 00 -> 00 1C -> 28
|
|
* 32 Bild 0: width*height Pixel unsigned char je Pixel (Graustufe 0-255)
|
|
* direkt danach: Label 0 unsigned char (Klasse 0-9)
|
|
*
|
|
* usw...
|
|
*/
|
|
|
|
|
|
//prüft, ob die Datei mit dem erwarteten Dateitag beginnt
|
|
static int checkFileTag(FILE *file)
|
|
{
|
|
int isValid = 0;
|
|
size_t tagLength = strlen(FILE_HEADER_STRING);
|
|
char buffer[BUFFER_SIZE] = {0};
|
|
|
|
if(tagLength < BUFFER_SIZE && fread(buffer, sizeof(char), tagLength, file) == tagLength)
|
|
{
|
|
isValid = strncmp(buffer, FILE_HEADER_STRING, tagLength) == 0;
|
|
}
|
|
|
|
return isValid;
|
|
}
|
|
|
|
//liest Anzahl, Breite und Höhe der Bildserie; Erfolg nur, wenn alle Werte gelesen werden konnten und positiv sind
|
|
static int readSeriesHeader(FILE *file, unsigned short *count, unsigned short *width, unsigned short *height)
|
|
{
|
|
return fread(count, sizeof(unsigned short), 1, file) == 1
|
|
&& fread(width, sizeof(unsigned short), 1, file) == 1
|
|
&& fread(height, sizeof(unsigned short), 1, file) == 1
|
|
&& *count > 0 && *width > 0 && *height > 0;
|
|
}
|
|
|
|
//liest die Pixelwerte eines einzelnen Bildes; buffer ist NULL im Fehlerfall
|
|
static GrayScaleImage readImage(FILE *file, unsigned int width, unsigned int height)
|
|
{
|
|
GrayScaleImage image = {NULL, 0, 0};
|
|
|
|
GrayScalePixelType *buffer = (GrayScalePixelType *)calloc(width * height, sizeof(GrayScalePixelType));
|
|
|
|
if(buffer != NULL && fread(buffer, sizeof(GrayScalePixelType), width * height, file) == width * height)
|
|
{
|
|
image.buffer = buffer;
|
|
image.width = width;
|
|
image.height = height;
|
|
}
|
|
else
|
|
{
|
|
free(buffer);
|
|
}
|
|
|
|
return image;
|
|
}
|
|
|
|
//liest die Klasse (Label) des zuletzt gelesenen Bildes
|
|
static int readLabel(FILE *file, unsigned char *label)
|
|
{
|
|
return fread(label, sizeof(unsigned char), 1, file) == 1;
|
|
}
|
|
|
|
static int isValidSeries(const GrayScaleImageSeries *series)
|
|
{
|
|
return series->images != NULL && series->labels != NULL && series->count > 0;
|
|
}
|
|
|
|
GrayScaleImageSeries *readImages(const char *path)
|
|
{
|
|
GrayScaleImageSeries *series = NULL;
|
|
FILE *file = fopen(path, "rb"); //Binärdatei, daher "rb"
|
|
|
|
if(file != NULL)
|
|
{
|
|
unsigned short count = 0;
|
|
unsigned short width = 0;
|
|
unsigned short height = 0;
|
|
|
|
if(checkFileTag(file) && readSeriesHeader(file, &count, &width, &height))
|
|
{
|
|
series = (GrayScaleImageSeries *)malloc(sizeof(GrayScaleImageSeries)); //struct containing *images, *lables and count
|
|
|
|
if(series != NULL)
|
|
{
|
|
series->images = (GrayScaleImage *)calloc(count, sizeof(GrayScaleImage)); //10000 * 784bytes in our example
|
|
series->labels = (unsigned char *)calloc(count, sizeof(unsigned char)); //10000bytes 1 for every picture in our example
|
|
series->count = count;
|
|
|
|
if(isValidSeries(series))
|
|
{
|
|
int allRead = 1;
|
|
|
|
for(unsigned int i = 0; i < count && allRead; i++)
|
|
{
|
|
series->images[i] = readImage(file, width, height);
|
|
allRead = series->images[i].buffer != NULL && readLabel(file, &series->labels[i]);
|
|
}
|
|
|
|
if(!allRead)
|
|
{
|
|
clearSeries(series);
|
|
series = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
clearSeries(series);
|
|
series = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
fclose(file);
|
|
}
|
|
|
|
return series;
|
|
}
|
|
|
|
void clearSeries(GrayScaleImageSeries *series)
|
|
{
|
|
if(series != NULL)
|
|
{
|
|
if(series->images != NULL)
|
|
{
|
|
//erst die Pixelbuffer der einzelnen Bilder, dann das Array selbst
|
|
for(unsigned int i = 0; i < series->count; i++)
|
|
{
|
|
free(series->images[i].buffer);
|
|
}
|
|
free(series->images);
|
|
}
|
|
|
|
free(series->labels);
|
|
free(series);
|
|
}
|
|
}
|