| 418 | } |
| 419 | |
| 420 | void DngDecoder::handleMetadata(const TiffIFD* raw) { |
| 421 | // Crop |
| 422 | if (raw->hasEntry(ACTIVEAREA)) { |
| 423 | TiffEntry *active_area = raw->getEntry(ACTIVEAREA); |
| 424 | if (active_area->count != 4) |
| 425 | ThrowRDE("active area has %d values instead of 4", active_area->count); |
| 426 | |
| 427 | const iRectangle2D fullImage(0, 0, mRaw->dim.x, mRaw->dim.y); |
| 428 | |
| 429 | const auto corners = active_area->getU32Array(4); |
| 430 | const iPoint2D topLeft(corners[1], corners[0]); |
| 431 | const iPoint2D bottomRight(corners[3], corners[2]); |
| 432 | |
| 433 | if (!(fullImage.isPointInsideInclusive(topLeft) && |
| 434 | fullImage.isPointInsideInclusive(bottomRight) && |
| 435 | bottomRight >= topLeft)) { |
| 436 | ThrowRDE("Rectangle (%u, %u, %u, %u) not inside image (%u, %u, %u, %u).", |
| 437 | topLeft.x, topLeft.y, bottomRight.x, bottomRight.y, |
| 438 | fullImage.getTopLeft().x, fullImage.getTopLeft().y, |
| 439 | fullImage.getBottomRight().x, fullImage.getBottomRight().y); |
| 440 | } |
| 441 | |
| 442 | iRectangle2D crop; |
| 443 | crop.setTopLeft(topLeft); |
| 444 | crop.setBottomRightAbsolute(bottomRight); |
| 445 | assert(fullImage.isThisInside(fullImage)); |
| 446 | |
| 447 | mRaw->subFrame(crop); |
| 448 | } |
| 449 | |
| 450 | if (raw->hasEntry(DEFAULTCROPORIGIN) && raw->hasEntry(DEFAULTCROPSIZE)) { |
| 451 | iRectangle2D cropped(0, 0, mRaw->dim.x, mRaw->dim.y); |
| 452 | TiffEntry *origin_entry = raw->getEntry(DEFAULTCROPORIGIN); |
| 453 | TiffEntry *size_entry = raw->getEntry(DEFAULTCROPSIZE); |
| 454 | |
| 455 | /* Read crop position (sometimes is rational so use float) */ |
| 456 | const auto tl = origin_entry->getFloatArray(2); |
| 457 | if (std::any_of(tl.cbegin(), tl.cend(), [](const auto v) { |
| 458 | return v < std::numeric_limits<iPoint2D::value_type>::min() || |
| 459 | v > std::numeric_limits<iPoint2D::value_type>::max(); |
| 460 | })) |
| 461 | ThrowRDE("Error decoding default crop origin"); |
| 462 | |
| 463 | iPoint2D cropOrigin(tl[0], tl[1]); |
| 464 | if (cropped.isPointInsideInclusive(cropOrigin)) |
| 465 | cropped = iRectangle2D(cropOrigin, {0, 0}); |
| 466 | |
| 467 | cropped.dim = mRaw->dim - cropped.pos; |
| 468 | |
| 469 | /* Read size (sometimes is rational so use float) */ |
| 470 | const auto sz = size_entry->getFloatArray(2); |
| 471 | if (std::any_of(sz.cbegin(), sz.cend(), [](const auto v) { |
| 472 | return v < std::numeric_limits<iPoint2D::value_type>::min() || |
| 473 | v > std::numeric_limits<iPoint2D::value_type>::max(); |
| 474 | })) |
| 475 | ThrowRDE("Error decoding default crop size"); |
| 476 | |
| 477 | iPoint2D size(sz[0], sz[1]); |
nothing calls this directly
no test coverage detected