"Fossies" - the Fresh Open Source Software Archive

Member "darktable-2.6.3/src/external/rawspeed/src/librawspeed/decoders/RawDecoder.cpp" (19 Oct 2019, 10581 Bytes) of package /linux/misc/darktable-2.6.3.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "RawDecoder.cpp" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.6.2_vs_2.6.3.

    1 /*
    2     RawSpeed - RAW file decoder.
    3 
    4     Copyright (C) 2009-2014 Klaus Post
    5     Copyright (C) 2014 Pedro CĂ´rte-Real
    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 #include "decoders/RawDecoder.h"
   23 #include "common/Common.h"                          // for uint32_t, roundUpD...
   24 #include "common/Point.h"                           // for iPoint2D, iRecta...
   25 #include "decoders/RawDecoderException.h"           // for ThrowRDE
   26 #include "decompressors/UncompressedDecompressor.h" // for UncompressedDeco...
   27 #include "io/Buffer.h"                              // for Buffer
   28 #include "io/FileIOException.h"                     // for FileIOException
   29 #include "io/IOException.h"                         // for IOException
   30 #include "metadata/BlackArea.h"                     // for BlackArea
   31 #include "metadata/Camera.h"                        // for Camera, Hints
   32 #include "metadata/CameraMetaData.h"                // for CameraMetaData
   33 #include "metadata/CameraSensorInfo.h"              // for CameraSensorInfo
   34 #include "metadata/ColorFilterArray.h"              // for ColorFilterArray
   35 #include "parsers/TiffParserException.h"            // for TiffParserException
   36 #include "tiff/TiffEntry.h"                         // for TiffEntry
   37 #include "tiff/TiffIFD.h"                           // for TiffIFD
   38 #include "tiff/TiffTag.h"                           // for BITSPERSAMPLE
   39 #include <array>                                    // for array
   40 #include <cassert>                                  // for assert
   41 #include <string>                                   // for string, basic_st...
   42 #include <vector>                                   // for vector
   43 
   44 using std::vector;
   45 using std::string;
   46 
   47 namespace rawspeed {
   48 
   49 RawDecoder::RawDecoder(const Buffer* file)
   50     : mRaw(RawImage::create()), mFile(file) {
   51   failOnUnknown = false;
   52   interpolateBadPixels = true;
   53   applyStage1DngOpcodes = true;
   54   applyCrop = true;
   55   uncorrectedRawValues = false;
   56   fujiRotate = true;
   57 }
   58 
   59 void RawDecoder::decodeUncompressed(const TiffIFD *rawIFD, BitOrder order) {
   60   TiffEntry *offsets = rawIFD->getEntry(STRIPOFFSETS);
   61   TiffEntry *counts = rawIFD->getEntry(STRIPBYTECOUNTS);
   62   uint32_t yPerSlice = rawIFD->getEntry(ROWSPERSTRIP)->getU32();
   63   uint32_t width = rawIFD->getEntry(IMAGEWIDTH)->getU32();
   64   uint32_t height = rawIFD->getEntry(IMAGELENGTH)->getU32();
   65   uint32_t bitPerPixel = rawIFD->getEntry(BITSPERSAMPLE)->getU32();
   66 
   67   if (width == 0 || height == 0 || width > 5632 || height > 3720)
   68     ThrowRDE("Unexpected image dimensions found: (%u; %u)", width, height);
   69 
   70   mRaw->dim = iPoint2D(width, height);
   71 
   72   if (counts->count != offsets->count) {
   73     ThrowRDE("Byte count number does not match strip size: "
   74              "count:%u, stips:%u ",
   75              counts->count, offsets->count);
   76   }
   77 
   78   if (yPerSlice == 0 || yPerSlice > static_cast<uint32_t>(mRaw->dim.y) ||
   79       roundUpDivision(mRaw->dim.y, yPerSlice) != counts->count) {
   80     ThrowRDE("Invalid y per slice %u or strip count %u (height = %u)",
   81              yPerSlice, counts->count, mRaw->dim.y);
   82   }
   83 
   84   switch (bitPerPixel) {
   85   case 12:
   86   case 14:
   87     break;
   88   default:
   89     ThrowRDE("Unexpected bits per pixel: %u.", bitPerPixel);
   90   }
   91 
   92   vector<RawSlice> slices;
   93   slices.reserve(counts->count);
   94   uint32_t offY = 0;
   95 
   96   for (uint32_t s = 0; s < counts->count; s++) {
   97     RawSlice slice;
   98     slice.offset = offsets->getU32(s);
   99     slice.count = counts->getU32(s);
  100 
  101     if (slice.count < 1)
  102       ThrowRDE("Slice %u is empty", s);
  103 
  104     if (offY + yPerSlice > height)
  105       slice.h = height - offY;
  106     else
  107       slice.h = yPerSlice;
  108 
  109     offY += yPerSlice;
  110 
  111     if (!mFile->isValid(slice.offset, slice.count))
  112       ThrowRDE("Slice offset/count invalid");
  113 
  114     slices.push_back(slice);
  115   }
  116 
  117   if (slices.empty())
  118     ThrowRDE("No valid slices found. File probably truncated.");
  119 
  120   assert(height <= offY);
  121   assert(slices.size() == counts->count);
  122 
  123   mRaw->createData();
  124 
  125   // Default white level is (2 ** BitsPerSample) - 1
  126   mRaw->whitePoint = (1UL << bitPerPixel) - 1UL;
  127 
  128   offY = 0;
  129   for (const RawSlice& slice : slices) {
  130     UncompressedDecompressor u(
  131         ByteStream(DataBuffer(mFile->getSubView(slice.offset, slice.count),
  132                               Endianness::little)),
  133         mRaw);
  134     iPoint2D size(width, slice.h);
  135     iPoint2D pos(0, offY);
  136     bitPerPixel = static_cast<int>(
  137         static_cast<uint64_t>(static_cast<uint64_t>(slice.count) * 8U) /
  138         (slice.h * width));
  139     const auto inputPitch = width * bitPerPixel / 8;
  140     if (!inputPitch)
  141       ThrowRDE("Bad input pitch. Can not decode anything.");
  142 
  143     u.readUncompressedRaw(size, pos, inputPitch, bitPerPixel, order);
  144 
  145     offY += slice.h;
  146   }
  147 }
  148 
  149 void RawDecoder::askForSamples(const CameraMetaData* meta, const string& make,
  150                                const string& model, const string& mode) {
  151   if ("dng" == mode)
  152     return;
  153 
  154   writeLog(DEBUG_PRIO_WARNING,
  155            "Unable to find camera in database: '%s' '%s' "
  156            "'%s'\nPlease consider providing samples on "
  157            "<https://raw.pixls.us/>, thanks!",
  158            make.c_str(), model.c_str(), mode.c_str());
  159 }
  160 
  161 bool RawDecoder::checkCameraSupported(const CameraMetaData* meta,
  162                                       const string& make, const string& model,
  163                                       const string& mode) {
  164   mRaw->metadata.make = make;
  165   mRaw->metadata.model = model;
  166   const Camera* cam = meta->getCamera(make, model, mode);
  167   if (!cam) {
  168     askForSamples(meta, make, model, mode);
  169 
  170     if (failOnUnknown)
  171       ThrowRDE("Camera '%s' '%s', mode '%s' not supported, and not allowed to guess. Sorry.", make.c_str(), model.c_str(), mode.c_str());
  172 
  173     // Assume the camera can be decoded, but return false, so decoders can see that we are unsure.
  174     return false;
  175   }
  176 
  177   if (!cam->supported)
  178     ThrowRDE("Camera not supported (explicit). Sorry.");
  179 
  180   if (cam->decoderVersion > getDecoderVersion())
  181     ThrowRDE("Camera not supported in this version. Update RawSpeed for support.");
  182 
  183   hints = cam->hints;
  184   return true;
  185 }
  186 
  187 void RawDecoder::setMetaData(const CameraMetaData* meta, const string& make,
  188                              const string& model, const string& mode,
  189                              int iso_speed) {
  190   mRaw->metadata.isoSpeed = iso_speed;
  191   const Camera* cam = meta->getCamera(make, model, mode);
  192   if (!cam) {
  193     askForSamples(meta, make, model, mode);
  194 
  195     if (failOnUnknown)
  196       ThrowRDE("Camera '%s' '%s', mode '%s' not supported, and not allowed to guess. Sorry.", make.c_str(), model.c_str(), mode.c_str());
  197 
  198     return;
  199   }
  200 
  201   // Only override CFA with the data from cameras.xml if it actually contained
  202   // the CFA.
  203   if (cam->cfa.getSize().area() > 0)
  204     mRaw->cfa = cam->cfa;
  205 
  206   mRaw->metadata.canonical_make = cam->canonical_make;
  207   mRaw->metadata.canonical_model = cam->canonical_model;
  208   mRaw->metadata.canonical_alias = cam->canonical_alias;
  209   mRaw->metadata.canonical_id = cam->canonical_id;
  210   mRaw->metadata.make = make;
  211   mRaw->metadata.model = model;
  212   mRaw->metadata.mode = mode;
  213 
  214   if (applyCrop) {
  215     iPoint2D new_size = cam->cropSize;
  216 
  217     // If crop size is negative, use relative cropping
  218     if (new_size.x <= 0)
  219       new_size.x = mRaw->dim.x - cam->cropPos.x + new_size.x;
  220 
  221     if (new_size.y <= 0)
  222       new_size.y = mRaw->dim.y - cam->cropPos.y + new_size.y;
  223 
  224     mRaw->subFrame(iRectangle2D(cam->cropPos, new_size));
  225   }
  226 
  227   const CameraSensorInfo *sensor = cam->getSensorInfo(iso_speed);
  228   mRaw->blackLevel = sensor->mBlackLevel;
  229   mRaw->whitePoint = sensor->mWhiteLevel;
  230   mRaw->blackAreas = cam->blackAreas;
  231   if (mRaw->blackAreas.empty() && !sensor->mBlackLevelSeparate.empty()) {
  232     auto cfaArea = mRaw->cfa.getSize().area();
  233     if (mRaw->isCFA && cfaArea <= sensor->mBlackLevelSeparate.size()) {
  234       for (auto i = 0UL; i < cfaArea; i++) {
  235         mRaw->blackLevelSeparate[i] = sensor->mBlackLevelSeparate[i];
  236       }
  237     } else if (!mRaw->isCFA && mRaw->getCpp() <= sensor->mBlackLevelSeparate.size()) {
  238       for (uint32_t i = 0; i < mRaw->getCpp(); i++) {
  239         mRaw->blackLevelSeparate[i] = sensor->mBlackLevelSeparate[i];
  240       }
  241     }
  242   }
  243 
  244   // Allow overriding individual blacklevels. Values are in CFA order
  245   // (the same order as the in the CFA tag)
  246   // A hint could be:
  247   // <Hint name="override_cfa_black" value="10,20,30,20"/>
  248   string cfa_black = hints.get("override_cfa_black", string());
  249   if (!cfa_black.empty()) {
  250     vector<string> v = splitString(cfa_black, ',');
  251     if (v.size() != 4) {
  252       mRaw->setError("Expected 4 values '10,20,30,20' as values for override_cfa_black hint.");
  253     } else {
  254       for (int i = 0; i < 4; i++) {
  255         mRaw->blackLevelSeparate[i] = stoi(v[i]);
  256       }
  257     }
  258   }
  259 }
  260 
  261 rawspeed::RawImage RawDecoder::decodeRaw() {
  262   try {
  263     RawImage raw = decodeRawInternal();
  264     raw->checkMemIsInitialized();
  265 
  266     raw->metadata.pixelAspectRatio =
  267         hints.get("pixel_aspect_ratio", raw->metadata.pixelAspectRatio);
  268     if (interpolateBadPixels) {
  269       raw->fixBadPixels();
  270       raw->checkMemIsInitialized();
  271     }
  272 
  273     return raw;
  274   } catch (TiffParserException &e) {
  275     ThrowRDE("%s", e.what());
  276   } catch (FileIOException &e) {
  277     ThrowRDE("%s", e.what());
  278   } catch (IOException &e) {
  279     ThrowRDE("%s", e.what());
  280   }
  281 }
  282 
  283 void RawDecoder::decodeMetaData(const CameraMetaData* meta) {
  284   try {
  285     decodeMetaDataInternal(meta);
  286   } catch (TiffParserException &e) {
  287     ThrowRDE("%s", e.what());
  288   } catch (FileIOException &e) {
  289     ThrowRDE("%s", e.what());
  290   } catch (IOException &e) {
  291     ThrowRDE("%s", e.what());
  292   }
  293 }
  294 
  295 void RawDecoder::checkSupport(const CameraMetaData* meta) {
  296   try {
  297     checkSupportInternal(meta);
  298   } catch (TiffParserException &e) {
  299     ThrowRDE("%s", e.what());
  300   } catch (FileIOException &e) {
  301     ThrowRDE("%s", e.what());
  302   } catch (IOException &e) {
  303     ThrowRDE("%s", e.what());
  304   }
  305 }
  306 
  307 } // namespace rawspeed