21#include "rawspeedconfig.h"
69 ThrowRDE(
"DNG, but version tag is missing. Will not guess.");
75 ThrowRDE(
"Not a supported DNG image format: v%i.%i.%i.%i",
76 static_cast<int>(v[0]),
static_cast<int>(v[1]),
77 static_cast<int>(v[2]),
static_cast<int>(v[3]));
88 for (
auto i = data->begin(); i != data->end();) {
92 bool isSubsampled =
false;
103 isSubsampled = NewSubFileType & (1 << 0);
107 isAlpha = NewSubFileType & (1 << 2);
111 bool supported = !isSubsampled && !isAlpha;
129 "ZLIB is not present! Deflate compression will not be supported!"
131 "but the deflate support was disabled at "
133 [[clang::fallthrough]];
138 "JPEG is not present! Lossy JPEG compression will not be supported!"
140 "chunk, but the jpeg support was "
141 "disabled at build!");
142 [[clang::fallthrough]];
161 if (active_area->
count != 4)
162 ThrowRDE(
"active area has %u values instead of 4", active_area->
count);
167 const iPoint2D topLeft(
static_cast<int>(corners[1]),
168 static_cast<int>(corners[0]));
169 const iPoint2D bottomRight(
static_cast<int>(corners[3]),
170 static_cast<int>(corners[2]));
174 bottomRight >= topLeft)) {
175 ThrowRDE(
"Rectangle (%i, %i, %i, %i) not inside image (%i, %i, %i, %i).",
176 topLeft.
x, topLeft.
y, bottomRight.
x, bottomRight.
y,
218 ThrowRDE(
"Unsupported CFA Layout.");
221 if (cfadim->
count != 2)
222 ThrowRDE(
"Couldn't read CFA pattern dimension");
231 ThrowRDE(
"CFA pattern dimension and pattern count does not "
236 mRaw->cfa.setSize(cfaSize);
238 for (
int y = 0;
y < cfaSize.
y;
y++) {
239 for (
int x = 0;
x < cfaSize.
x;
x++) {
242 auto c2 = getDNGCFAPatternAsCFAColor(c1);
244 ThrowRDE(
"Unsupported CFA Color: %u", c1);
259 mRaw->cfa.shiftRight(-
int(aa->pos.x));
260 mRaw->cfa.shiftDown(-
int(aa->pos.y));
267 if (!
mRootIFD->hasEntryRecursive(I))
270 illuminant->getU16() != 21 ||
273 return mRootIFD->getEntryRecursive(M);
284 if (mat->
count % 3 != 0)
289 mRaw->metadata.colorMatrix.reserve(mat->
count);
290 for (
const auto&
val : srat_vals) {
291 Success &=
val.den != 0;
294 mRaw->metadata.colorMatrix.emplace_back(
val);
297 mRaw->metadata.colorMatrix.clear();
306 if (tilew <= 0 || tileh <= 0)
307 ThrowRDE(
"Invalid tile size: (%u, %u)", tilew, tileh);
313 ThrowRDE(
"Zero tiles horizontally");
323 offsets->
count != counts->count) {
324 ThrowRDE(
"Tile count mismatch: offsets:%u count:%u", offsets->
count,
329 if ((offsets->
count / tilesX != tilesY || (offsets->
count % tilesX != 0)) ||
330 (offsets->
count / tilesY != tilesX || (offsets->
count % tilesY != 0))) {
331 ThrowRDE(
"Tile X/Y count mismatch: total:%u X:%u, Y:%u", offsets->
count,
335 return {
mRaw->dim, tilew, tileh};
343 ThrowRDE(
"Byte count number does not match strip size: "
344 "count:%u, stips:%u ",
352 if (yPerSlice == 0 ||
354 ThrowRDE(
"Invalid y per slice %u or strip count %u (height = %i)",
363 ThrowRDE(
"Only float format is supported for "
364 "deflate-compressed data.");
366 sample_format != 1) {
367 ThrowRDE(
"Only 16 bit unsigned data supported for "
368 "JPEG-compressed data.");
393 mRaw->whitePoint = 1;
399 if (whitelevel->
isInt())
422 const auto offset = offsets->
getU32(n);
423 const auto count = counts->
getU32(n);
429 mRootIFD->rootBuffer.getByteOrder()));
431 if (!tilesLegality.
insert(bs))
432 ThrowTPE(
"Two tiles overlap. Raw corrupt!");
434 slices.
slices.emplace_back(slices.
dsc, n, bs);
438 if (slices.
slices.empty())
459 if (data.size() > 1) {
461 "Multiple RAW chunks found - using first only!");
468 ThrowRDE(
"Unsupported bit per sample count: %i.", *
bps);
476 switch (sample_format) {
484 ThrowRDE(
"Only 16 bit unsigned or float point data supported. Sample "
485 "format %u is not supported.",
498 if (sample_format == 1 && *
bps > 16)
499 ThrowRDE(
"Integer precision larger than 16 bits currently not supported.");
501 if (sample_format == 3 && *
bps != 16 && *
bps != 24 && *
bps != 32)
502 ThrowRDE(
"Floating point must be 16/24/32 bits per sample.");
507 if (!
mRaw->dim.hasPositiveArea())
510#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
512 if (
mRaw->dim.x > 9536 ||
mRaw->dim.y > 7680) {
513 ThrowRDE(
"Unexpected image dimensions found: (%i; %i)",
mRaw->dim.x,
523 if (cpp < 1 || cpp > 4)
524 ThrowRDE(
"Unsupported samples per pixel count: %u.", cpp);
548 std::array<unsigned, 2> tl;
549 std::transform(tl_r.begin(), tl_r.end(), tl.begin(),
551 if (r.den == 0 || r.num % r.den != 0)
552 ThrowRDE(
"Error decoding default crop origin");
553 return r.num / r.den;
556 if (
iPoint2D cropOrigin(tl[0], tl[1]);
563 std::array<unsigned, 2> sz;
564 std::transform(sz_r.begin(), sz_r.end(), sz.begin(),
566 if (r.den == 0 || r.num % r.den != 0)
567 ThrowRDE(
"Error decoding default crop size");
568 return r.num / r.den;
572 size.isThisInside(
mRaw->dim) &&
573 (size + cropped.
pos).isThisInside(
mRaw->dim))
576 mRaw->subFrame(cropped);
583 for (
const auto& scale : scales) {
584 if (scale.num == 0 || scale.den == 0)
585 ThrowRDE(
"Error decoding default pixel scale");
587 mRaw->metadata.pixelAspectRatio =
588 static_cast<double>(scales[0]) /
static_cast<double>(scales[1]);
596 if (opcodes->
count > 0) {
603 mRaw->setError(e.what());
614 mRaw->sixteenBitLookup();
624 mRaw->scaleBlackWhite();
633 mRaw->setError(e.what());
635 mRaw->blackAreas.clear();
636 mRaw->blackLevel = 0;
637 mRaw->blackLevelSeparate =
639 auto blackLevelSeparate1D = *
mRaw->blackLevelSeparate->getAsArray1DRef();
640 std::fill(blackLevelSeparate1D.begin(), blackLevelSeparate1D.end(), 0);
642 mRaw->whitePoint = 65535;
651 if (as_shot_neutral->
count == 3) {
652 std::array<float, 4> wbCoeffs = {};
654 float c = as_shot_neutral->
getFloat(i);
655 wbCoeffs[i] = (c > 0.0F) ? (1.0F / c) : 0.0F;
657 mRaw->metadata.wbCoeffs = wbCoeffs;
662 if (!
mRaw->metadata.colorMatrix.empty() &&
666 assert(
mRaw->metadata.colorMatrix.size() % 3 == 0);
667 const auto numColorPlanes =
mRaw->metadata.colorMatrix.size() / 3;
668 if (numColorPlanes == 3 && as_shot_white_xy->
count == 2) {
670 const float x = as_shot_white_xy->
getFloat(0);
671 const float y = as_shot_white_xy->
getFloat(1);
673 constexpr float Y = 1.0F;
674 const std::array<float, 3> as_shot_white = {
675 {
x * Y /
y, Y, (1 -
x -
y) * Y /
y}};
678 std::array<float, 4> wbCoeffs = {};
681 float c = (
float(
mRaw->metadata.colorMatrix[(i * 3) + 0]) *
683 (
float(
mRaw->metadata.colorMatrix[(i * 3) + 1]) *
685 (
float(
mRaw->metadata.colorMatrix[(i * 3) + 2]) *
687 wbCoeffs[i] = (c > 0.0F) ? (1.0F / c) : 0.0F;
689 mRaw->metadata.wbCoeffs = wbCoeffs;
697 mRaw->metadata.isoSpeed =
705 mRaw->setError(e.what());
711 mRaw->metadata.make =
id.make;
712 mRaw->metadata.model =
id.model;
716 cam = meta->
getCamera(
id.make,
id.model,
"");
718 cam = meta->
getCamera(
id.make,
id.model);
725 mRaw->metadata.canonical_make =
id.make;
726 mRaw->metadata.canonical_model =
mRaw->metadata.canonical_alias =
id.model;
728 mRaw->metadata.canonical_id =
731 mRaw->metadata.canonical_id =
id.make +
" " +
id.model;
776 mRaw->getUncroppedDim().y);
779 for (
uint32_t i = 0; i < nrects; i++) {
780 iPoint2D topleft(rects[(i * 4UL) + 1UL], rects[i * 4UL]);
781 iPoint2D bottomright(rects[(i * 4UL) + 3UL], rects[(i * 4UL) + 2UL]);
785 (topleft < bottomright)))
790 if (topleft.
x <= top.
x && bottomright.
x >= (
mRaw->dim.x + top.
x)) {
791 mRaw->blackAreas.emplace_back(topleft.
y, bottomright.
y - topleft.
y,
796 else if (topleft.
y <= top.
y && bottomright.
y >= (
mRaw->dim.y + top.
y)) {
797 mRaw->blackAreas.emplace_back(topleft.
x, bottomright.
x - topleft.
x,
true);
800 return !
mRaw->blackAreas.empty();
807 if (bleveldim->
count == 2)
809 else if (bleveldim->
count == 1) {
826 if (
mRaw->getCpp() != 1)
830 if (black_entry->
count < blackdim.
area())
831 ThrowRDE(
"BLACKLEVEL entry is too small");
833 using BlackType =
decltype(
mRaw->blackLevelSeparateStorage)::value_type;
835 if (blackdim.
x < 2 || blackdim.
y < 2) {
837 float value = black_entry->
getFloat();
839 if (
static_cast<double>(value) < std::numeric_limits<BlackType>::min() ||
840 static_cast<double>(value) > std::numeric_limits<BlackType>::max())
841 ThrowRDE(
"Error decoding black level");
843 mRaw->blackLevelSeparate =
845 auto blackLevelSeparate1D = *
mRaw->blackLevelSeparate->getAsArray1DRef();
846 for (
int y = 0;
y < 2;
y++) {
847 for (
int x = 0;
x < 2;
x++)
851 mRaw->blackLevelSeparate =
853 auto blackLevelSeparate1D = *
mRaw->blackLevelSeparate->getAsArray1DRef();
854 for (
int y = 0;
y < 2;
y++) {
855 for (
int x = 0;
x < 2;
x++) {
856 float value = black_entry->
getFloat((
y * blackdim.
x) +
x);
858 if (
static_cast<double>(value) <
859 std::numeric_limits<BlackType>::min() ||
860 static_cast<double>(value) > std::numeric_limits<BlackType>::max())
861 ThrowRDE(
"Error decoding black level");
872 if (
static_cast<int>(blackleveldeltav->
count) <
mRaw->dim.y)
873 ThrowRDE(
"BLACKLEVELDELTAV array is too small");
874 std::array<float, 2> black_sum = {{}};
875 for (
int i = 0; i <
mRaw->dim.y; i++)
876 black_sum[i & 1] += blackleveldeltav->
getFloat(i);
878 auto blackLevelSeparate1D = *
mRaw->blackLevelSeparate->getAsArray1DRef();
879 for (
int i = 0; i < 4; i++) {
881 black_sum[i >> 1] /
static_cast<float>(
mRaw->dim.y) * 2.0F;
882 if (
static_cast<double>(value) < std::numeric_limits<BlackType>::min() ||
883 static_cast<double>(value) > std::numeric_limits<BlackType>::max())
884 ThrowRDE(
"Error decoding black level");
886 if (__builtin_sadd_overflow(blackLevelSeparate1D(i),
888 &blackLevelSeparate1D(i)))
889 ThrowRDE(
"Integer overflow when calculating black level");
896 if (
static_cast<int>(blackleveldeltah->
count) <
mRaw->dim.x)
897 ThrowRDE(
"BLACKLEVELDELTAH array is too small");
898 std::array<float, 2> black_sum = {{}};
899 for (
int i = 0; i <
mRaw->dim.x; i++)
900 black_sum[i & 1] += blackleveldeltah->
getFloat(i);
902 auto blackLevelSeparate1D = *
mRaw->blackLevelSeparate->getAsArray1DRef();
903 for (
int i = 0; i < 4; i++) {
905 black_sum[i & 1] /
static_cast<float>(
mRaw->dim.x) * 2.0F;
906 if (
static_cast<double>(value) < std::numeric_limits<BlackType>::min() ||
907 static_cast<double>(value) > std::numeric_limits<BlackType>::max())
908 ThrowRDE(
"Error decoding black level");
910 if (__builtin_sadd_overflow(blackLevelSeparate1D(i),
912 &blackLevelSeparate1D(i)))
913 ThrowRDE(
"Integer overflow when calculating black level");
926 mRaw->blackLevelSeparate =
928 auto blackLevelSeparate1D = *
mRaw->blackLevelSeparate->getAsArray1DRef();
929 std::fill(blackLevelSeparate1D.begin(), blackLevelSeparate1D.end(), 0);
assert(dim.area() >=area)
const DngTilingDescription dsc
std::vector< DngSliceElement > slices
bool checkCameraSupported(const CameraMetaData *meta, const TiffID &id, const std::string &mode)
AbstractTiffDecoder(TiffRootIFDOwner &&root, Buffer file)
TiffRootIFDOwner mRootIFD
std::string canonical_alias
std::string canonical_model
std::string canonical_make
DngDecoder(TiffRootIFDOwner &&rootIFD, Buffer file)
void decodeMetaDataInternal(const CameraMetaData *meta) override
void setBlack(const TiffIFD *raw) const
bool decodeMaskedAreas(const TiffIFD *raw) const
bool decodeBlackLevels(const TiffIFD *raw) const
void parseCFA(const TiffIFD *raw) const
void decodeData(const TiffIFD *raw, uint32_t sample_format) const
RawImage decodeRawInternal() override
static bool isAppropriateDecoder(const TiffRootIFD *rootIFD, Buffer file)
static void dropUnsuportedChunks(std::vector< const TiffIFD * > *data)
void handleMetadata(const TiffIFD *raw)
DngTilingDescription getTilingDescription(const TiffIFD *raw) const
void checkSupportInternal(const CameraMetaData *meta) override
void parseWhiteBalance() const
Optional< iRectangle2D > parseACTIVEAREA(const TiffIFD *raw) const
void parseColorMatrix() const
void applyOpCodes(const RawImage &ri) const
bool insert(const T &newElt)
bool uncorrectedRawValues
bool applyStage1DngOpcodes
static RawImage create(RawImageType type=RawImageType::UINT16)
std::vector< uint32_t > getU32Array(uint32_t count_) const
std::vector< NotARational< int32_t > > getSRationalArray(uint32_t count_) const
std::vector< uint16_t > getU16Array(uint32_t count_) const
float getFloat(uint32_t index=0) const
uint32_t getU32(uint32_t index=0) const
bool RAWSPEED_READONLY isInt() const
std::vector< NotARational< uint32_t > > getRationalArray(uint32_t count_) const
ByteStream getData() const
uint16_t getU16(uint32_t index=0) const
uint8_t getByte(uint32_t index=0) const
bool RAWSPEED_READONLY hasEntry(TiffTag tag) const
TiffEntry * getEntry(TiffTag tag) const
bool hasEntryRecursive(TiffTag tag) const
area_type RAWSPEED_READONLY area() const
bool RAWSPEED_READONLY hasPositiveArea() const
constexpr bool RAWSPEED_READONLY isPointInsideInclusive(const iPoint2D &subPoint) const
void setTopLeft(const iPoint2D &top_left)
constexpr bool RAWSPEED_READONLY isThisInside(const iRectangle2D &superRect) const
void setBottomRightAbsolute(const iPoint2D &bottom_right)
constexpr iPoint2D getTopLeft() const
constexpr iPoint2D getBottomRight() const
Optional< CFAColor > getDNGCFAPatternAsCFAColor(uint32_t c)
constexpr uint64_t RAWSPEED_READNONE roundUpDivisionSafe(uint64_t value, uint64_t div)
constexpr RAWSPEED_READNONE Ttgt implicit_cast(Tsrc value)
std::unique_ptr< TiffRootIFD > TiffRootIFDOwner
void writeLog(DEBUG_PRIO priority, const char *format,...)
Array2DRef(Array1DRef< T > data, int width, int height, int pitch) -> Array2DRef< T >
@ PHOTOMETRICINTERPRETATION