From a9ffeca886a50327f91f6fb92e5b4ecc72a520e6 Mon Sep 17 00:00:00 2001 From: hkc Date: Thu, 6 Oct 2022 19:52:59 +0300 Subject: [PATCH] Initial commit / Day0 --- hexdump.h | 104 +++++++++++++++++++++++++++++ jfif.h | 6 ++ main.c | 195 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 305 insertions(+) create mode 100644 hexdump.h create mode 100644 jfif.h create mode 100644 main.c diff --git a/hexdump.h b/hexdump.h new file mode 100644 index 0000000..d506683 --- /dev/null +++ b/hexdump.h @@ -0,0 +1,104 @@ +#ifndef _HEXDUMP_H_ +#define _HEXDUMP_H_ +#include +#include +void hexdump(void *data, size_t len); +void rgbdump(void *data, uint16_t w, uint16_t h); +void rgbadump(void *data, uint16_t w, uint16_t h); +#endif + +#ifdef HEXDUMP_IMPLEMENTATION +#if !defined(HEXDUMP_COLORS0) && !defined(HEXDUMP_COLORS1) +#define HEXDUMP_N_COLORS 8 +const uint8_t hexdump_colors[2][8] = { + { 197, 215, 227, 47, 39, 57, 135, 92 }, + { 124, 214, 226, 46, 31, 55, 127, 53 }, +}; +#else +#define HEXDUMP_RAINBOW +#ifndef HEXDUMP_N_COLORS +#define HEXDUMP_N_COLORS 8 +#endif +const uint8_t hexdump_colors[2][HEXDUMP_N_COLORS] = { + HEXDUMP_COLORS0, + HEXDUMP_COLORS1, +}; +#endif +#include +void hexdump(void *data, size_t len) +{ + uint8_t *ptr = data; + for (size_t i = 0; i < len;) + { +#ifdef HEXDUMP_RAINBOW + printf("\033[%dm%08zx\033[0m\t", ((i >> 4) & 1 ? 90 : 37), i); +#else + printf("%08zx\t", i); +#endif + for (int x = 0; x < 16; x++) + { +#ifdef HEXDUMP_RAINBOW + printf("\033[38;5;%dm", + hexdump_colors[(i >> 4) & 1][(x + i) % HEXDUMP_N_COLORS]); +#endif + if (i + x >= len) printf("-- "); + else printf("%02x ", ptr[i + x]); +#ifdef HEXDUMP_RAINBOW + printf("\033[0m"); +#endif + if (x % 4 == 3) printf("\t"); + } +#ifdef HEXDUMP_PRINTABLE + for (int x = 0; x < 16; x++) + { + if (i + x >= len) break; +#ifdef HEXDUMP_RAINBOW + printf("\033[38;5;%dm", + hexdump_colors[(i >> 4) & 1][(x + i) % HEXDUMP_N_COLORS]); +#endif + if (isprint(ptr[i + x])) + putchar(ptr[i + x]); + else + putchar('.'); +#ifdef HEXDUMP_RAINBOW + printf("\033[0m"); +#endif + } +#endif + printf("\n"); + i += 16; + } +} + +void rgbdump(void *data, uint16_t w, uint16_t h) +{ + uint8_t *ptr = data; + for (int y = 0; y < h; y += 2) + { + for (int x = 0; x < w; x++) + { + int i1 = x + y * w, i2 = x + (y + 1) * w; + printf("\033[38;2;%d;%d;%d;48;2;%d;%d;%dm\xe2\x96\x80", + ptr[i1 * 3 + 0], ptr[i1 * 3 + 1], ptr[i1 * 3 + 2], + ptr[i2 * 3 + 0], ptr[i2 * 3 + 1], ptr[i2 * 3 + 2]); + } + printf("\033[0m\n"); + } +} + +void rgbadump(void *data, uint16_t w, uint16_t h) +{ + uint8_t *ptr = data; + for (int y = 0; y < h; y += 2) + { + for (int x = 0; x < w; x++) + { + int i1 = x + y * w, i2 = x + (y + 1) * w; + printf("\033[38;2;%d;%d;%d;48;2;%d;%d;%dm\xe2\x96\x80", + ptr[i1 * 4 + 0], ptr[i1 * 4 + 1], ptr[i1 * 4 + 2], + ptr[i2 * 4 + 0], ptr[i2 * 4 + 1], ptr[i2 * 4 + 2]); + } + printf("\033[0m\n"); + } +} +#endif diff --git a/jfif.h b/jfif.h new file mode 100644 index 0000000..34f858b --- /dev/null +++ b/jfif.h @@ -0,0 +1,6 @@ +#ifndef _JFIF_H_ +#define _JFIF_H_ + + + +#endif diff --git a/main.c b/main.c new file mode 100644 index 0000000..d76f75f --- /dev/null +++ b/main.c @@ -0,0 +1,195 @@ +// x-run: gcc % -o main -g && ./main /home/hkc/images/wallpapers/photo_2020-09-18_10-05-14.jpg + +#include +#include +#include +#include +#include +#include +#include +#define HEXDUMP_RAINBOW +#define HEXDUMP_PRINTABLE +#define HEXDUMP_IMPLEMENTATION +#include "./hexdump.h" + +typedef uint16_t marker_t; + +typedef enum { + SOF0 = 0xFFC0, // Baseline DCT + SOF1 = 0xFFC1, // Extended seq DCT + SOF2 = 0xFFC2, // Progressive DCT + SOF3 = 0xFFC3, // Lossless + DHT = 0xFFC4, // Define Huffman Table + SOF5 = 0xFFC5, // + SOF6 = 0xFFC6, + SOF7 = 0xFFC7, + JPG = 0xFFC8, + SOF9 = 0xFFC9, + SOF10 = 0xFFCA, + SOF11 = 0xFFCB, + DAC = 0xFFCC, + SOF13 = 0xFFCD, + SOF14 = 0xFFCE, + SOF15 = 0xFFCF, + + +} marker_type_t; + +struct JFIF_SOF0_Component { + uint8_t id; + uint8_t TODO_0 : 4; + uint8_t TODO_1 : 4; +} __attribute__((packed)); + +struct JFIF_SOF0 { + uint16_t bit_depth; + uint16_t height; + uint8_t width; + uint8_t n_components; + struct JFIF_SOF0_Component *components; +} __attribute__((packed)); + +#define panic(...) { \ + fprintf(stderr, "!PANIC! at %s:%d\n", __FILE__, __LINE__);\ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\nerrno=%d (%s)\n", errno, strerror(errno)); \ + abort(); \ +} + +marker_t read_and_print_block(FILE *fp); +const char *marker_name(int marker); + +int main(int argc, char **argv) { + static uint8_t tmp[8192]; + FILE *fp = fopen(argv[1], "rb"); + fread(tmp, 1, 2, fp); + if (memcmp(tmp, "\xFF\xD8", 2)) { + panic("Invalid header!"); + } + + marker_t last_marker; + do { + last_marker = read_and_print_block(fp); + } while (last_marker != 0xFFD9); +} + + +marker_t read_and_print_block(FILE *fp) { + static uint8_t buffer[65536]; + marker_t marker; + uint16_t length; + + long int pos = ftell(fp); + + fread(&marker, sizeof(marker_t), 1, fp); + marker = be16toh(marker); + + if ((marker & 0xFF00) != 0xFF00) { + printf("!!!!!!!!\n"); + fseek(fp, pos & ~0xF, SEEK_SET); + fread(buffer, 1, 32, fp); + hexdump(buffer, 32); + panic("Invalid marker %04x at %ld (0x%lx)", marker, pos, pos); + } + + if (marker == 0xFFD9) return marker; + + fread(&length, sizeof(uint16_t), 1, fp); + length = be16toh(length) - 2; + printf("marker: %04x %8s (%d long) at %ld %lx\n", marker, marker_name(marker), length, pos, pos); + + fread(buffer, 1, length, fp); + + switch (marker) { + case SOF0: + printf("\033[91mSTART OF FRAME\033[0m\n"); + hexdump(buffer, length); + break; + + case 0xFFDA: // Start Of Scan + { + uint8_t n_components = buffer[0]; + uint8_t *cur = &buffer[1]; + + printf("components: %d\n", n_components); + for (uint8_t i = 0; i < n_components; i++) { + uint8_t selector = *cur++, + tables = *cur++; + printf("\t%d: %d in %d/%d\n", i, selector, tables >> 4, tables & 0xf); + } + uint8_t spectral_selector_start = *cur++, + spectral_selector_end = *cur++, + successive_approx = *cur++; + printf("spectral selector: %d..%d\n", spectral_selector_start, spectral_selector_end); + + int n_read = -1; + do { + n_read++; + fread(&buffer[n_read], 1, 1, fp); + } while (!(buffer[n_read - 1] == 0xFF && (buffer[n_read] & 0xF0) == 0xF0)); + printf("stopped after %d bytes\n", n_read); + hexdump(buffer, n_read); + fseek(fp, ftell(fp) - 1, SEEK_SET); + } + break; + + case 0xFFDB: // Quantization table + { + uint8_t destination = buffer[0]; + printf("\tdestination: %d\n", destination); + for (int y = 0; y < 8; y++) { + printf("\t"); + for (int x = 0; x < 8; x++) { + printf("%3d ", buffer[1 + x + y * 8]); + } + printf("\n"); + } + } + break; + + case 0xFFE0: // APP* + case 0xFFE1: + case 0xFFE2: + case 0xFFE3: + case 0xFFE4: + case 0xFFE5: + case 0xFFE6: + case 0xFFE7: + case 0xFFE8: + case 0xFFE9: + case 0xFFEA: + case 0xFFEB: + case 0xFFEC: + case 0xFFED: + case 0xFFEE: + case 0xFFEF: + break; + default: + hexdump(buffer, length); + break; + } + + return marker; +} + +const char *marker_name(int marker) { + switch (marker) { + case SOF0: return " SOF0"; + case SOF1: return " SOF1"; + case SOF2: return " SOF2"; + case SOF3: return " SOF3"; + case DHT: return " DHT"; + case SOF5: return " SOF5"; + case SOF6: return " SOF6"; + case SOF7: return " SOF7"; + case JPG: return " JPG"; + case SOF9: return " SOF9"; + case SOF10: return "SOF10"; + case SOF11: return "SOF11"; + case DAC: return " DAC"; + case SOF13: return "SOF13"; + case SOF14: return "SOF14"; + case SOF15: return "SOF15"; + default: return "N/A"; + } +}