Krolyxon
Commit 691c6d7

Branches

Refs →

nsxiv691c6d7

Added own exif tag handling in files exif.[ch]

Author
Bert Münnich
Date
2012-02-15 19:13 +0100
Parent
b752d5c
Commit
691c6d7e7e7667696dcf5996316fba6a120f2e7b

+212 −1

6 files changed

  1. M Makefile +1 −1
  2. A exif.c +131 −0
  3. A exif.h +41 −0
  4. M image.c +31 −0
  5. M thumbs.c +3 −0
  6. M types.h +5 −0
M Makefile View
@@ -8,7 +8,7 @@ LIBS = -lX11 -lImlib2 -lgif
88 PREFIX = /usr/local
99 MANPREFIX = $(PREFIX)/share/man
1010
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
1212 OBJ = $(SRC:.c=.o)
1313
1414 all: options sxiv
A exif.c View
@@ -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+}
A exif.h View
@@ -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 */
M image.c View
@@ -25,6 +25,7 @@
2525 #include <unistd.h>
2626 #include <gif_lib.h>
2727
28+#include "exif.h"
2829 #include "image.h"
2930 #include "options.h"
3031 #include "util.h"
@@ -64,6 +65,34 @@ void img_init(img_t *img, win_t *win) {
6465 img->multi.animate = false;
6566 }
6667
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+
6796 bool img_load_gif(img_t *img, const fileinfo_t *file) {
6897 GifFileType *gif;
6998 GifRowType *rows = NULL;
@@ -254,6 +283,8 @@ bool img_load(img_t *img, const fileinfo_t *file) {
254283 warn("could not open image: %s", file->name);
255284 return false;
256285 }
286+ if (STREQ(fmt, "jpeg"))
287+ exif_auto_orientate(file);
257288 if (STREQ(fmt, "gif"))
258289 img_load_gif(img, file);
259290
M thumbs.c View
@@ -26,6 +26,7 @@
2626 #include <unistd.h>
2727 #include <utime.h>
2828
29+#include "exif.h"
2930 #include "thumbs.h"
3031 #include "util.h"
3132 #include "config.h"
@@ -254,6 +255,8 @@ bool tns_load(tns_t *tns, int n, const fileinfo_t *file,
254255 imlib_free_image_and_decache();
255256 return false;
256257 }
258+ if (STREQ(fmt, "jpeg"))
259+ exif_auto_orientate(file);
257260
258261 w = imlib_image_get_width();
259262 h = imlib_image_get_height();
M types.h View
@@ -6,6 +6,11 @@ typedef enum {
66 true
77 } bool;
88
9+typedef enum {
10+ BO_BIG_ENDIAN,
11+ BO_LITTLE_ENDIAN
12+} byteorder_t;
13+
914 typedef enum {
1015 MODE_IMAGE,
1116 MODE_THUMB