63 [[maybe_unused]]
Buffer file) {
64 const auto id = rootIFD->
getID();
65 const std::string& make =
id.
make;
69 return make ==
"Panasonic" || make ==
"LEICA" || make ==
"LEICA CAMERA AG";
77 std::vector<T>& output) {
79 output.resize(bs.
getU16());
117 ThrowRDE(
"Strip byte offset list does not have enough entries for the "
118 "number of strips!");
120 ThrowRDE(
"Strip widths list does not have enough entries for the number of "
123 ThrowRDE(
"Strip heights list does not have enough entries for the number "
126 ThrowRDE(
"Strip line offset list does not have enough entries for the "
127 "number of strips!");
129 ThrowRDE(
"Strip bit length list does not have enough entries for the "
130 "number of strips!");
134 ThrowRDE(
"Non-zero shift down value encountered! Shift down decoding has "
135 "never been tested!");
138 if (
gammaClipVal != std::numeric_limits<uint16_t>::max()) {
139 ThrowRDE(
"Got non-no-op gammaClipVal (%u). Not known to happen "
140 "in-the-wild. Please file a bug!",
186 std::vector<uint16_t> mGammaLUT;
189 std::vector<uint32_t> encodedGammaPoints;
190 std::vector<uint32_t> encodedGammaSlopes;
199 const bool gamamPointsAreIdentity =
200 std::all_of(encodedGammaPoints.cbegin(), encodedGammaPoints.cend(),
201 [](
const uint32_t p) { return p == 0U; });
202 const bool gammaSlopesAreIdentity =
203 std::all_of(encodedGammaSlopes.cbegin(), encodedGammaSlopes.cend(),
204 [](
const uint32_t s) { return s == 65536U; });
206 if (!gamamPointsAreIdentity || !gammaSlopesAreIdentity) {
208 ThrowRDE(
"Non-identity gamma curve encountered. Never encountered in any "
211#pragma GCC diagnostic push
212#pragma GCC diagnostic ignored "-Wunreachable-code"
213 if (encodedGammaPoints.size() != 6 || encodedGammaSlopes.size() != 6) {
214 ThrowRDE(
"Gamma curve point and/or slope list is not the expected length "
217#pragma GCC diagnostic pop
221std::vector<Array1DRef<const uint8_t>>
223 std::vector<Array1DRef<const uint8_t>> mStrips;
225 const int totalStrips =
228 for (
int stripIdx = 0; stripIdx < totalStrips; ++stripIdx) {
246 ThrowRDE(
"Unexpected CFA, only RGGB is supported");
248 const DecompressorV8Params mParams(raw);
249 populateGammaLUT(mParams, raw);
250 const std::vector<Array1DRef<const uint8_t>> mStrips =
251 getInputStrips(mParams,
mFile);
269 bool isOldPanasonic =
280 if (isOldPanasonic) {
281 if (width == 0 || height == 0 || width > 4330 || height > 2751)
282 ThrowRDE(
"Unexpected image dimensions found: (%u; %u)", width, height);
286 if (offsets->
count != 1) {
290 if (!
mFile.isValid(offset))
291 ThrowRDE(
"Invalid image data offset, cannot decode.");
297 if (size >= width * height * 2) {
305 }
else if (size >= width * height * 3 / 2) {
318 hints.contains(
"zero_is_not_bad"), section_split_offset);
327 if (offsets->
count != 1) {
342 uint32_t section_split_offset = 0x1FF8;
344 section_split_offset);
356 if (bitsPerSample != 14 && bitsPerSample != 12)
357 ThrowRDE(
"Version %i: unexpected bits per sample: %i", version,
366 if (bitsPerSample != 14)
367 ThrowRDE(
"Version %i: unexpected bits per sample: %i", version,
377 if (bitsPerSample > 16)
378 ThrowRDE(
"Version %i: unexpected bits per sample: %i", version,
383 ThrowRDE(
"Version %i is unsupported", version);
398 ThrowRDE(
"No PANASONIC_CFAPATTERN entry found!");
403 ThrowRDE(
"Bad PANASONIC_CFAPATTERN entry (type %u, count %u).",
404 static_cast<unsigned>(CFA->
type), CFA->
count);
407 switch (
auto i = CFA->
getU16()) {
422 ThrowRDE(
"Unexpected CFA pattern: %u", i);
444 mRaw->metadata.mode = mode;
455 auto blackLevelsNeedOffsetting = [&]() {
456 bool isOldPanasonic =
465 const auto getBlack = [&raw, blackLevelsNeedOffsetting](
TiffTag t) {
467 if (!blackLevelsNeedOffsetting())
471 if (__builtin_sadd_overflow(
val, 15, &out))
472 ThrowRDE(
"Integer overflow when calculating black level");
476 const int blackRed = getBlack(
static_cast<TiffTag>(0x1c));
477 const int blackGreen = getBlack(
static_cast<TiffTag>(0x1d));
478 const int blackBlue = getBlack(
static_cast<TiffTag>(0x1e));
480 mRaw->blackLevelSeparate =
482 auto blackLevelSeparate1D = *
mRaw->blackLevelSeparate->getAsArray1DRef();
483 for (
int i = 0; i < 2; i++) {
484 for (
int j = 0; j < 2; j++) {
485 const int k = i + (2 * j);
489 blackLevelSeparate1D(k) = blackRed;
492 blackLevelSeparate1D(k) = blackGreen;
495 blackLevelSeparate1D(k) = blackBlue;
498 ThrowRDE(
"Unexpected CFA color %s.",
509 std::array<float, 4> wbCoeffs = {};
510 wbCoeffs[0] =
static_cast<float>(
512 wbCoeffs[1] =
static_cast<float>(
514 wbCoeffs[2] =
static_cast<float>(
516 mRaw->metadata.wbCoeffs = wbCoeffs;
519 std::array<float, 4> wbCoeffs = {};
520 wbCoeffs[0] =
static_cast<float>(
522 wbCoeffs[1] = 256.0F;
523 wbCoeffs[2] =
static_cast<float>(
525 mRaw->metadata.wbCoeffs = wbCoeffs;
530 float ratio = 3.0F / 2.0F;
532 if (!
mRaw->isAllocated())
535 ratio =
static_cast<float>(
mRaw->dim.x) /
static_cast<float>(
mRaw->dim.y);
537 float min_diff = fabs(ratio - (16.0F / 9.0F));
538 std::string closest_match =
"16:9";
540 float t = fabs(ratio - (3.0F / 2.0F));
542 closest_match =
"3:2";
546 t = fabs(ratio - (4.0F / 3.0F));
548 closest_match =
"4:3";
552 t = fabs(ratio - 1.0F);
554 closest_match =
"1:1";
558 return closest_match;
575 const uint16_t width = rightBorder - leftBorder;
576 const uint16_t height = bottomBorder - topBorder;
577 return {leftBorder, topBorder, width, height};
579 ThrowRDE(
"Cannot figure out vendor crop. Required entries were not found: "
bool checkCameraSupported(const CameraMetaData *meta, const TiffID &id, const std::string &mode)
void setMetaData(const CameraMetaData *meta, const TiffID &id, const std::string &mode, int iso_speed)
TiffRootIFDOwner mRootIFD
Array1DRef< const uint8_t > getAsArray1DRef() const
Buffer getSubView(size_type offset, size_type size_) const
static std::string colorToString(CFAColor c)
void decompress() const noexcept
void decompress() const noexcept
std::array< uint16_t, 4 > Bayer2x2
Four values, one for each component of the sensor's color filter array.
void decompress() const
Run the decompressor on the provided raw image.
std::string guessMode() const
iRectangle2D getDefaultCrop() override
void decodeMetaDataInternal(const CameraMetaData *meta) override
void checkSupportInternal(const CameraMetaData *meta) override
RawImage decodeRawV8(const TiffIFD &raw) const
static bool isAppropriateDecoder(const TiffRootIFD *rootIFD, Buffer file)
const TiffIFD * getRaw() const
RawImage decodeRawInternal() override
uint32_t getU32(uint32_t index=0) const
ByteStream getData() const
uint16_t getU16(uint32_t index=0) const
bool RAWSPEED_READONLY hasEntry(TiffTag tag) const
TiffEntry * getEntry(TiffTag tag) const
void populateGammaLUT(const DecompressorV8Params &mParams, const TiffIFD &ifd)
std::vector< Array1DRef< const uint8_t > > getInputStrips(const DecompressorV8Params &mParams, Buffer mInputFile)
void getPanasonicTiffVector(const TiffIFD &ifd, TiffTag tag, std::vector< T > &output)
Retrieve list of values from Panasonic TiffTag.
Optional< BayerPhase > getAsBayerPhase(const ColorFilterArray &CFA)
void writeLog(DEBUG_PRIO priority, const char *format,...)
Array2DRef(Array1DRef< T > data, int width, int height, int pitch) -> Array2DRef< T >
Array1DRef< const T > getAsArray1DRef(const std::vector< T > &vec)
@ PANASONIC_V8_STRIP_BYTE_OFFSETS
@ PANASONIC_V8_NUMBER_OF_STRIPS_V
@ PANASONIC_V8_STRIP_WIDTHS
@ PANASONIC_V8_NUMBER_OF_STRIPS_H
@ PANASONIC_V8_STRIP_LINE_OFFSETS
@ PANASONIC_V8_HUF_SHIFT_DOWN
@ PANASONIC_V8_INIT_PRED_GREEN1
@ PANASONIC_V8_INIT_PRED_BLUE
@ PANASONIC_V8_GAMMA_SLOPES
@ PANASONIC_SENSORTOPBORDER
@ PANASONIC_SENSORLEFTBORDER
@ PANASONIC_V8_INIT_PRED_RED
@ PANASONIC_SENSORBOTTOMBORDER
@ PANASONIC_V8_INIT_PRED_GREEN2
@ PANASONIC_V8_STRIP_DATA_SIZE
@ PANASONIC_BITSPERSAMPLE
@ PANASONIC_V8_STRIP_HEIGHTS
@ PANASONIC_V8_GAMMA_POINTS
@ PANASONIC_SENSORRIGHTBORDER
DecompressorParams getDecompressorParams() const
std::vector< uint32_t > stripBitLengths
DecompressorV8Params()=delete
std::vector< uint32_t > stripByteOffsets
std::vector< uint16_t > shiftDown
Decoding shift down value. Appears to be unused.
std::vector< uint32_t > stripLineOffsets
PanasonicV8Decompressor::Bayer2x2 initialPrediction
std::vector< uint16_t > stripWidths
uint16_t verticalStripCount
std::vector< uint16_t > stripHeights
uint16_t horizontalStripCount