Skip to content

Commit 65c98e1

Browse files
authored
Merge pull request #638 from LebedevRI/unknown-white-level
Unknown white level
2 parents 34e2a63 + 5519924 commit 65c98e1

File tree

12 files changed

+56
-41
lines changed

12 files changed

+56
-41
lines changed

src/librawspeed/adt/Optional.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ template <typename T> class Optional final {
8787

8888
explicit operator bool() const { return has_value(); }
8989

90+
template <typename U> T value_or(U&& fallback) const& {
91+
return impl.value_or(std::forward<U>(fallback));
92+
}
93+
9094
void reset() { impl.reset(); }
9195
};
9296

src/librawspeed/common/RawImage.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ class RawImageData : public ErrorLog {
163163
int blackLevel = -1;
164164
std::array<int, 4> blackLevelSeparateStorage;
165165
Optional<Array2DRef<int>> blackLevelSeparate;
166-
int whitePoint = 65536;
166+
Optional<int> whitePoint;
167167
std::vector<BlackArea> blackAreas;
168168

169169
/* Vector containing the positions of bad pixels */

src/librawspeed/common/RawImageDataFloat.cpp

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,8 @@ void RawImageDataFloat::scaleBlackWhite() {
122122

123123
const int skipBorder = 150;
124124
int gw = (dim.x - skipBorder) * cpp;
125-
if ((blackAreas.empty() && !blackLevelSeparate && blackLevel < 0) ||
126-
whitePoint == 65536) { // Estimate
125+
// NOTE: lack of whitePoint means that it is pre-normalized.
126+
if (blackAreas.empty() && !blackLevelSeparate && blackLevel < 0) { // Estimate
127127
float b = 100000000;
128128
float m = -10000000;
129129
for (int row = skipBorder * cpp; row < (dim.y - skipBorder); row++) {
@@ -135,10 +135,7 @@ void RawImageDataFloat::scaleBlackWhite() {
135135
}
136136
if (blackLevel < 0)
137137
blackLevel = static_cast<int>(b);
138-
if (whitePoint == 65536)
139-
whitePoint = static_cast<int>(m);
140-
writeLog(DEBUG_PRIO::INFO, "Estimated black:%d, Estimated white: %d",
141-
blackLevel, whitePoint);
138+
writeLog(DEBUG_PRIO::INFO, "Estimated black:%d", blackLevel);
142139
}
143140

144141
/* If filter has not set separate blacklevel, compute or fetch it */
@@ -161,8 +158,8 @@ void RawImageDataFloat::scaleValues(int start_y, int end_y) {
161158
v ^= 1;
162159
if ((mOffset.y & 1) != 0)
163160
v ^= 2;
164-
mul[i] =
165-
65535.0F / static_cast<float>(whitePoint - blackLevelSeparate1D(v));
161+
mul[i] = 65535.0F / static_cast<float>(whitePoint.value_or(1.0F) -
162+
blackLevelSeparate1D(v));
166163
sub[i] = static_cast<float>(blackLevelSeparate1D(v));
167164
}
168165
for (int y = start_y; y < end_y; y++) {

src/librawspeed/common/RawImageDataU16.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ void RawImageDataU16::scaleBlackWhite() {
149149
const int skipBorder = 250;
150150
int gw = (dim.x - skipBorder) * cpp;
151151
if ((blackAreas.empty() && !blackLevelSeparate && blackLevel < 0) ||
152-
whitePoint >= 65536) { // Estimate
152+
!whitePoint) { // Estimate
153153
int b = 65536;
154154
int m = 0;
155155
auto img = getU16DataAsCroppedArray2DRef();
@@ -162,11 +162,11 @@ void RawImageDataU16::scaleBlackWhite() {
162162
}
163163
if (blackLevel < 0)
164164
blackLevel = b;
165-
if (whitePoint >= 65536)
165+
if (!whitePoint)
166166
whitePoint = m;
167167
writeLog(DEBUG_PRIO::INFO,
168168
"ISO:%d, Estimated black:%d, Estimated white: %d",
169-
metadata.isoSpeed, blackLevel, whitePoint);
169+
metadata.isoSpeed, blackLevel, *whitePoint);
170170
}
171171

172172
/* Skip, if not needed */
@@ -189,7 +189,7 @@ void RawImageDataU16::scaleValues(int start_y, int end_y) {
189189

190190
#else
191191

192-
int depth_values = whitePoint - (*blackLevelSeparate)(0, 0);
192+
int depth_values = *whitePoint - (*blackLevelSeparate)(0, 0);
193193
float app_scale = 65535.0F / implicit_cast<float>(depth_values);
194194

195195
// Check SSE2
@@ -207,7 +207,7 @@ void RawImageDataU16::scaleValues_SSE2(int start_y, int end_y) {
207207
assert(blackLevelSeparate->width() == 2 && blackLevelSeparate->height() == 2);
208208
auto blackLevelSeparate1D = *blackLevelSeparate->getAsArray1DRef();
209209

210-
int depth_values = whitePoint - blackLevelSeparate1D(0);
210+
int depth_values = *whitePoint - blackLevelSeparate1D(0);
211211
float app_scale = 65535.0F / implicit_cast<float>(depth_values);
212212

213213
// Scale in 30.2 fp
@@ -228,10 +228,10 @@ void RawImageDataU16::scaleValues_SSE2(int start_y, int end_y) {
228228
// 10 bit fraction
229229
uint32_t mul = static_cast<int>(
230230
1024.0F * 65535.0F /
231-
static_cast<float>(whitePoint - blackLevelSeparate1D(mOffset.x & 1)));
231+
static_cast<float>(*whitePoint - blackLevelSeparate1D(mOffset.x & 1)));
232232
mul |= (static_cast<int>(
233233
1024.0F * 65535.0F /
234-
static_cast<float>(whitePoint -
234+
static_cast<float>(*whitePoint -
235235
blackLevelSeparate1D((mOffset.x + 1) & 1))))
236236
<< 16;
237237
uint32_t b = blackLevelSeparate1D(mOffset.x & 1) |
@@ -244,12 +244,12 @@ void RawImageDataU16::scaleValues_SSE2(int start_y, int end_y) {
244244

245245
mul = static_cast<int>(
246246
1024.0F * 65535.0F /
247-
static_cast<float>(whitePoint -
247+
static_cast<float>(*whitePoint -
248248
blackLevelSeparate1D(2 + (mOffset.x & 1))));
249249
mul |= (static_cast<int>(
250250
1024.0F * 65535.0F /
251-
static_cast<float>(
252-
whitePoint - blackLevelSeparate1D(2 + ((mOffset.x + 1) & 1)))))
251+
static_cast<float>(*whitePoint - blackLevelSeparate1D(
252+
2 + ((mOffset.x + 1) & 1)))))
253253
<< 16;
254254
b = blackLevelSeparate1D(2 + (mOffset.x & 1)) |
255255
(blackLevelSeparate1D(2 + ((mOffset.x + 1) & 1)) << 16);
@@ -348,7 +348,7 @@ void RawImageDataU16::scaleValues_plain(int start_y, int end_y) {
348348
assert(blackLevelSeparate->width() == 2 && blackLevelSeparate->height() == 2);
349349
auto blackLevelSeparate1D = *blackLevelSeparate->getAsArray1DRef();
350350

351-
int depth_values = whitePoint - blackLevelSeparate1D(0);
351+
int depth_values = *whitePoint - blackLevelSeparate1D(0);
352352
float app_scale = 65535.0F / implicit_cast<float>(depth_values);
353353

354354
// Scale in 30.2 fp
@@ -368,7 +368,7 @@ void RawImageDataU16::scaleValues_plain(int start_y, int end_y) {
368368
v ^= 2;
369369
mul[i] = static_cast<int>(
370370
16384.0F * 65535.0F /
371-
static_cast<float>(whitePoint - blackLevelSeparate1D(v)));
371+
static_cast<float>(*whitePoint - blackLevelSeparate1D(v)));
372372
sub[i] = blackLevelSeparate1D(v);
373373
}
374374
for (int y = start_y; y < end_y; y++) {

src/librawspeed/decoders/ArwDecoder.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,8 @@ void ArwDecoder::decodeMetaDataInternal(const CameraMetaData* meta) {
538538
auto id = mRootIFD->getID();
539539

540540
setMetaData(meta, id, "", iso);
541-
mRaw->whitePoint >>= mShiftDownScale;
541+
if (mRaw->whitePoint)
542+
mRaw->whitePoint = *mRaw->whitePoint >> mShiftDownScale;
542543
mRaw->blackLevel >>= mShiftDownScale;
543544

544545
// Set the whitebalance

src/librawspeed/decoders/Cr2Decoder.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ bool Cr2Decoder::decodeCanonColorData() const {
421421
for (int c = 0; c != 4; ++c)
422422
blackLevelSeparate1D(c) >>= bitDepthDiff;
423423
}
424-
mRaw->whitePoint >>= bitDepthDiff;
424+
mRaw->whitePoint = *mRaw->whitePoint >> bitDepthDiff;
425425
}
426426

427427
return true;
@@ -500,10 +500,10 @@ void Cr2Decoder::decodeMetaDataInternal(const CameraMetaData* meta) {
500500
mRaw->blackLevel = 0;
501501
mRaw->blackLevelSeparate = std::nullopt;
502502
}
503-
if (mShiftUpScaleForExif != 0 && isPowerOfTwo(1 + mRaw->whitePoint))
504-
mRaw->whitePoint = ((1 + mRaw->whitePoint) << mShiftUpScaleForExif) - 1;
503+
if (mShiftUpScaleForExif != 0 && isPowerOfTwo(1 + *mRaw->whitePoint))
504+
mRaw->whitePoint = ((1 + *mRaw->whitePoint) << mShiftUpScaleForExif) - 1;
505505
else
506-
mRaw->whitePoint <<= mShiftUpScaleForExif;
506+
mRaw->whitePoint = *mRaw->whitePoint << mShiftUpScaleForExif;
507507
}
508508

509509
bool Cr2Decoder::isSubSampled() const {

src/librawspeed/decoders/DngDecoder.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -602,9 +602,9 @@ void DngDecoder::handleMetadata(const TiffIFD* raw) {
602602
// Default white level is (2 ** BitsPerSample) - 1
603603
mRaw->whitePoint = implicit_cast<int>((1UL << bps) - 1UL);
604604
} else if (mRaw->getDataType() == RawImageType::F32) {
605-
// Default white level is 1.0f. But we can't represent that here.
606-
// Fall back to uninitialized value instead.
607-
mRaw->whitePoint = 65536;
605+
// Default white level is 1.0f. But we can't represent that here,
606+
// so just claim that we don't know it, and users shall default to 1.0F.
607+
mRaw->whitePoint.reset();
608608
}
609609

610610
if (raw->hasEntry(TiffTag::WHITELEVEL)) {

src/librawspeed/decoders/NefDecoder.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -612,8 +612,8 @@ void NefDecoder::decodeMetaDataInternal(const CameraMetaData* meta) {
612612
mRaw->cfa.setCFA(iPoint2D(2, 2), CFAColor::RED, CFAColor::GREEN,
613613
CFAColor::GREEN, CFAColor::BLUE);
614614

615-
int white = mRaw->whitePoint;
616-
int black = mRaw->blackLevel;
615+
auto makernotesWhite = mRaw->whitePoint;
616+
int makernotesBlack = mRaw->blackLevel;
617617

618618
if (mRootIFD->hasEntryRecursive(TiffTag::ISOSPEEDRATINGS))
619619
iso = mRootIFD->getEntryRecursive(TiffTag::ISOSPEEDRATINGS)->getU32();
@@ -651,10 +651,10 @@ void NefDecoder::decodeMetaDataInternal(const CameraMetaData* meta) {
651651
setMetaData(meta, id, "", iso);
652652
}
653653

654-
if (white != 65536)
655-
mRaw->whitePoint = white;
656-
if (black != -1)
657-
mRaw->blackLevel = black;
654+
if (makernotesWhite)
655+
mRaw->whitePoint = *makernotesWhite;
656+
if (makernotesBlack != -1)
657+
mRaw->blackLevel = makernotesBlack;
658658
}
659659

660660
// DecodeNikonYUY2 decodes 12 bit data in an YUY2-like pattern (2 Luma, 1 Chroma

src/librawspeed/decoders/OrfDecoder.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,8 @@ void OrfDecoder::decodeMetaDataInternal(const CameraMetaData* meta) {
346346
}
347347
// Adjust whitelevel based on the read black (we assume the dynamic
348348
// range is the same)
349-
mRaw->whitePoint -= (mRaw->blackLevel - blackLevelSeparate1D(0));
349+
mRaw->whitePoint =
350+
*mRaw->whitePoint - (mRaw->blackLevel - blackLevelSeparate1D(0));
350351
}
351352
}
352353
}

src/librawspeed/decompressors/VC5Decompressor.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -415,11 +415,11 @@ VC5Decompressor::VC5Decompressor(ByteStream bs, const RawImage& img)
415415
}
416416
}
417417

418-
if (img->whitePoint <= 0 || img->whitePoint > int(((1U << 16U) - 1U)))
419-
ThrowRDE("Bad white level %i", img->whitePoint);
418+
if (*img->whitePoint <= 0 || *img->whitePoint > int(((1U << 16U) - 1U)))
419+
ThrowRDE("Bad white level %i", *img->whitePoint);
420420

421421
outputBits = 0;
422-
for (int wp = img->whitePoint; wp != 0; wp >>= 1)
422+
for (int wp = *img->whitePoint; wp != 0; wp >>= 1)
423423
++outputBits;
424424
invariant(outputBits <= 16);
425425

0 commit comments

Comments
 (0)