Skip to content

Commit

Permalink
LJpeg: [full] LJpeg frame matches normal DNG tile size
Browse files Browse the repository at this point in the history
This is true for all RPU samples at least, even weird 3-component ones.

This seems like the missing info trivia which allows support
for different LJpeg CPS layouts (e.g. the square one)
  • Loading branch information
LebedevRI committed Mar 18, 2024
1 parent 3a250a2 commit e9e3f1b
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 6 deletions.
5 changes: 4 additions & 1 deletion fuzz/librawspeed/decompressors/LJpegDecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,14 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) {
const auto offsetY = bs.getU32();
const auto width = bs.getU32();
const auto height = bs.getU32();
const auto maxWidth = bs.getU32();
const auto maxHeight = bs.getU32();
const auto fixDng16Bug = bs.getU32();

rawspeed::LJpegDecoder j(bs, mRaw);
mRaw->createData();
j.decode(offsetX, offsetY, width, height, fixDng16Bug);
j.decode(offsetX, offsetY, width, height,
rawspeed::iPoint2D(maxWidth, maxHeight), fixDng16Bug);

// we can not check that all the image was initialized, because normally
// LJpegDecoder decodes just some one tile/slice.
Expand Down
10 changes: 8 additions & 2 deletions src/librawspeed/decoders/ArwDecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -385,8 +385,14 @@ void ArwDecoder::DecodeLJpeg(const TiffIFD* raw) {
ByteStream(
DataBuffer(mFile.getSubView(offset, length), Endianness::little)),
mRaw);
decoder.decode(implicit_cast<uint32_t>(tileX * tilew), tileY * tileh,
implicit_cast<uint32_t>(tilew), tileh, false);
auto offsetX = implicit_cast<uint32_t>(tileX * tilew);
auto offsetY = tileY * tileh;
auto tileWidth = implicit_cast<uint32_t>(tilew);
auto tileHeight = tileh;
auto maxDim = iPoint2D{implicit_cast<int>(tileWidth),
implicit_cast<int>(tileHeight)};
decoder.decode(offsetX, offsetY, tileWidth, tileHeight, maxDim,
/*fixDng16Bug=*/false);
} catch (const RawDecoderException& err) {
mRaw->setError(err.what());
} catch (const IOException& err) {
Expand Down
3 changes: 2 additions & 1 deletion src/librawspeed/decompressors/AbstractDngDecompressor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ template <> void AbstractDngDecompressor::decompressThread<7>() const noexcept {
Array1DRef(slices.data(), implicit_cast<int>(slices.size()))) {
try {
LJpegDecoder d(e.bs, mRaw);
d.decode(e.offX, e.offY, e.width, e.height, mFixLjpeg);
d.decode(e.offX, e.offY, e.width, e.height,
iPoint2D(e.dsc.tileW, e.dsc.tileH), mFixLjpeg);
} catch (const RawDecoderException& err) {
mRaw->setError(err.what());
} catch (const IOException& err) {
Expand Down
14 changes: 13 additions & 1 deletion src/librawspeed/decompressors/LJpegDecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ LJpegDecoder::LJpegDecoder(ByteStream bs, const RawImage& img)
}

void LJpegDecoder::decode(uint32_t offsetX, uint32_t offsetY, uint32_t width,
uint32_t height, bool fixDng16Bug_) {
uint32_t height, iPoint2D maxDim_,
bool fixDng16Bug_) {
if (offsetX >= static_cast<unsigned>(mRaw->dim.x))
ThrowRDE("X offset outside of image");
if (offsetY >= static_cast<unsigned>(mRaw->dim.y))
Expand All @@ -82,11 +83,18 @@ void LJpegDecoder::decode(uint32_t offsetX, uint32_t offsetY, uint32_t width,
if (width == 0 || height == 0)
return; // We do not need anything from this tile.

if (!maxDim_.hasPositiveArea() ||
implicit_cast<unsigned>(maxDim_.x) < width ||
implicit_cast<unsigned>(maxDim_.y) < height)
ThrowRDE("Requested tile is larger than tile's maximal dimensions");

offX = offsetX;
offY = offsetY;
w = width;
h = height;

maxDim = maxDim_;

fixDng16Bug = fixDng16Bug_;

AbstractLJpegDecoder::decodeSOI();
Expand Down Expand Up @@ -120,6 +128,10 @@ Buffer::size_type LJpegDecoder::decodeScan() {
const LJpegDecompressor::Frame jpegFrame = {N_COMP,
iPoint2D(frame.w, frame.h)};

if (iPoint2D(mRaw->getCpp() * maxDim.x, maxDim.y) !=

This comment has been minimized.

Copy link
@kmilos

kmilos Mar 26, 2024

Collaborator

I think this check would also fail for the Blackmagic/CinemaDNG case?

iPoint2D(N_COMP * frame.w, frame.h))
ThrowRDE("LJpeg frame does not match maximal tile size");

int numRowsPerRestartInterval;
if (numMCUsPerRestartInterval == 0) {
// Restart interval not enabled, so all of the rows
Expand Down
4 changes: 3 additions & 1 deletion src/librawspeed/decompressors/LJpegDecoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,13 @@ class LJpegDecoder final : public AbstractLJpegDecoder {
uint32_t w = 0;
uint32_t h = 0;

iPoint2D maxDim;

public:
LJpegDecoder(ByteStream bs, const RawImage& img);

void decode(uint32_t offsetX, uint32_t offsetY, uint32_t width,
uint32_t height, bool fixDng16Bug_);
uint32_t height, iPoint2D maxDim, bool fixDng16Bug_);
};

} // namespace rawspeed

0 comments on commit e9e3f1b

Please sign in to comment.