diff --git a/common/ImagePusher.cpp b/common/ImagePusher.cpp index 64c9f54f..66926b71 100644 --- a/common/ImagePusher.cpp +++ b/common/ImagePusher.cpp @@ -12,6 +12,7 @@ void PrepareCBORImage(DataMessage& message, message.image.ypixel = experiment.GetYPixelsNum(); message.image.pixel_depth_bytes = experiment.GetPixelDepth(); message.image.pixel_is_signed = experiment.IsPixelSigned(); + message.image.pixel_is_float = false; message.image.algorithm = experiment.GetCompressionAlgorithmEnum(); message.image.channel = "default"; } diff --git a/frame_serialize/ImageMessage.h b/frame_serialize/ImageMessage.h index ca0c54bf..741e668f 100644 --- a/frame_serialize/ImageMessage.h +++ b/frame_serialize/ImageMessage.h @@ -18,6 +18,7 @@ struct CBORImage { size_t ypixel; size_t pixel_depth_bytes; bool pixel_is_signed; + bool pixel_is_float = false; CompressionAlgorithm algorithm; std::string channel; }; diff --git a/frame_serialize/JFJochFrameDeserializer.cpp b/frame_serialize/JFJochFrameDeserializer.cpp index d1a5acf2..72574490 100644 --- a/frame_serialize/JFJochFrameDeserializer.cpp +++ b/frame_serialize/JFJochFrameDeserializer.cpp @@ -184,29 +184,40 @@ inline void GetCBORTypedArray(CBORImage &v, CborValue &value) { CborTag tag = GetCBORTag(value); switch (tag) { + case TagFloatLE: + v.pixel_is_signed = true; + v.pixel_depth_bytes = sizeof(float); + v.pixel_is_float = true; + break; case TagSignedInt8Bit: v.pixel_is_signed = true; v.pixel_depth_bytes = 1; + v.pixel_is_float = false; break; case TagUnsignedInt8Bit: v.pixel_is_signed = false; v.pixel_depth_bytes = 1; + v.pixel_is_float = false; break; case TagSignedInt16BitLE: v.pixel_is_signed = true; v.pixel_depth_bytes = 2; + v.pixel_is_float = false; break; case TagUnsignedInt16BitLE: v.pixel_is_signed = false; v.pixel_depth_bytes = 2; + v.pixel_is_float = false; break; case TagSignedInt32BitLE: v.pixel_is_signed = true; v.pixel_depth_bytes = 4; + v.pixel_is_float = false; break; case TagUnsignedInt32BitLE: v.pixel_is_signed = false; v.pixel_depth_bytes = 4; + v.pixel_is_float = false; break; default: throw JFJochException(JFJochExceptionCategory::CBORError, diff --git a/frame_serialize/JFJochFrameSerializer.cpp b/frame_serialize/JFJochFrameSerializer.cpp index 5db632fd..92747332 100644 --- a/frame_serialize/JFJochFrameSerializer.cpp +++ b/frame_serialize/JFJochFrameSerializer.cpp @@ -78,41 +78,43 @@ void CBOR_ENC_COMPRESSED(CborEncoder &encoder, } } -inline void CBOR_ENC_MULTIDIM_TYPED_ARRAY(CborEncoder &encoder, const char* key, - const void *image, size_t image_size, - size_t xpixel, size_t ypixel, CompressionAlgorithm algorithm, - size_t elem_size, bool elem_sign) { +inline void CBOR_ENC_2D_TYPED_ARRAY(CborEncoder &encoder, const CBORImage& image) { //if ((algorithm == CompressionAlgorithm::NO_COMPRESSION) && (xpixel * ypixel != image_size / elem_size)) // throw JFJochException(JFJochExceptionCategory::CBORError, "Mismatch in array size"); CborEncoder arrayEncoder, arrayEncoder_2; - cborErr(cbor_encode_text_stringz(&encoder, key)); + cborErr(cbor_encode_text_stringz(&encoder, image.channel.c_str())); cbor_encode_tag(&encoder, TagMultiDimArray); cborErr(cbor_encoder_create_array(&encoder, &arrayEncoder, 2)); cborErr(cbor_encoder_create_array(&arrayEncoder, &arrayEncoder_2, 2)); - cborErr(cbor_encode_uint(&arrayEncoder_2, ypixel)); - cborErr(cbor_encode_uint(&arrayEncoder_2, xpixel)); + cborErr(cbor_encode_uint(&arrayEncoder_2, image.ypixel)); + cborErr(cbor_encode_uint(&arrayEncoder_2, image.xpixel)); cborErr(cbor_encoder_close_container(&arrayEncoder, &arrayEncoder_2)); CborTag typed_array_tag; - if (elem_sign) { - if (elem_size == 4) + if (image.pixel_is_float) { + if (image.pixel_depth_bytes == 4) + typed_array_tag = TagFloatLE; + else + throw JFJochException(JFJochExceptionCategory::CBORError, "Array size not supported"); + } else if (image.pixel_is_signed) { + if (image.pixel_depth_bytes == 4) typed_array_tag = TagSignedInt32BitLE; - else if (elem_size == 2) + else if (image.pixel_depth_bytes == 2) typed_array_tag = TagSignedInt16BitLE; - else if (elem_size == 1) + else if (image.pixel_depth_bytes == 1) typed_array_tag = TagSignedInt8Bit; else throw JFJochException(JFJochExceptionCategory::CBORError, "Array size not supported"); } else { - if (elem_size == 4) + if (image.pixel_depth_bytes == 4) typed_array_tag = TagUnsignedInt32BitLE; - else if (elem_size == 2) + else if (image.pixel_depth_bytes == 2) typed_array_tag = TagUnsignedInt16BitLE; - else if (elem_size == 1) + else if (image.pixel_depth_bytes == 1) typed_array_tag = TagUnsignedInt8Bit; else throw JFJochException(JFJochExceptionCategory::CBORError, "Array size not supported"); @@ -120,7 +122,7 @@ inline void CBOR_ENC_MULTIDIM_TYPED_ARRAY(CborEncoder &encoder, const char* key, cbor_encode_tag(&arrayEncoder, typed_array_tag); - CBOR_ENC_COMPRESSED(arrayEncoder, image, image_size, algorithm, elem_size); + CBOR_ENC_COMPRESSED(arrayEncoder, image.data, image.size, image.algorithm, image.pixel_depth_bytes); cborErr(cbor_encoder_close_container(&encoder, &arrayEncoder)); } @@ -130,15 +132,20 @@ inline void CBOR_ENC_PIXEL_MASK(CborEncoder &encoder, const char* key, CborEncoder mapEncoder; cborErr(cbor_encode_text_stringz(&encoder, key)); cborErr(cbor_encoder_create_map(&encoder, &mapEncoder, pixel_mask.size())); - for (auto &[pixel_mask_key, pixel_mask_array]: pixel_mask) - CBOR_ENC_MULTIDIM_TYPED_ARRAY(mapEncoder, - pixel_mask_key.c_str(), - pixel_mask_array.data(), - pixel_mask_array.size() * sizeof(uint32_t), - xpixel, ypixel, - CompressionAlgorithm::NO_COMPRESSION, - sizeof(uint32_t), - false); + for (auto &[pixel_mask_key, pixel_mask_array]: pixel_mask) { + CBORImage image{ + .data = reinterpret_cast(pixel_mask_array.data()), + .size = pixel_mask_array.size() * sizeof(uint32_t), + .xpixel = xpixel, + .ypixel = ypixel, + .pixel_depth_bytes = sizeof(uint32_t), + .pixel_is_signed = false, + .pixel_is_float = false, + .algorithm = CompressionAlgorithm::NO_COMPRESSION, + .channel = pixel_mask_key + }; + CBOR_ENC_2D_TYPED_ARRAY(mapEncoder, image); + } cborErr(cbor_encoder_close_container(&encoder, &mapEncoder)); } @@ -195,16 +202,7 @@ inline void CBOR_ENC(CborEncoder &encoder, const char* key, const CBORImage& mes cborErr(cbor_encode_text_stringz(&encoder, key)); cborErr(cbor_encoder_create_map(&encoder, &mapEncoder, 1)); - CBOR_ENC_MULTIDIM_TYPED_ARRAY(mapEncoder, - message.channel.c_str(), - (uint8_t *) message.data, - message.size, - message.xpixel, - message.ypixel, - message.algorithm, - message.pixel_depth_bytes, - message.pixel_is_signed); - + CBOR_ENC_2D_TYPED_ARRAY(mapEncoder, message); cborErr(cbor_encoder_close_container(&encoder, &mapEncoder)); } diff --git a/tests/CBORTest.cpp b/tests/CBORTest.cpp index 2be10aae..e2fdc3ab 100644 --- a/tests/CBORTest.cpp +++ b/tests/CBORTest.cpp @@ -208,6 +208,7 @@ JFJochFrameSerializer serializer(buffer.data(), buffer.size()); .ypixel = 2, .pixel_depth_bytes = 2, .pixel_is_signed = true, + .pixel_is_float = false, .algorithm = CompressionAlgorithm::NO_COMPRESSION, .channel = "default" }; @@ -240,6 +241,7 @@ JFJochFrameSerializer serializer(buffer.data(), buffer.size()); REQUIRE(image_array.image.ypixel == 2); REQUIRE(image_array.image.pixel_depth_bytes == 2); REQUIRE(image_array.image.pixel_is_signed); + REQUIRE(!image_array.image.pixel_is_float); REQUIRE(image_array.image.channel == "default"); REQUIRE(image_array.image.size == test.size()); REQUIRE(image_array.indexing_result == message.indexing_result); @@ -274,6 +276,7 @@ JFJochFrameSerializer serializer(buffer.data(), buffer.size()); .ypixel = 512, .pixel_depth_bytes = 1, .pixel_is_signed = false, + .pixel_is_float = false, .algorithm = CompressionAlgorithm::NO_COMPRESSION, .channel = "default" }; @@ -297,6 +300,7 @@ JFJochFrameSerializer serializer(buffer.data(), buffer.size()); REQUIRE(image_array.image.ypixel == 512); REQUIRE(image_array.image.pixel_depth_bytes == 1); REQUIRE(!image_array.image.pixel_is_signed); + REQUIRE(!image_array.image.pixel_is_float); REQUIRE(image_array.image.channel == "default"); REQUIRE(image_array.image.size == test.size()); REQUIRE(image_array.indexing_result == message.indexing_result); @@ -305,6 +309,56 @@ JFJochFrameSerializer serializer(buffer.data(), buffer.size()); REQUIRE(memcmp(image_array.image.data, test.data(), test.size()) == 0); } +TEST_CASE("CBORSerialize_Image_Float", "[CBOR]") { + std::vector buffer(8*1024*1024); + JFJochFrameSerializer serializer(buffer.data(), buffer.size()); + + std::vector spots; + + std::vector test(512*1024); + for (int i = 0; i < test.size(); i++) + test[i] = i * 0.1f; + + CBORImage image { + .data = reinterpret_cast(test.data()), + .size = 1024 * 512 * sizeof(float), + .xpixel = 1024, + .ypixel = 512, + .pixel_depth_bytes = 4, + .pixel_is_signed = true, + .pixel_is_float = true, + .algorithm = CompressionAlgorithm::NO_COMPRESSION, + .channel = "default" + }; + + DataMessage message { + .number = 480, + .image = image, + .spots = spots, + .indexing_result = 3 + }; + + REQUIRE_NOTHROW(serializer.SerializeImage(message)); + + JFJochFrameDeserializer deserializer; + REQUIRE_NOTHROW(deserializer.Process(buffer.data(), serializer.GetBufferSize())); + REQUIRE(deserializer.GetType() == JFJochFrameDeserializer::Type::IMAGE); + + auto image_array = deserializer.GetDataMessage(); + REQUIRE(image_array.image.algorithm == CompressionAlgorithm::NO_COMPRESSION); + REQUIRE(image_array.image.xpixel == 1024); + REQUIRE(image_array.image.ypixel == 512); + REQUIRE(image_array.image.pixel_is_float); + REQUIRE(image_array.image.pixel_depth_bytes == 4); + REQUIRE(image_array.image.pixel_is_signed); + REQUIRE(image_array.image.channel == "default"); + REQUIRE(image_array.image.size == test.size() * sizeof(float)); + REQUIRE(image_array.indexing_result == message.indexing_result); + REQUIRE(image_array.receiver_available_send_buffers == message.receiver_available_send_buffers); + REQUIRE(image_array.number == 480); + REQUIRE(memcmp(image_array.image.data, test.data(), test.size() * sizeof(float)) == 0); +} + TEST_CASE("CBORSerialize_Image_Append", "[CBOR]") { std::vector buffer(8*1024*1024); JFJochFrameSerializer serializer(buffer.data(), buffer.size()); @@ -322,6 +376,7 @@ JFJochFrameSerializer serializer(buffer.data(), buffer.size()); .ypixel = 512, .pixel_depth_bytes = 1, .pixel_is_signed = false, + .pixel_is_float = false, .algorithm = CompressionAlgorithm::NO_COMPRESSION, .channel = "default" }; @@ -347,6 +402,7 @@ JFJochFrameSerializer serializer(buffer.data(), buffer.size()); REQUIRE(image_array.image.ypixel == 512); REQUIRE(image_array.image.pixel_depth_bytes == 1); REQUIRE(!image_array.image.pixel_is_signed); + REQUIRE(!image_array.image.pixel_is_float); REQUIRE(image_array.image.channel == "default"); REQUIRE(image_array.image.size == test.size()); REQUIRE(image_array.indexing_result == message.indexing_result); @@ -371,6 +427,7 @@ JFJochFrameSerializer serializer(buffer.data(), buffer.size()); .ypixel = 2, .pixel_depth_bytes = 4, .pixel_is_signed = true, + .pixel_is_float = false, .algorithm = CompressionAlgorithm::BSHUF_LZ4, .channel = "default" }; @@ -392,6 +449,7 @@ JFJochFrameSerializer serializer(buffer.data(), buffer.size()); REQUIRE(image_array.image.xpixel == 256); REQUIRE(image_array.image.ypixel == 2); REQUIRE(image_array.image.pixel_depth_bytes == 4); + REQUIRE(!image_array.image.pixel_is_float); REQUIRE(image_array.image.channel == "default"); REQUIRE(image_array.image.size == test.size()); REQUIRE(image_array.image.pixel_is_signed == true); @@ -630,6 +688,7 @@ JFJochFrameSerializer serializer(buffer.data(), buffer.size()); .ypixel = 512, .pixel_depth_bytes = 2, .pixel_is_signed = false, + .pixel_is_float = false, .algorithm = CompressionAlgorithm::BSHUF_LZ4, .channel = "default" }; @@ -681,6 +740,7 @@ JFJochFrameSerializer serializer(buffer.data(), buffer.size()); .ypixel = 512, .pixel_depth_bytes = 1, .pixel_is_signed = false, + .pixel_is_float = false, .algorithm = CompressionAlgorithm::NO_COMPRESSION, .channel = "default" };