Skip to content

Instantly share code, notes, and snippets.

@numinit
Last active September 17, 2016 08:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save numinit/2f97112b9705bbb87dbe to your computer and use it in GitHub Desktop.
Save numinit/2f97112b9705bbb87dbe to your computer and use it in GitHub Desktop.
/* gcc -Os -o jpeg jpeg.c
* ./jpeg in_file.jpg
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
typedef struct chunk {
uint16_t marker;
uint16_t size;
} jpeg_chunk __attribute__ ((__packed__));
char *markers[] = {"NUL", "TEM", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "RES", "SOF0", "SOF1", "SOF2", "SOF3", "DHT", "SOF5", "SOF6", "SOF7", "JPG", "SOF9", "SOF10", "SOF11", "DAC", "SOF13", "SOF14", "SOF15", "RST0", "RST1", "RST2", "RST3", "RST4", "RST5", "RST6", "RST7", "SOI", "EOI", "SOS", "DQT", "DNL", "DRI", "DHP", "EXP", "APP0", "APP1", "APP2", "APP3", "APP4", "APP5", "APP6", "APP7", "APP8", "APP9", "APP10", "APP11", "APP12", "APP13", "APP14", "APP15", "JPG0", "JPG1", "JPG2", "JPG3", "JPG4", "JPG5", "JPG6", "JPG7", "JPG8", "JPG9", "JPG10", "JPG11", "JPG12", "JPG13", "COM"};
int main(int argc, char **argv) {
FILE *f = fopen(argv[argc - 1], "r");
if (!f) {
printf("fopen returned null: error reading file `%s'\n", argv[argc - 1]);
return 1;
} else if (ferror(f)) {
printf("error reading file `%s'\n", argv[argc - 1]);
return 1;
}
uint8_t m1 = (uint8_t)fgetc(f), m2 = (uint8_t)fgetc(f);
size_t cur = ftell(f);
if (m1 != 0xff || m2 != 0xd8) {
printf("file isn't a jpeg\n");
return 1;
} else {
size_t size;
fseek(f, 0, SEEK_END);
size = ftell(f);
fseek(f, cur, SEEK_SET);
printf("> start of %zuB jpeg detected\n", size);
}
for (size_t i = 0, pos = 0, go = 1; go && !feof(f); i++) {
jpeg_chunk c;
pos = ftell(f);
fread((void *)&c, 1, sizeof(jpeg_chunk), f);
c.marker = (uint16_t)((c.marker >> 8) | (c.marker << 8));
c.size = (uint16_t)((c.size >> 8) | (c.size << 8));
if ((c.marker & 0xff00) == 0xff00) {
if (c.marker == 0xffda) {
printf(">> %#08zx | %02zu: %04x (image data)\n", pos, i, c.marker);
go = 0;
} else {
printf(">> %#08zx | %02zu: %04x %-6s => %dB\n", pos, i, c.marker, markers[c.marker & 0xff], c.size);
fseek(f, pos + c.size + 2, SEEK_SET);
}
} else {
printf(">> invalid marker before image data\n");
go = 0;
}
}
printf("> done\n");
fclose(f);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment