nsxiv691c6d7
Added own exif tag handling in files exif.[ch]
+212 −1
6 files changed
| @@ -8,7 +8,7 @@ LIBS = -lX11 -lImlib2 -lgif | |||
| 8 | 8 | PREFIX = /usr/local | |
| 9 | 9 | MANPREFIX = $(PREFIX)/share/man | |
| 10 | 10 | ||
| 11 | − | SRC = commands.c image.c main.c options.c thumbs.c util.c window.c | |
| 11 | + | SRC = commands.c exif.c image.c main.c options.c thumbs.c util.c window.c | |
| 12 | 12 | OBJ = $(SRC:.c=.o) | |
| 13 | 13 | ||
| 14 | 14 | all: options sxiv | |
| @@ -0,0 +1,131 @@ | |||
| 1 | + | /* sxiv: exif.c | |
| 2 | + | * Copyright (c) 2011 Bert Muennich <be.muennich at googlemail.com> | |
| 3 | + | * | |
| 4 | + | * This program is free software; you can redistribute it and/or modify it | |
| 5 | + | * under the terms of the GNU General Public License as published by the | |
| 6 | + | * Free Software Foundation; either version 2 of the License, or (at your | |
| 7 | + | * option) any later version. | |
| 8 | + | * | |
| 9 | + | * This program is distributed in the hope that it will be useful, but | |
| 10 | + | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 11 | + | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 12 | + | * General Public License for more details. | |
| 13 | + | * | |
| 14 | + | * You should have received a copy of the GNU General Public License along | |
| 15 | + | * with this program; if not, write to the Free Software Foundation, Inc., | |
| 16 | + | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |
| 17 | + | */ | |
| 18 | + | ||
| 19 | + | #define _POSIX_C_SOURCE 200112L | |
| 20 | + | ||
| 21 | + | #include <stdlib.h> | |
| 22 | + | #include <fcntl.h> | |
| 23 | + | #include <sys/stat.h> | |
| 24 | + | #include <unistd.h> | |
| 25 | + | ||
| 26 | + | #include "exif.h" | |
| 27 | + | #include "util.h" | |
| 28 | + | ||
| 29 | + | ssize_t s_read(int fd, const char *fn, void *buf, size_t n) { | |
| 30 | + | ssize_t ret; | |
| 31 | + | ||
| 32 | + | ret = read(fd, buf, n); | |
| 33 | + | if (ret < n) { | |
| 34 | + | warn("unexpected end-of-file: %s", fn); | |
| 35 | + | return -1; | |
| 36 | + | } else { | |
| 37 | + | return ret; | |
| 38 | + | } | |
| 39 | + | } | |
| 40 | + | ||
| 41 | + | unsigned short btous(unsigned char *buf, byteorder_t order) { | |
| 42 | + | if (buf == NULL) | |
| 43 | + | return 0; | |
| 44 | + | if (order == BO_BIG_ENDIAN) | |
| 45 | + | return buf[0] << 8 | buf[1]; | |
| 46 | + | else | |
| 47 | + | return buf[1] << 8 | buf[0]; | |
| 48 | + | } | |
| 49 | + | ||
| 50 | + | unsigned int btoui(unsigned char *buf, byteorder_t order) { | |
| 51 | + | if (buf == NULL) | |
| 52 | + | return 0; | |
| 53 | + | if (order == BO_BIG_ENDIAN) | |
| 54 | + | return buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]; | |
| 55 | + | else | |
| 56 | + | return buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0]; | |
| 57 | + | } | |
| 58 | + | ||
| 59 | + | int exif_orientation(const fileinfo_t *file) { | |
| 60 | + | int fd; | |
| 61 | + | unsigned char data[EXIF_MAX_LEN]; | |
| 62 | + | byteorder_t order = BO_BIG_ENDIAN; | |
| 63 | + | unsigned int cnt, len, idx, val; | |
| 64 | + | ||
| 65 | + | if (file == NULL || file->path == NULL) | |
| 66 | + | return -1; | |
| 67 | + | ||
| 68 | + | fd = open(file->path, O_RDONLY); | |
| 69 | + | if (fd < 0) | |
| 70 | + | return -1; | |
| 71 | + | ||
| 72 | + | if (s_read(fd, file->name, data, 4) < 0) | |
| 73 | + | goto abort; | |
| 74 | + | if (btous(data, order) != JPEG_MARKER_SOI) | |
| 75 | + | goto abort; | |
| 76 | + | if (btous(data + 2, order) != JPEG_MARKER_APP1) | |
| 77 | + | goto abort; | |
| 78 | + | ||
| 79 | + | if (s_read(fd, file->name, data, 2) < 0) | |
| 80 | + | goto abort; | |
| 81 | + | len = btous(data, order); | |
| 82 | + | if (len < 8) | |
| 83 | + | goto abort; | |
| 84 | + | ||
| 85 | + | if (s_read(fd, file->name, data, 6) < 0) | |
| 86 | + | goto abort; | |
| 87 | + | if (btoui(data, order) != EXIF_HEAD) | |
| 88 | + | goto abort; | |
| 89 | + | ||
| 90 | + | len -= 8; | |
| 91 | + | if (len < 12 || len > EXIF_MAX_LEN) | |
| 92 | + | goto abort; | |
| 93 | + | if (s_read(fd, file->name, data, len) < 0) | |
| 94 | + | goto abort; | |
| 95 | + | ||
| 96 | + | switch (btous(data, order)) { | |
| 97 | + | case EXIF_BO_BIG_ENDIAN: | |
| 98 | + | order = BO_BIG_ENDIAN; | |
| 99 | + | break; | |
| 100 | + | case EXIF_BO_LITTLE_ENDIAN: | |
| 101 | + | order = BO_LITTLE_ENDIAN; | |
| 102 | + | break; | |
| 103 | + | default: | |
| 104 | + | goto abort; | |
| 105 | + | break; | |
| 106 | + | } | |
| 107 | + | ||
| 108 | + | if (btous(data + 2, order) != EXIF_TAG_MARK) | |
| 109 | + | goto abort; | |
| 110 | + | idx = btoui(data + 4, order); | |
| 111 | + | if (idx > len - 2) | |
| 112 | + | goto abort; | |
| 113 | + | ||
| 114 | + | val = 0; | |
| 115 | + | cnt = btous(data + idx, order); | |
| 116 | + | ||
| 117 | + | for (idx += 2; cnt > 0 && idx < len - 12; cnt--, idx += 12) { | |
| 118 | + | if (btous(data + idx, order) == EXIF_TAG_ORIENTATION) { | |
| 119 | + | val = btous(data + idx + 8, order); | |
| 120 | + | printf("exif orientation: %s: %u\n", file->name, val); | |
| 121 | + | break; | |
| 122 | + | } | |
| 123 | + | } | |
| 124 | + | ||
| 125 | + | close(fd); | |
| 126 | + | return val; | |
| 127 | + | ||
| 128 | + | abort: | |
| 129 | + | close(fd); | |
| 130 | + | return -1; | |
| 131 | + | } | |
| @@ -0,0 +1,41 @@ | |||
| 1 | + | /* sxiv: exif.h | |
| 2 | + | * Copyright (c) 2011 Bert Muennich <be.muennich at googlemail.com> | |
| 3 | + | * | |
| 4 | + | * This program is free software; you can redistribute it and/or modify it | |
| 5 | + | * under the terms of the GNU General Public License as published by the | |
| 6 | + | * Free Software Foundation; either version 2 of the License, or (at your | |
| 7 | + | * option) any later version. | |
| 8 | + | * | |
| 9 | + | * This program is distributed in the hope that it will be useful, but | |
| 10 | + | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 11 | + | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 12 | + | * General Public License for more details. | |
| 13 | + | * | |
| 14 | + | * You should have received a copy of the GNU General Public License along | |
| 15 | + | * with this program; if not, write to the Free Software Foundation, Inc., | |
| 16 | + | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |
| 17 | + | */ | |
| 18 | + | ||
| 19 | + | #ifndef EXIF_H | |
| 20 | + | #define EXIF_H | |
| 21 | + | ||
| 22 | + | #include "types.h" | |
| 23 | + | ||
| 24 | + | enum { | |
| 25 | + | JPEG_MARKER_SOI = 0xFFD8, | |
| 26 | + | JPEG_MARKER_APP1 = 0xFFE1 | |
| 27 | + | }; | |
| 28 | + | ||
| 29 | + | enum { | |
| 30 | + | EXIF_MAX_LEN = 0x10000, | |
| 31 | + | EXIF_HEAD = 0x45786966, | |
| 32 | + | EXIF_BO_BIG_ENDIAN = 0x4D4D, | |
| 33 | + | EXIF_BO_LITTLE_ENDIAN = 0x4949, | |
| 34 | + | EXIF_TAG_MARK = 0x002A, | |
| 35 | + | EXIF_TAG_ORIENTATION = 0x0112 | |
| 36 | + | }; | |
| 37 | + | ||
| 38 | + | int exif_orientation(const fileinfo_t*); | |
| 39 | + | void exif_auto_orientate(const fileinfo_t*); /* in image.c */ | |
| 40 | + | ||
| 41 | + | #endif /* EXIF_H */ | |
| @@ -25,6 +25,7 @@ | |||
| 25 | 25 | #include <unistd.h> | |
| 26 | 26 | #include <gif_lib.h> | |
| 27 | 27 | ||
| 28 | + | #include "exif.h" | |
| 28 | 29 | #include "image.h" | |
| 29 | 30 | #include "options.h" | |
| 30 | 31 | #include "util.h" | |
| @@ -64,6 +65,34 @@ void img_init(img_t *img, win_t *win) { | |||
| 64 | 65 | img->multi.animate = false; | |
| 65 | 66 | } | |
| 66 | 67 | ||
| 68 | + | void exif_auto_orientate(const fileinfo_t *file) { | |
| 69 | + | switch (exif_orientation(file)) { | |
| 70 | + | case 5: | |
| 71 | + | imlib_image_orientate(1); | |
| 72 | + | case 2: | |
| 73 | + | imlib_image_flip_vertical(); | |
| 74 | + | break; | |
| 75 | + | ||
| 76 | + | case 3: | |
| 77 | + | imlib_image_orientate(2); | |
| 78 | + | break; | |
| 79 | + | ||
| 80 | + | case 7: | |
| 81 | + | imlib_image_orientate(1); | |
| 82 | + | case 4: | |
| 83 | + | imlib_image_flip_horizontal(); | |
| 84 | + | break; | |
| 85 | + | ||
| 86 | + | case 6: | |
| 87 | + | imlib_image_orientate(1); | |
| 88 | + | break; | |
| 89 | + | ||
| 90 | + | case 8: | |
| 91 | + | imlib_image_orientate(3); | |
| 92 | + | break; | |
| 93 | + | } | |
| 94 | + | } | |
| 95 | + | ||
| 67 | 96 | bool img_load_gif(img_t *img, const fileinfo_t *file) { | |
| 68 | 97 | GifFileType *gif; | |
| 69 | 98 | GifRowType *rows = NULL; | |
| @@ -254,6 +283,8 @@ bool img_load(img_t *img, const fileinfo_t *file) { | |||
| 254 | 283 | warn("could not open image: %s", file->name); | |
| 255 | 284 | return false; | |
| 256 | 285 | } | |
| 286 | + | if (STREQ(fmt, "jpeg")) | |
| 287 | + | exif_auto_orientate(file); | |
| 257 | 288 | if (STREQ(fmt, "gif")) | |
| 258 | 289 | img_load_gif(img, file); | |
| 259 | 290 | ||
| @@ -26,6 +26,7 @@ | |||
| 26 | 26 | #include <unistd.h> | |
| 27 | 27 | #include <utime.h> | |
| 28 | 28 | ||
| 29 | + | #include "exif.h" | |
| 29 | 30 | #include "thumbs.h" | |
| 30 | 31 | #include "util.h" | |
| 31 | 32 | #include "config.h" | |
| @@ -254,6 +255,8 @@ bool tns_load(tns_t *tns, int n, const fileinfo_t *file, | |||
| 254 | 255 | imlib_free_image_and_decache(); | |
| 255 | 256 | return false; | |
| 256 | 257 | } | |
| 258 | + | if (STREQ(fmt, "jpeg")) | |
| 259 | + | exif_auto_orientate(file); | |
| 257 | 260 | ||
| 258 | 261 | w = imlib_image_get_width(); | |
| 259 | 262 | h = imlib_image_get_height(); | |
| @@ -6,6 +6,11 @@ typedef enum { | |||
| 6 | 6 | true | |
| 7 | 7 | } bool; | |
| 8 | 8 | ||
| 9 | + | typedef enum { | |
| 10 | + | BO_BIG_ENDIAN, | |
| 11 | + | BO_LITTLE_ENDIAN | |
| 12 | + | } byteorder_t; | |
| 13 | + | ||
| 9 | 14 | typedef enum { | |
| 10 | 15 | MODE_IMAGE, | |
| 11 | 16 | MODE_THUMB | |