diff --git a/imageInput.c b/imageInput.c index bb30de1..c72388e 100644 --- a/imageInput.c +++ b/imageInput.c @@ -8,15 +8,127 @@ // TODO Implementieren Sie geeignete Hilfsfunktionen für das Lesen der Bildserie aus einer Datei +static int read_header(FILE *file, unsigned short *count, unsigned short *width, unsigned short *height) +{ + size_t headerLEN = strlen(FILE_HEADER_STRING); + char buffer[BUFFER_SIZE]; + + if (headerLEN >= BUFFER_SIZE) + { + return 0; + } + + if (fread(buffer, 1, headerLEN, file) != headerLEN) + { + return 0; + } + + buffer[headerLEN] = '\0'; + + if (strcmp(buffer, FILE_HEADER_STRING) != 0) + { + return 0; + } + + if (fread(count, sizeof(unsigned short), 1, file) != 1 || fread(width, sizeof(unsigned short), 1, file) != 1 || + fread(height, sizeof(unsigned short), 1, file) != 1) + { + return 0; + } + + return 1; +} + +static int read_single_image(FILE *file, GrayScaleImage *image) +{ + unsigned int number_of_pixel = image->width * image->height; + + if (fread(image->buffer, sizeof(GrayScalePixelType), number_of_pixel, file) != number_of_pixel) // fehler beim lesen + { + return 0; + } + return 1; +} + // TODO Vervollständigen Sie die Funktion readImages unter Benutzung Ihrer Hilfsfunktionen GrayScaleImageSeries *readImages(const char *path) { - GrayScaleImageSeries *series = NULL; - + FILE *file = fopen(path, "rb"); + if (!file) + { + return 0; + } + + unsigned short count, width, height; + + if (!read_header(file, &count, &width, &height)) + { + fclose(file); + return 0; + } + + GrayScaleImageSeries *series = malloc(sizeof(GrayScaleImageSeries)); + + if (!series) + { + fclose(file); + return 0; + } + + series->count = count; + series->images = malloc(count * sizeof(GrayScaleImage)); + series->labels = malloc(count * sizeof(unsigned char)); + + if (!series->images || !series->labels) + { + clearSeries(series); + fclose(file); + return 0; + } + + for (int i = 0; i < count; i++) + { + series->images[i].width = width; + series->images[i].height = height; + series->images[i].buffer = malloc(width * height * sizeof(GrayScalePixelType)); + + if (!series->images[i].buffer) + { + clearSeries(series); + fclose(file); + return 0; + } + + if (!read_single_image(file, &series->images[i])) + { + clearSeries(series); + fclose(file); + return 0; + } + + if (fread(&series->labels[i], 1, 1, file) != 1) + { + clearSeries(series); + fclose(file); + return 0; + } + } + + fclose(file); return series; } // TODO Vervollständigen Sie die Funktion clearSeries, welche eine Bildserie vollständig aus dem Speicher freigibt void clearSeries(GrayScaleImageSeries *series) { + if (series) + { + for (int i = 0; i < series->count; i++) + { + free(series->images[i].buffer); + } + free(series->images); + free(series->labels); + free(series); + } } \ No newline at end of file diff --git a/matrix.c b/matrix.c index 243669b..4349cf4 100644 --- a/matrix.c +++ b/matrix.c @@ -3,37 +3,39 @@ #include "matrix.h" #include -// TODO Matrix-Funktionen implementieren ... ok +// TODO Matrix-Funktionen implementieren Matrix createMatrix(unsigned int rows, unsigned int cols) { - Matrix matrix; + Matrix matrix; - if (rows == 0 || cols == 0) + if (rows == 0 || cols == 0) { matrix.rows = 0; - matrix.cols =0; - matrix.data = NULL; + matrix.cols = 0; + matrix.buffer = NULL; return matrix; } + matrix.rows = rows; matrix.cols = cols; - matrix.data = (MatrixTyype *)malloc(rows * cols * sizeof(MatrixType)); + matrix.buffer = (MatrixType *)malloc(rows * cols * sizeof(MatrixType)); - if (matrix.data == NULL) + if (matrix.buffer == NULL) { + matrix.rows = 0; matrix.cols = 0; return matrix; } - for (int i = 0; ibuffer != NULL){ - free (matrix->buffer); + if (matrix->buffer != NULL) + { + free(matrix->buffer); matrix->buffer = NULL; } + matrix->rows = 0; - matrix->cols = 0; + matrix->cols = 0; } void setMatrixAt(MatrixType value, Matrix matrix, unsigned int rowIdx, unsigned int colIdx) @@ -71,13 +75,104 @@ MatrixType getMatrixAt(const Matrix matrix, unsigned int rowIdx, unsigned int co return matrix.buffer[rowIdx * matrix.cols + colIdx]; } - Matrix add(const Matrix matrix1, const Matrix matrix2) { + if (matrix1.rows == matrix2.rows && matrix1.cols == matrix2.cols) // gleiche Dimension + { + Matrix result = createMatrix(matrix1.rows, matrix1.cols); + + if (result.buffer == NULL) + { + fprintf(stderr, "Fehler: Speicher konnte nicht reserviert werden!\n"); + return result; + } + + for (int i = 0; i < matrix1.rows; i++) + { + for (int j = 0; j < matrix1.cols; j++) + { + result.buffer[i * result.cols + j] = matrix1.buffer[i * matrix1.cols + j] + matrix2.buffer[i * matrix2.cols + j]; + } + } + return result; + } + if (matrix1.rows == matrix2.rows && matrix2.cols == 1) // Matrix 2 hat eine Spalte + { + Matrix result = createMatrix(matrix1.rows, matrix1.cols); + + if(result.buffer == NULL) + { + fprintf(stderr, "Fehler: Speicher konnte nicht reserviert werden!\n"); + return result; + } + for (int i = 0; i < matrix1.rows; i++) + { + for (int j = 0; j < matrix1.cols; j++) + { + result.buffer[i * result.cols + j] = matrix1.buffer[i * matrix1.cols + j] + matrix2.buffer[i]; + } + } + return result; + } + + if (matrix1.rows == matrix2.rows && matrix1.cols == 1) // Matrix 1 hat eine Spalte + { + Matrix result = createMatrix(matrix2.rows, matrix2.cols); + + if(result.buffer == NULL) + { + fprintf(stderr, "Fehler: Speicher konnte nicht reserviert werden!\n"); + return result; + } + for (int i = 0; i < matrix2.rows; i++) + { + for (int j = 0; j < matrix2.cols; j++) + { + result.buffer[i * result.cols + j] = matrix1.buffer[i] + matrix2.buffer[i * matrix2.cols + j]; + } + } + return result; + } + // passt nicht + fprintf(stderr, "Fehler: Matrizen haben unterschiedliche Größen (%u x %u) und (%u x %u)\n", + matrix1.rows, matrix1.cols, matrix2.rows, matrix2.cols); + + Matrix empty = {0, 0, NULL}; + return empty; } Matrix multiply(const Matrix matrix1, const Matrix matrix2) { - + if (matrix1.cols != matrix2.rows) + { + fprintf(stderr, "Fehler: Matrizen der Dimension (%u x %u) und (%u x %u) koennen nicht multipliziert werden\n", + matrix1.rows, matrix1.cols, matrix2.rows, matrix2.cols); + + Matrix empty = {0, 0, NULL}; + return empty; + } + + Matrix result = createMatrix(matrix1.rows, matrix2.cols); + + if (result.buffer == NULL) + { + fprintf(stderr, "Fehler: Speicher konnte nicht reserviert werden!\n"); + return result; + } + + for (int i = 0; i < matrix1.rows; i++) + { + for (int j = 0; j < matrix2.cols; j++) + { + MatrixType sum = 0.0; + + for (int k = 0; k < matrix1.cols; k++) + { + sum += matrix1.buffer[i * matrix1.cols + k] * matrix2.buffer[k * matrix2.cols + j]; + } + result.buffer[i * result.cols + j] = sum; + } + } + return result; } \ No newline at end of file diff --git a/matrix.h b/matrix.h index 55e728a..fb9adb1 100644 --- a/matrix.h +++ b/matrix.h @@ -9,12 +9,13 @@ typedef float MatrixType; typedef struct Matrix { - unsigend int rows; + unsigned int rows; unsigned int cols; - Matrixtype *data; + MatrixType *data; #define buffer data } Matrix; + Matrix createMatrix(unsigned int rows, unsigned int cols); void clearMatrix(Matrix *matrix); void setMatrixAt(MatrixType value, Matrix matrix, unsigned int rowIdx, unsigned int colIdx); diff --git a/matrixTests.c b/matrixTests.c index 686db1e..aef00af 100644 --- a/matrixTests.c +++ b/matrixTests.c @@ -1,4 +1,3 @@ - #include #include #include "matrix.h" @@ -71,6 +70,32 @@ void test_addFailsOnDifferentInputDimensions(void) TEST_ASSERT_EQUAL_UINT32(0, result.cols); } +void test_addSupportsBroadcasting(void) +{ + MatrixType buffer1[] = {1, 2, 3, 4, 5, 6}; + MatrixType buffer2[] = {7, 8}; + Matrix matrix1 = {.rows=2, .cols=3, .buffer=buffer1}; + Matrix matrix2 = {.rows=2, .cols=1, .buffer=buffer2}; + + Matrix result1 = add(matrix1, matrix2); + Matrix result2 = add(matrix2, matrix1); + + float expectedResults[] = {8, 9, 10, 12, 13, 14}; + + TEST_ASSERT_EQUAL_UINT32(matrix1.rows, result1.rows); + TEST_ASSERT_EQUAL_UINT32(matrix1.cols, result1.cols); + TEST_ASSERT_EQUAL_UINT32(matrix1.rows, result2.rows); + TEST_ASSERT_EQUAL_UINT32(matrix1.cols, result2.cols); + + TEST_ASSERT_EQUAL_INT(sizeof(expectedResults)/sizeof(expectedResults[0]), result1.rows * result1.cols); + TEST_ASSERT_EQUAL_FLOAT_ARRAY(expectedResults, result1.buffer, result1.cols * result1.rows); + TEST_ASSERT_EQUAL_INT(sizeof(expectedResults)/sizeof(expectedResults[0]), result2.rows * result2.cols); + TEST_ASSERT_EQUAL_FLOAT_ARRAY(expectedResults, result2.buffer, result2.cols * result2.rows); + + free(result1.buffer); + free(result2.buffer); +} + void test_multiplyReturnsCorrectResults(void) { MatrixType buffer1[] = {1, 2, 3, 4, 5, 6}; @@ -159,6 +184,7 @@ int main() RUN_TEST(test_clearMatrixSetsMembersToNull); RUN_TEST(test_addReturnsCorrectResult); RUN_TEST(test_addFailsOnDifferentInputDimensions); + RUN_TEST(test_addSupportsBroadcasting); RUN_TEST(test_multiplyReturnsCorrectResults); RUN_TEST(test_multiplyFailsOnWrongInputDimensions); RUN_TEST(test_getMatrixAtReturnsCorrectResult);