Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/pr/412' into panasonic-rw2-v7
Browse files Browse the repository at this point in the history
* upstream/pr/412:
  add back LibRaw copyright.
  formatting.
  fix missing header file from cmake list.
  simplify, consistency, and don't throw errors
  Panasonic V7 support.
  • Loading branch information
LebedevRI committed Jan 24, 2023
2 parents d911e51 + 578a44c commit 5822e55
Show file tree
Hide file tree
Showing 7 changed files with 319 additions and 0 deletions.
1 change: 1 addition & 0 deletions fuzz/all-fuzzers.txt
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ OlympusDecompressorFuzzer
PanasonicV4DecompressorFuzzer
PanasonicV5DecompressorFuzzer
PanasonicV6DecompressorFuzzer
PanasonicV7DecompressorFuzzer
PentaxDecompressorFuzzer
PhaseOneDecompressorFuzzer
RawParserFuzzer-GetDecoder
Expand Down
1 change: 1 addition & 0 deletions fuzz/librawspeed/decompressors/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ set(DECOMPRESSORS
"PanasonicV4Decompressor"
"PanasonicV5Decompressor"
"PanasonicV6Decompressor"
"PanasonicV7Decompressor"
"PentaxDecompressor"
"PhaseOneDecompressor"
"SamsungV0Decompressor"
Expand Down
57 changes: 57 additions & 0 deletions fuzz/librawspeed/decompressors/PanasonicV7Decompressor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
RawSpeed - RAW file decoder.
Copyright (C) 2022 Jordan Neumeyer
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "decompressors/PanasonicV7Decompressor.h"
#include "common/RawImage.h" // for RawImage, RawImageData
#include "common/RawspeedException.h" // for RawspeedException
#include "fuzz/Common.h" // for CreateRawImage
#include "io/Buffer.h" // for Buffer, DataBuffer
#include "io/ByteStream.h" // for ByteStream
#include "io/Endianness.h" // for Endianness, Endianness::little
#include <cassert> // for assert
#include <cstddef> // for size_t
#include <cstdint> // for uint8_t

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size);

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) {
assert(Data);

try {
const rawspeed::Buffer b(Data, Size);
const rawspeed::DataBuffer db(b, rawspeed::Endianness::little);
rawspeed::ByteStream bs(db);

rawspeed::RawImage mRaw(CreateRawImage(bs));

const auto bps = bs.get<uint32_t>();
rawspeed::ByteStream rawData = bs.getStream(bs.getRemainSize());

rawspeed::PanasonicV7Decompressor p(mRaw, rawData, bps);
mRaw->createData();
p.decompress();

mRaw->checkMemIsInitialized();
} catch (const rawspeed::RawspeedException&) {
// Exceptions are good, crashes are bad.
}

return 0;
}
7 changes: 7 additions & 0 deletions src/librawspeed/decoders/Rw2Decoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "decompressors/PanasonicV4Decompressor.h" // for PanasonicV4Decom...
#include "decompressors/PanasonicV5Decompressor.h" // for PanasonicV5Decom...
#include "decompressors/PanasonicV6Decompressor.h" // for PanasonicV6Decom...
#include "decompressors/PanasonicV7Decompressor.h" // for PanasonicV7Decom...
#include "decompressors/UncompressedDecompressor.h" // for UncompressedDeco...
#include "io/Buffer.h" // for Buffer, DataBuffer
#include "io/ByteStream.h" // for ByteStream
Expand Down Expand Up @@ -148,6 +149,12 @@ RawImage Rw2Decoder::decodeRawInternal() {
v6.decompress();
return mRaw;
}
case 7: {
PanasonicV7Decompressor v7(mRaw, bs, bitsPerSample);
mRaw->createData();
v7.decompress();
return mRaw;
}
default:
ThrowRDE("Version %i is unsupported", version);
}
Expand Down
2 changes: 2 additions & 0 deletions src/librawspeed/decompressors/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ FILE(GLOB SOURCES
"PanasonicV5Decompressor.h"
"PanasonicV6Decompressor.cpp"
"PanasonicV6Decompressor.h"
"PanasonicV7Decompressor.cpp"
"PanasonicV7Decompressor.h"
"PentaxDecompressor.cpp"
"PentaxDecompressor.h"
"PhaseOneDecompressor.cpp"
Expand Down
191 changes: 191 additions & 0 deletions src/librawspeed/decompressors/PanasonicV7Decompressor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
/*
RawSpeed - RAW file decoder.
Copyright (C) 2022 LibRaw LLC ([email protected])
Copyright (C) 2022 Jordan Neumeyer
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "rawspeedconfig.h" // for HAVE_OPENMP
#include "decompressors/PanasonicV7Decompressor.h"
#include "adt/Array2DRef.h" // for Array2DRef
#include "adt/Point.h" // for iPoint2D
#include "common/Common.h" // for rawspeed_get_number_of_pro...
#include "common/RawImage.h" // for RawImage, RawImageData
#include "decoders/RawDecoderException.h" // for ThrowException, ThrowRDE
#include <array> // for array
#include <cassert> // for assert
#include <cstdint> // for uint16_t
#include <functional>

namespace rawspeed {

PanasonicV7Decompressor::PanasonicV7Decompressor(const RawImage& img,
const ByteStream& input_,
const int bps_)
: mRaw(img) {
if (mRaw->getCpp() != 1 || mRaw->getDataType() != RawImageType::UINT16 ||
mRaw->getBpp() != sizeof(uint16_t))
ThrowRDE("Unexpected component count / data type");

bitsPerSample = bps_;
// Default to 14 bit.
pixelsPerBlock = bps_ != 12 ? PixelsPerBlock14Bit : PixelsPerBlock12Bit;

if (!mRaw->dim.hasPositiveArea() || mRaw->dim.x % pixelsPerBlock != 0) {
ThrowRDE("Unexpected image dimensions found: (%i; %i)", mRaw->dim.x,
mRaw->dim.y);
}

// How many blocks are needed for the given image size?
const auto numBlocks = mRaw->dim.area() / pixelsPerBlock;

// Does the input contain enough blocks?
// How many full blocks does the input contain? This is truncating division.
if (const auto haveBlocks = input_.getRemainSize() / BytesPerBlock;
haveBlocks < numBlocks)
ThrowRDE("Insufficient count of input blocks for a given image");

// We only want those blocks we need, no extras.
input = input_.peekStream(numBlocks, BytesPerBlock);
}

inline uint16_t
PanasonicV7Decompressor::streamedPixelRead(const ByteStream& bs,
int pixelpos) noexcept {
switch (pixelpos) {
case 0:
return bs.peekByte(0) | // low bits
((bs.peekByte(1) & 0x3F) << 8); // high bits

case 1:
return (bs.peekByte(1) >> 6) | (bs.peekByte(2) << 2) |
((bs.peekByte(3) & 0xF) << 10);

case 2:
return (bs.peekByte(3) >> 4) | (bs.peekByte(4) << 4) |
((bs.peekByte(5) & 3) << 12);

case 3:
return ((bs.peekByte(5) & 0xFC) >> 2) | (bs.peekByte(6) << 6);

case 4:
return bs.peekByte(7) | ((bs.peekByte(8) & 0x3F) << 8);

case 5:
return (bs.peekByte(8) >> 6) | (bs.peekByte(9) << 2) |
((bs.peekByte(10) & 0xF) << 10);

case 6:
return (bs.peekByte(10) >> 4) | (bs.peekByte(11) << 4) |
((bs.peekByte(12) & 3) << 12);

case 7:
return ((bs.peekByte(12) & 0xFC) >> 2) | (bs.peekByte(13) << 6);

case 8:
return bs.peekByte(14) | ((bs.peekByte(15) & 0x3F) << 8);

default:
// This shouldn't happen.
return 0;
}
}

inline uint16_t
PanasonicV7Decompressor::streamedPixelRead12Bit(const ByteStream& bs,
int pixelpos) noexcept {
switch (pixelpos) {
case 0:
return ((bs.peekByte(1) & 0xF) << 8) | bs.peekByte(0);

case 1:
return (bs.peekByte(2) << 4) | (bs.peekByte(1) >> 4);

case 2:
return ((bs.peekByte(4) & 0xF) << 8) | bs.peekByte(3);

case 3:
return (bs.peekByte(5) << 4) | (bs.peekByte(4) >> 4);

case 4:
return ((bs.peekByte(7) & 0xF) << 8) | bs.peekByte(6);

case 5:
return (bs.peekByte(8) << 4) | (bs.peekByte(7) >> 4);

case 6:
return ((bs.peekByte(10) & 0xF) << 8) | bs.peekByte(9);

case 7:
return (bs.peekByte(11) << 4) | (bs.peekByte(10) >> 4);

case 8:
return ((bs.peekByte(13) & 0xF) << 8) | bs.peekByte(12);

case 9:
return (bs.peekByte(14) << 4) | (bs.peekByte(13) >> 4);
default:
// This shouldn't happen.
return 0;
}
}

inline void __attribute__((always_inline))
// NOLINTNEXTLINE(bugprone-exception-escape): no exceptions will be thrown.
PanasonicV7Decompressor::decompressBlock(
ByteStream& rowInput, int row, int col,
const std::function<uint16_t(const ByteStream&, int)>& readPixelFn)
const noexcept {
const Array2DRef<uint16_t> out(mRaw->getU16DataAsUncroppedArray2DRef());
const auto stream =
rowInput.getStream(PanasonicV7Decompressor::BytesPerBlock);

for (int pix = 0; pix < pixelsPerBlock; pix++, col++) {
out(row, col) = readPixelFn(stream, pix);
}
}

// NOLINTNEXTLINE(bugprone-exception-escape): no exceptions will be thrown.
void PanasonicV7Decompressor::decompressRow(int row) const noexcept {
assert(mRaw->dim.x % pixelsPerBlock == 0);
const int blocksperrow = mRaw->dim.x / pixelsPerBlock;
const int bytesPerRow = PanasonicV7Decompressor::BytesPerBlock * blocksperrow;

// Default to 14 bit.
const auto readPixelFn =
bitsPerSample != 12 ? streamedPixelRead : streamedPixelRead12Bit;

ByteStream rowInput = input.getSubStream(bytesPerRow * row, bytesPerRow);
for (int rblock = 0, col = 0; rblock < blocksperrow;
rblock++, col += pixelsPerBlock) {
decompressBlock(rowInput, row, col, readPixelFn);
}
}

void PanasonicV7Decompressor::decompress() const {
#ifdef HAVE_OPENMP
#pragma omp parallel for num_threads(rawspeed_get_number_of_processor_cores()) \
schedule(static) default(none)
#endif
for (int row = 0; row < mRaw->dim.y;
++row) { // NOLINT(openmp-exception-escape): we know no exceptions will
// be thrown.
decompressRow(row);
}
}

} // namespace rawspeed
60 changes: 60 additions & 0 deletions src/librawspeed/decompressors/PanasonicV7Decompressor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
RawSpeed - RAW file decoder.
Copyright (C) 2022 Jordan Neumeyer
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#pragma once

#include "common/RawImage.h" // for RawImage
#include "decompressors/AbstractDecompressor.h" // for AbstractDecompressor
#include "io/ByteStream.h" // for ByteStream
#include <functional>

namespace rawspeed {

class PanasonicV7Decompressor final : public AbstractDecompressor {
RawImage mRaw;

ByteStream input;

int pixelsPerBlock;
int bitsPerSample;

static constexpr int PixelsPerBlock14Bit = 9;
static constexpr int PixelsPerBlock12Bit = 10;

static constexpr int BytesPerBlock = 16;

inline void __attribute__((always_inline))
// NOLINTNEXTLINE(bugprone-exception-escape): no exceptions will be thrown.
decompressBlock(ByteStream& rowInput, int row, int col,
const std::function<uint16_t(const ByteStream&, int)>& readPixel) const noexcept;

// NOLINTNEXTLINE(bugprone-exception-escape): no exceptions will be thrown.
void decompressRow(int row) const noexcept;

static uint16_t streamedPixelRead(const ByteStream& bs, int pixelpos) noexcept;
static uint16_t streamedPixelRead12Bit(const ByteStream& bs, int pixelpos) noexcept;

public:
PanasonicV7Decompressor(const RawImage& img, const ByteStream& input_, int bps_);

void decompress() const;
};

} // namespace rawspeed

0 comments on commit 5822e55

Please sign in to comment.