// Copyright (2019-2023) Paul Scherrer Institute #include #include "bitshuffle/bitshuffle.h" #include "FrameTransformation.h" #include "../common/RawToConvertedGeometry.h" #include "../common/JFJochException.h" template void FillVector(std::vector &v, int64_t fill_value) { auto ptr = (T *) v.data(); for (int i = 0; i < v.size() / sizeof(T); i++) ptr[i] = static_cast(fill_value); } FrameTransformation::FrameTransformation(const DiffractionExperiment &in_experiment) : experiment(in_experiment), pixel_depth(experiment.GetByteDepthImage()), pixel_signed(experiment.IsPixelSigned()), compressor(in_experiment.GetCompressionAlgorithm()), err_value(experiment.GetByteDepthImage() * RAW_MODULE_SIZE) { precompression_buffer.resize(experiment.GetPixelsNum() * pixel_depth); if (pixel_depth == 2) { if (pixel_signed) { FillVector(precompression_buffer, experiment.GetImageFillValue()); FillVector(err_value, experiment.GetImageFillValue()); } else { FillVector(precompression_buffer, experiment.GetImageFillValue()); FillVector(err_value, experiment.GetImageFillValue()); } } else if (pixel_depth == 4) { if (pixel_signed) { FillVector(precompression_buffer, experiment.GetImageFillValue()); FillVector(err_value, experiment.GetImageFillValue()); } else { FillVector(precompression_buffer, experiment.GetImageFillValue()); FillVector(err_value, experiment.GetImageFillValue()); } } } size_t FrameTransformation::CompressImage(void *output) { return compressor.Compress(output, precompression_buffer.data(), experiment.GetPixelsNum(), experiment.GetByteDepthImage()); } CompressedImage FrameTransformation::GetCompressedImage() { CompressedImage image{}; if (experiment.GetCompressionAlgorithm() == CompressionAlgorithm::NO_COMPRESSION) { image.data = (uint8_t *) precompression_buffer.data(); image.size = experiment.GetPixelsNum() * experiment.GetByteDepthImage(); } else { compressed_buffer.resize(MaxCompressedSize(experiment.GetCompressionAlgorithm(), experiment.GetPixelsNum(), experiment.GetByteDepthImage())); image.data = (uint8_t *) compressed_buffer.data(); image.size = CompressImage(compressed_buffer.data()); } image.xpixel = experiment.GetXPixelsNum(); image.ypixel = experiment.GetYPixelsNum(); image.algorithm = experiment.GetCompressionAlgorithm(); image.pixel_depth_bytes = experiment.GetByteDepthImage(); image.pixel_is_signed = pixel_signed; image.pixel_is_float = false; image.channel = "default"; return image; } void FrameTransformation::ProcessModule(const void *input, uint16_t module_number, int data_stream) { size_t module_number_abs = experiment.GetFirstModuleOfDataStream(data_stream) + module_number; if (!experiment.IsGeometryTransformed()) { size_t mod_size = RAW_MODULE_SIZE * pixel_depth; memcpy(precompression_buffer.data() + module_number_abs * mod_size, input, mod_size); } else { auto pixel0 = experiment.GetPixel0OfModule(module_number_abs); auto fast_step = experiment.GetModuleFastDirectionStep(module_number_abs); auto slow_step = experiment.GetModuleSlowDirectionStep(module_number_abs); if (pixel_depth == 2) { if (pixel_signed) TransferModuleAdjustMultipixels((int16_t *) precompression_buffer.data(), (int16_t *) input, slow_step, static_cast(INT16_MIN), static_cast(INT16_MAX), fast_step, pixel0); else TransferModuleAdjustMultipixels((uint16_t *) precompression_buffer.data(), (uint16_t *) input, slow_step, static_cast(0), static_cast(UINT16_MAX - 1), fast_step, pixel0); } else if (pixel_depth == 4) { if (pixel_signed) TransferModuleAdjustMultipixels((int32_t *) precompression_buffer.data(), (int32_t *) input, slow_step, static_cast(INT32_MIN), static_cast(INT32_MAX), fast_step, pixel0); else TransferModuleAdjustMultipixels((uint32_t *) precompression_buffer.data(), (uint32_t *) input, slow_step, static_cast(0), static_cast(UINT32_MAX - 1), fast_step, pixel0); } } } void FrameTransformation::ProcessModule(const DeviceOutput *output, int data_stream) { ProcessModule(output->pixels, output->module_statistics.module_number, data_stream); } const void *FrameTransformation::GetImage() const { return precompression_buffer.data(); } void FrameTransformation::FillNotCollectedModule(uint16_t module_number, int data_stream) { ProcessModule(err_value.data(), module_number, data_stream); }