diff --git a/Assignment9/.idea/runConfigurations/Assignment9.xml b/Assignment9/.idea/runConfigurations/Assignment9.xml
new file mode 100644
index 0000000..2d993cf
--- /dev/null
+++ b/Assignment9/.idea/runConfigurations/Assignment9.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Assignment9/.idea/runConfigurations/Test1.xml b/Assignment9/.idea/runConfigurations/Test1.xml
new file mode 100644
index 0000000..4fc2a99
--- /dev/null
+++ b/Assignment9/.idea/runConfigurations/Test1.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Assignment9/.idea/runConfigurations/Test2.xml b/Assignment9/.idea/runConfigurations/Test2.xml
new file mode 100644
index 0000000..3ccca8d
--- /dev/null
+++ b/Assignment9/.idea/runConfigurations/Test2.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Assignment9/.idea/runConfigurations/Test3.xml b/Assignment9/.idea/runConfigurations/Test3.xml
new file mode 100644
index 0000000..6f0a61c
--- /dev/null
+++ b/Assignment9/.idea/runConfigurations/Test3.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Assignment9/.idea/runConfigurations/Test4.xml b/Assignment9/.idea/runConfigurations/Test4.xml
new file mode 100644
index 0000000..e4a356b
--- /dev/null
+++ b/Assignment9/.idea/runConfigurations/Test4.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Assignment9/CMakeLists.txt b/Assignment9/CMakeLists.txt
index 163ccd2..ffc1a9a 100644
--- a/Assignment9/CMakeLists.txt
+++ b/Assignment9/CMakeLists.txt
@@ -1,4 +1,6 @@
cmake_minimum_required(VERSION 3.20)
project(Assignment9 C)
set(CMAKE_C_STANDARD 99)
-add_executable(Assignment9 src/main.c)
\ No newline at end of file
+add_executable(Assignment9 src/main.c
+ src/png.c
+ src/png.h)
\ No newline at end of file
diff --git a/Assignment9/documentation/EndiannessAndHomework9.c b/Assignment9/documentation/EndiannessAndHomework9.c
new file mode 100644
index 0000000..ae29c0d
--- /dev/null
+++ b/Assignment9/documentation/EndiannessAndHomework9.c
@@ -0,0 +1,68 @@
+#include
+#include
+#include
+// FILE format is: 'header', then 2023 skipped bytes, then the number of interest
+#define OURINT 1426915328
+#define OFFSETTODATA 2023
+
+int writeToFile(){
+
+ FILE* fp = fopen("toReadLater.txt","w+");
+ char c = 'h';
+ fwrite(&c, sizeof(char), 1, fp);
+ c = 'e';
+ fwrite(&c, sizeof(char), 1, fp);
+ c = 'a';
+ fwrite(&c, sizeof(char), 1, fp);
+ c = 'd';
+ fwrite(&c, sizeof(char), 1, fp);
+ c = 'e';
+ fwrite(&c, sizeof(char), 1, fp);
+ c = 'r';
+ fwrite(&c, sizeof(char), 1, fp);
+ unsigned int buf = OFFSETTODATA;
+ fwrite(&buf, sizeof(int), 1, fp);
+ fseek(fp, OFFSETTODATA, SEEK_CUR);
+
+ buf = OURINT;
+ fwrite(&buf, sizeof(int), 1, fp);
+ fclose(fp);
+}
+
+int readFromFile(){
+ FILE *fp = fopen("toReadLater.txt", "r+");
+ fseek(fp, 6 , SEEK_SET);
+ int skip = 0;
+ fread(&skip, sizeof(int), 1, fp);
+ // NOTE, in HW, the size of the section is a value in
+ // Big-Endian format, it will actually need conversion
+ fseek(fp, skip, SEEK_CUR);
+ unsigned int qBe = 0;
+ unsigned int qLe = 0;
+ int i;
+ unsigned char *c = (char *)(&qBe);
+ unsigned char *d = (char *)(&qLe);
+ for (i = 0; i < 4; i++)
+ {
+ c[i] = getc(fp);
+ printf("Byte %i: %i %x\n",i, c[i], c[i]);
+ }
+
+ for (i = 0; i < 4; i++)
+ {
+ d[4-i-1] = c[i];
+ }
+
+ printf("Translated using swapping the bytes order: %i\n", qLe);
+ qLe = ntohl(qBe);
+ printf("Translated using ntohl: %i\n", qLe);
+ fclose(fp);
+}
+int main (int argc, char** argv){
+ unsigned int wantToRead;
+ writeToFile();
+ printf("Sizeof (int) is:%li\n", sizeof(unsigned int));
+ readFromFile();
+
+ return 0;
+}
\ No newline at end of file
diff --git a/Assignment9/src/main.c b/Assignment9/src/main.c
index d65e213..bd1ed8a 100644
--- a/Assignment9/src/main.c
+++ b/Assignment9/src/main.c
@@ -1,3 +1,39 @@
+#include
+#include
+#include
+#include
+#include
+#include "png.h"
+
int main(int argc, char *argv[]) {
- return 0;
+ if (argc != 2) {
+ printf("Usage: %s \n", argv[0]);
+ exit(1);
+ }
+ if (strlen(argv[1]) > PATH_MAX) {
+ printf("Path too long\n");
+ exit(1);
+ }
+ char *path = argv[1];
+
+ char* png_buffer = load_file(get_fd(path));
+ if (!is_png(png_buffer)) {
+ printf("It's not a PNG file\n");
+ exit(1);
+ } else {
+ printf("It's a PNG file\n");
+ }
+ png_chunk **chunks = get_png_chunks(png_buffer);
+ int size = get_number_of_chunks(chunks);
+ for (int i = 0; i < size; i++) {
+ // Check if header is IDAT or IEND
+ bool is_idat = memcmp(chunks[i]->type, "IDAT", 4) == 0;
+ bool is_iend = memcmp(chunks[i]->type, "IEND", 4) == 0;
+ if (is_idat || is_iend) {
+ printf("Found %s chunk\n", chunks[i]->type);
+ } else {
+ printf("Found unknown: %s\n", chunks[i]->type);
+ }
+ printf("Chunk size is:%d\n", chunks[i]->length);
+ }
}
\ No newline at end of file
diff --git a/Assignment9/src/png.c b/Assignment9/src/png.c
new file mode 100644
index 0000000..ebb4eaa
--- /dev/null
+++ b/Assignment9/src/png.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright Notice
+ * ----------------
+ * Copyright © 1998, 1999 by: Glenn Randers-Pehrson
+ * This specification is a modification of the PNG 1.0 specification. It is being
+ * provided by the copyright holder under the provisions of the 1996 MIT copyright and license:
+ * Copyright © 1996 by: Massachusetts Institute of Technology (MIT)
+ * This W3C specification is being provided by the copyright holders under
+ * the following license. By obtaining, using and/or copying this specification, you
+ * agree that you have read, understood, and will comply with the following terms
+ * and conditions:
+ * Permission to use, copy, and distribute this specification for any purpose
+ * and without fee or royalty is hereby granted, provided that the full text of
+ * this NOTICE appears on ALL copies of the specification or portions thereof,
+ * including modifications, that you make.
+ * THIS SPECIFICATION IS PROVIDED ”AS IS,” AND COPYRIGHT HOLD-ERS
+ * MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
+ * IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, COPYRIGHT
+ * HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES OF MER-CHANTABILITY
+ * OR FITNESS FOR ANY PARTICULAR PURPOSE OR
+ * THAT THE USE OF THE SPECIFICATION WILL NOT INFRINGE ANY
+ * THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER
+ * RIGHTS. COPYRIGHT HOLDERS WILL BEAR NO LIABILITY FOR ANY
+ * USE OF THIS SPECIFICATION.
+ * The name and trademarks of copyright holders may NOT be used in
+ * ad-vertising or publicity pertaining to the specification without specific, written
+ * prior permission. Title to copyright in this specification and any associated
+ * documentation will at all times remain with copyright holders.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include "png.h"
+
+int get_fd(char *path) {
+ FILE *fp = fopen(path, "rb");
+ if (fp == NULL) {
+ perror("fopen");
+ exit(1);
+ }
+ int fd = fileno(fp);
+ if (fd == -1) {
+ perror("fileno");
+ exit(1);
+ }
+ return fd;
+}
+
+FILE *get_fp(int fd) {
+ FILE *fp = fdopen(fd, "rb");
+ if (fp == NULL) {
+ perror("fdopen");
+ exit(1);
+ }
+ return fp;
+}
+
+char *load_file(int fd) {
+ FILE *fp = get_fp(fd);
+ fseek(fp, 0, SEEK_END);
+ long size = ftell(fp);
+ rewind(fp);
+ char *buffer = malloc(size);
+ if (buffer == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+ fread(buffer, 1, size, fp);
+ // Iterate over buffer and convert from network byte order to host byte order
+ //for (int i = 0; i < size; i += 4) {
+ // uint32_t *ptr = (uint32_t *)(buffer + i);
+ // *ptr = ntohl(*ptr);
+ //}
+ fclose(fp);
+ return buffer;
+}
+
+int is_png(char *buffer) {
+ return memcmp(buffer, PNG_SIGNATURE, PNG_SIGNATURE_SIZE) == 0;
+}
+
+png_chunk *get_png_chunk(char *buffer, int offset) {
+ png_chunk *chunk = malloc(sizeof(png_chunk));
+ if (chunk == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+ memcpy(&chunk->length, buffer + offset + 0, 4);
+ chunk->length = ntohl(chunk->length);
+ memcpy(&chunk->type, buffer + offset + 4, 4);
+ chunk->data = malloc(chunk->length);
+ if (chunk->data == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+ memcpy(chunk->data, buffer + offset + 8, chunk->length);
+ memcpy(&chunk->crc, buffer + offset + 8 + chunk->length, 4);
+ return chunk;
+}
+
+png_chunk **get_png_chunks(char *buffer) {
+ png_chunk **chunks = malloc(sizeof(png_chunk *));
+ if (chunks == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+ int offset = PNG_SIGNATURE_SIZE;
+ int i = 0;
+ while (1) {
+ chunks[i] = get_png_chunk(buffer, offset);
+ offset += chunks[i]->length;
+ if (memcmp(chunks[i]->type, "IEND", 4) == 0) {
+ break;
+ }
+ i++;
+ chunks = realloc(chunks, sizeof(png_chunk *) * (i + 1));
+ if (chunks == NULL) {
+ perror("realloc");
+ exit(1);
+ }
+ }
+ return chunks;
+}
+
+int is_chunk_valid(png_chunk *chunk) {
+ uint32_t crc = htonl(chunk->crc);
+ //uint32_t calculated_crc = crc32(0, chunk->type, 4);
+ //calculated_crc = crc32(calculated_crc, chunk->data, chunk->length);
+ //return crc == calculated_crc;
+ return 1;
+}
+
+int is_chunk_critical(png_chunk *chunk) {
+ return chunk->type[0] >= 'A' && chunk->type[0] <= 'Z';
+}
+
+int get_number_of_chunks(png_chunk **chunks) {
+ int i = 0;
+ while (chunks[i] != NULL) {
+ i++;
+ }
+ return i;
+}
diff --git a/Assignment9/src/png.h b/Assignment9/src/png.h
new file mode 100644
index 0000000..4a68df5
--- /dev/null
+++ b/Assignment9/src/png.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright Notice
+ * ----------------
+ * Copyright © 1998, 1999 by: Glenn Randers-Pehrson
+ * This specification is a modification of the PNG 1.0 specification. It is being
+ * provided by the copyright holder under the provisions of the 1996 MIT copyright and license:
+ * Copyright © 1996 by: Massachusetts Institute of Technology (MIT)
+ * This W3C specification is being provided by the copyright holders under
+ * the following license. By obtaining, using and/or copying this specification, you
+ * agree that you have read, understood, and will comply with the following terms
+ * and conditions:
+ * Permission to use, copy, and distribute this specification for any purpose
+ * and without fee or royalty is hereby granted, provided that the full text of
+ * this NOTICE appears on ALL copies of the specification or portions thereof,
+ * including modifications, that you make.
+ * THIS SPECIFICATION IS PROVIDED ”AS IS,” AND COPYRIGHT HOLD-ERS
+ * MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
+ * IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, COPYRIGHT
+ * HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES OF MER-CHANTABILITY
+ * OR FITNESS FOR ANY PARTICULAR PURPOSE OR
+ * THAT THE USE OF THE SPECIFICATION WILL NOT INFRINGE ANY
+ * THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER
+ * RIGHTS. COPYRIGHT HOLDERS WILL BEAR NO LIABILITY FOR ANY
+ * USE OF THIS SPECIFICATION.
+ * The name and trademarks of copyright holders may NOT be used in
+ * ad-vertising or publicity pertaining to the specification without specific, written
+ * prior permission. Title to copyright in this specification and any associated
+ * documentation will at all times remain with copyright holders.
+ */
+
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+
+// http://www.libpng.org/pub/png/spec/1.2/PNG-Rationale.html#R.PNG-file-signature
+#define PNG_SIGNATURE "\211PNG\r\n\032\n"
+#define PNG_SIGNATURE_SIZE 8
+typedef struct png_chunk {
+ uint32_t length;
+ char type[4];
+ char *data;
+ uint32_t crc;
+} png_chunk;
+
+// Get file descriptor from path
+int get_fd(char *path);
+
+// Get FILE* from file descriptor
+FILE *get_fp(int fd);
+
+// Store file in heap memory
+char *load_file(int fd);
+
+// Check if file is a PNG
+int is_png(char *buffer);
+
+// Get PNG chunk
+png_chunk *get_png_chunk(char *buffer, int offset);
+
+// Get all PNG chunks
+png_chunk **get_png_chunks(char *buffer);
+
+// Get number of chunks
+int get_number_of_chunks(png_chunk **chunks);
+
+// Check if chunk is critical
+int is_chunk_critical(png_chunk *chunk);
+
+// Is chunk valid?
+int is_chunk_valid(png_chunk *chunk);
\ No newline at end of file