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!
10 * Code to add support for Canon CR2 and CRW files, version 0.2
12 * Developed by Daniel M. German, dmgerman at uvic.ca
14 * you can find the sources for this patch at http://turingmachine.org/~dmg/libdcraw/gqview/
31 #include "format_canon.h"
32 #include "format_raw.h"
42 int canonEnableDebug = 0;
43 /* This should be really a stack, but I am too lazy to implement */
44 #define DEBUG_ENABLE (canonEnableDebug = 0)
45 #define DEBUG_DISABLE (canonEnableDebug = 1)
46 /* It would be nice if these functions indented according to depth in the stack, but I am too lazy to implement */
48 #define DEBUG_ENTRY(a) (canonEnableDebug || fprintf(stderr, "Entering function: %s [%s:%d]\n", a, __FILE__, __LINE__))
49 #define DEBUG_EXIT(a) (canonEnableDebug || fprintf(stderr, "Exiting function: %s [%s:%d]\n", a, __FILE__, __LINE__))
50 #define DEBUG_1(a) (canonEnableDebug || fprintf(stderr, a " [%s:%d]\n", __FILE__, __LINE__))
51 #define DEBUG_2(a,b) (canonEnableDebug || fprintf(stderr, a " [%s:%d]\n",b, __FILE__, __LINE__))
52 #define DEBUG_3(a,b,c) (canonEnableDebug || fprintf(stderr, a " [%s:%d]\n",b, c, __FILE__, __LINE__))
57 #define DEBUG_ENTRY(a)
62 #define DEBUG_3(a,b,c)
69 The problem with gqview is that sometimes the data is to be read from
70 a file, and sometimes it is in memory. This function tries to isolate
71 the rest of the code from having to deal with both cases
73 This function reads a 4 byte unsigned integer, and fixes its endianism.
75 If fd >= 0 then the value is read from the corresponding file descriptor
77 in that case, if offset is > 0, then the value is read from that offset
79 otherwise it is read from the current file pointer
81 if fd < 0 then the value is read from the memory pointed by data + offset
84 offset is a pointer to the actual offset of the file.
86 sizeInt can be 2 or 4 (it is the number of bytes to read)
88 RETURNS true is no error, false if it can't read the value
92 static int canon_read_int(unsigned int *offset, const void *data, int sizeInt, unsigned int *value )
96 DEBUG_ENTRY("canon_read_int");
97 /* Verify values before we do anything */
98 if (sizeInt != 2 && sizeInt != 4) return FALSE;
99 if (offset == NULL) return FALSE;
100 if (*offset <= 0) return FALSE;
101 if (data == NULL) return FALSE;
102 if (value == NULL) return FALSE;
105 *value = GUINT32_FROM_LE(*(guint32*)(data + *offset));
107 DEBUG_3("Read 4 bytes %d %x", *value, *value);
109 *value = GUINT16_FROM_LE(*(guint32*)(data + *offset));
111 DEBUG_3("Read 2 bytes %d %x", *value, *value);
114 DEBUG_EXIT("canon_read_int");
120 #define CANON_HEADER_SIZE 26
124 The CR2 format is really a TIFF format. It is nicely documented in the TIFF V 6.0 document available from adobe.
126 The CR2 file contains two thumbnails, one tiny and one decent sized. The record Id of the latter is 0x0111.
128 The photo info is also available, in EXIF, and it looks like I don't need to do anything! Yeah!
132 static int canon_cr2_process_directory(void *data, int offsetIFD, guint *jpegLocation, guint *exifLocation)
135 int returnValue = FALSE;
137 DEBUG_ENTRY("canon_cr2_process_directory");
139 /* The directory is a link list, after an array of records, the next 4 byptes point to the offset of the next directory.
141 All offsets are absolution within the file (in CRWs the offsets are relative ).
145 while (offsetIFD != 0 && offsetIFD != 0xFFFF) {
148 /* Read directory, we start by reading number of entries in the directory */
151 if (!canon_read_int(&offset, data, 2, &countEntries)) {
154 DEBUG_2("Number of entries: %d\n", countEntries);
156 for (i=0;i<countEntries;i++) {
157 /* read each entry */
165 /* read record type */
166 if (!canon_read_int(&offset, data, 2, &recordId)) {
170 /* Did we find the JPEG */
171 if (recordId == 0x0111) {
172 DEBUG_1("This is the record to find**********************\n");
174 if (!canon_read_int(&offset, data, 4, jpegLocation)) {
177 DEBUG_3("JPEG Location %d 0x%x\n", *jpegLocation, *jpegLocation);
178 /* We don't want to keep reading, because there is another
179 0x0111 record at the end that contains the raw data */
183 /* advance pointer by skipping rest of record */
187 /* The next 4 bytes are the offset of next directory, if zero we are done
190 if (!canon_read_int(&offset, data, 4, &offsetIFD)) {
193 DEBUG_3("Value of NEXT offsetIFD: %d 0x%x\n", offsetIFD, offsetIFD);
197 DEBUG_1("Going to return true");
200 DEBUG_EXIT("canon_cr2_process_directory");
208 static int format_raw_test_canon_cr2(void *data, const guint len,
209 guint *image_offset, guint *exif_offset)
213 unsigned int offset = 4;
216 int returnValue = FALSE;
217 void *jpgInDataOffset;
219 DEBUG_ENTRY("format_raw_test_canon_cr2");
221 /* Verify signature */
222 if (memcmp(data, "\x49\x49\x2a\00", 4) != 0) {
223 DEBUG_1("This is not a CR2");
227 /* Get address of first directory */
228 offsetIFD = GUINT32_FROM_LE(*(guint32*)(data + 4));
231 DEBUG_2("Value of offsetIFD: %d\n", offsetIFD);
233 returnValue = canon_cr2_process_directory(data, offsetIFD, image_offset, exif_offset);
236 jpgInDataOffset = data + *image_offset;
238 /* Make sure we really got a JPEG */
240 if (memcmp(jpgInDataOffset, "\xff\xd8",2) != 0) {
241 /* It is not at the JPEG! */
242 DEBUG_2("THis is not a jpeg after all: there are the first 4 bytes 0x%x ", (int)jpgInDataOffset);
248 DEBUG_EXIT("format_raw_test_canon_cr2");
254 gint format_raw_test_canon(const void *data, const guint len,
255 guint *image_offset, guint *exif_offset)
259 /* There are at least 2 types of Canon raw files. CRW and CR2
261 CRW files have a proprietary format.
269 HEADER_LENGTH 32 bytes
270 int2 byteOrder; Always II (MM Motorola ---big endian, II Intel --little endian)
271 int4 length; Should be 26
272 char identifier[8];type HEAP, subtype heap CCDR
278 int returnValue = FALSE;
279 int heapHeaderOffset = 0;
280 int heapRecordsCount = 0;
286 unsigned int currentOffset;
287 /* File has to be little endian, first two bytes II */
292 if (format_raw_test_canon_cr2((void *)data, len, image_offset, exif_offset)) {
296 if (memcmp("II", data, 2) != 0) {
299 /* NO DEBUG BEFORE THIS POINT, we want to debug only Canon */
301 DEBUG_ENTRY("format_raw_test_canon");
303 DEBUG_2("Length of buffer read %u", len);
305 DEBUG_2("CRW header length Data %d", GUINT32_FROM_LE(*(guint32*)(data + 2)));
307 /* the length has to be CANON_HEADER_SIZE */
308 if (GUINT32_FROM_LE(*(guint32*)(data + 2)) != CANON_HEADER_SIZE) {
309 DEBUG_1("It is not the right size");
313 if (!memcmp("HEAPCCDR", data+6, 8) == 0) {
314 DEBUG_1("This file is not a Canon CRW raw photo");
319 /* Ok, so now we know that this is a CRW file */
321 /* The heap is a strange data structure. It is recursive, so a record
322 can contain a heap itself. That is indeed the case for the photo information
323 reecord. Luckily the first heap contains the jpeg, so we don't need to do
324 any recursive processing.
326 Its "header" is a the end. The header is a sequence of records,
327 and the data of each record is at the beginning of the heap
337 | # records | it should be 3
344 number of records: 2 bytes
345 for each record (10 bytes long)
350 In some records the length and offset are actually data,
351 but none for the ones in the first heap.
353 the offset is with respect to the beginning of the heap, not the
354 beginning of the file. That allows heaps to be "movable"
356 For the purpose of finding the JPEG, all we need is to scan the fist heap,
357 which contains the following record types:
359 0x2005 Record RAW data
360 0x2007 Record JPEG data
361 0x300a Record with photo info
367 DEBUG_2("We have a problem, the length is too small %d ", len);
370 currentOffset = len-4;
373 /* The last 4 bytes have the offset of the header of the heap */
374 if (!canon_read_int(¤tOffset, data, 4, &heapHeaderOffset))
377 /* The heapoffset has to be adjusted to the actual file size, the header is CANON_HEADER_SIZE bytes long */
378 heapHeaderOffset += CANON_HEADER_SIZE;
379 DEBUG_2("heap header Offset %d ", heapHeaderOffset);
381 /* Just check, it does not hurt, we don't want to crash */
382 if (heapHeaderOffset > len)
385 currentOffset = heapHeaderOffset;
386 /* Let us read the number of records in the heap */
387 if (!canon_read_int(¤tOffset, data, 2, &heapRecordsCount))
390 DEBUG_2("heap record count %d ", heapRecordsCount);
392 if (heapRecordsCount != 3) {
393 /* In all the cameras I have seen, this is always 3
394 if not, something is wrong, so just quit */
402 const void *jpgInDataOffset;
403 /* Read each record, to find jpg, it should be second */
405 if (!canon_read_int(¤tOffset, data, 2, &recordType))
408 DEBUG_2("record type 0x%x ", recordType);
410 if (recordType != 0x2007) {
411 /* Go to the next record, don't waste time,
412 but first, eat 8 bytes from header */
414 continue; /* Nah, wrong record, go to next */
416 /* Bingo, we are at the JPEG record */
419 if (!canon_read_int(¤tOffset, data, 4, &recordLength))
422 DEBUG_2("record length %d ", recordLength);
426 if (!canon_read_int(¤tOffset, data, 4, &recordOffset))
429 DEBUG_2("record offset 0x%d ", recordOffset);
431 /* Great, we now know where the JPEG is!
432 it is CANON_HEADER_SIZE (size of CRW header) + recordOffset
435 *image_offset = CANON_HEADER_SIZE + recordOffset;
436 DEBUG_2("image offset %d ", *image_offset);
438 /* keep checking for potential errors */
439 if (*image_offset > len) {
442 /* Get the JPEG is */
444 jpgInDataOffset = data + *image_offset;
446 if (memcmp(jpgInDataOffset, "\xff\xd8\xff\xdb",4) != 0) {
447 /* It is not at the JPEG! */
448 DEBUG_2("THis is not a jpeg after all: there are the first 4 bytes 0x%x ", (int)jpgInDataOffset);
454 /* undo whatever we need in case of an error*/
455 DEBUG_1("We scan all records, but nothing was found!!!!!!!!!!!!!!!!!!");
458 /* At this point we are returning */
461 DEBUG_1("****We got an embedded JPEG for a canon CRW");
465 DEBUG_EXIT("format_raw_test_canon");
476 *-----------------------------------------------------------------------------
477 * EXIF Makernote for Canon
478 *-----------------------------------------------------------------------------
481 typedef struct _CanonTag CanonTag;
484 const gchar *description;
488 static ExifTextList CanonSet1MacroMode[] = {
494 static ExifTextList CanonSet1Quality[] = {
501 static ExifTextList CanonSet1FlashMode[] = {
502 { 0, "flash not fired" },
505 { 3, "red eye reduction" },
506 { 4, "slow synchro" },
507 { 5, "auto with red eye reduction" },
508 { 6, "on with red eye reduction" },
509 { 16, "external flash" },
513 static ExifTextList CanonSet1DriveMode[] = {
514 { 0, "single or timer" },
519 static ExifTextList CanonSet1FocusMode[] = {
530 static ExifTextList CanonSet1ImageSize[] = {
534 /* where (or) does Medium 1/2 fit in here ? */
538 static ExifTextList CanonSet1ShootingMode[] = {
542 { 3, "fast shutter" },
543 { 4, "slow shutter" },
545 { 6, "black and white" },
550 { 11, "panoramic focus" },
554 /* Don't think this is interpreted correctly/completely, A60 at 2.5x Digital sets value of 3 */
555 static ExifTextList CanonSet1DigitalZoom[] = {
562 static ExifTextList CanonSet1ConSatSharp[] = {
569 static ExifTextList CanonSet1ISOSpeed[] = {
570 /* { 0, "not set/see EXIF tag" }, */
579 static ExifTextList CanonSet1MeteringMode[] = {
582 { 5, "center-weighted" },
586 static ExifTextList CanonSet1FocusType[] = {
594 static ExifTextList CanonSet1AutoFocusPoint[] = {
595 { 12288, "manual focus" },
603 static ExifTextList CanonSet1ExposureMode[] = {
606 { 2, "Tv priority" },
607 { 3, "Av priority" },
613 static ExifTextList CanonSet1FlashFired[] = {
619 static ExifTextList CanonSet1FocusCont[] = {
620 { 0, "no (single)" },
625 static ExifMarker CanonSet1[] = {
626 /* 0 is length of array in bytes (2 x array size) */
627 { 1, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.MacroMode", "Macro mode", CanonSet1MacroMode },
628 { 2, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.SelfTimer", "Self timer (10ths of second)", NULL },
629 { 3, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.Quality", "Quality", CanonSet1Quality },
630 { 4, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.FlashMode", "Flash mode", CanonSet1FlashMode },
631 { 5, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.DriveMode", "Drive mode", CanonSet1DriveMode },
632 { 7, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.FocusMode", "Focus mode", CanonSet1FocusMode },
633 { 10, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.ImageSize", "Image size", CanonSet1ImageSize },
634 { 11, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.ShootingMode","Shooting mode", CanonSet1ShootingMode },
635 { 11, EXIF_FORMAT_SHORT_UNSIGNED, 1, "ExposureProgram", "ExposureProgram", CanonSet1ShootingMode },
636 { 12, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.DigitalZoom", "Digital zoom", CanonSet1DigitalZoom },
637 { 13, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.Contrast", "Contrast", CanonSet1ConSatSharp },
638 { 14, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.Saturation", "Saturation", CanonSet1ConSatSharp },
639 { 15, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.Sharpness", "Sharpness", CanonSet1ConSatSharp },
640 { 16, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.ISOSpeed", "ISO speed", CanonSet1ISOSpeed },
641 { 16, EXIF_FORMAT_SHORT_UNSIGNED, 1, "ISOSpeedRatings", "ISO speed", CanonSet1ISOSpeed },
642 { 17, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.MeteringMode","Metering mode", CanonSet1MeteringMode },
643 { 18, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.FocusType", "Focus type", CanonSet1FocusType },
644 { 19, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.AutoFocus", "AutoFocus point", CanonSet1AutoFocusPoint },
645 { 20, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.ExposureMode","Exposure mode", CanonSet1ExposureMode },
646 { 20, EXIF_FORMAT_SHORT_UNSIGNED, 1, "ExposureMode", "Exposure mode", CanonSet1ExposureMode },
647 { 23, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.FocalLengthLong","Long focal length", NULL },
648 { 24, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.FocalLengthShort","Short focal length", NULL },
649 { 25, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.FocalLengthUnits","Focal units per mm", NULL },
650 { 28, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.FlashFired", "Flash fired", CanonSet1FlashFired },
651 { 29, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.FlashDetails","Flash details", NULL },
652 { 32, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.ContinuousFocus","Continuous focus", CanonSet1FocusCont },
656 static ExifTextList CanonSet2WhiteBalance[] = {
661 { 4, "flourescent" },
667 static ExifTextList CanonSet2FlashBias[] = {
688 static ExifMarker CanonSet2[] = {
689 /* 0 is length of array in bytes (2 x array size) */
690 { 7, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.WhiteBalance","White balance", CanonSet2WhiteBalance },
691 { 7, EXIF_FORMAT_SHORT_UNSIGNED, 1, "LightSource", "White balance", CanonSet2WhiteBalance },
692 { 9, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.SequenceNumber","Sequence number", NULL },
693 { 15, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.FlashBias", "Flash bias", CanonSet2FlashBias },
694 /* distance needs more than just this (metric) value */
695 { 19, EXIF_FORMAT_SHORT_UNSIGNED, 1, "MkN.Canon.SubjectDistance", "Subject Distance", NULL },
701 static ExifTextList CanonCustomEnable[] = {
707 static ExifTextList CanonCustomEnableInvert[] = {
713 static ExifTextList CanonCustomExposureLevel[] = {
719 static ExifTextList CanonCustomAVShutterSpeed[] = {
721 { 1, "1/200 (fixed)" },
725 static ExifTextList CanonCustomShutterCurtainSync[] = {
731 static CanonTag CanonCustom[] = {
732 { 1, "Noise reduction", CanonCustomEnable },
733 /* { 2, "Shutter/Auto Exposure Button Function", CanonCustomBTNShutter }, */
734 { 3, "Mirror lockup", CanonCustomEnable },
735 { 4, "Tv/Av and exposure level", CanonCustomExposureLevel },
736 { 5, "AF assist light", CanonCustomEnableInvert },
737 { 6, "Shutter speed in Av mode", CanonCustomAVShutterSpeed },
738 /* { 7, "Auto-Exposure bracketting sequence/auto cancellation", CanonCustom }, */
739 { 8, "Shutter sync", CanonCustomShutterCurtainSync },
740 /* { 9, "AF button function", CanonCustom }, */
741 { 10, "Fill flash auto reduction", CanonCustomEnableInvert },
742 /* { 11, "Menu button function", CanonCustom }, */
743 /* { 12, "Set button function", CanonCustom }, */
744 { 13, "Sensor cleaning", CanonCustomEnable },
750 static ExifMarker CanonExifMarkersList[] = {
751 { 1, EXIF_FORMAT_SHORT_UNSIGNED, -1, "MkN.Canon.Settings1", NULL, NULL },
752 { 4, EXIF_FORMAT_SHORT_UNSIGNED, -1, "MkN.Canon.Settings2", NULL, NULL },
753 { 6, EXIF_FORMAT_STRING, -1, "MkN.Canon.ImageType", "Image type", NULL },
754 { 7, EXIF_FORMAT_STRING, -1, "MkN.Canon.FirmwareVersion", "Firmware version", NULL },
755 { 8, EXIF_FORMAT_LONG_UNSIGNED, 1, "MkN.Canon.ImageNumber", "Image number", NULL },
756 { 9, EXIF_FORMAT_STRING, -1, "MkN.Canon.OwnerName", "Owner name", NULL },
757 { 12, EXIF_FORMAT_LONG_UNSIGNED, -1, "MkN.Canon.SerialNumber", "Camera serial number", NULL },
758 { 15, EXIF_FORMAT_SHORT_UNSIGNED, -1, "MkN.Canon.CustomFunctions", NULL, NULL },
762 static void canon_mknote_parse_settings(ExifData *exif,
763 guint16 *data, guint32 len, int byte_order,
769 while (list[i].tag != 0)
771 if (list[i].tag < len)
775 item = exif_item_new(EXIF_FORMAT_SHORT_UNSIGNED, list[i].tag, 1, &list[i]);
776 exif_item_copy_data(item, &data[list[i].tag], 1, EXIF_FORMAT_SHORT_UNSIGNED, byte_order);
777 exif->items = g_list_prepend(exif->items, item);
785 static void canon_mknote_parse_convert(ExifData *exif)
790 /* seems we need more than only this value for distance */
791 if (exif_get_integer(exif, "MkN.Canon.SubjectDistance", &value))
793 static ExifMarker marker= { 0x9206, EXIF_FORMAT_RATIONAL_UNSIGNED, 1,
794 "SubjectDistance", "Subject distance", NULL };
796 ExifRational *rational;
798 item = exif_item_new(marker.format, marker.tag, 1, &marker);
799 rational = item->data;
800 rational->num = value;
803 exif->items = g_list_prepend(exif->items, item);
806 result = exif_get_item(exif, "MkN.Canon.SerialNumber");
807 if (result && result->format == EXIF_FORMAT_LONG_UNSIGNED && result->data_len == 4)
809 static ExifMarker marker= { 12, EXIF_FORMAT_STRING, -1,
810 "SerialNumber", "Camera serial number", NULL };
816 n = (guint32)result->data;
817 text = g_strdup_printf("%04X%05d", n & 0xffff0000 >> 8, n & 0x0000ffff);
819 item = exif_item_new(marker.format, marker.tag, l, &marker);
820 memcpy(item->data, text, l);
823 exif->items = g_list_prepend(exif->items, item);
828 gint format_exif_makernote_canon_parse(ExifData *exif, unsigned char *tiff, int offset,
829 int size, int byte_order)
835 text = exif_get_data_as_text(exif, "Make");
836 found = (text && strncasecmp(text, "Canon", 5) == 0);
840 exif_parse_IFD_table(exif, tiff, offset, size, byte_order, CanonExifMarkersList) != 0)
845 item = exif_get_item(exif, "MkN.Canon.Settings1");
848 canon_mknote_parse_settings(exif, item->data, item->data_len, byte_order, CanonSet1);
851 item = exif_get_item(exif, "MkN.Canon.Settings2");
854 canon_mknote_parse_settings(exif, item->data, item->data_len, byte_order, CanonSet2);
858 canon_mknote_parse_convert(exif);