static void get_image_dimensions(ImageSize *is, int *width, int *height) { unsigned int length; unsigned int image_height, image_width; int num_components; int ci; length = read_2_bytes(is); read_1_byte(is); /* data_precision */ image_height = read_2_bytes(is); image_width = read_2_bytes(is); num_components = read_1_byte(is); *width = image_width; *height = image_height; if (length != (unsigned int) (8 + num_components * 3)) { *width = *height = -1; /* Bogus SOF marker length */ } else { for (ci = 0; ci < num_components; ci++) { read_1_byte(is); /* Component ID code */ read_1_byte(is); /* H, V sampling factors */ read_1_byte(is); /* Quantization table number */ } } }
static void process_SOFn (int marker) { unsigned int length; unsigned int image_height, image_width; int data_precision, num_components; const char * process; int ci; length = read_2_bytes(); /* usual parameter length count */ data_precision = read_1_byte(); image_height = read_2_bytes(); image_width = read_2_bytes(); num_components = read_1_byte(); switch (marker) { case M_SOF0: process = "Baseline"; break; case M_SOF1: process = "Extended sequential"; break; case M_SOF2: process = "Progressive"; break; case M_SOF3: process = "Lossless"; break; case M_SOF5: process = "Differential sequential"; break; case M_SOF6: process = "Differential progressive"; break; case M_SOF7: process = "Differential lossless"; break; case M_SOF9: process = "Extended sequential, arithmetic coding"; break; case M_SOF10: process = "Progressive, arithmetic coding"; break; case M_SOF11: process = "Lossless, arithmetic coding"; break; case M_SOF13: process = "Differential sequential, arithmetic coding"; break; case M_SOF14: process = "Differential progressive, arithmetic coding"; break; case M_SOF15: process = "Differential lossless, arithmetic coding"; break; default: process = "Unknown"; break; } printf("JPEG image is %uw * %uh, %d color components, %d bits per sample\n", image_width, image_height, num_components, data_precision); printf("JPEG process: %s\n", process); if (length != (unsigned int) (8 + num_components * 3)) ERREXIT("Bogus SOF marker length"); for (ci = 0; ci < num_components; ci++) { (void) read_1_byte(); /* Component ID code */ (void) read_1_byte(); /* H, V sampling factors */ (void) read_1_byte(); /* Quantization table number */ } }
uint64_t read_variable_uint() { uint8_t length = read_byte(); uint64_t value = 0; if (length < 0xfd) value = length; else if (length == 0xfd) value += read_2_bytes(); else if (length == 0xfe) value += read_4_bytes(); else if (length == 0xff) value += read_8_bytes(); return value; }
static void process_COM (int raw) { unsigned int length; int ch; int lastch = 0; /* Bill Allombert: set locale properly for isprint */ #ifdef HAVE_LOCALE_H setlocale(LC_CTYPE, ""); #endif /* Get the marker parameter length count */ length = read_2_bytes(); /* Length includes itself, so must be at least 2 */ if (length < 2) ERREXIT("Erroneous JPEG marker length"); length -= 2; while (length > 0) { ch = read_1_byte(); if (raw) { putc(ch, stdout); /* Emit the character in a readable form. * Nonprintables are converted to \nnn form, * while \ is converted to \\. * Newlines in CR, CR/LF, or LF form will be printed as one newline. */ } else if (ch == '\r') { printf("\n"); } else if (ch == '\n') { if (lastch != '\r') printf("\n"); } else if (ch == '\\') { printf("\\\\"); } else if (isprint(ch)) { putc(ch, stdout); } else { printf("\\%03o", ch); } lastch = ch; length--; } printf("\n"); /* Bill Allombert: revert to C locale */ #ifdef HAVE_LOCALE_H setlocale(LC_CTYPE, "C"); #endif }
static void process_COM (void) { unsigned int length; int ch; int lastch = 0; /* Get the marker parameter length count */ length = read_2_bytes(); /* Length includes itself, so must be at least 2 */ if (length < 2) ERREXIT("Erroneous JPEG marker length"); length -= 2; while (length > 0) { ch = read_1_byte(); /* Emit the character in a readable form. * Nonprintables are converted to \nnn form, * while \ is converted to \\. * Newlines in CR, CR/LF, or LF form will be printed as one newline. */ if (ch == '\r') { printf("\n"); } else if (ch == '\n') { if (lastch != '\r') printf("\n"); } else if (ch == '\\') { printf("\\\\"); } else if (isprint(ch)) { putc(ch, stdout); } else { printf("\\%03o", ch); } lastch = ch; length--; } printf("\n"); }
static void skip_variable (void) /* Skip over an unknown or uninteresting variable-length marker */ { unsigned int length; /* Get the marker parameter length count */ length = read_2_bytes(); /* Length includes itself, so must be at least 2 */ if (length < 2) ERREXIT("Erroneous JPEG marker length"); length -= 2; /* Skip over the remaining bytes */ while (length > 0) { (void) read_1_byte(); length--; } }
/* Skip over an unknown or uninteresting variable-length marker */ static int skip_variable(ImageSize *is) { int length; int res = 0; /* Get the marker parameter length count */ length = read_2_bytes(is); /* Length includes itself, so must be at least 2 */ if (length < 2 || length == EOF) { res = -1; /* error */ } else { length -= 2; /* Skip over the remaining bytes */ while (length > 0) { read_1_byte(is); length--; } } return res; }
unsigned int GetOrientationOfFile(char * filename) { read_byte_error_while_reading=0; myfile=0; int n_flag=0 , set_flag=0; unsigned int length=0, i=0; int is_motorola=0; /* Flag for byte order */ unsigned int offset=0, number_of_tags=0, tagnum=0; n_flag = 0; set_flag = 0; i = 1; myfile = fopen(filename, "rb"); if ( myfile == 0) { fprintf(stderr, " Can't open %s\n", filename); return 0; } /* Read File head, check for JPEG SOI + Exif APP1 */ for (i = 0; i < 4; i++) { exif_data[i] = (unsigned char) read_1_byte(); } if (exif_data[0] != 0xFF || exif_data[1] != 0xD8 || exif_data[2] != 0xFF || exif_data[3] != 0xE1) { fclose(myfile); return 0; } /* Get the marker parameter length count */ length = read_2_bytes(); /* Length includes itself, so must be at least 2 */ /* Following Exif data length must be at least 6 */ if (length < 8) { fclose(myfile); return 0; } length -= 8; /* Read Exif head, check for "Exif" */ for (i = 0; i < 6; i++) { exif_data[i] = (unsigned char) read_1_byte(); } if (exif_data[0] != 0x45 || exif_data[1] != 0x78 || exif_data[2] != 0x69 || exif_data[3] != 0x66 || exif_data[4] != 0 || exif_data[5] != 0) { fclose(myfile); return 0; } /* Read Exif body */ for (i = 0; i < length; i++) { exif_data[i] = (unsigned char) read_1_byte(); } if (length < 12) { fclose(myfile); return 0; } /* Length of an IFD entry */ /* Discover byte order */ if (exif_data[0] == 0x49 && exif_data[1] == 0x49) { is_motorola = 0; } else if (exif_data[0] == 0x4D && exif_data[1] == 0x4D) { is_motorola = 1; } else { fclose(myfile); return 0; } /* Check Tag Mark */ if (is_motorola) { if (exif_data[2] != 0) { fclose(myfile); return 0; } if (exif_data[3] != 0x2A) { fclose(myfile); return 0; } } else { if (exif_data[3] != 0) { fclose(myfile); return 0; } if (exif_data[2] != 0x2A) { fclose(myfile); return 0; } } /* Get first IFD offset (offset to IFD0) */ if (is_motorola) { if (exif_data[4] != 0) { fclose(myfile); return 0; } if (exif_data[5] != 0) { fclose(myfile); return 0; } offset = exif_data[6]; offset <<= 8; offset += exif_data[7]; } else { if (exif_data[7] != 0) { fclose(myfile); return 0; } if (exif_data[6] != 0) { fclose(myfile); return 0; } offset = exif_data[5]; offset <<= 8; offset += exif_data[4]; } if (offset > length - 2) { fclose(myfile); return 0; } /* check end of data segment */ /* Get the number of directory entries contained in this IFD */ if (is_motorola) { number_of_tags = exif_data[offset]; number_of_tags <<= 8; number_of_tags += exif_data[offset+1]; } else { number_of_tags = exif_data[offset+1]; number_of_tags <<= 8; number_of_tags += exif_data[offset]; } if (number_of_tags == 0) { fclose(myfile); return 0; } offset += 2; /* Search for Orientation Tag in IFD0 */ for (;;) { if (offset > length - 12) { fclose(myfile); return 0; }/* check end of data segment */ /* Get Tag number */ if (is_motorola) { tagnum = exif_data[offset]; tagnum <<= 8; tagnum += exif_data[offset+1]; } else { tagnum = exif_data[offset+1]; tagnum <<= 8; tagnum += exif_data[offset]; } if (tagnum == 0x0112) break; /* found Orientation Tag */ if (--number_of_tags == 0) { fclose(myfile); return 0; } offset += 12; } /* Get the Orientation value */ if (is_motorola) { if (exif_data[offset+8] != 0) { fclose(myfile); return 0; } set_flag = exif_data[offset+9]; } else { if (exif_data[offset+9] != 0) { fclose(myfile); return 0; } set_flag = exif_data[offset+8]; } if (set_flag > 8) { fclose(myfile); return 0; } fclose(myfile); /* All done. */ return (unsigned int) set_flag; }
int main (int argc, char **argv) { int n_flag, set_flag, exif_flag; unsigned int length, i; int is_motorola; /* Flag for byte order */ unsigned int offset, number_of_tags, tagnum; progname = argv[0]; if (progname == NULL || progname[0] == 0) progname = "jpegexiforient"; /* in case C library doesn't provide it */ if (argc < 2) { usage(stderr); return 1; } n_flag = 0; set_flag = 0; i = 1; while (argv[i][0] == '-') { switch (argv[i][1]) { case '-': switch (argv[i][2]) { case 'h': usage(stdout); return 0; case 'v': fprintf(stdout,"jpegexiforient\n"); return 0; default: usage(stderr); return 1; } case 'n': n_flag = 1; break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': set_flag = argv[i][1] - '0'; break; default: usage(stderr); return 1; } if (++i >= argc) { usage(stderr); return 1; } } if (set_flag) { if ((myfile = fopen(argv[i], "rb+")) == NULL) { fprintf(stderr, "%s: can't open %s\n", progname, argv[i]); return 0; } } else { if ((myfile = fopen(argv[i], "rb")) == NULL) { fprintf(stderr, "%s: can't open %s\n", progname, argv[i]); return 0; } } /* Read File head, check for JPEG SOI + Exif APP1 or APP0 */ for (i = 0; i < 4; i++) exif_data[i] = (unsigned char) read_1_byte(); if (exif_data[0] != 0xFF || exif_data[1] != 0xD8 || exif_data[2] != 0xFF) return 0; if (exif_data[3] != 0xE1) /* if file header is APP0, skip over the JFIF header and find the Exif header */ { exif_flag = 0; while (exif_flag == 0) { exif_data[0] = (unsigned char) read_1_byte(); if (exif_data[0] == 0xFF) { exif_data[0] = (unsigned char) read_1_byte(); if (exif_data[0] == 0xE1) exif_flag = 1; } } } /* Get the marker parameter length count */ length = read_2_bytes(); /* Length includes itself, so must be at least 2 */ /* Following Exif data length must be at least 6 */ if (length < 8) return 0; length -= 8; /* Read Exif head, check for "Exif" */ for (i = 0; i < 6; i++) exif_data[i] = (unsigned char) read_1_byte(); if (exif_data[0] != 0x45 || exif_data[1] != 0x78 || exif_data[2] != 0x69 || exif_data[3] != 0x66 || exif_data[4] != 0 || exif_data[5] != 0) return 0; /* Read Exif body */ for (i = 0; i < length; i++) exif_data[i] = (unsigned char) read_1_byte(); if (length < 12) return 0; /* Length of an IFD entry */ /* Discover byte order */ if (exif_data[0] == 0x49 && exif_data[1] == 0x49) is_motorola = 0; else if (exif_data[0] == 0x4D && exif_data[1] == 0x4D) is_motorola = 1; else return 0; /* Check Tag Mark */ if (is_motorola) { if (exif_data[2] != 0) return 0; if (exif_data[3] != 0x2A) return 0; } else { if (exif_data[3] != 0) return 0; if (exif_data[2] != 0x2A) return 0; } /* Get first IFD offset (offset to IFD0) */ if (is_motorola) { if (exif_data[4] != 0) return 0; if (exif_data[5] != 0) return 0; offset = exif_data[6]; offset <<= 8; offset += exif_data[7]; } else { if (exif_data[7] != 0) return 0; if (exif_data[6] != 0) return 0; offset = exif_data[5]; offset <<= 8; offset += exif_data[4]; } if (offset > length - 2) return 0; /* check end of data segment */ /* Get the number of directory entries contained in this IFD */ if (is_motorola) { number_of_tags = exif_data[offset]; number_of_tags <<= 8; number_of_tags += exif_data[offset+1]; } else { number_of_tags = exif_data[offset+1]; number_of_tags <<= 8; number_of_tags += exif_data[offset]; } if (number_of_tags == 0) return 0; offset += 2; /* Search for Orientation Tag in IFD0 */ for (;;) { if (offset > length - 12) return 0; /* check end of data segment */ /* Get Tag number */ if (is_motorola) { tagnum = exif_data[offset]; tagnum <<= 8; tagnum += exif_data[offset+1]; } else { tagnum = exif_data[offset+1]; tagnum <<= 8; tagnum += exif_data[offset]; } if (tagnum == 0x0112) break; /* found Orientation Tag */ if (--number_of_tags == 0) return 0; offset += 12; } if (set_flag) { /* Set the Orientation value */ if (is_motorola) { exif_data[offset+2] = 0; /* Format = unsigned short (2 octets) */ exif_data[offset+3] = 3; exif_data[offset+4] = 0; /* Number Of Components = 1 */ exif_data[offset+5] = 0; exif_data[offset+6] = 0; exif_data[offset+7] = 1; exif_data[offset+8] = 0; exif_data[offset+9] = (unsigned char)set_flag; exif_data[offset+10] = 0; exif_data[offset+11] = 0; } else { exif_data[offset+2] = 3; /* Format = unsigned short (2 octets) */ exif_data[offset+3] = 0; exif_data[offset+4] = 1; /* Number Of Components = 1 */ exif_data[offset+5] = 0; exif_data[offset+6] = 0; exif_data[offset+7] = 0; exif_data[offset+8] = (unsigned char)set_flag; exif_data[offset+9] = 0; exif_data[offset+10] = 0; exif_data[offset+11] = 0; } fseek(myfile, (4 + 2 + 6 + 2) + offset, SEEK_SET); fwrite(exif_data + 2 + offset, 1, 10, myfile); } else { /* Get the Orientation value */ if (is_motorola) { if (exif_data[offset+8] != 0) return 0; set_flag = exif_data[offset+9]; } else { if (exif_data[offset+9] != 0) return 0; set_flag = exif_data[offset+8]; } if (set_flag > 8) return 0; } /* Write out Orientation value */ if (n_flag) printf("%c", '0' + set_flag); else printf("%c\n", '0' + set_flag); /* All done. */ return 0; }