RawSpeed
fast raw decoding library
Loading...
Searching...
No Matches
DngOpcodes.cpp
Go to the documentation of this file.
1/*
2 RawSpeed - RAW file decoder.
3
4 Copyright (C) 2009-2014 Klaus Post
5 Copyright (C) 2017 Axel Waggershauser
6 Copyright (C) 2017 Roman Lebedev
7
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 2 of the License, or (at your option) any later version.
12
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public
19 License along with this library; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21*/
22
23#include "rawspeedconfig.h"
24#include "common/DngOpcodes.h"
25#include "adt/Casts.h"
27#include "adt/Mutex.h"
28#include "adt/Optional.h"
29#include "adt/Point.h"
30#include "common/Common.h"
31#include "common/RawImage.h"
33#include "io/Buffer.h"
34#include "io/ByteStream.h"
35#include "io/Endianness.h"
36#include <algorithm>
37#include <cassert>
38#include <cinttypes>
39#include <cmath>
40#include <cstdint>
41#include <cstdlib>
42#include <iterator>
43#include <limits>
44#include <memory>
45#include <tuple>
46#include <type_traits>
47#include <utility>
48#include <vector>
49
50#ifndef NDEBUG
51#include <exception>
52#endif
53
54using std::fill_n;
55using std::make_pair;
56using std::vector;
57
58namespace rawspeed {
59
60namespace {
61
62template <typename T>
67
69 iRectangle2D rect;
70 switch (ri->getDataType()) {
73 break;
76 break;
77 }
78 for (int* col : {&rect.pos.x, &rect.dim.x}) {
79 assert(*col % ri->getCpp() == 0 && "Column is width * cpp");
80 *col /= ri->getCpp();
81 }
82 return rect;
83}
84
85// FIXME: extract into `RawImage`?
86template <typename T>
88 if constexpr (std::is_same<T, uint16_t>())
90 if constexpr (std::is_same<T, float>())
92 __builtin_unreachable();
93}
94
95} // namespace
96
98#ifndef NDEBUG
100 bool setup_was_called = false;
101#endif
102
103 virtual void anchor() const;
104
105public:
106 explicit DngOpcode(const iRectangle2D& integrated_subimg_)
107#ifndef NDEBUG
108 : integrated_subimg(integrated_subimg_)
109#endif
110 {
111 assert(std::uncaught_exceptions() == 0 &&
112 "Creating DngOpcode during call stack unwinding?");
113 }
114
115 DngOpcode() = delete;
116 DngOpcode(const DngOpcode&) = delete;
117 DngOpcode(DngOpcode&&) noexcept = delete;
118 DngOpcode& operator=(const DngOpcode&) noexcept = delete;
119 DngOpcode& operator=(DngOpcode&&) noexcept = delete;
120
121 virtual ~DngOpcode() {
122 assert((std::uncaught_exceptions() > 0 || setup_was_called) &&
123 "Derived classes did not call our setup()!");
124 }
125
126 // Will be called once before processing.
127 // Can be used for preparing pre-calculated values, etc.
128 virtual void setup(const RawImage& ri) {
129#ifndef NDEBUG
130 setup_was_called = true;
131#endif
132 assert(integrated_subimg == getImageCropAsRectangle(ri) &&
133 "Current image sub-crop does not match the expected one!");
134
135 // NOP by default. child class shall final this if needed.
136 }
137
138 // Will be called for actual processing.
139 virtual void apply(const RawImage& ri) = 0;
140};
141
143 // Empty out-of-line definition for the purpose of anchoring
144 // the class's vtable to this Translational Unit.
145}
146
147// ****************************************************************************
148
151
152 void anchor() const override;
153
154public:
155 explicit FixBadPixelsConstant(const RawImage& ri, ByteStream& bs,
156 const iRectangle2D& integrated_subimg_)
157 : DngOpcodes::DngOpcode(integrated_subimg_), value(bs.getU32()) {
158 bs.getU32(); // Bayer Phase not used
159 }
160
161 void setup(const RawImage& ri) override {
163
164 // These limitations are present within the DNG SDK as well.
166 ThrowRDE("Only 16 bit images supported");
167
168 if (ri->getCpp() > 1)
169 ThrowRDE("Only 1 component images supported");
170 }
171
172 void apply(const RawImage& ri) override {
173 MutexLocker guard(&ri->mBadPixelMutex);
175 iPoint2D crop = ri->getCropOffset();
176 uint32_t offset = crop.x | (crop.y << 16);
177 for (auto row = 0; row < img.croppedHeight; ++row) {
178 for (auto col = 0; col < img.croppedWidth; ++col) {
179 if (img(row, col) == value)
180 ri->mBadPixelPositions.push_back(offset + (row << 16 | col));
181 }
182 }
183 }
184};
185
187 // Empty out-of-line definition for the purpose of anchoring
188 // the class's vtable to this Translational Unit.
189}
190
191// ****************************************************************************
192
195
196 void anchor() const override;
197
198protected:
199 explicit ROIOpcode(const RawImage& ri, ByteStream& bs,
200 const iRectangle2D& integrated_subimg_)
201 : DngOpcodes::DngOpcode(integrated_subimg_) {
202 const iRectangle2D subImage = {{0, 0}, integrated_subimg_.dim};
203
204 uint32_t top = bs.getU32();
205 uint32_t left = bs.getU32();
206 uint32_t bottom = bs.getU32();
207 uint32_t right = bs.getU32();
208
209 const iPoint2D topLeft(left, top);
210 const iPoint2D bottomRight(right, bottom);
211
212 if (!(subImage.isPointInsideInclusive(topLeft) &&
213 subImage.isPointInsideInclusive(bottomRight) &&
214 bottomRight >= topLeft)) {
215 ThrowRDE("Rectangle (%d, %d, %d, %d) not inside image (%d, %d, %d, %d).",
216 topLeft.x, topLeft.y, bottomRight.x, bottomRight.y,
217 subImage.getTopLeft().x, subImage.getTopLeft().y,
218 subImage.getBottomRight().x, subImage.getBottomRight().y);
219 }
220
221 roi.setTopLeft(topLeft);
222 roi.setBottomRightAbsolute(bottomRight);
223 assert(roi.isThisInside(subImage));
224 }
225
226 [[nodiscard]] const iRectangle2D& RAWSPEED_READONLY getRoi() const {
227 return roi;
228 }
229};
230
232 // Empty out-of-line definition for the purpose of anchoring
233 // the class's vtable to this Translational Unit.
234}
235
236// ****************************************************************************
237
239 void anchor() const override;
240
241public:
242 explicit DummyROIOpcode(const RawImage& ri, ByteStream& bs,
243 const iRectangle2D& integrated_subimg_)
244 : ROIOpcode(ri, bs, integrated_subimg_) {
246 }
247
248 using ROIOpcode::getRoi;
249
250 [[noreturn]] void apply(const RawImage& ri) override {
251 assert(false && "You should not be calling this.");
252 __builtin_unreachable();
253 }
254};
255
257 // Empty out-of-line definition for the purpose of anchoring
258 // the class's vtable to this Translational Unit.
259}
260
261// ****************************************************************************
262
264 std::vector<uint32_t> badPixels;
265
266 void anchor() const override;
267
268public:
269 explicit FixBadPixelsList(const RawImage& ri, ByteStream& bs,
270 const iRectangle2D& integrated_subimg_)
271 : DngOpcodes::DngOpcode(integrated_subimg_) {
272 // Although it is not really obvious from the spec,
273 // the coordinates appear to be global/crop-independent,
274 // and apply to the source uncropped image.
275 const iRectangle2D fullImage({0, 0}, ri->getUncroppedDim());
276
277 bs.getU32(); // Skip phase - we don't care
278 auto badPointCount = bs.getU32();
279 auto badRectCount = bs.getU32();
280
281 // first, check that we indeed have much enough data
282 const auto origPos = bs.getPosition();
283 bs.skipBytes(badPointCount, 2 * 4);
284 bs.skipBytes(badRectCount, 4 * 4);
285 bs.setPosition(origPos);
286
287 // Read points
288 badPixels.reserve(badPixels.size() + badPointCount);
289 for (auto i = 0U; i < badPointCount; ++i) {
290 auto y = bs.getU32();
291 auto x = bs.getU32();
292
293 if (const iPoint2D badPoint(x, y); !fullImage.isPointInside(badPoint))
294 ThrowRDE("Bad point not inside image.");
295
296 badPixels.emplace_back(y << 16 | x);
297 }
298
299 // Read rects
300 for (auto i = 0U; i < badRectCount; ++i) {
301 iRectangle2D fullImage_ = fullImage;
302 const DummyROIOpcode dummy(ri, bs, fullImage_);
303
304 const iRectangle2D badRect = dummy.getRoi();
305 assert(badRect.isThisInside(fullImage));
306
307 auto area = badRect.getHeight() * badRect.getWidth();
308 badPixels.reserve(badPixels.size() + area);
309 for (auto y = 0; y < badRect.getHeight(); ++y) {
310 for (auto x = 0; x < badRect.getWidth(); ++x) {
311 badPixels.emplace_back((badRect.getTop() + y) << 16 |
312 (badRect.getLeft() + x));
313 }
314 }
315 }
316 }
317
318 void apply(const RawImage& ri) override {
319 MutexLocker guard(&ri->mBadPixelMutex);
320 ri->mBadPixelPositions.insert(ri->mBadPixelPositions.begin(),
321 badPixels.begin(), badPixels.end());
322 }
323};
324
326 // Empty out-of-line definition for the purpose of anchoring
327 // the class's vtable to this Translational Unit.
328}
329
330// ****************************************************************************
331
332class DngOpcodes::TrimBounds final : public ROIOpcode {
333 void anchor() const override;
334
335public:
336 explicit TrimBounds(const RawImage& ri, ByteStream& bs,
337 iRectangle2D& integrated_subimg_)
338 : ROIOpcode(ri, bs, integrated_subimg_) {
339 integrated_subimg_.pos += getRoi().pos;
340 integrated_subimg_.dim = getRoi().dim;
341 }
342
343 void apply(const RawImage& ri) override { ri->subFrame(getRoi()); }
344};
345
347 // Empty out-of-line definition for the purpose of anchoring
348 // the class's vtable to this Translational Unit.
349}
350
351// ****************************************************************************
352
358
359 void anchor() const override;
360
361protected:
362 explicit PixelOpcode(const RawImage& ri, ByteStream& bs,
363 const iRectangle2D& integrated_subimg_)
364 : ROIOpcode(ri, bs, integrated_subimg_), firstPlane(bs.getU32()),
365 planes(bs.getU32()) {
366
367 if (planes == 0 || firstPlane > ri->getCpp() || planes > ri->getCpp() ||
368 firstPlane + planes > ri->getCpp()) {
369 ThrowRDE("Bad plane params (first %u, num %u), got planes = %u",
370 firstPlane, planes, ri->getCpp());
371 }
372
373 rowPitch = bs.getU32();
374 colPitch = bs.getU32();
375
376 const iRectangle2D& ROI = getRoi();
377
378 if (rowPitch < 1 || rowPitch > static_cast<uint32_t>(ROI.getHeight()) ||
379 colPitch < 1 || colPitch > static_cast<uint32_t>(ROI.getWidth()))
380 ThrowRDE("Invalid pitch");
381 }
382
383 [[nodiscard]] iPoint2D RAWSPEED_READONLY getPitch() const {
384 return {static_cast<int>(colPitch), static_cast<int>(rowPitch)};
385 }
386
387 // traverses the current ROI and applies the operation OP to each pixel,
388 // i.e. each pixel value v is replaced by op(x, y, v), where x/y are the
389 // coordinates of the pixel value v.
390 template <typename T, typename OP>
391 void applyOP(const RawImage& ri, OP op) const {
392 const CroppedArray2DRef<T> img = getDataAsCroppedArray2DRef<T>(ri);
393 int cpp = ri->getCpp();
394 const iRectangle2D& ROI = getRoi();
395 const iPoint2D numAffected(
398 for (int y = 0; y < numAffected.y; ++y) {
399 for (int x = 0; x < numAffected.x; ++x) {
400 for (auto p = 0U; p < planes; ++p) {
401 T& pixel =
402 img(ROI.getTop() + (rowPitch * y),
403 firstPlane + ((ROI.getLeft() + colPitch * x) * cpp) + p);
404 pixel = op(x, y, pixel);
405 }
406 }
407 }
408 }
409};
410
412 // Empty out-of-line definition for the purpose of anchoring
413 // the class's vtable to this Translational Unit.
414}
415
416// ****************************************************************************
417
419 void anchor() const override;
420
421protected:
422 vector<uint16_t> lookup = vector<uint16_t>(65536);
423
425
426 void setup(const RawImage& ri) final {
428
429 if (ri->getDataType() != RawImageType::UINT16)
430 ThrowRDE("Only 16 bit images supported");
431 }
432
433 void apply(const RawImage& ri) final {
434 applyOP<uint16_t>(ri, [this]([[maybe_unused]] uint32_t x,
435 [[maybe_unused]] uint32_t y,
436 uint16_t v) { return lookup[v]; });
437 }
438};
439
441 // Empty out-of-line definition for the purpose of anchoring
442 // the class's vtable to this Translational Unit.
443}
444
445// ****************************************************************************
446
447class DngOpcodes::TableMap final : public LookupOpcode {
448 void anchor() const override;
449
450public:
451 explicit TableMap(const RawImage& ri, ByteStream& bs,
452 const iRectangle2D& integrated_subimg_)
453 : LookupOpcode(ri, bs, integrated_subimg_) {
454 auto count = bs.getU32();
455
456 if (count == 0 || count > 65536)
457 ThrowRDE("Invalid size of lookup table");
458
459 for (auto i = 0U; i < count; ++i)
460 lookup[i] = bs.getU16();
461
462 if (count < lookup.size())
463 fill_n(&lookup[count], lookup.size() - count, lookup[count - 1]);
464 }
465};
466
468 // Empty out-of-line definition for the purpose of anchoring
469 // the class's vtable to this Translational Unit.
470}
471
472// ****************************************************************************
473
475 void anchor() const override;
476
477public:
478 explicit PolynomialMap(const RawImage& ri, ByteStream& bs,
479 const iRectangle2D& integrated_subimg_)
480 : LookupOpcode(ri, bs, integrated_subimg_) {
481 vector<double> polynomial;
482
483 const auto polynomial_size = bs.getU32() + 1UL;
484 (void)bs.check(implicit_cast<Buffer::size_type>(8UL * polynomial_size));
485 if (polynomial_size > 9)
486 ThrowRDE("A polynomial with more than 8 degrees not allowed");
487
488 polynomial.reserve(polynomial_size);
489 std::generate_n(std::back_inserter(polynomial), polynomial_size,
490 [&bs]() { return bs.get<double>(); });
491
492 // Create lookup
493 lookup.resize(65536);
494 for (auto i = 0UL; i < lookup.size(); ++i) {
495 double val = polynomial[0];
496 for (auto j = 1UL; j < polynomial.size(); ++j)
497 val += polynomial[j] * pow(implicit_cast<double>(i) / 65536.0,
499 lookup[i] = implicit_cast<uint16_t>(std::clamp<double>(
500 val * 65535.5, std::numeric_limits<uint16_t>::min(),
501 std::numeric_limits<uint16_t>::max()));
502 }
503 }
504};
505
507 // Empty out-of-line definition for the purpose of anchoring
508 // the class's vtable to this Translational Unit.
509}
510
511// ****************************************************************************
512
514 void anchor() const final;
515
516public:
517 struct SelectX final {
518 static uint32_t select(uint32_t x, uint32_t /*y*/) { return x; }
519 };
520
521 struct SelectY final {
522 static uint32_t select(uint32_t /*x*/, uint32_t y) { return y; }
523 };
524
525protected:
527 const iRectangle2D& integrated_subimg_)
528 : PixelOpcode(ri, bs, integrated_subimg_) {}
529};
530
532 // Empty out-of-line definition for the purpose of anchoring
533 // the class's vtable to this Translational Unit.
534}
535
536template <typename S>
538public:
539 void setup(const RawImage& ri) final {
541
542 // If we are working on a float image, no need to convert to int
543 if (ri->getDataType() != RawImageType::UINT16)
544 return;
545
546 deltaI.reserve(deltaF.size());
547 for (const auto f : deltaF) {
548 if (!valueIsOk(f))
549 ThrowRDE("Got float %f which is unacceptable.",
551 deltaI.emplace_back(static_cast<int>(f2iScale * f));
552 }
553 }
554
555protected:
556 const float f2iScale;
557 vector<float> deltaF;
558 vector<int> deltaI;
559
560 // only meaningful for uint16_t images!
561 virtual bool valueIsOk(float value) = 0;
562
564 const iRectangle2D& integrated_subimg_, float f2iScale_)
565 : DeltaRowOrColBase(ri, bs, integrated_subimg_), f2iScale(f2iScale_) {
566 const auto deltaF_count = bs.getU32();
567 (void)bs.check(deltaF_count, 4);
568
569 // See PixelOpcode::applyOP(). We will access deltaF/deltaI up to (excl.)
570 // either ROI.getWidth() or ROI.getHeight() index. Thus, we need to have
571 // either ROI.getRight() or ROI.getBottom() elements in there.
572 if (const auto expectedSize = roundUpDivisionSafe(
573 S::select(getRoi().getWidth(), getRoi().getHeight()),
574 S::select(getPitch().x, getPitch().y));
575 expectedSize != deltaF_count) {
576 ThrowRDE("Got unexpected number of elements (%" PRIu64 "), expected %u.",
577 expectedSize, deltaF_count);
578 }
579
580 deltaF.reserve(deltaF_count);
581 std::generate_n(std::back_inserter(deltaF), deltaF_count, [&bs]() {
582 const auto F = bs.get<float>();
583 switch (std::fpclassify(F)) {
584 case FP_NORMAL:
585 case FP_SUBNORMAL:
586 case FP_ZERO:
587 return F;
588 default:
589 ThrowRDE("Got bad float %f.", implicit_cast<double>(F));
590 }
591 });
592 }
593};
594
595// ****************************************************************************
596
597template <typename S>
599 // We have pixel value in range of [0..65535]. We apply some offset X.
600 // For this to generate a value within the same range , the offset X needs
601 // to have an absolute value of 65535. Since the offset is multiplied
602 // by f2iScale before applying, we need to divide by f2iScale here.
603 const double absLimit;
604
605 bool valueIsOk(float value) override {
606 return implicit_cast<double>(std::abs(value)) <= absLimit;
607 }
608
609public:
610 explicit OffsetPerRowOrCol(const RawImage& ri, ByteStream& bs,
611 const iRectangle2D& integrated_subimg_)
612 : DeltaRowOrCol<S>(ri, bs, integrated_subimg_, 65535.0F),
613 absLimit(double(std::numeric_limits<uint16_t>::max()) /
614 implicit_cast<double>(this->f2iScale)) {}
615
616 void apply(const RawImage& ri) override {
617 if (ri->getDataType() == RawImageType::UINT16) {
618 this->template applyOP<uint16_t>(
619 ri, [this](uint32_t x, uint32_t y, uint16_t v) {
620 return clampBits(this->deltaI[S::select(x, y)] + v, 16);
621 });
622 } else {
623 this->template applyOP<float>(ri,
624 [this](uint32_t x, uint32_t y, float v) {
625 return this->deltaF[S::select(x, y)] + v;
626 });
627 }
628 }
629};
630
631template <typename S>
633 // We have pixel value in range of [0..65535]. We scale by float X.
634 // For this to generate a value within the same range, the scale X needs
635 // to be in the range [0..65535]. However, we are operating with 32-bit
636 // signed integer space, so the new value can not be larger than 2^31,
637 // else we'd have signed integer overflow. Since the offset is multiplied
638 // by f2iScale before applying, we need to divide by f2iScale here.
639 static constexpr const float minLimit = 0.0;
640 static constexpr int rounding = 512;
641 const double maxLimit;
642
643 bool valueIsOk(float value) override {
644 return value >= minLimit && implicit_cast<double>(value) <= maxLimit;
645 }
646
647public:
648 explicit ScalePerRowOrCol(const RawImage& ri, ByteStream& bs,
649 const iRectangle2D& integrated_subimg_)
650 : DeltaRowOrCol<S>(ri, bs, integrated_subimg_, 1024.0F),
651 maxLimit((double(std::numeric_limits<int>::max() - rounding) /
652 double(std::numeric_limits<uint16_t>::max())) /
653 implicit_cast<double>(this->f2iScale)) {}
654
655 void apply(const RawImage& ri) override {
656 if (ri->getDataType() == RawImageType::UINT16) {
657 this->template applyOP<uint16_t>(ri, [this](uint32_t x, uint32_t y,
658 uint16_t v) {
659 return clampBits((this->deltaI[S::select(x, y)] * v + 512) >> 10, 16);
660 });
661 } else {
662 this->template applyOP<float>(ri,
663 [this](uint32_t x, uint32_t y, float v) {
664 return this->deltaF[S::select(x, y)] * v;
665 });
666 }
667 }
668};
669
670// ****************************************************************************
671
673 // DNG opcodes are always stored in big-endian byte order.
675
676 const auto opcode_count = bs.getU32();
677 auto origPos = bs.getPosition();
678
679 // validate opcode count. we either have to do this, or we can't preallocate
680 for (auto i = 0U; i < opcode_count; i++) {
681 bs.skipBytes(4); // code
682 bs.skipBytes(4); // version
683 bs.skipBytes(4); // flags
684 const auto opcode_size = bs.getU32();
685 bs.skipBytes(opcode_size);
686 }
687
688 bs.setPosition(origPos);
689
690 // okay, we may indeed have that many opcodes in here. now let's reserve
691 opcodes.reserve(opcode_count);
692
693 iRectangle2D integrated_subimg = getImageCropAsRectangle(ri);
694
695 for (auto i = 0U; i < opcode_count; i++) {
696 auto code = bs.getU32();
697 bs.skipBytes(4); // ignore version
698#ifdef DEBUG
699 bs.skipBytes(4); // ignore flags
700#else
701 auto flags = bs.getU32();
702#endif
703 const auto opcode_size = bs.getU32();
704 ByteStream opcode_bs = bs.getStream(opcode_size);
705
706 const char* opName = nullptr;
707 constructor_t opConstructor = nullptr;
708 if (auto Op = Map(code))
709 std::tie(opName, opConstructor) = *Op;
710 else
711 ThrowRDE("Unknown unhandled Opcode: %u", code);
712
713 if (opConstructor != nullptr)
714 opcodes.emplace_back(opConstructor(ri, opcode_bs, integrated_subimg));
715 else {
716#ifndef DEBUG
717 // Throw Error if not marked as optional
718 if (!(flags & 1))
719#endif
720 ThrowRDE("Unsupported Opcode: %u (%s)", code, opName);
721 }
722
723 if (opcode_bs.getRemainSize() != 0)
724 ThrowRDE("Inconsistent length of opcode");
725 }
726
727#ifdef DEBUG
728 assert(opcodes.size() == opcode_count);
729#endif
730}
731
732// Defined here as empty destructor, otherwise we'd need a complete definition
733// of the DngOpcode type in DngOpcodes.h
734DngOpcodes::~DngOpcodes() = default;
735
736void DngOpcodes::applyOpCodes(const RawImage& ri) const {
737 for (const auto& code : opcodes) {
738 code->setup(ri);
739 code->apply(ri);
740 }
741}
742
743template <class Opcode>
744std::unique_ptr<DngOpcodes::DngOpcode>
746 iRectangle2D& integrated_subimg) {
747 return std::make_unique<Opcode>(ri, bs, integrated_subimg);
748}
749
750// ALL opcodes specified in DNG Specification MUST be listed here.
751// however, some of them might not be implemented.
754 switch (code) {
755 case 1U:
756 return make_pair("WarpRectilinear", nullptr);
757 case 2U:
758 return make_pair("WarpFisheye", nullptr);
759 case 3U:
760 return make_pair("FixVignetteRadial", nullptr);
761 case 4U:
762 return make_pair(
763 "FixBadPixelsConstant",
765 case 5U:
766 return make_pair("FixBadPixelsList",
768 case 6U:
769 return make_pair("TrimBounds",
771 case 7U:
772 return make_pair("MapTable",
774 case 8U:
775 return make_pair("MapPolynomial",
777 case 9U:
778 return make_pair("GainMap", nullptr);
779 case 10U:
780 return make_pair(
781 "DeltaPerRow",
784 case 11U:
785 return make_pair(
786 "DeltaPerColumn",
789 case 12U:
790 return make_pair(
791 "ScalePerRow",
794 case 13U:
795 return make_pair(
796 "ScalePerColumn",
799 default:
800 return std::nullopt;
801 }
802}
803
804} // namespace rawspeed
constexpr auto RAWSPEED_READNONE clampBits(T value, unsigned int nBits)
Definition Bit.h:75
constexpr uint64_t RAWSPEED_READNONE roundUpDivisionSafe(uint64_t value, uint64_t div)
Definition Common.h:145
#define ThrowRDE(...)
iPoint2D dim(rawspeed::implicit_cast< int >(ceil(sqSide *sqARatio)), rawspeed::implicit_cast< int >(ceil(sqSide/sqARatio)))
Definition Common.cpp:55
assert(dim.area() >=area)
dim y
Definition Common.cpp:51
dim x
Definition Common.cpp:50
size_type check(size_type bytes) const
Definition ByteStream.h:63
size_type RAWSPEED_READONLY getRemainSize() const
Definition ByteStream.h:87
void setPosition(size_type newPos)
Definition ByteStream.h:83
ByteStream getStream(size_type size_)
Definition ByteStream.h:119
void skipBytes(size_type nbytes)
Definition ByteStream.h:130
size_type getPosition() const
Definition ByteStream.h:78
Endianness setByteOrder(Endianness endianness_)
Definition Buffer.h:156
DeltaRowOrColBase(const RawImage &ri, ByteStream &bs, const iRectangle2D &integrated_subimg_)
void setup(const RawImage &ri) final
virtual bool valueIsOk(float value)=0
DeltaRowOrCol(const RawImage &ri, ByteStream &bs, const iRectangle2D &integrated_subimg_, float f2iScale_)
const iRectangle2D integrated_subimg
DngOpcode(DngOpcode &&) noexcept=delete
virtual void apply(const RawImage &ri)=0
virtual void setup(const RawImage &ri)
virtual void anchor() const
DngOpcode(const DngOpcode &)=delete
DngOpcode(const iRectangle2D &integrated_subimg_)
void apply(const RawImage &ri) override
DummyROIOpcode(const RawImage &ri, ByteStream &bs, const iRectangle2D &integrated_subimg_)
const iRectangle2D &RAWSPEED_READONLY getRoi() const
void apply(const RawImage &ri) override
FixBadPixelsConstant(const RawImage &ri, ByteStream &bs, const iRectangle2D &integrated_subimg_)
void setup(const RawImage &ri) override
FixBadPixelsList(const RawImage &ri, ByteStream &bs, const iRectangle2D &integrated_subimg_)
void apply(const RawImage &ri) override
void setup(const RawImage &ri) final
PixelOpcode(const RawImage &ri, ByteStream &bs, const iRectangle2D &integrated_subimg_)
void apply(const RawImage &ri) final
bool valueIsOk(float value) override
OffsetPerRowOrCol(const RawImage &ri, ByteStream &bs, const iRectangle2D &integrated_subimg_)
void apply(const RawImage &ri) override
iPoint2D RAWSPEED_READONLY getPitch() const
void applyOP(const RawImage &ri, OP op) const
PixelOpcode(const RawImage &ri, ByteStream &bs, const iRectangle2D &integrated_subimg_)
PolynomialMap(const RawImage &ri, ByteStream &bs, const iRectangle2D &integrated_subimg_)
ROIOpcode(const RawImage &ri, ByteStream &bs, const iRectangle2D &integrated_subimg_)
void anchor() const override
const iRectangle2D &RAWSPEED_READONLY getRoi() const
ScalePerRowOrCol(const RawImage &ri, ByteStream &bs, const iRectangle2D &integrated_subimg_)
static constexpr const float minLimit
bool valueIsOk(float value) override
void apply(const RawImage &ri) override
TableMap(const RawImage &ri, ByteStream &bs, const iRectangle2D &integrated_subimg_)
void anchor() const override
void anchor() const override
void apply(const RawImage &ri) override
TrimBounds(const RawImage &ri, ByteStream &bs, iRectangle2D &integrated_subimg_)
DngOpcodes(const RawImage &ri, ByteStream bs)
std::vector< std::unique_ptr< DngOpcode > > opcodes
Definition DngOpcodes.h:45
static std::unique_ptr< DngOpcode > constructor(const RawImage &ri, ByteStream &bs, iRectangle2D &integrated_subimg)
static Optional< std::pair< const char *, DngOpcodes::constructor_t > > Map(uint32_t code)
std::unique_ptr< DngOpcode >(*)( const RawImage &ri, ByteStream &bs, iRectangle2D &integrated_subimg) constructor_t
Definition DngOpcodes.h:66
void applyOpCodes(const RawImage &ri) const
rawspeed::RawImageType getDataType() const
Definition RawImage.h:125
uint32_t RAWSPEED_READONLY getCpp() const
Definition RawImage.h:118
CroppedArray2DRef< float > getF32DataAsCroppedArray2DRef() noexcept
Definition RawImage.h:324
iPoint2D RAWSPEED_READONLY getCropOffset() const
Definition RawImage.cpp:171
iPoint2D RAWSPEED_READONLY getUncroppedDim() const
Definition RawImage.cpp:167
void subFrame(iRectangle2D cropped)
Definition RawImage.cpp:175
CroppedArray2DRef< uint16_t > getU16DataAsCroppedArray2DRef() noexcept
Definition RawImage.h:304
value_type x
Definition Point.h:102
value_type y
Definition Point.h:103
constexpr bool RAWSPEED_READONLY isPointInsideInclusive(const iPoint2D &subPoint) const
Definition Point.h:141
constexpr int getTop() const
Definition Point.h:117
constexpr bool RAWSPEED_READONLY isPointInside(const iPoint2D &subPoint) const
Definition Point.h:136
constexpr bool RAWSPEED_READONLY isThisInside(const iRectangle2D &superRect) const
Definition Point.h:146
constexpr int getHeight() const
Definition Point.h:122
constexpr iPoint2D getTopLeft() const
Definition Point.h:123
constexpr int getWidth() const
Definition Point.h:121
constexpr int getLeft() const
Definition Point.h:119
constexpr iPoint2D getBottomRight() const
Definition Point.h:124
CroppedArray2DRef< T > getDataAsCroppedArray2DRef(const RawImage &ri)
iRectangle2D getImageCropAsRectangle(CroppedArray2DRef< T > img)
constexpr uint64_t RAWSPEED_READNONE roundUpDivisionSafe(uint64_t value, uint64_t div)
Definition Common.h:145
constexpr RAWSPEED_READNONE Ttgt implicit_cast(Tsrc value)
Definition Casts.h:32
throw T(buf.data())
constexpr auto RAWSPEED_READNONE clampBits(T value, unsigned int nBits)
Definition Bit.h:75
constexpr RAWSPEED_READNONE Ttgt implicit_cast(Tsrc value)
Definition Casts.h:32
static uint32_t select(uint32_t x, uint32_t)
static uint32_t select(uint32_t, uint32_t y)