RawSpeed
fast raw decoding library
Loading...
Searching...
No Matches
Array2DRef.h
Go to the documentation of this file.
1/*
2 RawSpeed - RAW file decoder.
3
4 Copyright (C) 2018 Stefan Löffler
5 Copyright (C) 2018 Roman Lebedev
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20*/
21
22#pragma once
23
24#include "rawspeedconfig.h"
25#include "adt/Array1DRef.h"
26#include "adt/CroppedArray1DRef.h" // IWYU pragma: keep
27#include "adt/Invariant.h"
28#include "adt/Optional.h"
29#include <cstddef>
30#include <type_traits>
31#include <vector>
32
33namespace rawspeed {
34
35template <class T> class Array2DRef final {
37 int _pitch;
38
39 int _width;
41
42 friend Array2DRef<const T>; // We need to be able to convert to const version.
43
44 // We need to be able to convert to std::byte.
47
48public:
49 void establishClassInvariants() const noexcept;
50
52
53 using value_type = T;
54 using cvless_value_type = std::remove_cv_t<value_type>;
55
56 [[nodiscard]] int RAWSPEED_READONLY pitch() const;
57 [[nodiscard]] int RAWSPEED_READONLY width() const;
58 [[nodiscard]] int RAWSPEED_READONLY height() const;
59
60 Array2DRef() = delete;
61
62 Array2DRef(T* data, int width, int height, int pitch);
63
64 Array2DRef(T* data, int width, int height);
65
66 // Can not cast away constness.
67 template <typename T2>
68 requires(std::is_const_v<T2> && !std::is_const_v<T>)
69 Array2DRef(Array2DRef<T2> RHS) = delete;
70
71 // Can not change type to non-byte.
72 template <typename T2>
73 requires(!(std::is_const_v<T2> && !std::is_const_v<T>) &&
74 !std::is_same_v<std::remove_const_t<T>, std::remove_const_t<T2>> &&
75 !std::is_same_v<std::remove_const_t<T>, std::byte>)
76 Array2DRef(Array2DRef<T2> RHS) = delete;
77
78 // Conversion from Array2DRef<T> to Array2DRef<const T>.
79 template <typename T2>
80 requires(!std::is_const_v<T2> && std::is_const_v<T> &&
81 std::is_same_v<std::remove_const_t<T>, std::remove_const_t<T2>>)
82 Array2DRef(Array2DRef<T2> RHS) // NOLINT(google-explicit-constructor)
83 : Array2DRef(RHS.data, RHS._width, RHS._height, RHS._pitch) {}
84
85 // Const-preserving conversion from Array2DRef<T> to Array2DRef<std::byte>.
86 template <typename T2>
87 requires(
88 !(std::is_const_v<T2> && !std::is_const_v<T>) &&
89 !(std::is_same_v<std::remove_const_t<T>, std::remove_const_t<T2>>) &&
90 std::is_same_v<std::remove_const_t<T>, std::byte>)
91 Array2DRef(Array2DRef<T2> RHS) // NOLINT(google-explicit-constructor)
92 : Array2DRef(RHS.data, sizeof(T2) * RHS._width, RHS._height,
93 sizeof(T2) * RHS._pitch) {}
94
95 template <typename AllocatorType =
96 typename std::vector<cvless_value_type>::allocator_type>
97 static Array2DRef<T>
98 create(std::vector<cvless_value_type, AllocatorType>& storage, int width,
99 int height) {
100 using VectorTy = std::remove_reference_t<decltype(storage)>;
101 storage = VectorTy(width * height);
102 return {storage.data(), width, height};
103 }
104
106
107 Array1DRef<T> operator[](int row) const;
108
109 T& operator()(int row, int col) const;
110};
111
112// CTAD deduction guide
113template <typename T>
114explicit Array2DRef(Array1DRef<T> data, int width, int height,
115 int pitch) -> Array2DRef<T>;
116
117// CTAD deduction guide
118template <typename T>
119explicit Array2DRef(T* data, int width, int height, int pitch) -> Array2DRef<T>;
120
121// CTAD deduction guide
122template <typename T>
123explicit Array2DRef(T* data, int width, int height) -> Array2DRef<T>;
124
125template <class T>
126__attribute__((always_inline)) inline void
129 invariant(_width >= 0);
130 invariant(_height >= 0);
131 invariant(_pitch != 0);
132 invariant(_pitch >= 0);
133 invariant(_pitch >= _width);
134 invariant((_width == 0) == (_height == 0));
135 invariant(data.size() == _pitch * _height);
136}
137
138template <class T>
139inline Array2DRef<T>::Array2DRef(Array1DRef<T> data_, const int width_,
140 const int height_, const int pitch_)
141 : data(data_), _pitch(pitch_), _width(width_), _height(height_) {
142 establishClassInvariants();
143}
144
145template <class T>
146inline Array2DRef<T>::Array2DRef(T* data_, const int width_, const int height_,
147 const int pitch_)
148 : Array2DRef({data_, pitch_ * height_}, width_, height_, pitch_) {
149 establishClassInvariants();
150}
151
152template <class T>
153inline Array2DRef<T>::Array2DRef(T* data_, const int width_, const int height_)
154 : Array2DRef(data_, width_, height_, /*pitch=*/width_) {
156}
157
158template <class T>
159__attribute__((always_inline)) inline int Array2DRef<T>::pitch() const {
160 establishClassInvariants();
161 return _pitch;
162}
163
164template <class T>
165__attribute__((always_inline)) inline int Array2DRef<T>::width() const {
166 establishClassInvariants();
167 return _width;
168}
169
170template <class T>
171__attribute__((always_inline)) inline int Array2DRef<T>::height() const {
172 establishClassInvariants();
173 return _height;
174}
175
176template <class T>
177[[nodiscard]] inline Optional<Array1DRef<T>>
179 establishClassInvariants();
180 if (height() == 1 || _pitch == width())
181 return data.getCrop(/*offset=*/0, width() * height()).getAsArray1DRef();
182 return std::nullopt;
183}
184
185template <class T>
186inline Array1DRef<T> Array2DRef<T>::operator[](const int row) const {
187 establishClassInvariants();
188 invariant(row >= 0);
189 invariant(row < height());
190 return data.getCrop(row * _pitch, width()).getAsArray1DRef();
191}
192
193template <class T>
194__attribute__((always_inline)) inline T&
195Array2DRef<T>::operator()(const int row, const int col) const {
196 establishClassInvariants();
197 invariant(col >= 0);
198 invariant(col < width());
199 return (operator[](row))(col);
200}
201
202} // namespace rawspeed
#define invariant(expr)
Definition Invariant.h:27
Array1DRef< T > data
Definition Array2DRef.h:36
Array2DRef(Array1DRef< T > data, int width, int height, int pitch)
T & operator()(int row, int col) const
Array2DRef(Array2DRef< T2 > RHS)
Definition Array2DRef.h:91
int RAWSPEED_READONLY height() const
Array1DRef< T > operator[](int row) const
std::remove_cv_t< value_type > cvless_value_type
Definition Array2DRef.h:54
static Array2DRef< T > create(std::vector< cvless_value_type, AllocatorType > &storage, int width, int height)
Definition Array2DRef.h:98
int RAWSPEED_READONLY pitch() const
Optional< Array1DRef< T > > getAsArray1DRef() const
void establishClassInvariants() const noexcept
int RAWSPEED_READONLY width() const
throw T(buf.data())
Array2DRef(Array1DRef< T > data, int width, int height, int pitch) -> Array2DRef< T >
__attribute__((noinline)) __attribute__((visibility("default"))) JPEGStuffedByteStreamGenerator