From 67b86b70b724146de1114d4587c882dbcdb8819d Mon Sep 17 00:00:00 2001 From: Andrei Costinescu Date: Mon, 17 Jan 2022 15:28:15 +0100 Subject: [PATCH] Split Comm library into two (the one with core functionality; the other with opencv integration) --- CMakeLists.txt | 72 +++++++---- include/comm/data/DataCollection.h | 8 +- include/comm/data/DataCollectionWithOpenCV.h | 22 ++++ include/comm/data/ImageData.h | 37 +----- include/comm/data/ImageDataWithOpenCV.h | 37 ++++++ include/comm/data/ImageEncodeData.h | 16 ++- include/comm/data/ImageEncodeDataWithOpenCV.h | 32 +++++ include/comm/data/dataUtilsWithOpenCV.h | 15 +++ src/data/DataCollection.cpp | 9 +- src/data/DataCollectionWithOpenCV.cpp | 16 +++ src/data/ImageData.cpp | 48 +------- src/data/ImageDataWithOpenCV.cpp | 93 ++++++++++++++ src/data/ImageEncodeData.cpp | 19 ++- src/data/ImageEncodeDataWithOpenCV.cpp | 116 ++++++++++++++++++ src/data/dataUtilsWithOpenCV.cpp | 40 ++++++ tests/testAppSendUDPImage.cpp | 8 +- tests/testCommunication.cpp | 7 +- tests/testEchoUDP.cpp | 4 +- tests/testImageEncodeData.cpp | 10 +- tests/testSendImage.cpp | 6 +- tests/testSendImageUDP.cpp | 6 +- tests/testSerializationHeaderError.cpp | 8 +- tests/testTelemetry.cpp | 1 - tests/testUploadPictureFile.cpp | 16 +-- 24 files changed, 486 insertions(+), 160 deletions(-) create mode 100644 include/comm/data/DataCollectionWithOpenCV.h create mode 100644 include/comm/data/ImageDataWithOpenCV.h create mode 100644 include/comm/data/ImageEncodeDataWithOpenCV.h create mode 100644 include/comm/data/dataUtilsWithOpenCV.h create mode 100644 src/data/DataCollectionWithOpenCV.cpp create mode 100644 src/data/ImageDataWithOpenCV.cpp create mode 100644 src/data/ImageEncodeDataWithOpenCV.cpp create mode 100644 src/data/dataUtilsWithOpenCV.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 56e4f2c..84ed1a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,50 +8,74 @@ add_compile_options(-std=c++17 -pthread) option(WITH_OPENCV "Build the code with opencv" OFF) set(OPENCV_VERSION "" CACHE STRING "The opencv version to use in the project") -include_directories(include) +if (WIN32) + set(EXTERNAL_LIBRARIES ${EXTERNAL_LIBRARIES} wsock32 ws2_32) +else (WIN32) + set(EXTERNAL_LIBRARIES ${EXTERNAL_LIBRARIES} pthread) +endif (WIN32) +set(MASTER_LIBRARIES ${EXTERNAL_LIBRARIES}) if (WITH_OPENCV) if (WIN32) - SET(OpenCV_DIR "C:/Program Files (x86)/opencv/opencv_4.4.0") + set(OpenCV_DIR "C:/Program Files (x86)/opencv/opencv_4.4.0") endif (WIN32) if ("${OPENCV_VERSION}" STREQUAL "") - find_package(OpenCV REQUIRED) + find_package(OpenCV REQUIRED COMPONENTS highgui) else () - find_package(OpenCV ${OPENCV_VERSION} REQUIRED) + find_package(OpenCV ${OPENCV_VERSION} REQUIRED COMPONENTS highgui) endif () include_directories(${OpenCV_INCLUDE_DIRS}) - - set(EXTERNAL_LIBRARIES ${OpenCV_LIBS}) endif () -if (WIN32) - set(EXTERNAL_LIBRARIES ${EXTERNAL_LIBRARIES} wsock32 ws2_32) -else (WIN32) - set(EXTERNAL_LIBRARIES ${EXTERNAL_LIBRARIES} pthread) -endif (WIN32) -set(MASTER_LIBRARIES ${EXTERNAL_LIBRARIES}) +include_directories(include) set(UTILS_STUFF src/utils/NetworkIncludes.cpp src/utils/Buffer.cpp src/utils/SerializationHeader.cpp include/comm/utils/utils.hpp src/utils/NetworkData.cpp) set(SOCKET_STUFF src/socket/SocketPartner.cpp src/socket/SocketType.cpp src/socket/Socket.cpp src/socket/utils.cpp) -SET(COMMUNICATION_STUFF src/communication/Communication.cpp src/communication/TCPServer.cpp src/communication/Communicator.cpp) -SET(DATA_STUFF src/data/MessageType.cpp src/data/messages.cpp src/data/CommunicationData.cpp src/data/CoordinateData.cpp src/data/ImageData.cpp src/data/StatusData.cpp src/data/dataUtils.cpp src/data/CommunicatorState.cpp src/data/DataCollection.cpp src/data/BytesData.cpp src/data/ImageEncodeData.cpp) +set(COMMUNICATION_STUFF src/communication/Communication.cpp src/communication/TCPServer.cpp src/communication/Communicator.cpp) +set(DATA_STUFF src/data/MessageType.cpp src/data/messages.cpp src/data/CommunicationData.cpp src/data/CoordinateData.cpp src/data/ImageData.cpp src/data/StatusData.cpp src/data/dataUtils.cpp src/data/CommunicatorState.cpp src/data/DataCollection.cpp src/data/BytesData.cpp src/data/ImageEncodeData.cpp) -set(COMM_LIB "Communication") -add_library(${COMM_LIB} SHARED ${COMMUNICATION_STUFF} ${DATA_STUFF} ${SOCKET_STUFF} ${UTILS_STUFF}) -if (WITH_OPENCV) - # No idea what PUBLIC or PRIVATE does here... - target_compile_definitions(${COMM_LIB} PUBLIC -DCOMM_USE_OPENCV) -endif () +set(OPENCV_STUFF src/data/dataUtilsWithOpenCV.cpp src/data/DataCollectionWithOpenCV.cpp src/data/ImageDataWithOpenCV.cpp src/data/ImageEncodeDataWithOpenCV.cpp) + +set(COMM_LIB_SHARED ${PROJECT_TARGET}) +add_library(${COMM_LIB_SHARED} SHARED ${COMMUNICATION_STUFF} ${DATA_STUFF} ${SOCKET_STUFF} ${UTILS_STUFF}) +target_link_libraries(${COMM_LIB_SHARED} ${MASTER_LIBRARIES}) +target_include_directories(${COMM_LIB_SHARED} + PUBLIC + $ + $ + ) -set(COMM_LIB "${COMM_LIB}_static") +set(COMM_LIB "${PROJECT_TARGET}_static") add_library(${COMM_LIB} ${COMMUNICATION_STUFF} ${DATA_STUFF} ${SOCKET_STUFF} ${UTILS_STUFF}) +target_link_libraries(${COMM_LIB} ${MASTER_LIBRARIES}) +target_include_directories(${COMM_LIB} + PUBLIC + $ + $ + ) + if (WITH_OPENCV) - # No idea what PUBLIC or PRIVATE does here... - target_compile_definitions(${COMM_LIB} PUBLIC -DCOMM_USE_OPENCV) + set(OPENCV_COMM_LIB_SHARED ${PROJECT_TARGET}_OpenCV) + add_library(${OPENCV_COMM_LIB_SHARED} SHARED ${OPENCV_STUFF}) + target_link_libraries(${OPENCV_COMM_LIB_SHARED} ${PROJECT_TARGET} ${OpenCV_LIBS} ${MASTER_LIBRARIES}) + target_include_directories(${OPENCV_COMM_LIB_SHARED} + PUBLIC + $ + $ + ) + + set(OPENCV_COMM_LIB "${PROJECT_TARGET}_OpenCV_static") + add_library(${OPENCV_COMM_LIB} ${OPENCV_STUFF}) + target_link_libraries(${OPENCV_COMM_LIB} ${PROJECT_TARGET}_static ${OpenCV_LIBS} ${MASTER_LIBRARIES}) + target_include_directories(${OPENCV_COMM_LIB} + PUBLIC + $ + $ + ) endif () -set(MASTER_LIBRARIES ${COMM_LIB} ${MASTER_LIBRARIES}) +set(MASTER_LIBRARIES ${COMM_LIB} ${OPENCV_COMM_LIB} ${MASTER_LIBRARIES}) add_subdirectory(tests) diff --git a/include/comm/data/DataCollection.h b/include/comm/data/DataCollection.h index 6cf367d..4a03ab3 100644 --- a/include/comm/data/DataCollection.h +++ b/include/comm/data/DataCollection.h @@ -6,6 +6,7 @@ #define COMM_DATA_DATACOLLECTION_H #include +#include #include #include #include @@ -15,7 +16,9 @@ namespace comm { public: DataCollection(); - ~DataCollection(); + DataCollection(std::function dataCreationFunction); + + virtual ~DataCollection(); void reset(); @@ -23,9 +26,10 @@ namespace comm { CommunicationData *get(const MessageType &messageType); - private: + protected: std::map data; std::vector dataKeys; + std::function dataCreationFunction; }; } diff --git a/include/comm/data/DataCollectionWithOpenCV.h b/include/comm/data/DataCollectionWithOpenCV.h new file mode 100644 index 0000000..fbf4c9e --- /dev/null +++ b/include/comm/data/DataCollectionWithOpenCV.h @@ -0,0 +1,22 @@ +// +// Created by Andrei Costinescu (andreicostinescu96@gmail.com) on 01-Apr-21. +// + +#ifndef COMM_DATA_DATACOLLECTIONWITHOPENCV_H +#define COMM_DATA_DATACOLLECTIONWITHOPENCV_H + +#include + +namespace comm { + class DataCollectionWithOpenCV : public DataCollection { + public: + DataCollectionWithOpenCV(); + + DataCollectionWithOpenCV(std::function dataCreationFunction); + + ~DataCollectionWithOpenCV() override; + }; +} + + +#endif //COMM_DATA_DATACOLLECTIONWITHOPENCV_H diff --git a/include/comm/data/ImageData.h b/include/comm/data/ImageData.h index 1d35373..fb7eec8 100644 --- a/include/comm/data/ImageData.h +++ b/include/comm/data/ImageData.h @@ -8,18 +8,8 @@ #include #include -#ifdef COMM_USE_OPENCV - -#include - -#else - -typedef unsigned char uchar; - -#endif - namespace comm { - class ImageData : public CommunicationData { + class ImageData : public virtual CommunicationData { public: static const int headerSize; @@ -27,13 +17,9 @@ namespace comm { ImageData(); - #ifdef COMM_USE_OPENCV - - ImageData(cv::Mat image, int id); + ImageData(unsigned char *imageBytes, int imageByteSize, int imageHeight, int imageWidth, int imageType, int id); - #endif - - ImageData(uchar *imageBytes, int imageByteSize, int imageHeight, int imageWidth, int imageType, int id); + ~ImageData(); MessageType getMessageType() override; @@ -47,16 +33,8 @@ namespace comm { void setID(int id); - #ifdef COMM_USE_OPENCV - - void setImage(cv::Mat image); - - [[nodiscard]] cv::Mat getImage() const; - - #endif - - void setImage(unsigned char *_imageBytes, int _imageByteSize, int _imageHeight, int _imageWidth, - int _imageType); + virtual void setImage(unsigned char *_imageBytes, int _imageByteSize, int _imageHeight, int _imageWidth, + int _imageType); [[nodiscard]] int getID() const; @@ -73,10 +51,7 @@ namespace comm { [[nodiscard]] bool isImageDeserialized() const; protected: - #ifdef COMM_USE_OPENCV - cv::Mat image{}; - #endif - uchar *imageBytes; + unsigned char *imageBytes; int id, imageHeight, imageWidth, imageType, contentSize; bool imageDeserialized; }; diff --git a/include/comm/data/ImageDataWithOpenCV.h b/include/comm/data/ImageDataWithOpenCV.h new file mode 100644 index 0000000..9cb5a14 --- /dev/null +++ b/include/comm/data/ImageDataWithOpenCV.h @@ -0,0 +1,37 @@ +// +// Created by Andrei Costinescu (andreicostinescu96@gmail.com) on 10.03.2021. +// + +#ifndef COMM_DATA_IMAGEDATAWITHOPENCV_H +#define COMM_DATA_IMAGEDATAWITHOPENCV_H + +#include +#include + +namespace comm { + class ImageDataWithOpenCV : public virtual ImageData { + public: + ImageDataWithOpenCV(); + + ImageDataWithOpenCV(cv::Mat image, int id); + + ImageDataWithOpenCV(unsigned char *imageBytes, int imageByteSize, int imageHeight, int imageWidth, int imageType, int id); + + ~ImageDataWithOpenCV() override; + + char *getDeserializeBuffer() override; + + bool deserialize(Buffer *buffer, int start, bool forceCopy, bool verbose) override; + + void setImage(cv::Mat image); + + [[nodiscard]] cv::Mat getImage() const; + + void setImage(unsigned char *_imageBytes, int _imageByteSize, int _imageHeight, int _imageWidth, int _imageType) override; + + protected: + cv::Mat image{}; + }; +} + +#endif //COMM_DATA_IMAGEDATAWITHOPENCV_H diff --git a/include/comm/data/ImageEncodeData.h b/include/comm/data/ImageEncodeData.h index e88d9ff..ce00066 100644 --- a/include/comm/data/ImageEncodeData.h +++ b/include/comm/data/ImageEncodeData.h @@ -9,7 +9,7 @@ #include namespace comm { - class ImageEncodeData : public ImageData { + class ImageEncodeData : public virtual ImageData { public: static const int headerSize; @@ -25,12 +25,10 @@ namespace comm { ImageEncodeData(); - #ifdef COMM_USE_OPENCV - ImageEncodeData(cv::Mat image, int id, Encoding encoding); - #endif + ImageEncodeData(const std::vector &imageEncodedBytes, int imageHeight, int imageWidth, + int imageType, int id, Encoding encoding); - ImageEncodeData(const std::vector &imageEncodedBytes, int imageHeight, int imageWidth, int imageType, - int id, Encoding encoding); + ~ImageEncodeData() override; MessageType getMessageType() override; @@ -46,11 +44,11 @@ namespace comm { Encoding getEncoding(); - void setImageEncodedBytes(const std::vector &imageEncodedBytes, int imageHeight, int imageWidth, + void setImageEncodedBytes(const std::vector &imageEncodedBytes, int imageHeight, int imageWidth, int imageType, int id, Encoding _encoding); - private: - std::vector encodedImage; + protected: + std::vector encodedImage; int encodedContentSize; Encoding encoding; }; diff --git a/include/comm/data/ImageEncodeDataWithOpenCV.h b/include/comm/data/ImageEncodeDataWithOpenCV.h new file mode 100644 index 0000000..c27c513 --- /dev/null +++ b/include/comm/data/ImageEncodeDataWithOpenCV.h @@ -0,0 +1,32 @@ +// +// Created by Andrei Costinescu (andreicostinescu96@gmail.com) on 29-May-21. +// + +#ifndef COMM_DATA_IMAGEENCODEDATAWITHOPENCV_H +#define COMM_DATA_IMAGEENCODEDATAWITHOPENCV_H + +#include +#include +#include + +namespace comm { + class ImageEncodeDataWithOpenCV : public ImageEncodeData, public ImageDataWithOpenCV { + public: + ImageEncodeDataWithOpenCV(); + + ImageEncodeDataWithOpenCV(cv::Mat image, int id, Encoding encoding); + + ImageEncodeDataWithOpenCV(const std::vector &imageEncodedBytes, int imageHeight, int imageWidth, + int imageType, int id, Encoding encoding); + + ~ImageEncodeDataWithOpenCV() override; + + bool serialize(Buffer *buffer, int start, bool forceCopy, bool verbose) override; + + char *getDeserializeBuffer() override; + + bool deserialize(Buffer *buffer, int start, bool forceCopy, bool verbose) override; + }; +} + +#endif //COMM_DATA_IMAGEENCODEDATAWITHOPENCV_H diff --git a/include/comm/data/dataUtilsWithOpenCV.h b/include/comm/data/dataUtilsWithOpenCV.h new file mode 100644 index 0000000..5f23cbd --- /dev/null +++ b/include/comm/data/dataUtilsWithOpenCV.h @@ -0,0 +1,15 @@ +// +// Created by Andrei Costinescu (andreicostinescu96@gmail.com) on 24.03.2021. +// + +#ifndef COMM_DATA_DATAUTILSWITHOPENCV_H +#define COMM_DATA_DATAUTILSWITHOPENCV_H + +#include +#include + +namespace comm { + CommunicationData *createCommunicationDataPtrWithOpenCV(const MessageType &messageType); +} + +#endif //COMM_DATA_DATAUTILSWITHOPENCV_H diff --git a/src/data/DataCollection.cpp b/src/data/DataCollection.cpp index 7268590..2ea787c 100644 --- a/src/data/DataCollection.cpp +++ b/src/data/DataCollection.cpp @@ -12,7 +12,10 @@ using namespace comm; using namespace std; -DataCollection::DataCollection() : data(), dataKeys() {} +DataCollection::DataCollection() : DataCollection(createCommunicationDataPtr) {} + +DataCollection::DataCollection(function dataCreationFunction) + : data(), dataKeys(), dataCreationFunction(move(dataCreationFunction)) {} DataCollection::~DataCollection() { cout << "In DataCollection destructor: " << endl; @@ -20,7 +23,7 @@ DataCollection::~DataCollection() { } void DataCollection::reset() { - for (const auto &_data : this->data) { + for (const auto &_data: this->data) { cout << "\tDelete " << _data.first << ": " << _data.second << endl; delete _data.second; } @@ -40,7 +43,7 @@ CommunicationData *DataCollection::get(const MessageType &messageType) { CommunicationData *commData; string stringMessageType = messageTypeToString(messageType); if (!mapGetIfContains(this->data, stringMessageType, commData)) { - for (const auto &dataKey : this->dataKeys) { + for (const auto &dataKey: this->dataKeys) { if (dataKey == stringMessageType) { (*cerror) << "The data key assertion will fail for key = " << stringMessageType << endl; } diff --git a/src/data/DataCollectionWithOpenCV.cpp b/src/data/DataCollectionWithOpenCV.cpp new file mode 100644 index 0000000..3c6f0e4 --- /dev/null +++ b/src/data/DataCollectionWithOpenCV.cpp @@ -0,0 +1,16 @@ +// +// Created by Andrei Costinescu (andreicostinescu96@gmail.com) on 01-Apr-21. +// + +#include +#include + +using namespace comm; +using namespace std; + +DataCollectionWithOpenCV::DataCollectionWithOpenCV() : DataCollection(createCommunicationDataPtrWithOpenCV) {} + +DataCollectionWithOpenCV::DataCollectionWithOpenCV(function dataCreationFunction) + : DataCollection(move(dataCreationFunction)) {} + +DataCollectionWithOpenCV::~DataCollectionWithOpenCV() = default; diff --git a/src/data/ImageData.cpp b/src/data/ImageData.cpp index 7f534b9..3ce740a 100644 --- a/src/data/ImageData.cpp +++ b/src/data/ImageData.cpp @@ -8,9 +8,6 @@ using namespace comm; using namespace std; -#ifdef COMM_USE_OPENCV -using namespace cv; -#endif const int ImageData::headerSize = 5 * sizeof(int); @@ -42,19 +39,13 @@ int ImageData::getOpenCVType(int imageChannels, int bytesPerElement, bool unsign ImageData::ImageData() : id(-1), imageHeight(0), imageWidth(0), imageType(0), contentSize(0), imageDeserialized(true), imageBytes(nullptr) {} -ImageData::ImageData(uchar *imageBytes, int imageByteSize, int imageHeight, int imageWidth, int imageType, int id) : +ImageData::ImageData(unsigned char *imageBytes, int imageByteSize, int imageHeight, int imageWidth, int imageType, + int id) : id(id), imageHeight(imageHeight), imageWidth(imageWidth), imageType(imageType), contentSize(imageByteSize), imageDeserialized(true), imageBytes(imageBytes) {} -#ifdef COMM_USE_OPENCV - -ImageData::ImageData(cv::Mat image, int id) : ImageData() { - this->setID(id); - this->setImage(std::move(image)); -} - -#endif +ImageData::~ImageData() = default; MessageType ImageData::getMessageType() { return MessageType::IMAGE; @@ -120,17 +111,9 @@ int ImageData::getExpectedDataSize() const { char *ImageData::getDeserializeBuffer() { switch (this->deserializeState) { - case 0: { - return nullptr; - } + case 0: case 1: { - #ifdef COMM_USE_OPENCV - this->image = Mat(this->imageHeight, this->imageWidth, this->imageType); - return reinterpret_cast(this->image.data); - #else return nullptr; - #endif - } default : { throw runtime_error("Impossible deserialize state... " + to_string(this->deserializeState)); @@ -177,23 +160,6 @@ void ImageData::setID(int _id) { this->id = _id; } -#ifdef COMM_USE_OPENCV - -void ImageData::setImage(Mat _image) { - this->image = std::move(_image); - this->imageBytes = this->image.data; - this->imageHeight = this->image.rows; - this->imageWidth = this->image.cols; - this->imageType = this->image.type(); - this->contentSize = (int) this->image.step[0] * this->imageHeight; -} - -Mat ImageData::getImage() const { - return this->image; -} - -#endif - void ImageData::setImage(unsigned char *_imageBytes, int _imageByteSize, int _imageHeight, int _imageWidth, int _imageType) { this->imageBytes = _imageBytes; @@ -201,13 +167,7 @@ void ImageData::setImage(unsigned char *_imageBytes, int _imageByteSize, int _im this->imageWidth = _imageWidth; this->imageType = _imageType; this->contentSize = _imageByteSize; - #if COMM_USE_OPENCV - if (this->imageBytes != nullptr) { - this->image = Mat(this->imageHeight, this->imageWidth, this->imageType); - memcpy(this->image.data, this->imageBytes, this->contentSize); } - #endif -} int ImageData::getID() const { return this->id; diff --git a/src/data/ImageDataWithOpenCV.cpp b/src/data/ImageDataWithOpenCV.cpp new file mode 100644 index 0000000..1fe58f0 --- /dev/null +++ b/src/data/ImageDataWithOpenCV.cpp @@ -0,0 +1,93 @@ +// +// Created by Andrei Costinescu (andreicostinescu96@gmail.com) on 10.03.2021. +// + +#include +#include +#include +#include + +using namespace comm; +using namespace cv; +using namespace std; + +ImageDataWithOpenCV::ImageDataWithOpenCV() : ImageData() {} + +ImageDataWithOpenCV::ImageDataWithOpenCV(unsigned char *imageBytes, int imageByteSize, int imageHeight, int imageWidth, + int imageType, int id) : + ImageData(imageBytes, imageByteSize, imageHeight, imageWidth, imageType, id) {} + + +ImageDataWithOpenCV::ImageDataWithOpenCV(cv::Mat image, int id) : ImageData() { + this->setID(id); + this->setImage(std::move(image)); +} + +ImageDataWithOpenCV::~ImageDataWithOpenCV() = default; + +char *ImageDataWithOpenCV::getDeserializeBuffer() { + switch (this->deserializeState) { + case 0: { + return nullptr; + } + case 1: { + this->image = Mat(this->imageHeight, this->imageWidth, this->imageType); + return reinterpret_cast(this->image.data); + } + default : { + throw runtime_error("Impossible deserialize state... " + to_string(this->deserializeState)); + } + } +} + +bool ImageDataWithOpenCV::deserialize(Buffer *buffer, int start, bool forceCopy, bool verbose) { + switch (this->deserializeState) { + case 0: { + this->imageDeserialized = false; + this->id = buffer->getInt(start); + this->imageHeight = buffer->getInt(start + 4); + this->imageWidth = buffer->getInt(start + 8); + this->imageType = buffer->getInt(start + 12); + this->contentSize = buffer->getInt(start + 16); + this->deserializeState = 1; + return false; + } + case 1: { + if (forceCopy) { + // this->image = Mat(this->imageHeight, this->imageWidth, this->imageType); + memcpy(this->image.data, buffer->getBuffer() + start, this->contentSize); + this->imageBytes = this->image.data; + } + this->imageDeserialized = true; + this->deserializeState = 0; + return true; + } + default: { + (*cerror) << "Impossible deserialize state... " << this->deserializeState << endl; + this->resetDeserializeState(); + return false; + } + } +} + +void ImageDataWithOpenCV::setImage(Mat _image) { + this->image = std::move(_image); + this->imageBytes = this->image.data; + this->imageHeight = this->image.rows; + this->imageWidth = this->image.cols; + this->imageType = this->image.type(); + this->contentSize = (int) this->image.step[0] * this->imageHeight; +} + +Mat ImageDataWithOpenCV::getImage() const { + return this->image; +} + +void ImageDataWithOpenCV::setImage(unsigned char *_imageBytes, int _imageByteSize, int _imageHeight, int _imageWidth, + int _imageType) { + ImageData::setImage(_imageBytes, _imageByteSize, _imageHeight, _imageWidth, _imageType); + if (this->imageBytes != nullptr) { + this->image = Mat(this->imageHeight, this->imageWidth, this->imageType); + memcpy(this->image.data, this->imageBytes, this->contentSize); + } +} diff --git a/src/data/ImageEncodeData.cpp b/src/data/ImageEncodeData.cpp index 31f713e..3b3bb56 100644 --- a/src/data/ImageEncodeData.cpp +++ b/src/data/ImageEncodeData.cpp @@ -43,18 +43,15 @@ ImageEncodeData::Encoding ImageEncodeData::convertStringToEncoding(const string ImageEncodeData::ImageEncodeData() : ImageData(), encoding(Encoding::PNG), encodedContentSize(0), encodedImage() {} -#ifdef COMM_USE_OPENCV -ImageEncodeData::ImageEncodeData(cv::Mat image, int id, Encoding encoding) : - ImageData(std::move(image), id), encoding(encoding), encodedContentSize(0), encodedImage() {} -#endif - -ImageEncodeData::ImageEncodeData(const vector &imageEncodedBytes, int imageHeight, int imageWidth, int imageType, - int id, Encoding encoding) : +ImageEncodeData::ImageEncodeData(const vector &imageEncodedBytes, int imageHeight, int imageWidth, + int imageType, int id, Encoding encoding) : ImageData(nullptr, 0, imageHeight, imageWidth, imageType, id), encoding(encoding), encodedContentSize(0), encodedImage(imageEncodedBytes) { - this->encodedContentSize = this->encodedImage.size(); + this->encodedContentSize = (int) this->encodedImage.size(); } +ImageEncodeData::~ImageEncodeData() = default; + MessageType ImageEncodeData::getMessageType() { return MessageType::IMAGE_ENCODE; } @@ -176,11 +173,11 @@ ImageEncodeData::Encoding ImageEncodeData::getEncoding() { return this->encoding; } -void ImageEncodeData::setImageEncodedBytes(const std::vector &imageEncodedBytes, int imageHeight, int imageWidth, - int imageType, int id, Encoding _encoding) { +void ImageEncodeData::setImageEncodedBytes(const std::vector &imageEncodedBytes, int imageHeight, + int imageWidth, int imageType, int id, Encoding _encoding) { this->id = id; this->setImage(nullptr, 0, imageHeight, imageWidth, imageType); this->encodedImage = imageEncodedBytes; - this->encodedContentSize = this->encodedImage.size(); + this->encodedContentSize = (int) this->encodedImage.size(); this->encoding = _encoding; } diff --git a/src/data/ImageEncodeDataWithOpenCV.cpp b/src/data/ImageEncodeDataWithOpenCV.cpp new file mode 100644 index 0000000..8cb9d37 --- /dev/null +++ b/src/data/ImageEncodeDataWithOpenCV.cpp @@ -0,0 +1,116 @@ +// +// Created by Andrei Costinescu (andreicostinescu96@gmail.com) on 29-May-21. +// + +#include +#include +#include + +using namespace comm; +using namespace std; + +ImageEncodeDataWithOpenCV::ImageEncodeDataWithOpenCV() : ImageEncodeData() {} + +ImageEncodeDataWithOpenCV::ImageEncodeDataWithOpenCV(cv::Mat image, int id, Encoding encoding) : + ImageDataWithOpenCV(move(image), id), ImageEncodeData() { + this->encoding = encoding; +} + +ImageEncodeDataWithOpenCV::ImageEncodeDataWithOpenCV(const vector &imageEncodedBytes, int imageHeight, + int imageWidth, int imageType, int id, Encoding encoding) : + ImageDataWithOpenCV(nullptr, 0, imageHeight, imageWidth, imageType, id), ImageEncodeData() { + this->encoding = encoding; + this->encodedImage = imageEncodedBytes; + this->encodedContentSize = (int) this->encodedImage.size(); +} + +ImageEncodeDataWithOpenCV::~ImageEncodeDataWithOpenCV() = default; + +bool ImageEncodeDataWithOpenCV::serialize(Buffer *buffer, int start, bool forceCopy, bool verbose) { + switch (this->serializeState) { + case 0: { + buffer->setBufferContentSize(start + ImageEncodeData::headerSize); + buffer->setInt(this->id, start); + buffer->setInt(this->imageHeight, start + 4); + buffer->setInt(this->imageWidth, start + 8); + buffer->setInt(this->imageType, start + 12); + + if (this->imageBytes != nullptr) { + cv::imencode("." + ImageEncodeData::convertEncodingToString(this->encoding), this->image, + this->encodedImage); + this->encodedContentSize = (int) this->encodedImage.size(); + } + + buffer->setInt(this->encodedContentSize, start + 16); + buffer->setInt(this->encoding, start + 20); + if (verbose) { + cout << "Serialize: " << this->imageHeight << ", " << this->imageWidth << ", " << this->imageType + << ", " << this->encodedContentSize << endl; + char *dataBuffer = buffer->getBuffer(); + cout << "Serialized content: "; + for (int i = 0; i < ImageEncodeData::headerSize; i++) { + cout << ((int) (unsigned char) dataBuffer[start + i]) << " "; + } + cout << endl; + } + this->serializeState = 1; + return false; + } + case 1: { + buffer->setBufferContentSize(this->encodedContentSize); + char *writeBuffer = buffer->getBuffer(); + for (int i = 0; i < this->encodedContentSize; i++) { + writeBuffer[i] = this->encodedImage[i]; + } + this->serializeState = 0; + return true; + } + default: { + (*cerror) << "Impossible serialize state... " << this->serializeState << endl; + this->resetSerializeState(); + return false; + } + } +} + +char *ImageEncodeDataWithOpenCV::getDeserializeBuffer() { + return ImageEncodeData::getDeserializeBuffer(); +} + +bool ImageEncodeDataWithOpenCV::deserialize(Buffer *buffer, int start, bool forceCopy, bool verbose) { + switch (this->deserializeState) { + case 0: { + this->imageDeserialized = false; + this->id = buffer->getInt(start); + this->imageHeight = buffer->getInt(start + 4); + this->imageWidth = buffer->getInt(start + 8); + this->imageType = buffer->getInt(start + 12); + this->encodedContentSize = buffer->getInt(start + 16); + this->encoding = Encoding(buffer->getInt(start + 20)); + this->deserializeState = 1; + return false; + } + case 1: { + this->encodedImage.resize(this->encodedContentSize); + assert((buffer->getBufferContentSize() - start) == this->encodedContentSize); + + char *encodedBuffer = buffer->getBuffer(); + for (int i = 0; i < this->encodedContentSize; i++) { + this->encodedImage[i] = encodedBuffer[i]; + } + // TODO: change the flag depending on the image type! + cv::imdecode(this->encodedImage, cv::IMREAD_COLOR, &this->image); + if (this->image.data != nullptr) { + this->imageDeserialized = true; + } + + this->deserializeState = 0; + return true; + } + default: { + (*cerror) << "Impossible deserialize state... " << this->deserializeState << endl; + this->resetDeserializeState(); + return false; + } + } +} diff --git a/src/data/dataUtilsWithOpenCV.cpp b/src/data/dataUtilsWithOpenCV.cpp new file mode 100644 index 0000000..3e798af --- /dev/null +++ b/src/data/dataUtilsWithOpenCV.cpp @@ -0,0 +1,40 @@ +// +// Created by Andrei Costinescu (andreicostinescu96@gmail.com) on 24.03.2021. +// + +#include +#include +#include +#include +#include +#include +#include + +using namespace comm; +using namespace std; + +CommunicationData *comm::createCommunicationDataPtrWithOpenCV(const MessageType &messageType) { + switch (messageType) { + case MessageType::NOTHING: { + return nullptr; + } + case MessageType::COORDINATE: { + return new CoordinateData(); + } + case MessageType::IMAGE: { + return new ImageDataWithOpenCV(); + } + case MessageType::STATUS: { + return new StatusData(); + } + case MessageType::BYTES: { + return new BytesData(); + } + case MessageType::IMAGE_ENCODE: { + return new ImageEncodeDataWithOpenCV(); + } + default : { + throw runtime_error("Unknown message type: " + to_string(messageType)); + } + } +} diff --git a/tests/testAppSendUDPImage.cpp b/tests/testAppSendUDPImage.cpp index bf5f0c8..5ad9124 100644 --- a/tests/testAppSendUDPImage.cpp +++ b/tests/testAppSendUDPImage.cpp @@ -4,12 +4,10 @@ #include #include -#include +#include #include #include -#include #include -#include using namespace comm; using namespace cv; @@ -26,7 +24,7 @@ void createUDPServer() { comm.createSocket(SocketType::UDP, SocketPartner(true, false), port, 2000, 50); Mat lena = cv::imread("../../data/Lena.png"); - ImageData image; + ImageDataWithOpenCV image; StatusData status; MessageType messageType; while (!quit) { @@ -90,7 +88,7 @@ void createUDPClient() { Communication comm; comm.createSocket(SocketType::UDP, SocketPartner("127.0.0.1", port, false), 0, 2000, 1000); - ImageData image; + ImageDataWithOpenCV image; StatusData status; MessageType messageType; status.setData("UDP"); diff --git a/tests/testCommunication.cpp b/tests/testCommunication.cpp index a2f5732..77b4239 100644 --- a/tests/testCommunication.cpp +++ b/tests/testCommunication.cpp @@ -7,10 +7,9 @@ #include #include #include -#include +#include #include #include -#include #include #include @@ -133,7 +132,7 @@ void sender(SocketType socketType, bool withHeader, bool withMessageType, bool s this_thread::sleep_for(chrono::seconds(2)); cout << "\n\n"; - ImageData i; + ImageDataWithOpenCV i; receiveImage(p, socketType, i, imageCap, withHeader, withMessageType, syphonWronglySerializedData); i.setID(i.getID() + 1); @@ -189,7 +188,7 @@ void receiver(SocketType socketType, bool withHeader, bool withMessageType, bool this_thread::sleep_for(chrono::seconds(2)); cout << "\n\n"; - ImageData i; + ImageDataWithOpenCV i; i.setID(0); i.setImage(*lena); sendImage(p, socketType, i, imageCap, withHeader, withMessageType, syphonWronglySerializedData); diff --git a/tests/testEchoUDP.cpp b/tests/testEchoUDP.cpp index e358a9c..1337b92 100644 --- a/tests/testEchoUDP.cpp +++ b/tests/testEchoUDP.cpp @@ -4,7 +4,7 @@ #include #include -#include +#include #include #include #include @@ -21,7 +21,7 @@ void createUDPEcho(SocketType socketType) { Communication comm; comm.createSocket(socketType, SocketPartner(true, false), port, 2000, 50); - ImageData image; + ImageDataWithOpenCV image; StatusData status; MessageType messageType; while (!quit) { diff --git a/tests/testImageEncodeData.cpp b/tests/testImageEncodeData.cpp index 57909f0..6afbccc 100644 --- a/tests/testImageEncodeData.cpp +++ b/tests/testImageEncodeData.cpp @@ -2,8 +2,8 @@ // Created by Andrei Costinescu (andreicostinescu96@gmail.com) on 29-May-21. // -#include -#include +#include +#include #include using namespace comm; @@ -13,9 +13,9 @@ int main() { cout << "Hello World!" << endl; cv::Mat lena = cv::imread("../../data/Lena.png"); - DataCollection data; - ImageEncodeData image(lena, 0, ImageEncodeData::JPEG), *decodedImage; - decodedImage = (ImageEncodeData *) (data.get(MessageType::IMAGE_ENCODE)); + DataCollectionWithOpenCV data; + ImageEncodeDataWithOpenCV image(lena, 0, ImageEncodeData::JPEG), *decodedImage; + decodedImage = dynamic_cast(data.get(MessageType::IMAGE_ENCODE)); cout << "Image size: " << lena.rows << "x" << lena.cols << ": " << lena.type() << "; raw image bytes = " << image.getImageBytesSize() << endl; diff --git a/tests/testSendImage.cpp b/tests/testSendImage.cpp index d4fead0..bf30e7d 100644 --- a/tests/testSendImage.cpp +++ b/tests/testSendImage.cpp @@ -3,7 +3,7 @@ // #include -#include +#include #include #include #include @@ -26,7 +26,7 @@ void udpStreamer(SocketType socketType) { cv::namedWindow("Camera image"); // Mat image = cv::imread("../../data/Lena.png"); Mat image; - ImageData i; + ImageDataWithOpenCV i; int id = 0; while (!udpStopFlag && (limit < 0 or id < limit)) { camera >> image; @@ -72,7 +72,7 @@ void tcpStreamer() { cv::namedWindow("Camera image"); // Mat image = cv::imread("../../data/Lena.png"); Mat image; - ImageData i; + ImageDataWithOpenCV i; int id = 0; while (!tcpStopFlag && (limit < 0 or id < limit)) { camera >> image; diff --git a/tests/testSendImageUDP.cpp b/tests/testSendImageUDP.cpp index b5ade9d..c6ed84c 100644 --- a/tests/testSendImageUDP.cpp +++ b/tests/testSendImageUDP.cpp @@ -4,7 +4,7 @@ #include #include -#include +#include #include #include #include @@ -33,7 +33,7 @@ void sender(SocketType udpSocketType) { assert(strcmp(s.getData(), "hello") == 0); Mat image = cv::imread("../../data/Lena.png"); - ImageData i(image, 1); + ImageDataWithOpenCV i(image, 1); if (!p.transmitData(udpSocketType, &i, false, false, 0, true)) { cout << "Error: " << p.getErrorCode() << "; " << p.getErrorString() << "; " << getLastErrorString() << endl; } else { @@ -69,7 +69,7 @@ void receiver(SocketType udpSocketType) { this_thread::sleep_for(chrono::seconds(2)); cout << "\n\n"; - ImageData i; + ImageDataWithOpenCV i; if (!comm->recvData(udpSocketType, &i, false, false, false, 10, true)) { cout << "Error: " << comm->getErrorCode() << "; " << comm->getErrorString() << "; " << getLastErrorString() << endl; diff --git a/tests/testSerializationHeaderError.cpp b/tests/testSerializationHeaderError.cpp index 79288ec..b13034b 100644 --- a/tests/testSerializationHeaderError.cpp +++ b/tests/testSerializationHeaderError.cpp @@ -3,9 +3,7 @@ // #include -#include - -#include +#include using namespace comm; using namespace cv; @@ -14,7 +12,7 @@ using namespace std; SocketType socketType = SocketType::UDP; void rawSendImage(Communication &sender, Mat image, int prematureStop = 0, bool withHeader = true) { - ImageData sendData(std::move(image), 0); + ImageDataWithOpenCV sendData(std::move(image), 0); Buffer sendBuffer; if (withHeader) { @@ -56,7 +54,7 @@ int main() { Communication sender, receiver; sender.createSocket(socketType, SocketPartner("127.0.0.1", 8400, false)); receiver.createSocket(socketType, nullptr, 8400, 2000, 50); - ImageData recvData; + ImageDataWithOpenCV recvData; rawSendImage(sender, lena, 2); rawSendImage(sender, lena, 0, false); diff --git a/tests/testTelemetry.cpp b/tests/testTelemetry.cpp index a323dc5..aa0008d 100644 --- a/tests/testTelemetry.cpp +++ b/tests/testTelemetry.cpp @@ -4,7 +4,6 @@ #include #include -#include #include #include #include diff --git a/tests/testUploadPictureFile.cpp b/tests/testUploadPictureFile.cpp index 4b31ea1..3ef469c 100644 --- a/tests/testUploadPictureFile.cpp +++ b/tests/testUploadPictureFile.cpp @@ -3,11 +3,10 @@ // #include -#include -#include +#include +#include #include #include -#include using namespace comm; using namespace cv; @@ -15,7 +14,7 @@ using namespace std; void readBinaryFile(const string &path, char *&contentBuffer, int &contentSize) { char *buffer; - long size; + long long size; ifstream file(path, ios::in | ios::binary | ios::ate); size = file.tellg(); file.seekg(0, ios::beg); @@ -25,7 +24,7 @@ void readBinaryFile(const string &path, char *&contentBuffer, int &contentSize) cout << "the complete file is in a buffer"; contentBuffer = buffer; - contentSize = size; + contentSize = (int) size; } int main() { @@ -34,12 +33,13 @@ int main() { char *contentBuffer; int contentSize; readBinaryFile("../../data/Lena.png", contentBuffer, contentSize); - vector imageEncodedBytes(contentSize); + vector imageEncodedBytes(contentSize); for (int i = 0; i < contentSize; i++) { imageEncodedBytes[i] = contentBuffer[i]; } - DataCollection data; - ImageEncodeData image, *decodedImage = (ImageEncodeData *) data.get(MessageType::IMAGE_ENCODE); + DataCollectionWithOpenCV data; + ImageEncodeDataWithOpenCV image, *decodedImage = dynamic_cast(data.get( + MessageType::IMAGE_ENCODE)); ImageEncodeData::Encoding encoding = ImageEncodeData::Encoding::PNG; image.setImageEncodedBytes(imageEncodedBytes, 330, 330, (int) CV_8UC3, 0, encoding);