comparison src/format_canon.c @ 45:7cfa60beda76

Thu May 26 13:57:19 2005 John Ellis <johne@verizon.net> * format_raw.[ch]: Move camera specific code to manufacturer specific format_*.c files. Change code so that file descripter version is now a separate functions that wraps the standard parser by using mmap. * format_canon.[ch]: Moved Canon specific raw support here, removed file descriptor versions of parser. This Canon raw file parser written by Daniel M. German. * format_fuji.[ch]: Move Fuji specific raw support here, parser written by Lars Ellenberg. * exif.c: Update for change to format_raw_img_exif_offsets. * filelist.c: Add cr2 extension to Canon raw format list. * image-load.c: Fixes for changes to format_raw_img_exif_offset_fd so that buffer is refilled using new offset of file descriptor. * src/Makefile.am: Add format_canon.[ch], format_fuji.[ch] to build. ##### Note: GQview CVS on sourceforge is not always up to date, please use ##### ##### an offical release when making enhancements and translation updates. #####
author gqview
date Thu, 26 May 2005 18:10:52 +0000
parents
children aa4c0e1b54b0
comparison
equal deleted inserted replaced
44:458e396d3f35 45:7cfa60beda76
1 /*
2 * GQView
3 * (C) 2005 John Ellis
4 *
5 * This software is released under the GNU General Public License (GNU GPL).
6 * Please read the included file COPYING for more information.
7 * This software comes with no warranty of any kind, use at your own risk!
8 *
9 *
10 * Code to add support for Canon CR2 and CRW files, version 0.2
11 *
12 * Developed by Daniel M. German, dmgerman at uvic.ca
13 *
14 * you can find the sources for this patch at http://turingmachine.org/~dmg/libdcraw/gqview/
15 *
16 */
17
18 #ifdef HAVE_CONFIG_H
19 # include "config.h"
20 #endif
21
22
23 #include <stdio.h>
24 #include <string.h>
25 #include <unistd.h>
26
27 #include <glib.h>
28
29 #include "intl.h"
30
31 #include "format_canon.h"
32 #include "format_raw.h"
33
34
35 #if 0
36 #define CANON_DEBUG
37 #endif
38
39 #ifdef CANON_DEBUG
40 int canonEnableDebug = 0;
41 /* This should be really a stack, but I am too lazy to implement */
42 #define DEBUG_ENABLE (canonEnableDebug = 0)
43 #define DEBUG_DISABLE (canonEnableDebug = 1)
44 /* It would be nice if these functions indented according to depth in the stack, but I am too lazy to implement */
45
46 #define DEBUG_ENTRY(a) (canonEnableDebug || fprintf(stderr, "Entering function: %s [%s:%d]\n", a, __FILE__, __LINE__))
47 #define DEBUG_EXIT(a) (canonEnableDebug || fprintf(stderr, "Exiting function: %s [%s:%d]\n", a, __FILE__, __LINE__))
48 #define DEBUG_1(a) (canonEnableDebug || fprintf(stderr, a " [%s:%d]\n", __FILE__, __LINE__))
49 #define DEBUG_2(a,b) (canonEnableDebug || fprintf(stderr, a " [%s:%d]\n",b, __FILE__, __LINE__))
50 #define DEBUG_3(a,b,c) (canonEnableDebug || fprintf(stderr, a " [%s:%d]\n",b, c, __FILE__, __LINE__))
51
52 #else
53 #define DEBUG_ENABLE
54 #define DEBUG_DISABLE
55 #define DEBUG_ENTRY(a)
56 #define DEBUG_EXIT(a)
57
58 #define DEBUG_1(a)
59 #define DEBUG_2(a,b)
60 #define DEBUG_3(a,b,c)
61 #endif
62
63
64 /* canon_read_int4
65
66
67 The problem with gqview is that sometimes the data is to be read from
68 a file, and sometimes it is in memory. This function tries to isolate
69 the rest of the code from having to deal with both cases
70
71 This function reads a 4 byte unsigned integer, and fixes its endianism.
72
73 If fd >= 0 then the value is read from the corresponding file descriptor
74
75 in that case, if offset is > 0, then the value is read from that offset
76
77 otherwise it is read from the current file pointer
78
79 if fd < 0 then the value is read from the memory pointed by data + offset
80
81
82 offset is a pointer to the actual offset of the file.
83
84 sizeInt can be 2 or 4 (it is the number of bytes to read)
85
86 RETURNS true is no error, false if it can't read the value
87
88
89 */
90 static int canon_read_int(unsigned int *offset, const void *data, int sizeInt, unsigned int *value )
91 {
92 DEBUG_DISABLE;
93
94 DEBUG_ENTRY("canon_read_int");
95 /* Verify values before we do anything */
96 if (sizeInt != 2 && sizeInt != 4) return FALSE;
97 if (offset == NULL) return FALSE;
98 if (*offset <= 0) return FALSE;
99 if (data == NULL) return FALSE;
100 if (value == NULL) return FALSE;
101
102 if (sizeInt == 4) {
103 *value = GUINT32_FROM_LE(*(guint32*)(data + *offset));
104 *offset +=4;
105 DEBUG_3("Read 4 bytes %d %x", *value, *value);
106 } else {
107 *value = GUINT16_FROM_LE(*(guint32*)(data + *offset));
108 *offset +=2;
109 DEBUG_3("Read 2 bytes %d %x", *value, *value);
110 }
111
112 DEBUG_EXIT("canon_read_int");
113
114 DEBUG_ENABLE;
115 return TRUE;
116 }
117
118 #define CANON_HEADER_SIZE 26
119
120 /*
121
122 The CR2 format is really a TIFF format. It is nicely documented in the TIFF V 6.0 document available from adobe.
123
124 The CR2 file contains two thumbnails, one tiny and one decent sized. The record Id of the latter is 0x0111.
125
126 The photo info is also available, in EXIF, and it looks like I don't need to do anything! Yeah!
127
128 */
129
130 static int canon_cr2_process_directory(void *data, int offsetIFD, guint *jpegLocation, guint *exifLocation)
131 {
132 unsigned int offset;
133 int returnValue = FALSE;
134
135 DEBUG_ENTRY("canon_cr2_process_directory");
136
137 /* The directory is a link list, after an array of records, the next 4 byptes point to the offset of the next directory.
138
139 All offsets are absolution within the file (in CRWs the offsets are relative ).
140
141 */
142
143 while (offsetIFD != 0 && offsetIFD != 0xFFFF) {
144 int countEntries=0;
145 int i;
146 /* Read directory, we start by reading number of entries in the directory */
147
148 offset = offsetIFD;
149 if (!canon_read_int(&offset, data, 2, &countEntries)) {
150 goto return_only;
151 }
152 DEBUG_2("Number of entries: %d\n", countEntries);
153
154 for (i=0;i<countEntries;i++) {
155 /* read each entry */
156
157 int recordId;
158 #if 0
159 int format;
160 int size;
161 #endif
162
163 /* read record type */
164 if (!canon_read_int(&offset, data, 2, &recordId)) {
165 goto return_only;
166 }
167
168 /* Did we find the JPEG */
169 if (recordId == 0x0111) {
170 DEBUG_1("This is the record to find**********************\n");
171 offset +=6;
172 if (!canon_read_int(&offset, data, 4, jpegLocation)) {
173 goto return_only;
174 }
175 DEBUG_3("JPEG Location %d 0x%x\n", *jpegLocation, *jpegLocation);
176 /* We don't want to keep reading, because there is another
177 0x0111 record at the end that contains the raw data */
178 returnValue = TRUE;
179 goto return_only;
180 } else {
181 /* advance pointer by skipping rest of record */
182 offset += 10;
183 }
184 }
185 /* The next 4 bytes are the offset of next directory, if zero we are done
186
187 */
188 if (!canon_read_int(&offset, data, 4, &offsetIFD)) {
189 goto return_only;
190 }
191 DEBUG_3("Value of NEXT offsetIFD: %d 0x%x\n", offsetIFD, offsetIFD);
192 }
193
194 returnValue = TRUE;
195 DEBUG_1("Going to return true");
196
197 return_only:
198 DEBUG_EXIT("canon_cr2_process_directory");
199
200 return TRUE;
201
202
203 }
204
205
206 static int format_raw_test_canon_cr2(void *data, const guint len,
207 guint *image_offset, guint *exif_offset)
208 {
209 #if 0
210 char signature[4];
211 unsigned int offset = 4;
212 #endif
213 int offsetIFD;
214 int returnValue = FALSE;
215 void *jpgInDataOffset;
216
217 DEBUG_ENTRY("format_raw_test_canon_cr2");
218
219 /* Verify signature */
220 if (memcmp(data, "\x49\x49\x2a\00", 4) != 0) {
221 DEBUG_1("This is not a CR2");
222 goto return_only;
223 }
224
225 /* Get address of first directory */
226 offsetIFD = GUINT32_FROM_LE(*(guint32*)(data + 4));
227
228
229 DEBUG_2("Value of offsetIFD: %d\n", offsetIFD);
230
231 returnValue = canon_cr2_process_directory(data, offsetIFD, image_offset, exif_offset);
232
233 if (returnValue) {
234 jpgInDataOffset = data + *image_offset;
235
236 /* Make sure we really got a JPEG */
237
238 if (memcmp(jpgInDataOffset, "\xff\xd8",2) != 0) {
239 /* It is not at the JPEG! */
240 DEBUG_2("THis is not a jpeg after all: there are the first 4 bytes 0x%x ", (int)jpgInDataOffset);
241 returnValue = FALSE;
242 }
243 }
244
245 return_only:
246 DEBUG_EXIT("format_raw_test_canon_cr2");
247
248 return returnValue;
249 }
250
251
252 gint format_raw_test_canon(const void *data, const guint len,
253 guint *image_offset, guint *exif_offset)
254 {
255
256
257 /* There are at least 2 types of Canon raw files. CRW and CR2
258
259 CRW files have a proprietary format.
260
261 HEADER
262 Heap
263 RAW data
264 JPEG data
265 PHoto data
266
267 HEADER_LENGTH 32 bytes
268 int2 byteOrder; Always II (MM Motorola ---big endian, II Intel --little endian)
269 int4 length; Should be 26
270 char identifier[8];type HEAP, subtype heap CCDR
271 int2 version;
272 int2 subversion;
273 char unused[14];
274 */
275
276 int returnValue = FALSE;
277 int heapHeaderOffset = 0;
278 int heapRecordsCount = 0;
279 #if 0
280 guint32 rawInt4;
281 guint16 rawInt2;
282 #endif
283 int i;
284 unsigned int currentOffset;
285 /* File has to be little endian, first two bytes II */
286
287 if (len < 100)
288 return FALSE;
289
290 if (format_raw_test_canon_cr2((void *)data, len, image_offset, exif_offset)) {
291 return TRUE;
292 }
293
294 if (memcmp("II", data, 2) != 0) {
295 return FALSE;
296 }
297 /* NO DEBUG BEFORE THIS POINT, we want to debug only Canon */
298
299 DEBUG_ENTRY("format_raw_test_canon");
300
301 DEBUG_2("Length of buffer read %u", len);
302
303 DEBUG_2("CRW header length Data %d", GUINT32_FROM_LE(*(guint32*)(data + 2)));
304
305 /* the length has to be CANON_HEADER_SIZE */
306 if (GUINT32_FROM_LE(*(guint32*)(data + 2)) != CANON_HEADER_SIZE) {
307 DEBUG_1("It is not the right size");
308 goto return_only;
309 }
310
311 if (!memcmp("HEAPCCDR", data+6, 8) == 0) {
312 DEBUG_1("This file is not a Canon CRW raw photo");
313 goto return_only;
314
315 }
316
317 /* Ok, so now we know that this is a CRW file */
318
319 /* The heap is a strange data structure. It is recursive, so a record
320 can contain a heap itself. That is indeed the case for the photo information
321 reecord. Luckily the first heap contains the jpeg, so we don't need to do
322 any recursive processing.
323
324 Its "header" is a the end. The header is a sequence of records,
325 and the data of each record is at the beginning of the heap
326
327 +-----------------+
328 | data raw |
329 +-----------------+
330 | data jpeg |
331 +-----------------+
332 | data photo info |
333 +-----------------+
334 |header of heap |
335 | # records | it should be 3
336 | raw info |
337 | jpeg info |
338 | photo info |
339 +-----------------+
340
341 The header contains
342 number of records: 2 bytes
343 for each record (10 bytes long)
344 type: 2 bytes
345 length: 4 bytes
346 offset: 4 bytes
347
348 In some records the length and offset are actually data,
349 but none for the ones in the first heap.
350
351 the offset is with respect to the beginning of the heap, not the
352 beginning of the file. That allows heaps to be "movable"
353
354 For the purpose of finding the JPEG, all we need is to scan the fist heap,
355 which contains the following record types:
356
357 0x2005 Record RAW data
358 0x2007 Record JPEG data
359 0x300a Record with photo info
360
361 */
362
363
364 if (len < 0x10000) {
365 DEBUG_2("We have a problem, the length is too small %d ", len);
366 goto return_only;
367 }
368 currentOffset = len-4;
369
370
371 /* The last 4 bytes have the offset of the header of the heap */
372 if (!canon_read_int(&currentOffset, data, 4, &heapHeaderOffset))
373 goto return_only;
374
375 /* The heapoffset has to be adjusted to the actual file size, the header is CANON_HEADER_SIZE bytes long */
376 heapHeaderOffset += CANON_HEADER_SIZE;
377 DEBUG_2("heap header Offset %d ", heapHeaderOffset);
378
379 /* Just check, it does not hurt, we don't want to crash */
380 if (heapHeaderOffset > len)
381 goto return_only;
382
383 currentOffset = heapHeaderOffset;
384 /* Let us read the number of records in the heap */
385 if (!canon_read_int(&currentOffset, data, 2, &heapRecordsCount))
386 goto return_only;
387
388 DEBUG_2("heap record count %d ", heapRecordsCount);
389
390 if (heapRecordsCount != 3) {
391 /* In all the cameras I have seen, this is always 3
392 if not, something is wrong, so just quit */
393 goto return_only;
394 }
395
396 for (i=0;i<3;i++) {
397 int recordType;
398 int recordOffset;
399 int recordLength;
400 const void *jpgInDataOffset;
401 /* Read each record, to find jpg, it should be second */
402
403 if (!canon_read_int(&currentOffset, data, 2, &recordType))
404 goto return_only;
405
406 DEBUG_2("record type 0x%x ", recordType);
407
408 if (recordType != 0x2007) {
409 /* Go to the next record, don't waste time,
410 but first, eat 8 bytes from header */
411 currentOffset += 8;
412 continue; /* Nah, wrong record, go to next */
413 }
414 /* Bingo, we are at the JPEG record */
415
416 /* Read length */
417 if (!canon_read_int(&currentOffset, data, 4, &recordLength))
418 goto return_only;
419
420 DEBUG_2("record length %d ", recordLength);
421
422 /* Read offset */
423
424 if (!canon_read_int(&currentOffset, data, 4, &recordOffset))
425 goto return_only;
426
427 DEBUG_2("record offset 0x%d ", recordOffset);
428
429 /* Great, we now know where the JPEG is!
430 it is CANON_HEADER_SIZE (size of CRW header) + recordOffset
431 */
432
433 *image_offset = CANON_HEADER_SIZE + recordOffset;
434 DEBUG_2("image offset %d ", *image_offset);
435
436 /* keep checking for potential errors */
437 if (*image_offset > len) {
438 goto return_only;
439 }
440 /* Get the JPEG is */
441
442 jpgInDataOffset = data + *image_offset;
443
444 if (memcmp(jpgInDataOffset, "\xff\xd8\xff\xdb",4) != 0) {
445 /* It is not at the JPEG! */
446 DEBUG_2("THis is not a jpeg after all: there are the first 4 bytes 0x%x ", (int)jpgInDataOffset);
447 goto return_only;
448 }
449 returnValue = TRUE;
450 goto return_only;
451 }
452 /* undo whatever we need in case of an error*/
453 DEBUG_1("We scan all records, but nothing was found!!!!!!!!!!!!!!!!!!");
454
455
456 /* At this point we are returning */
457 return_only:
458 if (returnValue) {
459 DEBUG_1("****We got an embedded JPEG for a canon CRW");
460
461 }
462
463 DEBUG_EXIT("format_raw_test_canon");
464 return returnValue;
465
466 #undef DEBUG_2
467 #undef DEBUG
468 #undef DEBUG_ENTRY
469 #undef DEBUG_EXIT
470
471 }
472
473