From 421c593a6106ba7942870874c9558dcb61622814 Mon Sep 17 00:00:00 2001 From: Lauchmelder Date: Fri, 28 Oct 2022 18:53:52 +0200 Subject: [PATCH] initial commit --- .gitignore | 6 +++ CMakeLists.txt | 9 ++++ img/lenna.jpg | Bin 0 -> 37073 bytes src/CMakeLists.txt | 6 +++ src/loader.c | 110 +++++++++++++++++++++++++++++++++++++++++++++ src/loader.h | 6 +++ src/main.c | 27 +++++++++++ src/util.h | 12 +++++ 8 files changed, 176 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 img/lenna.jpg create mode 100644 src/CMakeLists.txt create mode 100644 src/loader.c create mode 100644 src/loader.h create mode 100644 src/main.c create mode 100644 src/util.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..932896b --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.vs/ + +[Oo]ut/ +[Bb]uild/ + +*.json \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..85cf80e --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,9 @@ +# CMakeList.txt : Top-level CMake project file, do global configuration +# and include sub-projects here. +# +cmake_minimum_required (VERSION 3.8) + +project ("jpeg-dissect") + +# Include sub-projects. +add_subdirectory ("src") diff --git a/img/lenna.jpg b/img/lenna.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7a0e4b7ab220b6d607d3c5962f3f50ce3908e252 GIT binary patch literal 37073 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

@U7UqRN8=OS~(+&%M8uH$UgkmE~ls3 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 +#include + +#include "util.h" + +static int load_segment(FILE* fp); + +static int load_rst_segment(FILE* fp, uint8_t n); +static int load_app_segment(FILE* fp, uint8_t n); + +static int load_app0_segment(FILE* fp); + +int load_jpeg(const char* filename) +{ + FILE* fp = fopen(filename, "r"); + if (fp == NULL) + { + return 1; + } + + while (!feof(fp)) + { + if (load_segment(fp) != 0) + { + fprintf(stderr, "Segment loading failed\n"); + return 1; + } + } + + fclose(fp); + return 0; +} + +int load_segment(FILE* fp) +{ + uint8_t segment_marker[2]; + size_t segment_marker_size = sizeof(segment_marker); + + if (fread(segment_marker, sizeof(uint8_t), segment_marker_size, fp) != segment_marker_size) + { + fprintf(stderr, "Marker terminated unexpectedly\n"); + return 1; + } + + if (segment_marker[0] != 0xFF) + { + fprintf(stderr, "Ill-formatted marker\n"); + return 1; + } + + // Handle special APPn/RSTn markers + if (segment_marker[1] >= 0xD0 && segment_marker[1] <= 0xD7) + { + if (load_rst_segment(fp, segment_marker[1] | 0x0F) != 0) + { + return 1; + } + } + else if ((segment_marker[1] & 0xF0) == 0xE0) + { + if (load_app_segment(fp, segment_marker[1] & 0x0F) != 0) + { + return 1; + } + } + else + { + switch (segment_marker[1]) + { + case 0xD8: // Start of image + DEBUG_LOG("SOI marker encountered"); + break; + + default: + fprintf(stderr, "Unimplemented marker 0xFF 0x%02X\n", segment_marker[1]); + return 1; + } + } + + return 0; +} + +int load_rst_segment(FILE* fp, uint8_t n) +{ + DEBUG_LOG("RST%d marker encountered", n); + return 1; +} + +int load_app_segment(FILE* fp, uint8_t n) +{ + DEBUG_LOG("APP%d marker encountered", n); + + switch (n) + { + case 0: return load_app0_segment(); + + default: + fprintf(stderr, "Unknown APP segment ID %d\n", n); + return 1; + } + + return 0; +} + +int load_app0_segment(FILE* fp) +{ + +} \ No newline at end of file diff --git a/src/loader.h b/src/loader.h new file mode 100644 index 0000000..856938d --- /dev/null +++ b/src/loader.h @@ -0,0 +1,6 @@ +#ifndef _LODAER_H +#define _LOADER_H + +int load_jpeg(const char* filename); + +#endif // _LOADER_H \ No newline at end of file diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..c41dfb2 --- /dev/null +++ b/src/main.c @@ -0,0 +1,27 @@ +#include +#include "loader.h" + +static void print_usage(void) +{ + printf("Usage: ./jpeg-dissect \n"); +} + +int main(int argc, char** argv) +{ + if (argc != 2) + { + print_usage(); + return 1; + } + + const char* filename = argv[1]; + printf("Supplied file: %s\n", filename); + + if (load_jpeg(filename) != 0) + { + fprintf(stderr, "Failed to load jpeg\n"); + return 1; + } + + return 0; +} diff --git a/src/util.h b/src/util.h new file mode 100644 index 0000000..64db194 --- /dev/null +++ b/src/util.h @@ -0,0 +1,12 @@ +#ifndef _UTIL_H +#define _UTIL_H + +#include + +#ifdef NDEBUG +#define DEBUG_LOG +#else +#define DEBUG_LOG(msg, ...) printf("[DEBUG] " ##msg "\n", __VA_ARGS__); +#endif + +#endif // _UTIL_H \ No newline at end of file