|
42 | 42 | #include "io/IOException.h" |
43 | 43 | #include <algorithm> |
44 | 44 | #include <array> |
| 45 | +#include <climits> |
45 | 46 | #include <cstddef> |
46 | 47 | #include <cstdint> |
47 | 48 | #include <limits> |
| 49 | +#include <numeric> |
48 | 50 | #include <utility> |
49 | 51 | #include <vector> |
50 | 52 |
|
@@ -196,6 +198,24 @@ void isValidImageGrid(iRectangle2D imgDim, |
196 | 198 | ThrowRDE("Tiles do not cover whole output image"); |
197 | 199 | } |
198 | 200 |
|
| 201 | +int minBitsPerPixelNeeded( |
| 202 | + Array1DRef<const PanasonicV8Decompressor::DecoderLUTEntry> mDecoderLUT) { |
| 203 | + invariant(mDecoderLUT.size() > 0); |
| 204 | + const auto r = std::accumulate( |
| 205 | + mDecoderLUT.begin(), mDecoderLUT.end(), std::numeric_limits<int>::max(), |
| 206 | + [](int init, const PanasonicV8Decompressor::DecoderLUTEntry& e) { |
| 207 | + if (e.isSentinel()) |
| 208 | + return init; |
| 209 | + invariant(e.bitcount > 0); |
| 210 | + const auto total = e.bitcount + e.diffCat; |
| 211 | + invariant(total > 0); |
| 212 | + return std::min(init, total); |
| 213 | + }); |
| 214 | + invariant(r > 0); |
| 215 | + invariant(r <= (16 + 17)); |
| 216 | + return r; |
| 217 | +} |
| 218 | + |
199 | 219 | } // namespace |
200 | 220 |
|
201 | 221 | std::vector<iRectangle2D> |
@@ -248,6 +268,14 @@ PanasonicV8Decompressor::PanasonicV8Decompressor( |
248 | 268 | } |
249 | 269 | if (!mRawOutput->dim.hasPositiveArea()) |
250 | 270 | ThrowRDE("Unexpected image dimensions"); |
| 271 | + const auto minBpp = minBitsPerPixelNeeded(mDecoderLUT); |
| 272 | + for (int stripIdx = 0; stripIdx < mParams.mStrips.size(); ++stripIdx) { |
| 273 | + const auto strip = mParams.mStrips(stripIdx); |
| 274 | + const auto maxPixelsInStrip = (uint64_t{CHAR_BIT} * strip.size()) / minBpp; |
| 275 | + const auto outRect = mParams.mOutRect(stripIdx); |
| 276 | + if (outRect.dim.area() > maxPixelsInStrip) |
| 277 | + ThrowRDE("Input strip is unsufficient to produce requested tile"); |
| 278 | + } |
251 | 279 | } |
252 | 280 |
|
253 | 281 | void PanasonicV8Decompressor::decompress() const { |
|
0 commit comments