1 /* -*- mode:c++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil; -*- */
2 /*
3  * libopenraw - canon.cpp
4  *
5  * Copyright (C) 2018-2020 Hubert Figuière
6  *
7  * This library is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * as published by the Free Software Foundation, either version 3 of
10  * the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library.  If not, see
19  * <http://www.gnu.org/licenses/>.
20  */
21 
22 #include <array>
23 
24 #include "canon.hpp"
25 #include "ifddir.hpp"
26 #include "option.hpp"
27 #include "trace.hpp"
28 
29 namespace OpenRaw {
30 namespace Internals {
31 
32 #define OR_MAKE_CANON_TYPEID(camid)                     \
33     OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON, camid)
34 
35 const ModelIdMap canon_modelid_map = {
36     // TIF
37     { 0x80000001, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_1D) },
38     { 0x80000167, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_1DS) },
39     // CRW and CR2
40     { 0x80000174, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_1DMKII) },
41     { 0x80000175, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_20D) },
42     { 0x80000188, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_1DSMKII) },
43     { 0x80000189, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_350D) },
44     { 0x80000213, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_5D) },
45     { 0x80000232, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_1DMKIIN) },
46     { 0x80000234, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_30D) },
47     { 0x80000236, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_400D) },
48     { 0x80000169, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_1DMKIII) },
49     { 0x80000190, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_40D) },
50     { 0x80000215, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_1DSMKIII) },
51     { 0x02230000, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_G9) },
52     { 0x80000176, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_450D) },
53     { 0x80000254, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_1000D) },
54     { 0x80000261, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_50D) },
55     { 0x02490000, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_G10) },
56     { 0x80000218, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_5DMKII) },
57     { 0x02460000, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_SX1_IS) },
58     { 0x80000252, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_500D) },
59     { 0x02700000, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_G11) },
60     { 0x02720000, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_S90) },
61     { 0x80000250, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_7D) },
62     { 0x80000281, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_1DMKIV) },
63     { 0x80000270, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_550D) },
64     { 0x02950000, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_S95) },
65     { 0x80000287, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_60D) },
66     { 0x02920000, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_G12) },
67     { 0x80000286, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_600D) },
68     { 0x80000288, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_1100D) },
69     { 0x03110000, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_S100) },
70     { 0x80000269, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_1DX) },
71     { 0x03080000, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_G1X) },
72     { 0x80000285, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_5DMKIII) },
73     { 0x80000301, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_650D) },
74     { 0x80000331, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_M) },
75     { 0x03320000, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_S100V) },
76     { 0x03360000, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_S110) },
77     { 0x03330000, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_G15) },
78     { 0x03340000, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_SX50_HS) },
79     { 0x80000302, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_6D) },
80     { 0x80000326, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_700D) },
81     { 0x80000346, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_100D) },
82     { 0x80000325, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_70D) },
83     { 0x03540000, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_G16) },
84     { 0x03550000, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_S120) },
85 //    { 0x80000355, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_M2) },
86     { 0x80000327, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_1200D) },
87     { 0x03640000, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_G1XMKII) },
88     { 0x80000289, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_7DMKII) },
89     { 0x03780000, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_G7X) },
90     { 0x03750000, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_SX60_HS) },
91     { 0x80000382, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_5DS) },
92     { 0x80000401, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_5DS_R) },
93     { 0x80000393, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_750D) },
94     { 0x80000347, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_760D) },
95     { 0x03740000, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_M3) },
96     { 0x03850000, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_G3X) },
97     { 0x03950000, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_G5X) },
98     { 0x03930000, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_G9X) },
99     { 0x03840000, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_M10) },
100     { 0x80000328, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_1DXMKII) },
101     { 0x80000350, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_80D) },
102     { 0x03970000, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_G7XMKII) },
103     { 0x80000404, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_1300D) },
104     { 0x80000349, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_5DMKIV) },
105     { 0x03940000, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_M5) },
106     { 0x04100000, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_G9XMKII) },
107     { 0x80000405, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_800D) },
108     { 0x80000408, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_77D) },
109     { 0x04070000, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_M6) },
110     { 0x80000417, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_200D) },
111     { 0x80000406, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_6DMKII) },
112     { 0x03980000, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_M100) },
113     { 0x04180000, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_G1XMKIII) },
114     { 0x80000432, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_2000D) },
115     { 0x80000422, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_3000D) },
116     // CR3
117     { 0x00000412, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_M50) },
118     { 0x80000424, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_R) },
119     { 0x80000433, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_RP) },
120     { 0x80000421, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_R5) },
121     { 0x80000453, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_R6) },
122     { 0x80000436, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_250D) },
123     { 0x00000804, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_G5XMKII) },
124     { 0x00000805, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_SX70_HS) },
125     { 0x00000808, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_G7XMKIII) },
126     { 0x80000437, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_90D) },
127     { 0x00000811, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_M6MKII) },
128     { 0x00000812, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_M200) },
129     { 0x80000428, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_1DXMKIII) },
130     { 0x80000435, OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_850D) },
131 };
132 
133 Option<std::array<uint32_t, 4>>
canon_parse_sensorinfo(const std::vector<uint16_t> & sensor_info)134 canon_parse_sensorinfo(const std::vector<uint16_t>& sensor_info)
135 {
136     if (sensor_info.size() > 8) {
137         std::array<uint32_t, 4> result;
138         result[0] = sensor_info[5];
139         result[1] = sensor_info[6];
140         if (sensor_info[7] <= sensor_info[5]) {
141             LOGWARN("sensor_info: bottom %u <= top %u\n",
142                     sensor_info[7], sensor_info[5]);
143             return OptionNone();
144         }
145         uint32_t w = sensor_info[7] - sensor_info[5];
146         // it seems that this could lead to an odd number. Make it even.
147         if (w % 2) {
148             w++;
149         }
150         result[2] = w;
151         if (sensor_info[8] <= sensor_info[6]) {
152             LOGWARN("sensor_info: right %u <= left %u\n",
153                     sensor_info[8], sensor_info[6]);
154             return OptionNone();
155         }
156         uint32_t h = sensor_info[8] - sensor_info[6];
157         // same as for width
158         if (h % 2) {
159             h++;
160         }
161         result[3] = h;
162         return option_some(std::move(result));
163     }
164     else {
165         LOGWARN("SensorInfo is too small: %lu - skipping.\n",
166                 (LSIZE)sensor_info.size());
167     }
168     return OptionNone();
169 }
170 
canon_get_sensorinfo(const IfdDir::Ref & ifddir)171 Option<std::array<uint32_t, 4>> canon_get_sensorinfo(const IfdDir::Ref& ifddir)
172 {
173     auto e = ifddir->getEntry(IFD::MNOTE_CANON_SENSORINFO);
174     if (!e) {
175         return OptionNone();
176     }
177     auto result = ifddir->getEntryArrayValue<uint16_t>(*e);
178     if (result) {
179         return canon_parse_sensorinfo(result.value());
180     }
181     return OptionNone();
182 }
183 
184 }
185 }
186