Simplify vflist_get_formatted()
[geeqie.git] / src / format_fuji.c
1 /*
2  * Copyright (C) 2005 Lars Ellenberg
3  * Copyright (C) 2005 John Ellis
4  * Copyright (C) 2008 - 2016 The Geeqie Team
5  *
6  * Author: Lars Ellenberg
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program; if not, write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #  include "config.h"
25 #endif
26
27 #ifndef HAVE_EXIV2
28
29 #include <stdio.h>
30 #include <string.h>
31 #include <unistd.h>
32
33 #include <glib.h>
34
35 #include "intl.h"
36
37 #include "main.h"
38 #include "format_fuji.h"
39 #include "format_raw.h"
40
41 #include "exif.h"
42
43
44 /*
45  *-----------------------------------------------------------------------------
46  * Raw (RAF) embedded jpeg extraction for Fujifilm
47  *-----------------------------------------------------------------------------
48  */
49
50
51 gboolean format_fuji_raw(guchar *data, const guint len,
52                          guint *image_offset, guint *exif_offset)
53 {
54         guint io;
55         guint eo;
56
57         if (len < 128 ||
58             memcmp(data, "FUJIFILM", 8) != 0)
59                 {
60                 return FALSE;
61                 }
62
63         /* offset to jpeg is embedded at bytes 84-87 */
64         io = exif_byte_get_int32(data + 84, EXIF_BYTE_ORDER_MOTOROLA);
65         if (io + 4 > len) return FALSE;
66
67         /* verify jpeg marker */
68         if (memcmp(data + io, "\xff\xd8\xff\xe1", 4) != 0)
69                 {
70                 return FALSE;
71                 }
72
73         /* Exif is stored in the jpeg, so use the same offset */
74         eo=io;
75
76         if (image_offset) *image_offset = io;
77         if (exif_offset) *exif_offset = eo;
78
79         return TRUE;
80 }
81
82
83 /*
84  *-----------------------------------------------------------------------------
85  * EXIF Makernote for Fujifilm
86  *-----------------------------------------------------------------------------
87  */
88
89 static ExifTextList FujiTagSharpness[] = {
90         { 1,    "soft" },
91         { 2,    "soft" },
92         { 3,    "normal" },
93         { 4,    "hard" },
94         { 5,    "hard" },
95         EXIF_TEXT_LIST_END
96 };
97
98 static ExifTextList FujiTagWhiteBalance[]= {
99         { 0,    "auto" },
100         { 256,  "daylight" },
101         { 512,  "cloudy" },
102         { 768,  "daylight color-fluorescence" },
103         { 769,  "daywhite color-fluorescence" },
104         { 770,  "white-fluorescence" },
105         { 1024, "incandescent" },
106         { 3840, "custom" },
107         EXIF_TEXT_LIST_END
108 };
109
110 static ExifTextList FujiTagColorTone[]= {
111         { 0,    "normal" },
112         { 256,  "high" },
113         { 512,  "low" },
114         EXIF_TEXT_LIST_END
115 };
116
117 static ExifTextList FujiTagFlashMode[]= {
118         { 0,    "auto" },
119         { 1,    "on" },
120         { 2,    "off" },
121         { 3,    "red-eye reduction" },
122         EXIF_TEXT_LIST_END
123 };
124
125 static ExifTextList FujiTagOffOn[]= {
126         { 0,    "off" },
127         { 1,    "on" },
128         EXIF_TEXT_LIST_END
129 };
130
131 static ExifTextList FujiTagFocusMode[]= {
132         { 0,    "auto" },
133         { 1,    "manual" },
134         EXIF_TEXT_LIST_END
135 };
136
137 static ExifTextList FujiTagPictureMode[]= {
138         { 0,    "auto" },
139         { 1,    "portrait" },
140         { 2,    "landscape" },
141         { 4,    "sports" },
142         { 5,    "night" },
143         { 6,    "program AE" },
144         { 256,  "aperture priority AE" },
145         { 512,  "shutter priority AE" },
146         { 768,  "manual" },
147         EXIF_TEXT_LIST_END
148 };
149
150 static ExifTextList FujiTagNoYes[]= {
151         { 0,    "no" },
152         { 1,    "yes" },
153         EXIF_TEXT_LIST_END
154 };
155
156
157 static ExifMarker FujiExifMarkersList[] = {
158 { 0x1000,       EXIF_FORMAT_STRING, 8,          "Fuji.Quality",         "Quality",      NULL },
159 { 0x1001,       EXIF_FORMAT_SHORT_UNSIGNED, 1,  "Fuji.Sharpness",       "Sharpness",    FujiTagSharpness },
160 { 0x1002,       EXIF_FORMAT_SHORT_UNSIGNED, 1,  "Fuji.WhiteBalance",    "White balance",FujiTagWhiteBalance },
161 { 0x1003,       EXIF_FORMAT_SHORT_UNSIGNED, 1,  "Fuji.Color",           "Color",        FujiTagColorTone },
162 { 0x1004,       EXIF_FORMAT_SHORT_UNSIGNED, 1,  "Fuji.Tone",            "Tone",         FujiTagColorTone },
163 { 0x1010,       EXIF_FORMAT_SHORT_UNSIGNED, 1,  "Fuji.FlashMode",       "Flash mode",   FujiTagFlashMode },
164 { 0x1011,       EXIF_FORMAT_RATIONAL, 1,        "Fuji.FlashStrength",   "Flash strength", NULL },
165 { 0x1020,       EXIF_FORMAT_SHORT_UNSIGNED, 1,  "Fuji.Macro",           "Macro",        FujiTagOffOn },
166 { 0x1021,       EXIF_FORMAT_SHORT_UNSIGNED, 1,  "Fuji.FocusMode",       "Focus mode",   FujiTagFocusMode },
167 { 0x1030,       EXIF_FORMAT_SHORT_UNSIGNED, 1,  "Fuji.SlowSync",        "Slow synchro", FujiTagOffOn },
168 { 0x1031,       EXIF_FORMAT_SHORT_UNSIGNED, 1,  "Fuji.PictureMode",     "Picture mode", FujiTagPictureMode },
169 { 0x1100,       EXIF_FORMAT_SHORT_UNSIGNED, 1,  "Fuji.ContTake/Bracket",
170                                                         "Continuous / Auto bracket",    FujiTagOffOn },
171 { 0x1300,       EXIF_FORMAT_SHORT_UNSIGNED, 1,  "Fuji.BlurWarning",     "Blue warning", FujiTagNoYes },
172 { 0x1301,       EXIF_FORMAT_SHORT_UNSIGNED, 1,  "Fuji.FocusWarning",    "Focus warning",FujiTagNoYes },
173 { 0x1302,       EXIF_FORMAT_SHORT_UNSIGNED, 1,  "Fuji.AEWarning",       "AE warning",   FujiTagNoYes },
174 EXIF_MARKER_LIST_END
175 };
176
177
178
179 gboolean format_fuji_makernote(ExifData *exif, guchar *tiff, guint offset,
180                                guint size, ExifByteOrder bo)
181 {
182         guchar *data;
183         guint ifdstart;
184
185         if (offset + 8 + 4 >= size) return FALSE;
186
187         data = tiff + offset;
188
189         /* Fuji tag format starts with "FUJIFILM",
190          * followed by 4 bytes indicating offset to IFD directory using Fuji tags,
191          * byte order is always little endian (II).
192          */
193         if (memcmp(data, "FUJIFILM", 8) != 0) return FALSE;
194
195         ifdstart = exif_byte_get_int32(data + 8, EXIF_BYTE_ORDER_INTEL);
196         if (offset + ifdstart >= size) return FALSE;
197
198         if (exif_parse_IFD_table(exif, tiff + offset, ifdstart, size - offset,
199                                  EXIF_BYTE_ORDER_INTEL, 0, FujiExifMarkersList) != 0)
200                 {
201                 return FALSE;
202                 }
203
204         return TRUE;
205 }
206
207 #endif
208 /* not HAVE_EXIV2 */
209 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */