| 113 | // for technical details about Cr2 mRAW/sRAW, see http://lclevy.free.fr/cr2/ |
| 114 | |
| 115 | RawImage Cr2Decoder::decodeNewFormat() { |
| 116 | TiffEntry* sensorInfoE = mRootIFD->getEntryRecursive(CANON_SENSOR_INFO); |
| 117 | if (!sensorInfoE) |
| 118 | ThrowTPE("failed to get SensorInfo from MakerNote"); |
| 119 | |
| 120 | assert(sensorInfoE != nullptr); |
| 121 | |
| 122 | if (isSubSampled() != (getSubSampling() != iPoint2D{1, 1})) |
| 123 | ThrowTPE("Subsampling sanity check failed"); |
| 124 | |
| 125 | mRaw->dim = {sensorInfoE->getU16(1), sensorInfoE->getU16(2)}; |
| 126 | mRaw->setCpp(1); |
| 127 | mRaw->isCFA = !isSubSampled(); |
| 128 | |
| 129 | if (isSubSampled()) { |
| 130 | iPoint2D& subSampling = mRaw->metadata.subsampling; |
| 131 | subSampling = getSubSampling(); |
| 132 | if (!(subSampling.x > 1 || subSampling.y > 1)) |
| 133 | ThrowRDE("RAW is expected to be subsampled, but it's not"); |
| 134 | |
| 135 | if (mRaw->dim.x % subSampling.x != 0) |
| 136 | ThrowRDE("Raw width is not a multiple of horizontal subsampling factor"); |
| 137 | mRaw->dim.x /= subSampling.x; |
| 138 | |
| 139 | if (mRaw->dim.y % subSampling.y != 0) |
| 140 | ThrowRDE("Raw height is not a multiple of vertical subsampling factor"); |
| 141 | mRaw->dim.y /= subSampling.y; |
| 142 | |
| 143 | mRaw->dim.x *= 2 + subSampling.x * subSampling.y; |
| 144 | } |
| 145 | |
| 146 | TiffIFD* raw = mRootIFD->getSubIFDs()[3].get(); |
| 147 | |
| 148 | Cr2Slicing slicing; |
| 149 | // there are four cases: |
| 150 | // * there is a tag with three components, |
| 151 | // $ last two components are non-zero: all fine then. |
| 152 | // $ first two components are zero, last component is non-zero |
| 153 | // we let Cr2Decompressor guess it (it'll throw if fails) |
| 154 | // $ else the image is considered corrupt. |
| 155 | // * there is a tag with not three components, the image is considered |
| 156 | // corrupt. $ there is no tag, we let Cr2Decompressor guess it (it'll throw if |
| 157 | // fails) |
| 158 | TiffEntry* cr2SliceEntry = raw->getEntryRecursive(CANONCR2SLICE); |
| 159 | if (cr2SliceEntry) { |
| 160 | if (cr2SliceEntry->count != 3) { |
| 161 | ThrowRDE("Found RawImageSegmentation tag with %d elements, should be 3.", |
| 162 | cr2SliceEntry->count); |
| 163 | } |
| 164 | |
| 165 | if (cr2SliceEntry->getU16(1) != 0 && cr2SliceEntry->getU16(2) != 0) { |
| 166 | // first component can be either zero or non-zero, don't care |
| 167 | slicing = Cr2Slicing(/*numSlices=*/1 + cr2SliceEntry->getU16(0), |
| 168 | /*sliceWidth=*/cr2SliceEntry->getU16(1), |
| 169 | /*lastSliceWidth=*/cr2SliceEntry->getU16(2)); |
| 170 | } else if (cr2SliceEntry->getU16(0) == 0 && cr2SliceEntry->getU16(1) == 0 && |
| 171 | cr2SliceEntry->getU16(2) != 0) { |
| 172 | // PowerShot G16, PowerShot S120, let Cr2Decompressor guess. |
nothing calls this directly
no test coverage detected