Let image loader backend decide how to process image buffer
[geeqie.git] / src / format-fuji.cc
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 #include <config.h>
24
25 #if !HAVE_EXIV2
26
27 #include "format-fuji.h"
28
29 #include <cstdio>
30 #include <cstring>
31 #include <unistd.h>
32
33 #include <glib.h>
34
35 #include "exif.h"
36
37
38 /*
39  *-----------------------------------------------------------------------------
40  * Raw (RAF) embedded jpeg extraction for Fujifilm
41  *-----------------------------------------------------------------------------
42  */
43
44
45 gboolean format_fuji_raw(guchar *data, const guint len,
46                          guint *image_offset, guint *exif_offset)
47 {
48         guint io;
49         guint eo;
50
51         if (len < 128 ||
52             memcmp(data, "FUJIFILM", 8) != 0)
53                 {
54                 return FALSE;
55                 }
56
57         /* offset to jpeg is embedded at bytes 84-87 */
58         io = exif_byte_get_int32(data + 84, EXIF_BYTE_ORDER_MOTOROLA);
59         if (io + 4 > len) return FALSE;
60
61         /* verify jpeg marker */
62         if (memcmp(data + io, "\xff\xd8\xff\xe1", 4) != 0)
63                 {
64                 return FALSE;
65                 }
66
67         /* Exif is stored in the jpeg, so use the same offset */
68         eo=io;
69
70         if (image_offset) *image_offset = io;
71         if (exif_offset) *exif_offset = eo;
72
73         return TRUE;
74 }
75
76
77 /*
78  *-----------------------------------------------------------------------------
79  * EXIF Makernote for Fujifilm
80  *-----------------------------------------------------------------------------
81  */
82
83 static ExifTextList FujiTagSharpness[] = {
84         { 1,    "soft" },
85         { 2,    "soft" },
86         { 3,    "normal" },
87         { 4,    "hard" },
88         { 5,    "hard" },
89         EXIF_TEXT_LIST_END
90 };
91
92 static ExifTextList FujiTagWhiteBalance[]= {
93         { 0,    "auto" },
94         { 256,  "daylight" },
95         { 512,  "cloudy" },
96         { 768,  "daylight color-fluorescence" },
97         { 769,  "daywhite color-fluorescence" },
98         { 770,  "white-fluorescence" },
99         { 1024, "incandescent" },
100         { 3840, "custom" },
101         EXIF_TEXT_LIST_END
102 };
103
104 static ExifTextList FujiTagColorTone[]= {
105         { 0,    "normal" },
106         { 256,  "high" },
107         { 512,  "low" },
108         EXIF_TEXT_LIST_END
109 };
110
111 static ExifTextList FujiTagFlashMode[]= {
112         { 0,    "auto" },
113         { 1,    "on" },
114         { 2,    "off" },
115         { 3,    "red-eye reduction" },
116         EXIF_TEXT_LIST_END
117 };
118
119 static ExifTextList FujiTagOffOn[]= {
120         { 0,    "off" },
121         { 1,    "on" },
122         EXIF_TEXT_LIST_END
123 };
124
125 static ExifTextList FujiTagFocusMode[]= {
126         { 0,    "auto" },
127         { 1,    "manual" },
128         EXIF_TEXT_LIST_END
129 };
130
131 static ExifTextList FujiTagPictureMode[]= {
132         { 0,    "auto" },
133         { 1,    "portrait" },
134         { 2,    "landscape" },
135         { 4,    "sports" },
136         { 5,    "night" },
137         { 6,    "program AE" },
138         { 256,  "aperture priority AE" },
139         { 512,  "shutter priority AE" },
140         { 768,  "manual" },
141         EXIF_TEXT_LIST_END
142 };
143
144 static ExifTextList FujiTagNoYes[]= {
145         { 0,    "no" },
146         { 1,    "yes" },
147         EXIF_TEXT_LIST_END
148 };
149
150
151 static ExifMarker FujiExifMarkersList[] = {
152 { 0x1000,       EXIF_FORMAT_STRING, 8,          "Fuji.Quality",         "Quality",      nullptr },
153 { 0x1001,       EXIF_FORMAT_SHORT_UNSIGNED, 1,  "Fuji.Sharpness",       "Sharpness",    FujiTagSharpness },
154 { 0x1002,       EXIF_FORMAT_SHORT_UNSIGNED, 1,  "Fuji.WhiteBalance",    "White balance",FujiTagWhiteBalance },
155 { 0x1003,       EXIF_FORMAT_SHORT_UNSIGNED, 1,  "Fuji.Color",           "Color",        FujiTagColorTone },
156 { 0x1004,       EXIF_FORMAT_SHORT_UNSIGNED, 1,  "Fuji.Tone",            "Tone",         FujiTagColorTone },
157 { 0x1010,       EXIF_FORMAT_SHORT_UNSIGNED, 1,  "Fuji.FlashMode",       "Flash mode",   FujiTagFlashMode },
158 { 0x1011,       EXIF_FORMAT_RATIONAL, 1,        "Fuji.FlashStrength",   "Flash strength", nullptr },
159 { 0x1020,       EXIF_FORMAT_SHORT_UNSIGNED, 1,  "Fuji.Macro",           "Macro",        FujiTagOffOn },
160 { 0x1021,       EXIF_FORMAT_SHORT_UNSIGNED, 1,  "Fuji.FocusMode",       "Focus mode",   FujiTagFocusMode },
161 { 0x1030,       EXIF_FORMAT_SHORT_UNSIGNED, 1,  "Fuji.SlowSync",        "Slow synchro", FujiTagOffOn },
162 { 0x1031,       EXIF_FORMAT_SHORT_UNSIGNED, 1,  "Fuji.PictureMode",     "Picture mode", FujiTagPictureMode },
163 { 0x1100,       EXIF_FORMAT_SHORT_UNSIGNED, 1,  "Fuji.ContTake/Bracket",
164                                                         "Continuous / Auto bracket",    FujiTagOffOn },
165 { 0x1300,       EXIF_FORMAT_SHORT_UNSIGNED, 1,  "Fuji.BlurWarning",     "Blue warning", FujiTagNoYes },
166 { 0x1301,       EXIF_FORMAT_SHORT_UNSIGNED, 1,  "Fuji.FocusWarning",    "Focus warning",FujiTagNoYes },
167 { 0x1302,       EXIF_FORMAT_SHORT_UNSIGNED, 1,  "Fuji.AEWarning",       "AE warning",   FujiTagNoYes },
168 EXIF_MARKER_LIST_END
169 };
170
171
172
173 gboolean format_fuji_makernote(ExifData *exif, guchar *tiff, guint offset,
174                                guint size, ExifByteOrder)
175 {
176         guchar *data;
177         guint ifdstart;
178
179         if (offset + 8 + 4 >= size) return FALSE;
180
181         data = tiff + offset;
182
183         /* Fuji tag format starts with "FUJIFILM",
184          * followed by 4 bytes indicating offset to IFD directory using Fuji tags,
185          * byte order is always little endian (II).
186          */
187         if (memcmp(data, "FUJIFILM", 8) != 0) return FALSE;
188
189         ifdstart = exif_byte_get_int32(data + 8, EXIF_BYTE_ORDER_INTEL);
190         if (offset + ifdstart >= size) return FALSE;
191
192         if (exif_parse_IFD_table(exif, tiff + offset, ifdstart, size - offset,
193                                  EXIF_BYTE_ORDER_INTEL, 0, FujiExifMarkersList) != 0)
194                 {
195                 return FALSE;
196                 }
197
198         return TRUE;
199 }
200 #else
201 using dummy_variable = int;
202 #endif
203 /* not HAVE_EXIV2 */
204 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */