Skip to content

Commit d662550

Browse files
authored
Merge pull request #604 from LebedevRI/next
And some more `ArrayRef` touchups
2 parents b818e86 + f93114c commit d662550

39 files changed

+286
-226
lines changed

fuzz/librawspeed/common/DngOpcodes.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) {
6161
rawspeed::Array2DRef<uint16_t> img =
6262
mRaw->getU16DataAsUncroppedArray2DRef();
6363
const uint16_t fill = bs.getU16();
64-
for (auto row = 0; row < img.height; ++row) {
65-
for (auto col = 0; col < img.width; ++col) {
64+
for (auto row = 0; row < img.height(); ++row) {
65+
for (auto col = 0; col < img.width(); ++col) {
6666
img(row, col) = fill;
6767
}
6868
}
@@ -71,8 +71,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) {
7171
case rawspeed::RawImageType::F32: {
7272
rawspeed::Array2DRef<float> img = mRaw->getF32DataAsUncroppedArray2DRef();
7373
const float fill = bs.getFloat();
74-
for (auto row = 0; row < img.height; ++row) {
75-
for (auto col = 0; col < img.width; ++col) {
74+
for (auto row = 0; row < img.height(); ++row) {
75+
for (auto col = 0; col < img.width(); ++col) {
7676
img(row, col) = fill;
7777
}
7878
}

src/librawspeed/adt/Array1DRef.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ template <class T> class Array1DRef final {
7979
numElts(sizeof(T2) * RHS.numElts) {}
8080

8181
[[nodiscard]] CroppedArray1DRef<T> getCrop(int offset, int numElts) const;
82+
[[nodiscard]] CroppedArray1DRef<T> getBlock(int numElts, int index) const;
8283

8384
[[nodiscard]] int RAWSPEED_READONLY size() const;
8485

@@ -116,6 +117,17 @@ template <class T>
116117
return {*this, offset, size};
117118
}
118119

120+
template <class T>
121+
[[nodiscard]] CroppedArray1DRef<T> Array1DRef<T>::getBlock(int size,
122+
int index) const {
123+
establishClassInvariants();
124+
invariant(index >= 0);
125+
invariant(size >= 0);
126+
invariant(index <= numElts);
127+
invariant(size <= numElts);
128+
return getCrop(size * index, size);
129+
}
130+
119131
template <class T> inline T* Array1DRef<T>::addressOf(const int eltIdx) const {
120132
establishClassInvariants();
121133
invariant(eltIdx >= 0);

src/librawspeed/adt/Array2DRef.h

Lines changed: 63 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#pragma once
2323

2424
#include "adt/Array1DRef.h"
25+
#include "adt/CroppedArray1DRef.h" // IWYU pragma: keep
2526
#include "adt/Invariant.h"
2627
#include "adt/Optional.h"
2728
#include <cstddef>
@@ -31,27 +32,34 @@
3132
namespace rawspeed {
3233

3334
template <class T> class Array2DRef final {
34-
T* _data;
35+
Array1DRef<T> data;
3536
int _pitch;
3637

38+
int _width;
39+
int _height;
40+
3741
friend Array2DRef<const T>; // We need to be able to convert to const version.
3842

3943
// We need to be able to convert to std::byte.
4044
friend Array2DRef<std::byte>;
4145
friend Array2DRef<const std::byte>;
4246

47+
Array2DRef(Array1DRef<T> data, int width, int height, int pitch);
48+
4349
public:
4450
void establishClassInvariants() const noexcept;
4551

4652
using value_type = T;
4753
using cvless_value_type = std::remove_cv_t<value_type>;
4854

49-
int width;
50-
int height;
55+
[[nodiscard]] int RAWSPEED_READONLY width() const;
56+
[[nodiscard]] int RAWSPEED_READONLY height() const;
5157

5258
Array2DRef() = delete;
5359

54-
Array2DRef(T* data, int width, int height, int pitch = 0);
60+
Array2DRef(T* data, int width, int height, int pitch);
61+
62+
Array2DRef(T* data, int width, int height);
5563

5664
// Can not cast away constness.
5765
template <typename T2>
@@ -70,8 +78,8 @@ template <class T> class Array2DRef final {
7078
requires(!std::is_const_v<T2> && std::is_const_v<T> &&
7179
std::is_same_v<std::remove_const_t<T>, std::remove_const_t<T2>>)
7280
Array2DRef(Array2DRef<T2> RHS) // NOLINT google-explicit-constructor
73-
: _data(RHS._data), _pitch(RHS._pitch), width(RHS.width),
74-
height(RHS.height) {}
81+
: data(RHS.data), _pitch(RHS._pitch), _width(RHS.width()),
82+
_height(RHS.height()) {}
7583

7684
// Const-preserving conversion from Array2DRef<T> to Array2DRef<std::byte>.
7785
template <typename T2>
@@ -80,8 +88,8 @@ template <class T> class Array2DRef final {
8088
std::remove_const_t<T2>>) &&
8189
std::is_same_v<std::remove_const_t<T>, std::byte>)
8290
Array2DRef(Array2DRef<T2> RHS) // NOLINT google-explicit-constructor
83-
: _data(reinterpret_cast<T*>(RHS._data)), _pitch(sizeof(T2) * RHS._pitch),
84-
width(sizeof(T2) * RHS.width), height(RHS.height) {}
91+
: data(RHS.data), _pitch(sizeof(T2) * RHS._pitch),
92+
_width(sizeof(T2) * RHS.width()), _height(RHS.height()) {}
8593

8694
template <typename AllocatorType =
8795
typename std::vector<cvless_value_type>::allocator_type>
@@ -102,53 +110,81 @@ template <class T> class Array2DRef final {
102110

103111
// CTAD deduction guide
104112
template <typename T>
105-
explicit Array2DRef(T* data, int width, int height, int pitch = 0)
113+
explicit Array2DRef(Array1DRef<T> data, int width, int height, int pitch)
106114
-> Array2DRef<T>;
107115

116+
// CTAD deduction guide
117+
template <typename T>
118+
explicit Array2DRef(T* data, int width, int height, int pitch) -> Array2DRef<T>;
119+
120+
// CTAD deduction guide
121+
template <typename T>
122+
explicit Array2DRef(T* data, int width, int height) -> Array2DRef<T>;
123+
108124
template <class T>
109125
inline void Array2DRef<T>::establishClassInvariants() const noexcept {
110-
invariant(_data);
111-
invariant(width >= 0);
112-
invariant(height >= 0);
126+
data.establishClassInvariants();
127+
invariant(_width >= 0);
128+
invariant(_height >= 0);
129+
invariant(_pitch != 0);
113130
invariant(_pitch >= 0);
114-
invariant(_pitch >= width);
131+
invariant(_pitch >= _width);
132+
invariant((_width == 0) == (_height == 0));
133+
invariant(data.size() == _pitch * _height);
115134
}
116135

117136
template <class T>
118-
Array2DRef<T>::Array2DRef(T* data, const int width_, const int height_,
119-
const int pitch_ /* = 0 */)
120-
: _data(data), _pitch(pitch_ == 0 ? width_ : pitch_), width(width_),
121-
height(height_) {
137+
Array2DRef<T>::Array2DRef(Array1DRef<T> data_, const int width_,
138+
const int height_, const int pitch_)
139+
: data(data_), _pitch(pitch_), _width(width_), _height(height_) {
140+
establishClassInvariants();
141+
}
142+
143+
template <class T>
144+
Array2DRef<T>::Array2DRef(T* data_, const int width_, const int height_,
145+
const int pitch_)
146+
: Array2DRef({data_, pitch_ * height_}, width_, height_, pitch_) {
147+
establishClassInvariants();
148+
}
149+
150+
template <class T>
151+
Array2DRef<T>::Array2DRef(T* data_, const int width_, const int height_)
152+
: Array2DRef(data_, width_, height_, /*pitch=*/width_) {
153+
establishClassInvariants();
154+
}
155+
156+
template <class T> inline int Array2DRef<T>::width() const {
157+
establishClassInvariants();
158+
return _width;
159+
}
160+
161+
template <class T> inline int Array2DRef<T>::height() const {
122162
establishClassInvariants();
163+
return _height;
123164
}
124165

125166
template <class T>
126167
[[nodiscard]] inline Optional<Array1DRef<T>>
127168
Array2DRef<T>::getAsArray1DRef() const {
128169
establishClassInvariants();
129-
if (height == 1 || _pitch == width)
130-
return {{_data, width * height}};
170+
if (height() == 1 || _pitch == width())
171+
return data.getCrop(/*offset=*/0, width() * height()).getAsArray1DRef();
131172
return std::nullopt;
132173
}
133174

134175
template <class T>
135176
inline Array1DRef<T> Array2DRef<T>::operator[](const int row) const {
136177
establishClassInvariants();
137178
invariant(row >= 0);
138-
invariant(row < height);
139-
#pragma GCC diagnostic push
140-
#pragma GCC diagnostic ignored "-Wpragmas"
141-
#pragma GCC diagnostic ignored "-Wunknown-warning-option"
142-
#pragma GCC diagnostic ignored "-Wunsafe-buffer-usage"
143-
return Array1DRef<T>(&_data[row * _pitch], width);
144-
#pragma GCC diagnostic pop
179+
invariant(row < height());
180+
return data.getCrop(row * _pitch, width()).getAsArray1DRef();
145181
}
146182

147183
template <class T>
148184
inline T& Array2DRef<T>::operator()(const int row, const int col) const {
149185
establishClassInvariants();
150186
invariant(col >= 0);
151-
invariant(col < width);
187+
invariant(col < width());
152188
return (operator[](row))(col);
153189
}
154190

src/librawspeed/adt/CroppedArray2DRef.h

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@ template <class T> class CroppedArray2DRef final {
6060

6161
// Conversion from Array2DRef<T> to CroppedArray2DRef<T>.
6262
CroppedArray2DRef(Array2DRef<T> RHS) // NOLINT google-explicit-constructor
63-
: base(RHS), offsetCols(0), offsetRows(0), croppedWidth(base.width),
64-
croppedHeight(base.height) {}
63+
: base(RHS), offsetCols(0), offsetRows(0), croppedWidth(base.width()),
64+
croppedHeight(base.height()) {}
6565

6666
CroppedArray2DRef(Array2DRef<T> base_, int offsetCols_, int offsetRows_,
6767
int croppedWidth_, int croppedHeight_);
@@ -94,12 +94,13 @@ inline void CroppedArray2DRef<T>::establishClassInvariants() const noexcept {
9494
invariant(offsetRows >= 0);
9595
invariant(croppedWidth >= 0);
9696
invariant(croppedHeight >= 0);
97-
invariant(offsetCols <= base.width);
98-
invariant(offsetRows <= base.height);
99-
invariant(croppedWidth <= base.width);
100-
invariant(croppedHeight <= base.height);
101-
invariant(offsetCols + croppedWidth <= base.width);
102-
invariant(offsetRows + croppedHeight <= base.height);
97+
invariant(offsetCols <= base.width());
98+
invariant(offsetRows <= base.height());
99+
invariant(croppedWidth <= base.width());
100+
invariant(croppedHeight <= base.height());
101+
invariant(offsetCols + croppedWidth <= base.width());
102+
invariant(offsetRows + croppedHeight <= base.height());
103+
invariant((croppedWidth == 0) == (croppedHeight == 0));
103104
}
104105

105106
template <class T>

src/librawspeed/common/BayerPhase.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@ inline std::array<T, 4> applyPhaseShift(std::array<T, 4> srcData,
8484

8585
std::array<T, 4> tgtData;
8686
const Array2DRef<T> tgt(tgtData.data(), 2, 2);
87-
for (int row = 0; row < tgt.height; ++row) {
88-
for (int col = 0; col < tgt.width; ++col) {
87+
for (int row = 0; row < tgt.height(); ++row) {
88+
for (int col = 0; col < tgt.width(); ++col) {
8989
tgt(row, col) = src((coordOffset.y + row) % 2, (coordOffset.x + col) % 2);
9090
}
9191
}
@@ -133,8 +133,8 @@ inline Optional<BayerPhase> getAsBayerPhase(const ColorFilterArray& CFA) {
133133

134134
std::array<CFAColor, 4> patData;
135135
const Array2DRef<CFAColor> pat(patData.data(), 2, 2);
136-
for (int row = 0; row < pat.height; ++row) {
137-
for (int col = 0; col < pat.width; ++col) {
136+
for (int row = 0; row < pat.height(); ++row) {
137+
for (int col = 0; col < pat.width(); ++col) {
138138
pat(row, col) = CFA.getColorAt(col, row);
139139
}
140140
}

src/librawspeed/common/Common.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,19 +61,19 @@ inline void copyPixelsImpl(Array1DRef<std::byte> dest,
6161

6262
inline void copyPixelsImpl(Array2DRef<std::byte> dest,
6363
Array2DRef<const std::byte> src) {
64-
invariant(src.width > 0);
65-
invariant(src.height > 0);
66-
invariant(dest.width > 0);
67-
invariant(dest.height > 0);
68-
invariant(src.height == dest.height);
69-
invariant(src.width == dest.width);
64+
invariant(src.width() > 0);
65+
invariant(src.height() > 0);
66+
invariant(dest.width() > 0);
67+
invariant(dest.height() > 0);
68+
invariant(src.height() == dest.height());
69+
invariant(src.width() == dest.width());
7070
if (auto [destAsStrip, srcAsStrip] =
7171
std::make_tuple(dest.getAsArray1DRef(), src.getAsArray1DRef());
7272
destAsStrip && srcAsStrip) {
7373
copyPixelsImpl(*destAsStrip, *srcAsStrip);
7474
return;
7575
}
76-
for (int row = 0; row != src.height; ++row)
76+
for (int row = 0; row != src.height(); ++row)
7777
copyPixelsImpl(dest[row], src[row]);
7878
}
7979

src/librawspeed/common/RawImage.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ void RawImageData::fixBadPixelsThread(int start_y, int end_y) {
299299

300300
for (int y = start_y; y < end_y; y++) {
301301
for (int x = 0; x < gw; x++) {
302-
const auto block = bad[y].getCrop((32 * x) / 8, 4);
302+
const auto block = bad[y].getBlock(32 / 8, x);
303303

304304
// Test if there is a bad pixel within these 32 pixels
305305
if (std::all_of(block.begin(), block.end(),

src/librawspeed/common/RawImage.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ class RawImageData : public ErrorLog {
161161
ColorFilterArray cfa;
162162
int blackLevel = -1;
163163
std::array<int, 4> blackLevelSeparateStorage;
164-
Array2DRef<int> blackLevelSeparate = {blackLevelSeparateStorage.data(), 0, 0};
164+
Optional<Array2DRef<int>> blackLevelSeparate;
165165
int whitePoint = 65536;
166166
std::vector<BlackArea> blackAreas;
167167

src/librawspeed/common/RawImageDataFloat.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ void RawImageDataFloat::calculateBlackAreas() {
8888
}
8989

9090
blackLevelSeparate = Array2DRef(blackLevelSeparateStorage.data(), 2, 2);
91-
auto blackLevelSeparate1D = *blackLevelSeparate.getAsArray1DRef();
91+
auto blackLevelSeparate1D = *blackLevelSeparate->getAsArray1DRef();
9292

9393
if (!totalpixels) {
9494
for (int& i : blackLevelSeparate1D)
@@ -122,8 +122,7 @@ void RawImageDataFloat::scaleBlackWhite() {
122122

123123
const int skipBorder = 150;
124124
int gw = (dim.x - skipBorder) * cpp;
125-
if ((blackAreas.empty() && blackLevelSeparate.width == 0 &&
126-
blackLevelSeparate.height == 0 && blackLevel < 0) ||
125+
if ((blackAreas.empty() && !blackLevelSeparate && blackLevel < 0) ||
127126
whitePoint == 65536) { // Estimate
128127
float b = 100000000;
129128
float m = -10000000;
@@ -143,7 +142,7 @@ void RawImageDataFloat::scaleBlackWhite() {
143142
}
144143

145144
/* If filter has not set separate blacklevel, compute or fetch it */
146-
if (blackLevelSeparate.width == 0 && blackLevelSeparate.height == 0)
145+
if (!blackLevelSeparate)
147146
calculateBlackAreas();
148147

149148
startWorker(RawImageWorker::RawImageWorkerTask::SCALE_VALUES, true);
@@ -154,8 +153,8 @@ void RawImageDataFloat::scaleValues(int start_y, int end_y) {
154153
int gw = dim.x * cpp;
155154
std::array<float, 4> mul;
156155
std::array<float, 4> sub;
157-
assert(blackLevelSeparate.width == 2 && blackLevelSeparate.height == 2);
158-
auto blackLevelSeparate1D = *blackLevelSeparate.getAsArray1DRef();
156+
assert(blackLevelSeparate->width() == 2 && blackLevelSeparate->height() == 2);
157+
auto blackLevelSeparate1D = *blackLevelSeparate->getAsArray1DRef();
159158
for (int i = 0; i < 4; i++) {
160159
int v = i;
161160
if ((mOffset.x & 1) != 0)

0 commit comments

Comments
 (0)