You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1008 lines
43 KiB
C++

// ***************************************************************** -*- C++ -*-
/*
* Copyright (C) 2004, 2005, 2006 Andreas Huggel <ahuggel@gmx.net>
*
* This program is part of the Exiv2 distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA.
*/
/*
File : canonmn.cpp
Version: $Rev$
Authors: Andreas Huggel (ahu) <ahuggel@gmx.net>
David Cannings (dc) <david@edeca.net>
Credits: EXIF MakerNote of Canon by David Burren <http://www.burren.cx/david/canon.html>
Canon makernote tags by Phil Harvey <http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Canon.html>
*/
// *****************************************************************************
#include "rcsid.hpp"
EXIV2_RCSID("@(#) $Id$")
// *****************************************************************************
// included header files
#include "types.hpp"
#include "canonmn.hpp"
#include "makernote.hpp"
#include "value.hpp"
#include "ifd.hpp"
// + standard includes
#include <string>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <cassert>
#include <cstring>
#include <cmath>
// *****************************************************************************
// class member definitions
namespace Exiv2 {
//! @cond IGNORE
CanonMakerNote::RegisterMn::RegisterMn()
{
MakerNoteFactory::registerMakerNote("Canon", "*", createCanonMakerNote);
MakerNoteFactory::registerMakerNote(
canonIfdId, MakerNote::AutoPtr(new CanonMakerNote));
MakerNoteFactory::registerMakerNote(
canonCsIfdId, MakerNote::AutoPtr(new CanonMakerNote));
MakerNoteFactory::registerMakerNote(
canonSiIfdId, MakerNote::AutoPtr(new CanonMakerNote));
MakerNoteFactory::registerMakerNote(
canonPaIfdId, MakerNote::AutoPtr(new CanonMakerNote));
MakerNoteFactory::registerMakerNote(
canonCfIfdId, MakerNote::AutoPtr(new CanonMakerNote));
MakerNoteFactory::registerMakerNote(
canonPiIfdId, MakerNote::AutoPtr(new CanonMakerNote));
ExifTags::registerMakerTagInfo(canonIfdId, tagInfo_);
ExifTags::registerMakerTagInfo(canonCsIfdId, tagInfoCs_);
ExifTags::registerMakerTagInfo(canonSiIfdId, tagInfoSi_);
ExifTags::registerMakerTagInfo(canonPaIfdId, tagInfoPa_);
ExifTags::registerMakerTagInfo(canonCfIfdId, tagInfoCf_);
ExifTags::registerMakerTagInfo(canonPiIfdId, tagInfoPi_);
}
//! @endcond
// Canon MakerNote Tag Info
const TagInfo CanonMakerNote::tagInfo_[] = {
TagInfo(0x0000, "0x0000", "0x0000", "Unknown", canonIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0001, "CameraSettings", "CameraSettings", "Various camera settings", canonIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0002, "0x0002", "0x0002", "Unknown", canonIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0003, "0x0003", "0x0003", "Unknown", canonIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0004, "ShotInfo", "ShotInfo", "Shot information", canonIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0005, "Panorama", "Panorama", "Panorama", canonIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0006, "ImageType", "ImageType", "Image type", canonIfdId, makerTags, asciiString, printValue),
TagInfo(0x0007, "FirmwareVersion", "Firmware Version", "Firmware version", canonIfdId, makerTags, asciiString, printValue),
TagInfo(0x0008, "ImageNumber", "ImageNumber", "Image number", canonIfdId, makerTags, unsignedLong, print0x0008),
TagInfo(0x0009, "OwnerName", "OwnerName", "Owner Name", canonIfdId, makerTags, asciiString, printValue),
TagInfo(0x000c, "SerialNumber", "SerialNumber", "Camera serial number", canonIfdId, makerTags, unsignedLong, print0x000c),
TagInfo(0x000d, "0x000d", "0x000d", "Unknown", canonIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x000f, "CustomFunctions", "CustomFunctions", "Custom Functions", canonIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0012, "PictureInfo", "PictureInfo", "Picture info", canonIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x00a9, "WhiteBalanceTable", "WhiteBalanceTable", "White balance table", canonIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x00b5, "0x00b5", "0x00b5", "Unknown", canonIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x00c0, "0x00c0", "0x00c0", "Unknown", canonIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x00c1, "0x00c1", "0x00c1", "Unknown", canonIfdId, makerTags, unsignedShort, printValue),
// End of list marker
TagInfo(0xffff, "(UnknownCanonMakerNoteTag)", "(UnknownCanonMakerNoteTag)", "Unknown CanonMakerNote tag", canonIfdId, makerTags, invalidTypeId, printValue)
};
const TagInfo* CanonMakerNote::tagList()
{
return tagInfo_;
}
//! Macro, tag 0x0001
extern const TagDetails canonCsMacro[] = {
{ 1, "On" },
{ 2, "Off" }
};
//! Quality, tag 0x0003
extern const TagDetails canonCsQuality[] = {
{ 1, "Economy" },
{ 2, "Normal" },
{ 3, "Fine" },
{ 4, "RAW" },
{ 5, "Superfine" }
};
//! FlashMode, tag 0x0004
extern const TagDetails canonCsFlashMode[] = {
{ 0, "Off" },
{ 1, "Auto" },
{ 2, "On" },
{ 3, "Red-eye" },
{ 4, "Slow sync" },
{ 5, "Auto + red-eye" },
{ 6, "On + red-eye" },
{ 16, "External" }
};
//! DriveMode, tag 0x0005
extern const TagDetails canonCsDriveMode[] = {
{ 0, "Single / timer" },
{ 1, "Continuous" },
{ 2, "Movie" },
{ 3, "Continuous, speed priority" },
{ 4, "Continuous, low" },
{ 5, "Continuous, high" }
};
//! FocusMode, tag 0x0007
extern const TagDetails canonCsFocusMode[] = {
{ 0, "One shot AF" },
{ 1, "AI servo AF" },
{ 2, "AI focus AF" },
{ 3, "Manual focus" },
{ 4, "Single" },
{ 5, "Continuous" },
{ 6, "Manual focus" },
{ 16, "Pan focus" }
};
//! ImageSize, tag 0x000a
extern const TagDetails canonCsImageSize[] = {
{ 0, "Large" },
{ 1, "Medium" },
{ 2, "Small" },
{ 5, "Medium 1" },
{ 6, "Medium 2" },
{ 7, "Medium 3" }
};
//! EasyMode, tag 0x000b
extern const TagDetails canonCsEasyMode[] = {
{ 0, "Full auto" },
{ 1, "Manual" },
{ 2, "Landscape" },
{ 3, "Fast shutter" },
{ 4, "Slow shutter" },
{ 5, "Night Scene" },
{ 6, "Gray scale" },
{ 7, "Sepia" },
{ 8, "Portrait" },
{ 9, "Sports" },
{ 10, "Macro / close-up" },
{ 11, "Black & white" },
{ 12, "Pan focus" },
{ 13, "Vivid" },
{ 14, "Neutral" },
{ 15, "Flash off" },
{ 16, "Long shutter" },
{ 17, "Super macro" },
{ 18, "Foliage" },
{ 19, "Indoor" },
{ 20, "Fireworks" },
{ 21, "Beach" },
{ 22, "Underwater" },
{ 23, "Snow" },
{ 24, "Kids & pets" },
{ 25, "Night SnapShot" },
{ 26, "Digital macro" },
{ 27, "My Colors" },
{ 28, "Still image" }
};
//! DigitalZoom, tag 0x000c
extern const TagDetails canonCsDigitalZoom[] = {
{ 0, "None" },
{ 1, "2x" },
{ 2, "4x" },
{ 3, "Other" }
};
//! Contrast, Saturation Sharpness, tags 0x000d, 0x000e, 0x000f
extern const TagDetails canonCsLnh[] = {
{ 0xffff, "Low" },
{ 0x0000, "Normal" },
{ 0x0001, "High" }
};
//! ISOSpeeds, tag 0x0010
extern const TagDetails canonCsISOSpeed[] = {
{ 0, "n/a" },
{ 15, "Auto" },
{ 16, "50" },
{ 17, "100" },
{ 18, "200" },
{ 19, "400" },
{ 20, "800" }
};
//! MeteringMode, tag 0x0011
extern const TagDetails canonCsMeteringMode[] = {
{ 0, "Default" },
{ 1, "Spot" },
{ 2, "Average" },
{ 3, "Evaluative" },
{ 4, "Partial" },
{ 5, "Center weighted" }
};
//! FocusType, tag 0x0012
extern const TagDetails canonCsFocusType[] = {
{ 0, "Manual" },
{ 1, "Auto" },
{ 2, "Not known" },
{ 3, "Macro" },
{ 4, "Very close" },
{ 5, "Close" },
{ 6, "Middle range" },
{ 7, "Far range" },
{ 8, "Pan focus" },
{ 9, "Super macro" },
{ 10, "Infinity" }
};
//! AFPoint, tag 0x0013
extern const TagDetails canonCsAfPoint[] = {
{ 0x2005, "Manual AF point selection" },
{ 0x3000, "None (MF)" },
{ 0x3001, "Auto-selected" },
{ 0x3002, "Right" },
{ 0x3003, "Center" },
{ 0x3004, "Left" },
{ 0x4001, "Auto AF point selection" }
};
//! ExposureProgram, tag 0x0014
extern const TagDetails canonCsExposureProgram[] = {
{ 0, "Easy shooting (Auto)" },
{ 1, "Program (P)" },
{ 2, "Shutter priority (Tv)" },
{ 3, "Aperture priority (Av)" },
{ 4, "Manual (M)" },
{ 5, "A-DEP" },
{ 6, "M-DEP" }
};
//! FlashActivity, tag 0x001c
extern const TagDetails canonCsFlashActivity[] = {
{ 0, "Did not fire" },
{ 1, "Fired" }
};
//! FlashDetails, tag 0x001d
extern const TagDetailsBitmask canonCsFlashDetails[] = {
{ 0x4000, "External flash" },
{ 0x2000, "Internal flash" },
{ 0x0001, "Manual" },
{ 0x0002, "TTL" },
{ 0x0004, "A-TTL" },
{ 0x0008, "E-TTL" },
{ 0x0010, "FP sync enabled" },
{ 0x0080, "2nd-curtain sync used" },
{ 0x0800, "FP sync used" }
};
//! FocusContinuous, tag 0x0020
extern const TagDetails canonCsFocusContinuous[] = {
{ 0, "Single" },
{ 1, "Continuous" }
};
//! AESetting, tag 0x0021
extern const TagDetails canonCsAESetting[] = {
{ 0, "Normal AE" },
{ 1, "Exposure compensation" },
{ 2, "AE lock" },
{ 3, "AE lock + exposure compensation" },
{ 4, "No AE" }
};
//! ImageStabilization, tag 0x0022
extern const TagDetails canonCsImageStabilization[] = {
{ 0, "Off" },
{ 1, "On" },
{ 2, "On, shot only" }
};
//! PhotoEffect, tag 0x0028
extern const TagDetails canonCsPhotoEffect[] = {
{ 0, "Off" },
{ 1, "Vivid" },
{ 2, "Neutral" },
{ 3, "Smooth" },
{ 4, "Sepia" },
{ 5, "B&W" },
{ 6, "Custom" },
{ 100, "My color data" }
};
// Canon Camera Settings Tag Info
const TagInfo CanonMakerNote::tagInfoCs_[] = {
TagInfo(0x0001, "Macro", "Macro", "Macro mode", canonCsIfdId, makerTags, unsignedShort, EXV_PRINT_TAG(canonCsMacro)),
TagInfo(0x0002, "Selftimer", "Selftimer", "Self timer", canonCsIfdId, makerTags, unsignedShort, printCs0x0002),
TagInfo(0x0003, "Quality", "Quality", "Quality", canonCsIfdId, makerTags, unsignedShort, EXV_PRINT_TAG(canonCsQuality)),
TagInfo(0x0004, "FlashMode", "Flash Mode", "Flash mode setting", canonCsIfdId, makerTags, unsignedShort, EXV_PRINT_TAG(canonCsFlashMode)),
TagInfo(0x0005, "DriveMode", "Drive Mode", "Drive mode setting", canonCsIfdId, makerTags, unsignedShort, EXV_PRINT_TAG(canonCsDriveMode)),
TagInfo(0x0006, "0x0006", "0x0006", "Unknown", canonCsIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0007, "FocusMode", "Focus Mode", "Focus mode setting", canonCsIfdId, makerTags, unsignedShort, EXV_PRINT_TAG(canonCsFocusMode)),
TagInfo(0x0008, "0x0008", "0x0008", "Unknown", canonCsIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0009, "0x0009", "0x0009", "Unknown", canonCsIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x000a, "ImageSize", "Image Size", "Image size", canonCsIfdId, makerTags, unsignedShort, EXV_PRINT_TAG(canonCsImageSize)),
TagInfo(0x000b, "EasyMode", "Easy Mode", "Easy shooting mode", canonCsIfdId, makerTags, unsignedShort, EXV_PRINT_TAG(canonCsEasyMode)),
TagInfo(0x000c, "DigitalZoom", "Digital Zoom", "Digital zoom", canonCsIfdId, makerTags, unsignedShort, EXV_PRINT_TAG(canonCsDigitalZoom)),
TagInfo(0x000d, "Contrast", "Contrast", "Contrast setting", canonCsIfdId, makerTags, unsignedShort, EXV_PRINT_TAG(canonCsLnh)),
TagInfo(0x000e, "Saturation", "Saturation", "Saturation setting", canonCsIfdId, makerTags, unsignedShort, EXV_PRINT_TAG(canonCsLnh)),
TagInfo(0x000f, "Sharpness", "Sharpness", "Sharpness setting", canonCsIfdId, makerTags, unsignedShort, EXV_PRINT_TAG(canonCsLnh)),
TagInfo(0x0010, "ISOSpeed", "ISO Speed Mode", "ISO speed setting", canonCsIfdId, makerTags, unsignedShort, EXV_PRINT_TAG(canonCsISOSpeed)),
TagInfo(0x0011, "MeteringMode", "Metering Mode", "Metering mode setting", canonCsIfdId, makerTags, unsignedShort, EXV_PRINT_TAG(canonCsMeteringMode)),
TagInfo(0x0012, "FocusType", "Focus Type", "Focus type setting", canonCsIfdId, makerTags, unsignedShort, EXV_PRINT_TAG(canonCsFocusType)),
TagInfo(0x0013, "AFPoint", "AFPoint", "AF point selected", canonCsIfdId, makerTags, unsignedShort, EXV_PRINT_TAG(canonCsAfPoint)),
TagInfo(0x0014, "ExposureProgram", "Exposure Program", "Exposure mode setting", canonCsIfdId, makerTags, unsignedShort, EXV_PRINT_TAG(canonCsExposureProgram)),
TagInfo(0x0015, "0x0015", "0x0015", "Unknown", canonCsIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0016, "0x0016", "0x0016", "Unknown", canonCsIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0017, "Lens", "Lens", "'long' and 'short' focal length of lens (in 'focal units') and 'focal units' per mm", canonCsIfdId, makerTags, unsignedShort, printCsLens),
TagInfo(0x0018, "0x0018", "0x0018", "Unknown", canonCsIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0019, "0x0019", "0x0019", "Unknown", canonCsIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x001a, "0x001a", "0x001a", "Unknown", canonCsIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x001b, "0x001b", "0x001b", "Unknown", canonCsIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x001c, "FlashActivity", "FlashActivity", "Flash activity", canonCsIfdId, makerTags, unsignedShort, EXV_PRINT_TAG(canonCsFlashActivity)),
TagInfo(0x001d, "FlashDetails", "FlashDetails", "Flash details", canonCsIfdId, makerTags, unsignedShort, EXV_PRINT_TAG_BITMASK(canonCsFlashDetails)),
TagInfo(0x001e, "0x001e", "0x001e", "Unknown", canonCsIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x001f, "0x001f", "0x001f", "Unknown", canonCsIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0020, "FocusContinuous", "Focus Continuous", "Focus continuous setting", canonCsIfdId, makerTags, unsignedShort, EXV_PRINT_TAG(canonCsFocusContinuous)),
TagInfo(0x0021, "AESetting", "AESetting", "AE setting", canonCsIfdId, makerTags, unsignedShort, EXV_PRINT_TAG(canonCsAESetting)),
TagInfo(0x0022, "ImageStabilization", "ImageStabilization", "Image stabilization", canonCsIfdId, makerTags, unsignedShort, EXV_PRINT_TAG(canonCsImageStabilization)),
TagInfo(0x0023, "DisplayAperture", "DisplayAperture", "Display aperture", canonCsIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0024, "ZoomSourceWidth", "ZoomSourceWidth", "Zoom source width", canonCsIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0025, "ZoomTargetWidth", "ZoomTargetWidth", "Zoom target width", canonCsIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0026, "0x0026", "0x0026", "Unknown", canonCsIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0027, "0x0027", "0x0027", "Unknown", canonCsIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0028, "PhotoEffect", "PhotoEffect", "Photo effect", canonCsIfdId, makerTags, unsignedShort, EXV_PRINT_TAG(canonCsPhotoEffect)),
TagInfo(0x0029, "0x0029", "0x0029", "Unknown", canonCsIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x002a, "ColorTone", "ColorTone", "Color tone", canonCsIfdId, makerTags, unsignedShort, printValue),
// End of list marker
TagInfo(0xffff, "(UnknownCanonCsTag)", "(UnknownCanonCsTag)", "Unknown Canon Camera Settings 1 tag", canonCsIfdId, makerTags, invalidTypeId, printValue)
};
const TagInfo* CanonMakerNote::tagListCs()
{
return tagInfoCs_;
}
//! WhiteBalance, tag 0x0007
extern const TagDetails canonSiWhiteBalance[] = {
{ 0, "Auto" },
{ 1, "Sunny" },
{ 2, "Cloudy" },
{ 3, "Tungsten" },
{ 4, "Fluorescent" },
{ 5, "Flash" },
{ 6, "Custom" },
{ 7, "Black & White" },
{ 8, "Shade" },
{ 9, "Manual Temperature (Kelvin)" },
{ 10, "PC Set 1" },
{ 11, "PC Set 2" },
{ 12, "PC Set 3" },
{ 14, "Daylight Fluorescent" },
{ 15, "Custom 1" },
{ 16, "Custom 2" },
{ 17, "Underwater" }
};
//! AFPointUsed, tag 0x000e
extern const TagDetailsBitmask canonSiAFPointUsed[] = {
{ 0x0004, "left" },
{ 0x0002, "center" },
{ 0x0001, "right" }
};
//! FlashBias, tag 0x000f
extern const TagDetails canonSiFlashBias[] = {
{ 0xffc0, "-2 EV" },
{ 0xffcc, "-1.67 EV" },
{ 0xffd0, "-1.50 EV" },
{ 0xffd4, "-1.33 EV" },
{ 0xffe0, "-1 EV" },
{ 0xffec, "-0.67 EV" },
{ 0xfff0, "-0.50 EV" },
{ 0xfff4, "-0.33 EV" },
{ 0x0000, "0 EV" },
{ 0x000c, "0.33 EV" },
{ 0x0010, "0.50 EV" },
{ 0x0014, "0.67 EV" },
{ 0x0020, "1 EV" },
{ 0x002c, "1.33 EV" },
{ 0x0030, "1.50 EV" },
{ 0x0034, "1.67 EV" },
{ 0x0040, "2 EV" }
};
// Canon Shot Info Tag
const TagInfo CanonMakerNote::tagInfoSi_[] = {
TagInfo(0x0001, "0x0001", "0x0001", "Unknown", canonSiIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0002, "ISOSpeed", "ISO Speed Used", "ISO speed used", canonSiIfdId, makerTags, unsignedShort, printSi0x0002),
TagInfo(0x0003, "0x0003", "0x0003", "Unknown", canonSiIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0004, "TargetAperture", "TargetAperture", "Target Aperture", canonSiIfdId, makerTags, unsignedShort, printSi0x0015),
TagInfo(0x0005, "TargetShutterSpeed", "TargetShutterSpeed", "Target shutter speed", canonSiIfdId, makerTags, unsignedShort, printSi0x0016),
TagInfo(0x0006, "0x0006", "0x0006", "Unknown", canonSiIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0007, "WhiteBalance", "WhiteBalance", "White balance setting", canonSiIfdId, makerTags, unsignedShort, EXV_PRINT_TAG(canonSiWhiteBalance)),
TagInfo(0x0008, "0x0008", "0x0008", "Unknown", canonSiIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0009, "Sequence", "Sequence", "Sequence number (if in a continuous burst)", canonSiIfdId, makerTags, unsignedShort, printSi0x0009),
TagInfo(0x000a, "0x000a", "0x000a", "Unknown", canonSiIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x000b, "0x000b", "0x000b", "Unknown", canonSiIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x000c, "0x000c", "0x000c", "Unknown", canonSiIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x000d, "0x000d", "0x000d", "Unknown", canonSiIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x000e, "AFPointUsed", "AFPointUsed", "AF point used", canonSiIfdId, makerTags, unsignedShort, printSi0x000e),
TagInfo(0x000f, "FlashBias", "FlashBias", "Flash bias", canonSiIfdId, makerTags, unsignedShort, EXV_PRINT_TAG(canonSiFlashBias)),
TagInfo(0x0010, "0x0010", "0x0010", "Unknown", canonSiIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0011, "0x0011", "0x0011", "Unknown", canonSiIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0012, "0x0012", "0x0012", "Unknown", canonSiIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0013, "SubjectDistance", "SubjectDistance", "Subject distance (units are not clear)", canonSiIfdId, makerTags, unsignedShort, printSi0x0013),
TagInfo(0x0014, "0x0014", "0x0014", "Unknown", canonSiIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0015, "ApertureValue", "ApertureValue", "Aperture", canonSiIfdId, makerTags, unsignedShort, printSi0x0015),
TagInfo(0x0016, "ShutterSpeedValue", "ShutterSpeedValue", "Shutter speed", canonSiIfdId, makerTags, unsignedShort, printSi0x0016),
TagInfo(0x0017, "0x0017", "0x0017", "Unknown", canonSiIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0018, "0x0018", "0x0018", "Unknown", canonSiIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0019, "0x0019", "0x0019", "Unknown", canonSiIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x001a, "0x001a", "0x001a", "Unknown", canonSiIfdId, makerTags, unsignedShort, printValue),
// End of list marker
TagInfo(0xffff, "(UnknownCanonSiTag)", "(UnknownCanonSiTag)", "Unknown Canon Camera Settings 2 tag", canonSiIfdId, makerTags, invalidTypeId, printValue)
};
const TagInfo* CanonMakerNote::tagListSi()
{
return tagInfoSi_;
}
//! PanoramaDirection, tag 0x0005
extern const TagDetails canonPaDirection[] = {
{ 0, "Left to right" },
{ 1, "Right to left" },
{ 2, "Bottom to top" },
{ 3, "Top to bottom" },
{ 4, "2x2 matrix (Clockwise)" }
};
// Canon Panorama Info
const TagInfo CanonMakerNote::tagInfoPa_[] = {
TagInfo(0x0002, "PanoramaFrame", "PanoramaFrame", "Panorama frame number", canonPaIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0005, "PanoramaDirection", "PanoramaDirection", "Panorama direction", canonPaIfdId, makerTags, unsignedShort, EXV_PRINT_TAG(canonPaDirection)),
// End of list marker
TagInfo(0xffff, "(UnknownCanonCs2Tag)", "(UnknownCanonCs2Tag)", "Unknown Canon Panorama tag", canonPaIfdId, makerTags, invalidTypeId, printValue)
};
const TagInfo* CanonMakerNote::tagListPa()
{
return tagInfoPa_;
}
// Canon Custom Function Tag Info
const TagInfo CanonMakerNote::tagInfoCf_[] = {
TagInfo(0x0001, "NoiseReduction", "NoiseReduction", "Long exposure noise reduction", canonCfIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0002, "ShutterAeLock", "ShutterAeLock", "Shutter/AE lock buttons", canonCfIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0003, "MirrorLockup", "MirrorLockup", "Mirror lockup", canonCfIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0004, "ExposureLevelIncrements", "ExposureLevelIncrements", "Tv/Av and exposure level", canonCfIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0005, "AFAssist", "AFAssist", "AF assist light", canonCfIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0006, "FlashSyncSpeedAv", "FlashSyncSpeedAv", "Shutter speed in Av mode", canonCfIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0007, "AEBSequence", "AEBSequence", "AEB sequence/auto cancellation", canonCfIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0008, "ShutterCurtainSync", "ShutterCurtainSync", "Shutter curtain sync", canonCfIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0009, "LensAFStopButton", "LensAFStopButton", "Lens AF stop button Fn. Switch", canonCfIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x000a, "FillFlashAutoReduction", "FillFlashAutoReduction", "Auto reduction of fill flash", canonCfIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x000b, "MenuButtonReturn", "MenuButtonReturn", "Menu button return position", canonCfIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x000c, "SetButtonFunction", "SetButtonFunction", "SET button func. when shooting", canonCfIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x000d, "SensorCleaning", "SensorCleaning", "Sensor cleaning", canonCfIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x000e, "SuperimposedDisplay", "SuperimposedDisplay", "Superimposed display", canonCfIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x000f, "ShutterReleaseNoCFCard", "ShutterReleaseNoCFCard", "Shutter Release W/O CF Card", canonCfIfdId, makerTags, unsignedShort, printValue),
// End of list marker
TagInfo(0xffff, "(UnknownCanonCfTag)", "(UnknownCanonCfTag)", "Unknown Canon Custom Function tag", canonCfIfdId, makerTags, invalidTypeId, printValue)
};
const TagInfo* CanonMakerNote::tagListCf()
{
return tagInfoCf_;
}
//! AFPointsUsed, tag 0x0016
extern const TagDetailsBitmask canonPiAFPointsUsed[] = {
{ 0x01, "right" },
{ 0x02, "mid-right" },
{ 0x04, "bottom" },
{ 0x08, "center" },
{ 0x10, "top" },
{ 0x20, "mid-left" },
{ 0x40, "left" }
};
//! AFPointsUsed20D, tag 0x001a
extern const TagDetailsBitmask canonPiAFPointsUsed20D[] = {
{ 0x001, "top" },
{ 0x002, "upper-left" },
{ 0x004, "upper-right" },
{ 0x008, "left" },
{ 0x010, "center" },
{ 0x020, "right" },
{ 0x040, "lower-left" },
{ 0x080, "lower-right" },
{ 0x100, "bottom" }
};
// Canon Picture Info Tag
const TagInfo CanonMakerNote::tagInfoPi_[] = {
TagInfo(0x0002, "ImageWidth", "ImageWidth", "Image width", canonPiIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0003, "ImageHeight", "ImageHeight", "Image height", canonPiIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0004, "ImageWidthAsShot", "ImageWidthAsShot", "Image width (as shot)", canonPiIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0005, "ImageHeightAsShot", "ImageHeightAsShot", "Image height (as shot)", canonPiIfdId, makerTags, unsignedShort, printValue),
TagInfo(0x0016, "AFPointsUsed", "AFPointsUsed", "AF points used", canonPiIfdId, makerTags, unsignedShort, EXV_PRINT_TAG_BITMASK(canonPiAFPointsUsed20D)),
TagInfo(0x001a, "AFPointsUsed20D", "AFPointsUsed20D", "AF points used (20D)", canonPiIfdId, makerTags, unsignedShort, EXV_PRINT_TAG_BITMASK(canonPiAFPointsUsed20D)),
// End of list marker
TagInfo(0xffff, "(UnknownCanonPiTag)", "(UnknownCanonPiTag)", "Unknown Canon Picture Info tag", canonPiIfdId, makerTags, invalidTypeId, printValue)
};
const TagInfo* CanonMakerNote::tagListPi()
{
return tagInfoPi_;
}
int CanonMakerNote::read(const byte* buf,
long len,
long start,
ByteOrder byteOrder,
long shift)
{
int rc = IfdMakerNote::read(buf, len, start, byteOrder, shift);
if (rc) return rc;
// Decode camera settings 1 and add settings as additional entries
Entries::iterator cs = ifd_.findTag(0x0001);
if (cs != ifd_.end() && cs->type() == unsignedShort) {
for (uint16_t c = 1; cs->count() > c; ++c) {
if (c == 23 && cs->count() > 25) {
// Pack related lens info into one tag
addCsEntry(canonCsIfdId, c, cs->offset() + c*2,
cs->data() + c*2, 3);
c += 2;
}
else {
addCsEntry(canonCsIfdId, c, cs->offset() + c*2,
cs->data() + c*2, 1);
}
}
// Discard the original entry
ifd_.erase(cs);
}
// Decode camera settings 2 and add settings as additional entries
cs = ifd_.findTag(0x0004);
if (cs != ifd_.end() && cs->type() == unsignedShort) {
for (uint16_t c = 1; cs->count() > c; ++c) {
addCsEntry(canonSiIfdId, c, cs->offset() + c*2,
cs->data() + c*2, 1);
}
// Discard the original entry
ifd_.erase(cs);
}
// Decode panorama information and add each as an additional entry
cs = ifd_.findTag(0x0005);
if (cs != ifd_.end() && cs->type() == unsignedShort) {
for (uint16_t c = 1; cs->count() > c; ++c) {
addCsEntry(canonPaIfdId, c, cs->offset() + c*2,
cs->data() + c*2, 1);
}
// Discard the original entry
ifd_.erase(cs);
}
// Decode custom functions and add each as an additional entry
cs = ifd_.findTag(0x000f);
if (cs != ifd_.end() && cs->type() == unsignedShort) {
for (uint16_t c = 1; cs->count() > c; ++c) {
addCsEntry(canonCfIfdId, c, cs->offset() + c*2,
cs->data() + c*2, 1);
}
// Discard the original entry
ifd_.erase(cs);
}
// Decode picture info and add each as an additional entry
cs = ifd_.findTag(0x0012);
if (cs != ifd_.end() && cs->type() == unsignedShort) {
for (uint16_t c = 1; cs->count() > c; ++c) {
addCsEntry(canonPiIfdId, c, cs->offset() + c*2,
cs->data() + c*2, 1);
}
// Discard the original entry
ifd_.erase(cs);
}
// Copy remaining ifd entries
entries_.insert(entries_.begin(), ifd_.begin(), ifd_.end());
// Set idx
int idx = 0;
Entries::iterator e = entries_.end();
for (Entries::iterator i = entries_.begin(); i != e; ++i) {
i->setIdx(++idx);
}
return 0;
}
void CanonMakerNote::addCsEntry(IfdId ifdId,
uint16_t tag,
long offset,
const byte* data,
int count)
{
Entry e(false);
e.setIfdId(ifdId);
e.setTag(tag);
e.setOffset(offset);
e.setValue(unsignedShort, count, data, 2*count);
add(e);
}
void CanonMakerNote::add(const Entry& entry)
{
assert(alloc_ == entry.alloc());
assert( entry.ifdId() == canonIfdId
|| entry.ifdId() == canonCsIfdId
|| entry.ifdId() == canonSiIfdId
|| entry.ifdId() == canonPaIfdId
|| entry.ifdId() == canonCfIfdId
|| entry.ifdId() == canonPiIfdId);
// allow duplicates
entries_.push_back(entry);
}
long CanonMakerNote::copy(byte* buf, ByteOrder byteOrder, long offset)
{
if (byteOrder_ == invalidByteOrder) byteOrder_ = byteOrder;
assert(ifd_.alloc());
ifd_.clear();
// Add all standard Canon entries to the IFD
Entries::const_iterator end = entries_.end();
for (Entries::const_iterator i = entries_.begin(); i != end; ++i) {
if (i->ifdId() == canonIfdId) {
ifd_.add(*i);
}
}
// Collect camera settings entries and add the original Canon tag
Entry cs;
if (assemble(cs, canonCsIfdId, 0x0001, byteOrder_)) {
ifd_.erase(0x0001);
ifd_.add(cs);
}
// Collect shot info entries and add the original Canon tag
Entry si;
if (assemble(si, canonSiIfdId, 0x0004, byteOrder_)) {
ifd_.erase(0x0004);
ifd_.add(si);
}
// Collect panorama entries and add the original Canon tag
Entry pa;
if (assemble(pa, canonPaIfdId, 0x0005, byteOrder_)) {
ifd_.erase(0x0005);
ifd_.add(pa);
}
// Collect custom function entries and add the original Canon tag
Entry cf;
if (assemble(cf, canonCfIfdId, 0x000f, byteOrder_)) {
ifd_.erase(0x000f);
ifd_.add(cf);
}
// Collect picture info entries and add the original Canon tag
Entry pi;
if (assemble(pi, canonPiIfdId, 0x0012, byteOrder_)) {
ifd_.erase(0x0012);
ifd_.add(pi);
}
return IfdMakerNote::copy(buf, byteOrder_, offset);
} // CanonMakerNote::copy
void CanonMakerNote::updateBase(byte* pNewBase)
{
byte* pBase = ifd_.updateBase(pNewBase);
if (absShift_ && !alloc_) {
Entries::iterator end = entries_.end();
for (Entries::iterator pos = entries_.begin(); pos != end; ++pos) {
pos->updateBase(pBase, pNewBase);
}
}
} // CanonMakerNote::updateBase
long CanonMakerNote::size() const
{
Ifd ifd(canonIfdId, 0, alloc_); // offset doesn't matter
// Add all standard Canon entries to the IFD
Entries::const_iterator end = entries_.end();
for (Entries::const_iterator i = entries_.begin(); i != end; ++i) {
if (i->ifdId() == canonIfdId) {
ifd.add(*i);
}
}
// Collect camera settings entries and add the original Canon tag
Entry cs(alloc_);
if (assemble(cs, canonCsIfdId, 0x0001, littleEndian)) {
ifd.erase(0x0001);
ifd.add(cs);
}
// Collect shot info entries and add the original Canon tag
Entry si(alloc_);
if (assemble(si, canonSiIfdId, 0x0004, littleEndian)) {
ifd.erase(0x0004);
ifd.add(si);
}
// Collect panorama entries and add the original Canon tag
Entry pa(alloc_);
if (assemble(pa, canonPaIfdId, 0x0005, littleEndian)) {
ifd.erase(0x0005);
ifd.add(pa);
}
// Collect custom function entries and add the original Canon tag
Entry cf(alloc_);
if (assemble(cf, canonCfIfdId, 0x000f, littleEndian)) {
ifd.erase(0x000f);
ifd.add(cf);
}
// Collect picture info entries and add the original Canon tag
Entry pi(alloc_);
if (assemble(pi, canonPiIfdId, 0x0012, littleEndian)) {
ifd.erase(0x0012);
ifd.add(pi);
}
return headerSize() + ifd.size() + ifd.dataSize();
} // CanonMakerNote::size
long CanonMakerNote::assemble(Entry& e,
IfdId ifdId,
uint16_t tag,
ByteOrder byteOrder) const
{
DataBuf buf(1024);
memset(buf.pData_, 0x0, 1024);
uint16_t len = 0;
Entries::const_iterator end = entries_.end();
for (Entries::const_iterator i = entries_.begin(); i != end; ++i) {
if (i->ifdId() == ifdId) {
uint16_t pos = i->tag() * 2;
uint16_t size = pos + static_cast<uint16_t>(i->size());
assert(size <= 1024);
memcpy(buf.pData_ + pos, i->data(), i->size());
if (len < size) len = size;
}
}
if (len > 0) {
// Number of shorts in the buffer (rounded up)
uint16_t s = (len+1) / 2;
us2Data(buf.pData_, s*2, byteOrder);
e.setIfdId(canonIfdId);
e.setIdx(0); // don't care
e.setTag(tag);
e.setOffset(0); // will be calculated when the IFD is written
e.setValue(unsignedShort, s, buf.pData_, s*2);
}
return len;
} // CanonMakerNote::assemble
Entries::const_iterator CanonMakerNote::findIdx(int idx) const
{
return std::find_if(entries_.begin(), entries_.end(),
FindEntryByIdx(idx));
}
CanonMakerNote::CanonMakerNote(bool alloc)
: IfdMakerNote(canonIfdId, alloc)
{
}
CanonMakerNote::CanonMakerNote(const CanonMakerNote& rhs)
: IfdMakerNote(rhs)
{
entries_ = rhs.entries_;
}
CanonMakerNote::AutoPtr CanonMakerNote::create(bool alloc) const
{
return AutoPtr(create_(alloc));
}
CanonMakerNote* CanonMakerNote::create_(bool alloc) const
{
return new CanonMakerNote(alloc);
}
CanonMakerNote::AutoPtr CanonMakerNote::clone() const
{
return AutoPtr(clone_());
}
CanonMakerNote* CanonMakerNote::clone_() const
{
return new CanonMakerNote(*this);
}
std::ostream& CanonMakerNote::print0x0008(std::ostream& os,
const Value& value)
{
std::string n = value.toString();
if (n.length() < 4) return os << "(" << n << ")";
return os << n.substr(0, n.length() - 4) << "-"
<< n.substr(n.length() - 4);
}
std::ostream& CanonMakerNote::print0x000c(std::ostream& os,
const Value& value)
{
std::istringstream is(value.toString());
uint32_t l;
is >> l;
return os << std::setw(4) << std::setfill('0') << std::hex
<< ((l & 0xffff0000) >> 16)
<< std::setw(5) << std::setfill('0') << std::dec
<< (l & 0x0000ffff);
}
std::ostream& CanonMakerNote::printCs0x0002(std::ostream& os,
const Value& value)
{
if (value.typeId() != unsignedShort) return os << value;
long l = value.toLong();
if (l == 0) {
os << "Off";
}
else {
os << l / 10.0 << " s";
}
return os;
}
std::ostream& CanonMakerNote::printCsLens(std::ostream& os,
const Value& value)
{
if (value.typeId() != unsignedShort) return os << value;
if (value.count() < 3) return os << value;
float fu = value.toFloat(2);
if (fu == 0.0) return os << value;
float len1 = value.toLong(0) / fu;
float len2 = value.toLong(1) / fu;
std::ostringstream oss;
oss.copyfmt(os);
os << std::fixed << std::setprecision(1);
if (len1 == len2) {
os << len1 << " mm";
} else {
os << len2 << " - " << len1 << " mm";
}
os.copyfmt(oss);
return os;
}
std::ostream& CanonMakerNote::printSi0x0002(std::ostream& os,
const Value& value)
{
// Ported from Exiftool by Will Stokes
return os << exp(canonEv(value.toLong()) * log(2.0)) * 100.0 / 32.0;
}
std::ostream& CanonMakerNote::printSi0x0009(std::ostream& os,
const Value& value)
{
if (value.typeId() != unsignedShort) return os << value;
long l = value.toLong();
os << l << "";
// Todo: determine unit
return os;
}
std::ostream& CanonMakerNote::printSi0x000e(std::ostream& os,
const Value& value)
{
if (value.typeId() != unsignedShort) return os << value;
long l = value.toLong();
long num = (l & 0xf000) >> 12;
os << num << " focus points; ";
long used = l & 0x0fff;
if (used == 0) {
os << "none";
}
else {
EXV_PRINT_TAG_BITMASK(canonSiAFPointUsed)(os, value);
}
os << " used";
return os;
}
std::ostream& CanonMakerNote::printSi0x0013(std::ostream& os,
const Value& value)
{
if (value.typeId() != unsignedShort) return os << value;
long l = value.toLong();
if (l == 0xffff) {
os << "Infinite";
}
else {
os << l << "";
}
return os;
}
std::ostream& CanonMakerNote::printSi0x0015(std::ostream& os,
const Value& value)
{
if (value.typeId() != unsignedShort) return os << value;
std::ostringstream oss;
oss.copyfmt(os);
os << std::setprecision(2)
<< "F" << fnumber(canonEv(value.toLong()));
os.copyfmt(oss);
return os;
}
std::ostream& CanonMakerNote::printSi0x0016(std::ostream& os,
const Value& value)
{
if (value.typeId() != unsignedShort) return os << value;
URational ur = exposureTime(canonEv(value.toLong()));
os << ur.first;
if (ur.second > 1) {
os << "/" << ur.second;
}
return os << " s";
}
// *****************************************************************************
// free functions
MakerNote::AutoPtr createCanonMakerNote( bool alloc,
const byte* /*buf*/,
long /*len*/,
ByteOrder /*byteOrder*/,
long /*offset*/)
{
return MakerNote::AutoPtr(new CanonMakerNote(alloc));
}
float canonEv(long val)
{
// temporarily remove sign
int sign = 1;
if (val < 0) {
sign = -1;
val = -val;
}
// remove fraction
float frac = static_cast<float>(val & 0x1f);
val -= long(frac);
// convert 1/3 (0x0c) and 2/3 (0x14) codes
if (frac == 0x0c) {
frac = 32.0f / 3;
}
else if (frac == 0x14) {
frac = 64.0f / 3;
}
return sign * (val + frac) / 32.0f;
}
} // namespace Exiv2