diff --git a/recipes/wavelet_buffer/all/conandata.yml b/recipes/wavelet_buffer/all/conandata.yml new file mode 100644 index 0000000000..c3d3c0e5c3 --- /dev/null +++ b/recipes/wavelet_buffer/all/conandata.yml @@ -0,0 +1,4 @@ +sources: + "0.4.0": + url: "https://github.com/panda-official/WaveletBuffer/archive/refs/tags/v0.4.0.tar.gz" + sha256: "0a30080a6d1e9e7f8947ae0c3395d3c86888900c7ae09730f8dd0ed5138daab2" diff --git a/recipes/wavelet_buffer/all/conanfile.py b/recipes/wavelet_buffer/all/conanfile.py new file mode 100644 index 0000000000..a83f0c5ea6 --- /dev/null +++ b/recipes/wavelet_buffer/all/conanfile.py @@ -0,0 +1,177 @@ +from conan import ConanFile +from conan.tools.cmake import CMakeToolchain, CMakeDeps, CMake, cmake_layout +from conan.tools.files import get, copy, rmdir +from conan.tools.microsoft import check_min_vs, is_msvc +from conan.tools.build import check_min_cppstd +from conan.tools.scm import Version +from conan.errors import ConanInvalidConfiguration + +import os + +required_conan_version = ">=1.50" + + +class WaveletBufferConan(ConanFile): + name = "wavelet_buffer" + license = "MPL-2.0" + description = "An universal C++ compression library based on wavelet transformation" + topics = ("compression", "signal-processing", "wavelet") + homepage = "https://github.com/panda-official/WaveletBuffer" + url = "https://github.com/conan-io/conan-center-index" + default_options = { + "cimg/*:enable_fftw": False, + "cimg/*:enable_jpeg": False, + "cimg/*:enable_openexr": False, + "cimg/*:enable_png": False, + "cimg/*:enable_tiff": False, + "cimg/*:enable_ffmpeg": False, + "cimg/*:enable_opencv": False, + "shared": False, + "fPIC": True, + } + + # Binary configuration + settings = "os", "compiler", "build_type", "arch" + options = {"shared": [True, False], "fPIC": [True, False]} + + def requirements(self): + self.requires("openblas/0.3.20") + self.requires("blaze/3.8") + self.requires("libjpeg-turbo/2.1.2") + self.requires("cimg/3.0.2") + + def config_options(self): + if self.settings.os == "Windows": + del self.options.fPIC + + def configure(self): + if self.options.shared: + try: + del self.options.fPIC + except Exception: + pass + + def source(self): + get( + self, + **self.conan_data["sources"][self.version], + destination=self.source_folder, + strip_root=True, + ) + + def layout(self): + cmake_layout(self) + + def generate(self): + tc = CMakeToolchain(self) + tc.variables["CONAN_EXPORTED"] = True + tc.generate() + + tc = CMakeDeps(self) + tc.generate() + + @property + def _minimum_cpp_standard(self): + return 20 + + @property + def _minimum_compilers_version(self): + return { + "gcc": "8", + "clang": "12", + "apple-clang": "12", + } + + def validate(self): + if self.info.settings.compiler.get_safe("cppstd"): + check_min_cppstd(self, self._minimum_cpp_standard) + + # Compiler version check + check_min_vs(self, 192) + if not is_msvc(self): + minimum_version = self._minimum_compilers_version.get( + str(self.info.settings.compiler), False + ) + if not minimum_version: + self.output.warn( + "{} recipe lacks information about the {} compiler support.".format( + self.name, self.settings.compiler + ) + ) + else: + if Version(self.info.settings.compiler.version) < minimum_version: + raise ConanInvalidConfiguration( + "{} requires C++{} support. The current compiler {} {} does not support it.".format( + self.ref, + self._minimum_cpp_standard, + self.settings.compiler, + self.settings.compiler.version, + ) + ) + + if is_msvc(self) and self.info.options.shared: + raise ConanInvalidConfiguration( + f"{self.ref} can not be built as shared on Visual Studio and msvc." + ) + + # Dependency options check + cimg = self.dependencies["cimg"] + if cimg.options.enable_fftw: + raise ConanInvalidConfiguration( + f"{self.ref} requires the option 'cimg:enable_fftw=False'" + ) + if cimg.options.enable_jpeg: + raise ConanInvalidConfiguration( + f"{self.ref} requires the option 'cimg:enable_jpeg=False'" + ) + if cimg.options.enable_openexr: + raise ConanInvalidConfiguration( + f"{self.ref} requires the option 'cimg:enable_openexr=False'" + ) + if cimg.options.enable_tiff: + raise ConanInvalidConfiguration( + f"{self.ref} requires the option 'cimg:enable_tiff=False'" + ) + if cimg.options.enable_png: + raise ConanInvalidConfiguration( + f"{self.ref} requires the option 'cimg:enable_png=False'" + ) + if cimg.options.enable_ffmpeg: + raise ConanInvalidConfiguration( + f"{self.ref} requires the option 'cimg:enable_ffmpeg=False'" + ) + if cimg.options.enable_opencv: + raise ConanInvalidConfiguration( + f"{self.ref} requires the option 'cimg:enable_opencv=False'" + ) + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def package(self): + copy( + self, + pattern="LICENSE", + dst=os.path.join(self.package_folder, "licenses"), + src=self.source_folder, + ) + + cmake = CMake(self) + cmake.install() + + rmdir(self, os.path.join(self.package_folder, "share")) + + def package_info(self): + self.cpp_info.libs = ["wavelet_buffer", "sf_compressor"] + self.cpp_info.set_property("cmake_file_name", "wavelet_buffer") + self.cpp_info.set_property( + "cmake_target_name", "wavelet_buffer::wavelet_buffer" + ) + + # TODO: to remove in conan v2 once cmake_find_package_* generators removed + self.cpp_info.filenames["cmake_find_package"] = "wavelet_buffer" + self.cpp_info.filenames["cmake_find_package_multi"] = "wavelet_buffer" + self.cpp_info.names["cmake_find_package"] = "wavelet_buffer" + self.cpp_info.names["cmake_find_package_multi"] = "wavelet_buffer" diff --git a/recipes/wavelet_buffer/all/test_package/CMakeLists.txt b/recipes/wavelet_buffer/all/test_package/CMakeLists.txt new file mode 100644 index 0000000000..17f70e46ab --- /dev/null +++ b/recipes/wavelet_buffer/all/test_package/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.15) +project(WaveletBufferTest CXX) + +find_package(wavelet_buffer CONFIG REQUIRED) + +add_executable(test_package test_package.cpp) +target_compile_features(test_package PUBLIC cxx_std_20) +target_link_libraries(test_package wavelet_buffer::wavelet_buffer) diff --git a/recipes/wavelet_buffer/all/test_package/conanfile.py b/recipes/wavelet_buffer/all/test_package/conanfile.py new file mode 100644 index 0000000000..0653d43c77 --- /dev/null +++ b/recipes/wavelet_buffer/all/test_package/conanfile.py @@ -0,0 +1,29 @@ +import os + +from conan import ConanFile +from conan.tools.build import can_run +from conan.tools.cmake import CMake +from conan.tools.layout import cmake_layout + + +class HelloTestConan(ConanFile): + settings = "os", "compiler", "build_type", "arch" + generators = "CMakeDeps", "CMakeToolchain", "VirtualRunEnv" + + test_type = "explicit" + + def requirements(self): + self.requires(self.tested_reference_str) + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def layout(self): + cmake_layout(self) + + def test(self): + if can_run(self): + cmd = os.path.join(self.cpp.build.bindirs[0], "test_package") + self.run(cmd, env="conanrun") diff --git a/recipes/wavelet_buffer/all/test_package/test_package.cpp b/recipes/wavelet_buffer/all/test_package/test_package.cpp new file mode 100644 index 0000000000..c37d44129c --- /dev/null +++ b/recipes/wavelet_buffer/all/test_package/test_package.cpp @@ -0,0 +1,47 @@ +#include + +#include + +using drift::Signal1D; +using drift::WaveletBuffer; +using drift::WaveletParameters; +using drift::WaveletTypes; +using DenoiseAlgo = drift::ThresholdAbsDenoiseAlgorithm; + +int main() { + Signal1D original = blaze::generate( + 1000, [](auto index) { return static_cast(index % 100); }); + + std::cout << "Original size: " << original.size() * 4 << std::endl; + WaveletBuffer buffer(WaveletParameters{ + .signal_shape = {original.size()}, + .signal_number = 1, + .decomposition_steps = 3, + .wavelet_type = WaveletTypes::kDB1, + }); + + // Wavelet decomposition of the signal and denoising + buffer.Decompose(original, DenoiseAlgo(0, 0.3)); + + // Compress the buffer + std::string arch; + if (buffer.Serialize(&arch, 16)) { + std::cout << "Compressed size: " << arch.size() << std::endl; + } else { + std::cerr << "Serialization error" << std::endl; + return EXIT_FAILURE; + } + + // Decompress the buffer + auto restored_buffer = WaveletBuffer::Parse(arch); + Signal1D output_signal; + + // Restore the signal from wavelet decomposition + restored_buffer->Compose(&output_signal); + + std::cout << "Distance between original and restored signal: " + << blaze::norm(original - output_signal) / original.size() + << std::endl; + std::cout << "Compression rate: " << original.size() * 4. / arch.size() * 100 + << "%" << std::endl; +} diff --git a/recipes/wavelet_buffer/all/test_v1_package/CMakeLists.txt b/recipes/wavelet_buffer/all/test_v1_package/CMakeLists.txt new file mode 100644 index 0000000000..925ecbe19e --- /dev/null +++ b/recipes/wavelet_buffer/all/test_v1_package/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.1) +project(test_package) + +include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) +conan_basic_setup(TARGETS) + +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../test_package/ + ${CMAKE_CURRENT_BINARY_DIR}/test_package/) diff --git a/recipes/wavelet_buffer/all/test_v1_package/conanfile.py b/recipes/wavelet_buffer/all/test_v1_package/conanfile.py new file mode 100644 index 0000000000..c492184eec --- /dev/null +++ b/recipes/wavelet_buffer/all/test_v1_package/conanfile.py @@ -0,0 +1,19 @@ +from conans import ConanFile, CMake +from conan.tools.build import cross_building +import os + + +# legacy validation with Conan 1.x +class TestPackageV1Conan(ConanFile): + settings = "os", "arch", "compiler", "build_type" + generators = "cmake", "cmake_find_package_multi" + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def test(self): + if not cross_building(self): + bin_path = os.path.join("bin", "test_package") + self.run(bin_path, run_environment=True) diff --git a/recipes/wavelet_buffer/config.yml b/recipes/wavelet_buffer/config.yml new file mode 100644 index 0000000000..af29e78bd9 --- /dev/null +++ b/recipes/wavelet_buffer/config.yml @@ -0,0 +1,3 @@ +versions: + "0.4.0": + folder: all