61 [[maybe_unused]]
Buffer file) {
62 const auto id = rootIFD->
getID();
63 const std::string& make =
id.
make;
67 return make ==
"SONY";
76 if (width == 0 || height == 0 || width > 3360 || height > 2460)
77 ThrowRDE(
"Unexpected image dimensions found: (%u; %u)", width, height);
87 uint8_t offset =
mFile[key_off];
88 const Buffer keyData =
mFile.getSubView(key_off + (4 * offset), 4);
91 static const size_t head_size = 40;
92 const auto head_orig =
93 mFile.getSubView(head_off, head_size).getAsArray1DRef();
94 vector<uint8_t> head(head_size);
95 SonyDecrypt(head_orig, {head.data(), head_size}, head_size / 4, key);
96 for (
int i = 26; i > 22; i--)
97 key = key << 8 | head[i - 1];
100 const auto image_data =
mFile.getSubView(off, len).getAsArray1DRef();
101 std::vector<uint8_t> image_decoded(len);
105 Buffer di(image_decoded.data(), len);
115 u.readUncompressedRaw();
122 model && model->getString() ==
"DSLR-A100") {
141 if (
hints.contains(
"srf_format"))
148 std::vector<uint16_t> curve(0x4001);
150 std::array<uint32_t, 6> sony_curve = {{0, 0, 0, 0, 0, 4095}};
153 sony_curve[i + 1] = (c->
getU16(i) >> 2) & 0xfff;
155 for (
uint32_t i = 0; i < 0x4001; i++)
159 for (
uint32_t j = sony_curve[i] + 1; j <= sony_curve[i + 1]; j++)
173 if (1 == compression) {
178 if (7 == compression) {
185 if (32767 != compression)
186 ThrowRDE(
"Unsupported compression %i", compression);
191 if (offsets->
count != 1) {
196 "Byte count number does not match strip size: count:%u, strips:%u ",
203 switch (bitPerPixel) {
209 ThrowRDE(
"Unexpected bits per pixel: %u", bitPerPixel);
217 if (data.size() > 1) {
218 for (
auto& i : data) {
226 if (width == 0 || height == 0 || height % 2 != 0 || width > 9600 ||
228 ThrowRDE(
"Unexpected image dimensions found: (%u; %u)", width, height);
230 bool arw1 =
uint64_t(counts->
getU32()) * 8 != width * height * bitPerPixel;
243 if (!
mFile.isValid(off))
244 ThrowRDE(
"Data offset after EOF, file probably truncated");
246 if (!
mFile.isValid(off, c2))
247 c2 =
mFile.getSize() - off;
257 DecodeARW2(input, width, height, bitPerPixel);
260 if (bitPerPixel == 12)
274 if (width == 0 || height == 0 || width > 9600 || height > 6376)
275 ThrowRDE(
"Unexpected image dimensions found: (%u; %u)", width, height);
278 ThrowRDE(
"Strip is empty, nothing to decode!");
282 if (
hints.contains(
"sr2_format")) {
288 u.readUncompressedRaw();
295 u.readUncompressedRaw();
306 if (photometric != 32803)
307 ThrowRDE(
"Unsupported photometric interpretation: %u", photometric);
309 switch (bitPerPixel) {
315 ThrowRDE(
"Unexpected bits per pixel: %u", bitPerPixel);
318 if (width == 0 || height == 0 || width % 2 != 0 || height % 2 != 0 ||
319 width > 9728 || height > 6656)
320 ThrowRDE(
"Unexpected image dimensions found: (%u; %u)", width, height);
327 if (tilew <= 0 || tileh <= 0 || tileh % 2 != 0)
328 ThrowRDE(
"Invalid tile size: (%" PRIu64
", %u)", tilew, tileh);
334 ThrowRDE(
"Zero tiles horizontally");
351 ThrowRDE(
"Tile count mismatch: offsets:%u count:%u", offsets->
count,
356 if ((offsets->
count / tilesX != tilesY || (offsets->
count % tilesX != 0)) ||
357 (offsets->
count / tilesY != tilesX || (offsets->
count % tilesY != 0))) {
358 ThrowRDE(
"Tile X/Y count mismatch: total:%u X:%u, Y:%u", offsets->
count,
363 for (
int tile = 0U; tile < implicit_cast<int>(offsets->
count); tile++) {
366 if (!tilesLegality.
insert(
mFile.getSubView(offset, length)))
367 ThrowRDE(
"Two tiles overlap. Raw corrupt!");
372#pragma omp parallel for schedule(static) default(none) \
373 shared(offsets, counts) firstprivate(tilesX, tilew, tileh)
375 for (
int tile = 0U; tile < static_cast<int>(offsets->
count); tile++) {
377 const uint32_t tileX = tile % tilesX;
378 const uint32_t tileY = tile / tilesX;
387 auto offsetY = tileY * tileh;
389 auto tileHeight = tileh;
392 decoder.
decode(offsetX, offsetY, tileWidth, tileHeight, maxDim,
395 mRaw->setError(err.what());
397 mRaw->setError(err.what());
400 __builtin_unreachable();
404 std::string firstErr;
405 if (
mRaw->isTooManyErrors(1, &firstErr)) {
406 ThrowRDE(
"Too many errors encountered. Giving up. First Error:\n%s",
412 mRaw->subFrame(crop);
431 u.readUncompressedRaw();
457 ThrowRDE(
"Can not parse DNGPRIVATEDATA, invalid tag (0x%x).", tag);
471 ThrowRDE(
"Found entry of zero length, corrupt.");
473 if (0x574247 != tag) {
482 std::array<uint16_t, 4> tmp;
483 for (
auto& coeff : tmp)
486 std::array<float, 4> wbCoeffs = {};
487 wbCoeffs[0] =
static_cast<float>(tmp[0]);
488 wbCoeffs[1] =
static_cast<float>(tmp[1]);
489 wbCoeffs[2] =
static_cast<float>(tmp[3]);
490 mRaw->metadata.wbCoeffs = wbCoeffs;
510 if (
mRaw->whitePoint)
516 if (
id.model ==
"DSLR-A100") {
522 mRaw->setError(e.what());
536 std::array<uint32_t, 128> pad;
539 for (
int p = 0; p < 4; p++)
540 pad[p] = key =
uint32_t((key * 48828125UL) + 1UL);
541 pad[3] = pad[3] << 1 | (pad[0] ^ pad[2]) >> 31;
542 for (
int p = 4; p < 127; p++)
543 pad[p] = (pad[p - 4] ^ pad[p - 2]) << 1 | (pad[p - 3] ^ pad[p - 1]) >> 31;
544 for (
int p = 0; p < 127; p++)
549 for (
int i = 0; i != len; ++i) {
550 pad[p & 127] = pad[(p + 1) & 127] ^ pad[(p + 1 + 64) & 127];
581 if (!sony_offset || !sony_length || !sony_key || sony_key->
count != 4)
582 ThrowRDE(
"couldn't find the correct metadata for WB decoding");
584 assert(sony_offset !=
nullptr);
587 assert(sony_length !=
nullptr);
593 assert(sony_key !=
nullptr);
598 const auto EncryptedBuffer =
601 const auto DecryptedBufferSize = off + EncryptedBuffer.size();
602 std::vector<uint8_t> DecryptedBuffer(DecryptedBufferSize);
608 Buffer decIFD(DecryptedBuffer.data(), DecryptedBufferSize);
611 ifds_decoded.insert(Padding);
614 TiffRootIFD encryptedIFD(
nullptr, &ifds_decoded, dbIDD, off);
620 std::array<float, 4> wbCoeffs = {};
624 mRaw->metadata.wbCoeffs = wbCoeffs;
629 std::array<float, 4> wbCoeffs = {};
633 mRaw->metadata.wbCoeffs = wbCoeffs;
639 ThrowRDE(
"Black Level has %u entries instead of 4", bl->
count);
640 mRaw->blackLevelSeparate =
642 auto blackLevelSeparate1D = *
mRaw->blackLevelSeparate->getAsArray1DRef();
643 for (
int i = 0; i < 4; ++i)
650 ThrowRDE(
"White Level has %u entries instead of 1 or 3", wl->
count);
assert(dim.area() >=area)
void setMetaData(const CameraMetaData *meta, const TiffID &id, const std::string &mode, int iso_speed)
TiffRootIFDOwner mRootIFD
CroppedArray1DRef< T > getBlock(int numElts, int index) const
int RAWSPEED_READONLY size() const
void decodeMetaDataInternal(const CameraMetaData *meta) override
void DecodeARW2(ByteStream input, uint32_t w, uint32_t h, uint32_t bpp)
static std::vector< uint16_t > decodeCurve(const TiffIFD *raw)
static void SonyDecrypt(Array1DRef< const uint8_t > ibuf, Array1DRef< uint8_t > obuf, int len, uint32_t key)
RawImage decodeTransitionalArw()
int mShiftDownScaleForExif
RawImage decodeRawInternal() override
void DecodeUncompressed(const TiffIFD *raw) const
void DecodeLJpeg(const TiffIFD *raw)
static bool isAppropriateDecoder(const TiffRootIFD *rootIFD, Buffer file)
Array1DRef< const uint8_t > getAsArray1DRef() const
Buffer getSubView(size_type offset, size_type size_) const
const uint8_t * begin() const
size_type check(size_type bytes) const
size_type RAWSPEED_READONLY getRemainSize() const
const uint8_t * getData(size_type count)
ByteStream getSubStream(size_type offset, size_type size_) const
void skipBytes(size_type nbytes)
size_type getPosition() const
Endianness getByteOrder() const
Endianness setByteOrder(Endianness endianness_)
void decode(uint32_t offsetX, uint32_t offsetY, uint32_t width, uint32_t height, iPoint2D maxDim, bool fixDng16Bug_)
bool insert(const T &newElt)
bool uncorrectedRawValues
void decompress(ByteStream input) const
DataBuffer getRootIfdData() const
float getFloat(uint32_t index=0) const
uint32_t getU32(uint32_t index=0) const
ByteStream getData() const
uint16_t getU16(uint32_t index=0) const
TiffEntry *RAWSPEED_READONLY getEntryRecursive(TiffTag tag) const
bool RAWSPEED_READONLY hasEntry(TiffTag tag) const
TiffEntry * getEntry(TiffTag tag) const
constexpr uint64_t RAWSPEED_READNONE roundUpDivisionSafe(uint64_t value, uint64_t div)
constexpr RAWSPEED_READNONE Ttgt implicit_cast(Tsrc value)
constexpr uint64_t RAWSPEED_READNONE roundDown(uint64_t value, uint64_t multiple)
Array2DRef(Array1DRef< T > data, int width, int height, int pitch) -> Array2DRef< T >
void RAWSPEED_UNLIKELY_FUNCTION RAWSPEED_NOINLINE static char buf[bufSize]
@ PHOTOMETRICINTERPRETATION
uint32_t getU32LE(const void *data)
uint32_t getU32BE(const void *data)