56 ThrowCME(R
"("make" attribute not found.)");
59 camera.attribute("model").as_string();
61 if (!camera.attribute(
"model"))
62 ThrowCME(R
"("model" attribute not found.)");
67 const std::string_view
v = camera.attribute(
"supported").as_string(
"yes");
73 if (v ==
"no-samples")
77 if (v ==
"unknown-no-samples")
79 ThrowCME(
"Attribute 'supported' has unknown value.");
81 mode = camera.attribute(
"mode").as_string(
"");
84 for (xml_node c : camera.children()) {
91 if (alias_num >= camera->
aliases.size())
92 ThrowCME(
"Internal error, alias number out of range specified.");
105std::string name(
const xml_node& a) {
return a.name(); }
137 if (c ==
"FUJI_GREEN")
150void Camera::parseColorRow(
const xml_node& c) {
151 if (name(c) !=
"ColorRow")
154 int y = c.attribute(
"y").as_int(-1);
156 ThrowCME(
"Invalid y coordinate in CFA array of camera %s %s",
make.c_str(),
159 std::string key = c.child_value();
160 if (
static_cast<int>(key.size()) !=
cfa.getSize().x) {
161 ThrowCME(
"Invalid number of colors in definition for row %d in "
162 "camera %s %s. Expected %d, found %zu.",
163 y,
make.c_str(),
model.c_str(),
cfa.getSize().x, key.size());
165 for (
size_t x = 0;
x < key.size(); ++
x) {
168 auto c2 = getAsCFAColor(
static_cast<char>(tolower(c1)));
170 ThrowCME(
"Invalid color in CFA array of camera %s %s: %c",
make.c_str(),
173 cfa.setColorAt(iPoint2D(
static_cast<int>(
x),
y), *c2);
177void Camera::parseColor(
const xml_node& c) {
178 if (name(c) !=
"Color")
181 int x = c.attribute(
"x").as_int(-1);
183 ThrowCME(
"Invalid x coordinate in CFA array of camera %s %s",
make.c_str(),
187 int y = c.attribute(
"y").as_int(-1);
189 ThrowCME(
"Invalid y coordinate in CFA array of camera %s %s",
make.c_str(),
193 const auto* c1 = c.child_value();
195 auto c2 = getAsCFAColor(c1);
197 ThrowCME(
"Invalid color in CFA array of camera %s %s: %s",
make.c_str(),
200 cfa.setColorAt(iPoint2D(
x,
y), *c2);
203void Camera::parseCFA(
const xml_node& cur) {
204 if (name(cur) !=
"CFA" && name(cur) !=
"CFA2")
207 cfa.setSize(iPoint2D(cur.attribute(
"width").as_int(0),
208 cur.attribute(
"height").as_int(0)));
209 for (xml_node c : cur.children()) {
210 if (name(c) ==
"ColorRow") {
212 }
else if (name(c) ==
"Color") {
218void Camera::parseCrop(
const xml_node& cur) {
219 if (name(cur) !=
"Crop")
222 const auto widthAttr = cur.attribute(
"width");
223 const auto heightAttr = cur.attribute(
"height");
224 const auto xAttr = cur.attribute(
"x");
225 const auto yAttr = cur.attribute(
"y");
232 cropAvailable = !(widthAttr.empty() && heightAttr.empty() && xAttr.empty() &&
236 ThrowCME(
"Negative X axis crop specified in camera %s %s",
make.c_str(),
239 ThrowCME(
"Negative Y axis crop specified in camera %s %s",
make.c_str(),
243void Camera::parseBlackAreas(
const xml_node& cur) {
245 if (name(cur) !=
"BlackAreas")
246 ThrowCME(
"Not an BlackAreas node!");
248 for (xml_node c : cur.children()) {
249 if (name(c) ==
"Vertical") {
250 int x = c.attribute(
"x").as_int(-1);
253 "Invalid x coordinate in vertical BlackArea of in camera %s %s",
257 int w = c.attribute(
"width").as_int(-1);
259 ThrowCME(
"Invalid width in vertical BlackArea of in camera %s %s",
265 }
else if (name(c) ==
"Horizontal") {
267 int y = c.attribute(
"y").as_int(-1);
269 ThrowCME(
"Invalid y coordinate in horizontal BlackArea of camera %s %s",
273 int h = c.attribute(
"height").as_int(-1);
275 ThrowCME(
"Invalid height in horizontal BlackArea of camera %s %s",
284void Camera::parseAliases(
const xml_node& cur) {
285 if (name(cur) !=
"Aliases")
288 for (xml_node c : cur.children(
"Alias")) {
289 aliases.emplace_back(c.child_value());
291 c.attribute(
"id").as_string(c.child_value()));
295void Camera::parseHints(
const xml_node& cur) {
296 if (name(cur) !=
"Hints")
299 for (xml_node c : cur.children(
"Hint")) {
300 std::string name = c.attribute(
"name").as_string();
302 ThrowCME(
"Could not find name for hint for %s %s camera.",
make.c_str(),
305 std::string value = c.attribute(
"value").as_string();
307 hints.add(name, value);
311void Camera::parseID(
const xml_node& cur) {
312 if (name(cur) !=
"ID")
317 ThrowCME(
"Could not find make for ID for %s %s camera.",
make.c_str(),
322 ThrowCME(
"Could not find model for ID for %s %s camera.",
make.c_str(),
328void Camera::parseSensor(
const xml_node& cur) {
329 if (name(cur) !=
"Sensor")
332 auto stringToListOfInts = [&cur](
const char* attribute) {
334 for (
const std::string&
s :
336 ret.push_back(stoi(
s));
340 int min_iso = cur.attribute(
"iso_min").as_int(0);
341 int max_iso = cur.attribute(
"iso_max").as_int(0);
342 int black = cur.attribute(
"black").as_int(-1);
343 int white = cur.attribute(
"white").as_int(65536);
345 vector<int> black_colors = stringToListOfInts(
"black_colors");
346 vector<int> iso_list = stringToListOfInts(
"iso_list");
347 if (!iso_list.empty()) {
348 for (
int iso : iso_list) {
349 sensorInfo.emplace_back(black, white, iso, iso, black_colors);
352 sensorInfo.emplace_back(black, white, min_iso, max_iso, black_colors);
356void Camera::parseColorMatrix(
const xml_node& cur) {
357 if (name(cur) !=
"ColorMatrix")
358 ThrowCME(
"Not an ColorMatrix node!");
360 unsigned planes = cur.attribute(
"planes").as_uint(~0U);
362 ThrowCME(
"Color matrix has unknown number of planes!");
364 static constexpr int NumColsPerPlane = 3;
365 color_matrix.resize(NumColsPerPlane * planes, NotARational<int>(0, 0));
367 for (xml_node ColorMatrixRow : cur.children(
"ColorMatrixRow")) {
368 if (name(ColorMatrixRow) !=
"ColorMatrixRow")
369 ThrowCME(
"Not an ColorMatrixRow node!");
371 auto plane = ColorMatrixRow.attribute(
"plane").as_uint(~0U);
372 if (plane == ~0U || plane >= planes)
373 ThrowCME(
"Color matrix row is for unknown plane!");
375 const std::vector<std::string> ColsOfRow =
378 if (ColsOfRow.size() != NumColsPerPlane)
379 ThrowCME(
"Color matrix row has incorrect number of columns!");
381 std::transform(ColsOfRow.begin(), ColsOfRow.end(),
383 [](
const std::string& Col) -> NotARational<int> {
384 return {std::stoi(Col), 10'000};
389void Camera::parseColorMatrices(
const xml_node& cur) {
390 if (name(cur) !=
"ColorMatrices")
391 ThrowCME(
"Not an ColorMatrices node!");
393 for (xml_node ColorMatrix : cur.children(
"ColorMatrix"))
394 parseColorMatrix(ColorMatrix);
397void Camera::parseCameraChild(
const xml_node& cur) {
398 if (name(cur) ==
"CFA" || name(cur) ==
"CFA2") {
400 }
else if (name(cur) ==
"Crop") {
402 }
else if (name(cur) ==
"BlackAreas") {
403 parseBlackAreas(cur);
404 }
else if (name(cur) ==
"Aliases") {
406 }
else if (name(cur) ==
"Hints") {
408 }
else if (name(cur) ==
"ID") {
410 }
else if (name(cur) ==
"Sensor") {
412 }
else if (name(cur) ==
"ColorMatrices") {
413 parseColorMatrices(cur);
426 vector<const CameraSensorInfo*> candidates;
428 if (i.isIsoWithin(iso))
429 candidates.push_back(&i);
431 assert(!candidates.empty());
433 if (candidates.size() == 1)
434 return candidates.front();
436 for (
const auto* i : candidates) {
442 return candidates.front();
assert(dim.area() >=area)
Camera(const Camera *camera, uint32_t alias_num)
std::string canonical_alias
std::string canonical_model
std::vector< CameraSensorInfo > sensorInfo
std::vector< std::string > canonical_aliases
std::string canonical_make
std::vector< BlackArea > blackAreas
const CameraSensorInfo * getSensorInfo(int iso) const
std::vector< std::string > aliases
SupportStatus supportStatus
std::vector< NotARational< int > > color_matrix
integral_constant< int, N > v
std::vector< std::string > splitString(const std::string &input, char c=' ')