Files
Jungfraujoch/common/CompressedImage.cpp
2025-05-28 18:49:27 +02:00

227 lines
8.1 KiB
C++

// SPDX-FileCopyrightText: 2025 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#include "CompressedImage.h"
#include <utility>
#include "JFJochDecompress.h"
CompressedImage::CompressedImage()
: data(nullptr),
size(0),
xpixel(0),
ypixel(0),
mode(CompressedImageMode::Uint8),
algorithm(CompressionAlgorithm::NO_COMPRESSION),
channel("default"){}
size_t CompressedImage::GetUncompressedSize() const {
return xpixel * ypixel * GetByteDepth() * GetNumChannels();
}
bool CompressedImage::IsSigned() const {
switch (mode) {
case CompressedImageMode::Int8:
case CompressedImageMode::Int16:
case CompressedImageMode::Int32:
case CompressedImageMode::Float16:
case CompressedImageMode::Float32:
case CompressedImageMode::Float64:
return true;
case CompressedImageMode::Uint8:
case CompressedImageMode::Uint16:
case CompressedImageMode::Uint32:
case CompressedImageMode::RGB:
return false;
default:
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Image mode not implemented");
}
}
size_t CompressedImage::GetByteDepth() const {
switch (mode) {
case CompressedImageMode::Int8:
case CompressedImageMode::Uint8:
case CompressedImageMode::RGB:
return 1;
case CompressedImageMode::Int16:
case CompressedImageMode::Uint16:
case CompressedImageMode::Float16:
return 2;
case CompressedImageMode::Int32:
case CompressedImageMode::Uint32:
case CompressedImageMode::Float32:
return 4;
case CompressedImageMode::Float64:
return 8;
default:
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Image mode not implemented");
}
}
size_t CompressedImage::GetNumChannels() const {
switch (mode) {
case CompressedImageMode::Int8:
case CompressedImageMode::Int16:
case CompressedImageMode::Int32:
case CompressedImageMode::Uint8:
case CompressedImageMode::Uint16:
case CompressedImageMode::Uint32:
case CompressedImageMode::Float16:
case CompressedImageMode::Float32:
case CompressedImageMode::Float64:
return 1;
case CompressedImageMode::RGB:
return 3;
default:
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Image mode not implemented");
}
}
void CompressedImage::GetUncompressed(std::vector<uint8_t> &buffer) const {
buffer.resize(GetUncompressedSize());
JFJochDecompressPtr(buffer.data(),
algorithm, data, size,
xpixel * ypixel * GetNumChannels(),
GetByteDepth());
}
const uint8_t *CompressedImage::GetUncompressedPtr(std::vector<uint8_t> &buffer) const {
if (algorithm == CompressionAlgorithm::NO_COMPRESSION)
return data;
else {
GetUncompressed(buffer);
return buffer.data();
}
}
CompressedImageMode CalcImageMode(size_t byte_depth, bool is_float, bool is_signed) {
if (is_float) {
switch (byte_depth) {
case 2:
return CompressedImageMode::Float16;
case 4:
return CompressedImageMode::Float32;
case 8:
return CompressedImageMode::Float64;
default:
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Not supported");
}
} else if (is_signed) {
switch (byte_depth) {
case 1:
return CompressedImageMode::Int8;
case 2:
return CompressedImageMode::Int16;
case 4:
return CompressedImageMode::Int32;
default:
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Not supported");
}
} else {
switch (byte_depth) {
case 1:
return CompressedImageMode::Uint8;
case 2:
return CompressedImageMode::Uint16;
case 4:
return CompressedImageMode::Uint32;
default:
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Not supported");
}
}
}
CompressedImage::CompressedImage(const void *in_data, size_t in_size,
size_t in_xpixel, size_t in_ypixel,
CompressedImageMode in_mode,
CompressionAlgorithm in_algorithm,
std::string in_channel)
: data(static_cast<const uint8_t *>(in_data)),
size(in_size),
xpixel(in_xpixel),
ypixel(in_ypixel),
mode(in_mode),
algorithm(in_algorithm),
channel(std::move(in_channel)) {
if (xpixel == 0 || ypixel == 0)
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"xpixel/ypixel cannot be zero");
if (data == nullptr) {
if (size != 0)
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "For empty image, size must be 0");
} else if (algorithm == CompressionAlgorithm::NO_COMPRESSION && GetUncompressedSize() != size)
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Mismatch in size for uncompressed image " + std::to_string(size)
+ " expected size "
+ std::to_string(GetUncompressedSize()));
}
CompressedImage::CompressedImage(const std::vector<rgb> &input, size_t xpixel, size_t ypixel)
: CompressedImage(input.data(), input.size() * sizeof(rgb),
xpixel, ypixel, CompressedImageMode::RGB) {}
CompressedImage::CompressedImage(const std::vector<float> &input, size_t xpixel, size_t ypixel)
: CompressedImage(input.data(), input.size() * sizeof(float),
xpixel, ypixel, CompressedImageMode::Float32) {}
CompressedImage::CompressedImage(const std::vector<uint16_t> &input, size_t xpixel, size_t ypixel)
: CompressedImage(input.data(), input.size() * sizeof(uint16_t),
xpixel, ypixel, CompressedImageMode::Uint16) {}
CompressedImage::CompressedImage(const std::vector<uint32_t> &input, size_t xpixel, size_t ypixel)
: CompressedImage(input.data(), input.size() * sizeof(uint32_t),
xpixel, ypixel, CompressedImageMode::Uint32) {}
CompressedImage::CompressedImage(const std::vector<int16_t> &input, size_t xpixel, size_t ypixel)
: CompressedImage(input.data(), input.size() * sizeof(int16_t),
xpixel, ypixel, CompressedImageMode::Int16) {}
CompressedImage::CompressedImage(const std::vector<int32_t> &input, size_t xpixel, size_t ypixel)
: CompressedImage(input.data(), input.size() * sizeof(int32_t),
xpixel, ypixel, CompressedImageMode::Int32) {}
CompressedImage &CompressedImage::Channel(std::string in_channel) {
channel = std::move(in_channel);
return *this;
}
CompressedImage::CompressedImage(const std::vector<uint8_t> &input, size_t xpixel, size_t ypixel,
CompressedImageMode mode, CompressionAlgorithm algorithm)
: CompressedImage(input.data(), input.size(),xpixel, ypixel, mode,
algorithm) {}
std::string CompressedImage::GetChannel() const {
return channel;
}
size_t CompressedImage::GetWidth() const {
return xpixel;
}
size_t CompressedImage::GetHeight() const {
return ypixel;
}
CompressedImageMode CompressedImage::GetMode() const {
return mode;
}
CompressionAlgorithm CompressedImage::GetCompressionAlgorithm() const {
return algorithm;
}
const uint8_t *CompressedImage::GetCompressed() const {
return data;
}
size_t CompressedImage::GetCompressedSize() const {
return size;
}