6eef366653f8e944cc9dae8c046eefa2eaf5aec9
[geeqie.git] / src / format_fuji.c
1 /*
2  *  GQView
3  *  (C) 2005 John Ellis
4  *
5  *  Authors:
6  *    Original version 2005 Lars Ellenberg, base on dcraw by David coffin.
7  *
8  * This software is released under the GNU General Public License (GNU GPL).
9  * Please read the included file COPYING for more information.
10  * This software comes with no warranty of any kind, use at your own risk!
11  */
12
13 #ifdef HAVE_CONFIG_H
14 #  include "config.h"
15 #endif
16
17
18 #include <stdio.h>
19 #include <string.h>
20 #include <unistd.h>
21
22 #include <glib.h>
23
24 #include "intl.h"
25
26 #include "format_fuji.h"
27 #include "format_raw.h"
28
29 #include "exif.h"
30
31
32 /*
33  *-----------------------------------------------------------------------------
34  * Raw (RAF) embedded jpeg extraction for Fujifilm
35  *-----------------------------------------------------------------------------
36  */
37
38
39 gint format_fuji_raw(unsigned char *data, const guint len,
40                      guint *image_offset, guint *exif_offset)
41 {
42         guint io;
43         guint eo;
44
45         if (len < 128 ||
46             memcmp(data, "FUJIFILM", 8) != 0)
47                 {
48                 return FALSE;
49                 }
50
51         io = GUINT32_FROM_BE(*(guint32*)(data + 84));
52         eo = *image_offset + 12;
53
54         /* verify jpeg marker */
55         if (memcmp(data + io, "\xff\xd8\xff\xe1", 4) != 0)
56                 {
57                 return FALSE;
58                 }
59
60         if (image_offset) *image_offset = io;
61         if (exif_offset) *exif_offset = eo;
62
63         printf("raw Fuji format file\n");
64
65         return TRUE;
66 }
67
68
69 /*
70  *-----------------------------------------------------------------------------
71  * EXIF Makernote for Fujifilm
72  *-----------------------------------------------------------------------------
73  */
74
75 static ExifTextList FujiTagSharpness[] = {
76         { 1,    "soft" },
77         { 2,    "soft" },
78         { 3,    "normal" },
79         { 4,    "hard" },
80         { 5,    "hard" },
81         EXIF_TEXT_LIST_END
82 };
83
84 static ExifTextList FujiTagWhiteBalance[]= {
85         { 0,    "auto" },
86         { 256,  "daylight" },
87         { 512,  "cloudy" },
88         { 768,  "daylight color-fluorescence" },
89         { 769,  "daywhite color-fluorescence" },
90         { 770,  "white-fluorescence" },
91         { 1024, "incandescent" },
92         { 3840, "custom" },
93         EXIF_TEXT_LIST_END
94 };
95
96 static ExifTextList FujiTagColorTone[]= {
97         { 0,    "normal" },
98         { 256,  "high" },
99         { 512,  "low" },
100         EXIF_TEXT_LIST_END
101 };
102
103 static ExifTextList FujiTagFlashMode[]= {
104         { 0,    "auto" },
105         { 1,    "on" },
106         { 2,    "off" },
107         { 3,    "red-eye reduction" },
108         EXIF_TEXT_LIST_END
109 };
110
111 static ExifTextList FujiTagOffOn[]= {
112         { 0,    "off" },
113         { 1,    "on" },
114         EXIF_TEXT_LIST_END
115 };
116
117 static ExifTextList FujiTagFocusMode[]= {
118         { 0,    "auto" },
119         { 1,    "manual" },
120         EXIF_TEXT_LIST_END
121 };
122
123 static ExifTextList FujiTagPictureMode[]= {
124         { 0,    "auto" },
125         { 1,    "portrait" },
126         { 2,    "landscape" },
127         { 4,    "sports" },
128         { 5,    "night" },
129         { 6,    "program AE" },
130         { 256,  "aperture priority AE" },
131         { 512,  "shutter priority AE" },
132         { 768,  "manual" },
133         EXIF_TEXT_LIST_END
134 };
135
136 static ExifTextList FujiTagNoYes[]= {
137         { 0,    "no" },
138         { 1,    "yes" },
139         EXIF_TEXT_LIST_END
140 };
141
142 #if 0
143 static ExifTextList FujiTag[]= {
144         { ,     "" },
145         { ,     "" },
146         EXIF_TEXT_LIST_END
147 };
148 #endif
149
150
151 static ExifMarker FujiExifMarkersList[] = {
152 { 0x1000,       EXIF_FORMAT_STRING, 8,          "Fuji.Quality",         "Quality",      NULL },
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", NULL },
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 gint format_fuji_makernote(ExifData *exif, unsigned char *tiff, guint offset,
174                            guint size, ExifByteOrder bo)
175 {
176         unsigned char *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