| 145 | } |
| 146 | |
| 147 | void DngDecoder::parseCFA(const TiffIFD* raw) { |
| 148 | |
| 149 | // Check if layout is OK, if present |
| 150 | if (raw->hasEntry(CFALAYOUT) && raw->getEntry(CFALAYOUT)->getU16() != 1) |
| 151 | ThrowRDE("Unsupported CFA Layout."); |
| 152 | |
| 153 | TiffEntry* cfadim = raw->getEntry(CFAREPEATPATTERNDIM); |
| 154 | if (cfadim->count != 2) |
| 155 | ThrowRDE("Couldn't read CFA pattern dimension"); |
| 156 | |
| 157 | // Does NOT contain dimensions as some documents state |
| 158 | TiffEntry* cPat = raw->getEntry(CFAPATTERN); |
| 159 | |
| 160 | iPoint2D cfaSize(cfadim->getU32(1), cfadim->getU32(0)); |
| 161 | if (cfaSize.area() != cPat->count) { |
| 162 | ThrowRDE("CFA pattern dimension and pattern count does not " |
| 163 | "match: %d.", |
| 164 | cPat->count); |
| 165 | } |
| 166 | |
| 167 | mRaw->cfa.setSize(cfaSize); |
| 168 | |
| 169 | static const map<uint32_t, CFAColor> int2enum = { |
| 170 | {0, CFA_RED}, {1, CFA_GREEN}, {2, CFA_BLUE}, {3, CFA_CYAN}, |
| 171 | {4, CFA_MAGENTA}, {5, CFA_YELLOW}, {6, CFA_WHITE}, |
| 172 | }; |
| 173 | |
| 174 | for (int y = 0; y < cfaSize.y; y++) { |
| 175 | for (int x = 0; x < cfaSize.x; x++) { |
| 176 | uint32_t c1 = cPat->getByte(x + y * cfaSize.x); |
| 177 | CFAColor c2 = CFA_UNKNOWN; |
| 178 | |
| 179 | try { |
| 180 | c2 = int2enum.at(c1); |
| 181 | } catch (std::out_of_range&) { |
| 182 | ThrowRDE("Unsupported CFA Color: %u", c1); |
| 183 | } |
| 184 | |
| 185 | mRaw->cfa.setColorAt(iPoint2D(x, y), c2); |
| 186 | } |
| 187 | } |
| 188 | |
| 189 | // the cfa is specified relative to the ActiveArea. we want it relative (0,0) |
| 190 | // Since in handleMetadata(), in subFrame() we unconditionally shift CFA by |
| 191 | // activearea+DefaultCropOrigin; here we need to undo the 'ACTIVEAREA' part. |
| 192 | if (!raw->hasEntry(ACTIVEAREA)) |
| 193 | return; |
| 194 | |
| 195 | TiffEntry* active_area = raw->getEntry(ACTIVEAREA); |
| 196 | if (active_area->count != 4) |
| 197 | ThrowRDE("active area has %d values instead of 4", active_area->count); |
| 198 | |
| 199 | const auto aa = active_area->getFloatArray(2); |
| 200 | if (std::any_of(aa.cbegin(), aa.cend(), [](const auto v) { |
| 201 | return v < std::numeric_limits<iPoint2D::value_type>::min() || |
| 202 | v > std::numeric_limits<iPoint2D::value_type>::max(); |
| 203 | })) |
| 204 | ThrowRDE("Error decoding active area"); |
nothing calls this directly
no test coverage detected