From 43e721b9842bdfb32062598a8fdf99a32241269c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Karas?= Date: Mon, 30 May 2022 15:45:20 +0200 Subject: [PATCH 1/7] fix includes for Magick++ v7 --- src/pipeline_deflicker.cpp | 2 +- src/pipeline_frame_prepare.cpp | 3 ++- src/pipeline_handler.cpp | 2 +- src/timelapse_capture.cpp | 1 + src/timelapse_capture.h | 2 +- 5 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/pipeline_deflicker.cpp b/src/pipeline_deflicker.cpp index b27e960..0b415ca 100644 --- a/src/pipeline_deflicker.cpp +++ b/src/pipeline_deflicker.cpp @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include diff --git a/src/pipeline_frame_prepare.cpp b/src/pipeline_frame_prepare.cpp index e7d503d..e844288 100644 --- a/src/pipeline_frame_prepare.cpp +++ b/src/pipeline_frame_prepare.cpp @@ -24,8 +24,9 @@ #include #include +#include + #include -#include #include diff --git a/src/pipeline_handler.cpp b/src/pipeline_handler.cpp index c8855f8..935b680 100644 --- a/src/pipeline_handler.cpp +++ b/src/pipeline_handler.cpp @@ -22,7 +22,7 @@ #include #include -#include +#include #include #include diff --git a/src/timelapse_capture.cpp b/src/timelapse_capture.cpp index 4aa69fb..a43f08e 100644 --- a/src/timelapse_capture.cpp +++ b/src/timelapse_capture.cpp @@ -44,6 +44,7 @@ #include #include +#include #include #include diff --git a/src/timelapse_capture.h b/src/timelapse_capture.h index c71061b..a13281f 100644 --- a/src/timelapse_capture.h +++ b/src/timelapse_capture.h @@ -29,7 +29,7 @@ #include #include -#include +#include #include #include From a337091af21ccea6b6b75268d29fbb52a82ec8cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Karas?= Date: Mon, 30 May 2022 22:02:58 +0200 Subject: [PATCH 2/7] prepare compatibility with ImageMagick 7 --- src/TimeLapse/magick_utils.h | 79 ++++++++++++++++++++++++++++++++++ src/capture.cpp | 9 ++-- src/pipeline_deflicker.cpp | 33 +++++++++----- src/pipeline_frame_prepare.cpp | 7 +-- 4 files changed, 110 insertions(+), 18 deletions(-) create mode 100644 src/TimeLapse/magick_utils.h diff --git a/src/TimeLapse/magick_utils.h b/src/TimeLapse/magick_utils.h new file mode 100644 index 0000000..96d6e33 --- /dev/null +++ b/src/TimeLapse/magick_utils.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2022 Lukáš Karas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#pragma once + +#include +#include +#include + +namespace timelapse { +// methods for Magick++ 6 vs. 7 compatibility + +inline Magick::Quantum scaleDoubleToQuantum(double d) { +#if MagickLibVersion < 0x700 + return Magick::Color::scaleDoubleToQuantum(d); +#else + using Magick::Quantum; // QuantumRange expands to an unqualified Quantum cast. + return static_cast(d*QuantumRange); +#endif +} + +inline double scaleQuantumToDouble(Magick::Quantum q) { +#if MagickLibVersion < 0x700 + return Magick::Color::scaleQuantumToDouble(q); +#else + using Magick::Quantum; + return static_cast(q)/QuantumRange; +#endif +} + +inline double redDouble(const Magick::Color &color) { +#if MagickLibVersion < 0x700 + return scaleQuantumToDouble(color.redQuantum()); +#else + return scaleQuantumToDouble(color.quantumRed()); +#endif +} + +inline double greenDouble(const Magick::Color &color) { +#if MagickLibVersion < 0x700 + return scaleQuantumToDouble(color.greenQuantum()); +#else + return scaleQuantumToDouble(color.quantumGreen()); +#endif +} + +inline double blueDouble(const Magick::Color &color) { +#if MagickLibVersion < 0x700 + return scaleQuantumToDouble(color.blueQuantum()); +#else + return scaleQuantumToDouble(color.quantumBlue()); +#endif +} + +inline void imageOpacity(Magick::Image &image, double opacity) { +#if MagickLibVersion < 0x700 + image.opacity(scaleDoubleToQuantum(opacity)); +#else + image.alpha(static_cast(scaleDoubleToQuantum(opacity))); +#endif +} + +} diff --git a/src/capture.cpp b/src/capture.cpp index a61f6a4..7017a2a 100644 --- a/src/capture.cpp +++ b/src/capture.cpp @@ -18,9 +18,10 @@ */ #include +#include #include -#include +#include #include #include @@ -94,9 +95,9 @@ void MatrixMeteringAlg::update(Magick::Image img) { // compute grey-scale histogram for (std::pair p : histogram) { - double r = Magick::Color::scaleQuantumToDouble(p.first.redQuantum()); - double g = Magick::Color::scaleQuantumToDouble(p.first.greenQuantum()); - double b = Magick::Color::scaleQuantumToDouble(p.first.blueQuantum()); + double r = redDouble(p.first); + double g = greenDouble(p.first); + double b = blueDouble(p.first); double grey = 0.299 * r + 0.587 * g + 0.114 * b; int i = std::max( std::min(GREY_HISTOGRAM_RESOLUTION, (int) (grey * ((double) GREY_HISTOGRAM_RESOLUTION))), diff --git a/src/pipeline_deflicker.cpp b/src/pipeline_deflicker.cpp index 0b415ca..0293b86 100644 --- a/src/pipeline_deflicker.cpp +++ b/src/pipeline_deflicker.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -52,12 +53,12 @@ namespace timelapse { unsigned long pixelCount = 0; for (std::pair p : histogram) { pixelCount += p.second; - sumR += p.second * Magick::Color::scaleDoubleToQuantum( - std::pow(Magick::Color::scaleQuantumToDouble(p.first.redQuantum()), powArg)); - sumG += p.second * Magick::Color::scaleDoubleToQuantum( - std::pow(Magick::Color::scaleQuantumToDouble(p.first.greenQuantum()), powArg)); - sumB += p.second * Magick::Color::scaleDoubleToQuantum( - std::pow(Magick::Color::scaleQuantumToDouble(p.first.blueQuantum()), powArg)); + sumR += p.second * scaleDoubleToQuantum( + std::pow(redDouble(p.first), powArg)); + sumG += p.second * scaleDoubleToQuantum( + std::pow(greenDouble(p.first), powArg)); + sumB += p.second * scaleDoubleToQuantum( + std::pow(blueDouble(p.first), powArg)); } // We use the following formula to get the perceived luminance. @@ -68,11 +69,17 @@ namespace timelapse { void ComputeLuminance::onInputImg(InputImageInfo info, Magick::Image img) { + // We use the following formula to get the perceived luminance. +#if MagickLibVersion < 0x700 Magick::Image::ImageStatistics stat; img.statistics(&stat); - - // We use the following formula to get the perceived luminance. info.luminance = 0.299 * stat.red.mean + 0.587 * stat.green.mean + 0.114 * stat.blue.mean; +#else + Magick::ImageStatistics stat=img.statistics(); + info.luminance = 0.299 * stat.channel(Magick::RedPixelChannel).mean() + + 0.587 * stat.channel(Magick::GreenPixelChannel).mean() + + 0.114 * stat.channel(Magick::BluePixelChannel).mean(); +#endif *verboseOutput << info.fileInfo().filePath() << " luminance: " << info.luminance @@ -165,8 +172,8 @@ namespace timelapse { for (int iteration = 0; iteration < 10; iteration++) { gamma *= 1 / ( - std::log(Magick::Color::scaleQuantumToDouble(targetLuminance)) / - std::log(Magick::Color::scaleQuantumToDouble(expectedLuminance))); + std::log(scaleQuantumToDouble(targetLuminance)) / + std::log(scaleQuantumToDouble(expectedLuminance))); expectedLuminance = ComputeLuminance::computeLuminance(histogram, gamma); @@ -182,10 +189,15 @@ namespace timelapse { img.gamma(gamma); if (debugView) { +#if MagickLibVersion < 0x700 original.transform( Magick::Geometry(original.columns(), original.rows()), Magick::Geometry(original.columns() / 2, original.rows()) ); +#else + original.crop(Magick::Geometry(original.columns(), original.rows())); + original.resize(Magick::Geometry(original.columns() / 2, original.rows())); +#endif img.composite(original, 0, 0, Magick::DissolveCompositeOp); } //img.brightnessContrast(brighnessChange, /* contrast */0.0); @@ -193,4 +205,3 @@ namespace timelapse { } } - diff --git a/src/pipeline_frame_prepare.cpp b/src/pipeline_frame_prepare.cpp index e844288..a2d7727 100644 --- a/src/pipeline_frame_prepare.cpp +++ b/src/pipeline_frame_prepare.cpp @@ -20,6 +20,7 @@ #include #include +#include #include @@ -88,9 +89,9 @@ namespace timelapse { if (f - f1 > 0 && img2 != nullptr) { // for 100 % transparency, we don't have to composite Magick::Image secondLayer = *img2; *verboseOutput << "Blend with next image with " << (opacity * 100) << " % transparency" << endl; - - //secondLayer.opacity(((double) QuantumRange) * opacity); - secondLayer.opacity(Magick::Color::scaleDoubleToQuantum(opacity)); + + imageOpacity(secondLayer, opacity); + blended.composite(secondLayer, 0, 0, Magick::DissolveCompositeOp); } //writeFrame(f, blended); From 7cc6d5b6c47da462e349bc43383e4466e4882a70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Karas?= Date: Mon, 12 Oct 2026 00:49:27 +0200 Subject: [PATCH 3/7] use upstream vid.stab in github actions --- .github/workflows/ubuntu-2004-cmake.yml | 4 ++-- .github/workflows/ubuntu-2204-cmake.yml | 4 ++-- .github/workflows/ubuntu-2404-cmake.yml | 4 ++-- .github/workflows/ubuntu-2604-cmake.yml | 4 ++-- README.md | 4 +--- 5 files changed, 9 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ubuntu-2004-cmake.yml b/.github/workflows/ubuntu-2004-cmake.yml index b8cce8c..56ef05d 100644 --- a/.github/workflows/ubuntu-2004-cmake.yml +++ b/.github/workflows/ubuntu-2004-cmake.yml @@ -26,10 +26,10 @@ jobs: cmake cmake-data build-essential libmagick++-dev qtbase5-dev qtmultimedia5-dev ffmpeg git libv4l-dev libgphoto2-dev" - - name: Install patched vidstab + - name: Install upstream vidstab shell: bash working-directory: /tmp - run: "git clone -b improvements https://github.com/Karry/vid.stab.git vidstab && + run: "git clone https://github.com/georgmartius/vid.stab.git vidstab && cd vidstab && cmake . && make -j $(nproc) && diff --git a/.github/workflows/ubuntu-2204-cmake.yml b/.github/workflows/ubuntu-2204-cmake.yml index bde4b87..7a9a0b6 100644 --- a/.github/workflows/ubuntu-2204-cmake.yml +++ b/.github/workflows/ubuntu-2204-cmake.yml @@ -26,10 +26,10 @@ jobs: cmake cmake-data build-essential libmagick++-dev qtbase5-dev qtmultimedia5-dev ffmpeg git libv4l-dev libgphoto2-dev" - - name: Install patched vidstab + - name: Install upstream vidstab shell: bash working-directory: /tmp - run: "git clone -b improvements https://github.com/Karry/vid.stab.git vidstab && + run: "git clone https://github.com/georgmartius/vid.stab.git vidstab && cd vidstab && cmake . && make -j $(nproc) && diff --git a/.github/workflows/ubuntu-2404-cmake.yml b/.github/workflows/ubuntu-2404-cmake.yml index 75b4054..7328391 100644 --- a/.github/workflows/ubuntu-2404-cmake.yml +++ b/.github/workflows/ubuntu-2404-cmake.yml @@ -26,10 +26,10 @@ jobs: cmake cmake-data build-essential libmagick++-dev qtbase5-dev qtmultimedia5-dev ffmpeg git libv4l-dev libgphoto2-dev" - - name: Install patched vidstab + - name: Install upstream vidstab shell: bash working-directory: /tmp - run: "git clone -b improvements https://github.com/Karry/vid.stab.git vidstab && + run: "git clone https://github.com/georgmartius/vid.stab.git vidstab && cd vidstab && cmake . && make -j $(nproc) && diff --git a/.github/workflows/ubuntu-2604-cmake.yml b/.github/workflows/ubuntu-2604-cmake.yml index d4679e4..aeadc14 100644 --- a/.github/workflows/ubuntu-2604-cmake.yml +++ b/.github/workflows/ubuntu-2604-cmake.yml @@ -25,10 +25,10 @@ jobs: cmake cmake-data build-essential libmagick++-dev qtbase5-dev qtmultimedia5-dev ffmpeg git libv4l-dev libgphoto2-dev" - - name: Install patched vidstab + - name: Install upstream vidstab shell: bash working-directory: /tmp - run: "git clone -b improvements https://github.com/Karry/vid.stab.git vidstab && + run: "git clone https://github.com/georgmartius/vid.stab.git vidstab && cd vidstab && cmake . && make -j $(nproc) && diff --git a/README.md b/README.md index d13659b..fa08e43 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ sudo apt-get install cmake cmake-data build-essential libmagick++-dev qtbase5-de build & install libvidstab*: ``` -git clone -b improvements https://github.com/Karry/vid.stab.git vidstab +git clone https://github.com/georgmartius/vid.stab.git vidstab cd vidstab cmake . make -j `nproc` @@ -58,8 +58,6 @@ sudo make install sudo ldconfig cd .. ``` -* This fork of vid.stab contains some fixes for processing RGB image that are not merged to -to upstream yet ( https://github.com/georgmartius/vid.stab ) build & install TimeLapse tools: From 77a18dcaec84f6f9fab652b0f615adf9dfc5c776 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Karas?= Date: Mon, 12 Oct 2026 09:24:56 +0200 Subject: [PATCH 4/7] fix debug image composition in deflicker tool with Magick 7 --- src/pipeline_deflicker.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/pipeline_deflicker.cpp b/src/pipeline_deflicker.cpp index 0293b86..439ba69 100644 --- a/src/pipeline_deflicker.cpp +++ b/src/pipeline_deflicker.cpp @@ -195,8 +195,7 @@ namespace timelapse { Magick::Geometry(original.columns() / 2, original.rows()) ); #else - original.crop(Magick::Geometry(original.columns(), original.rows())); - original.resize(Magick::Geometry(original.columns() / 2, original.rows())); + original.crop(Magick::Geometry(original.columns() / 2, original.rows())); #endif img.composite(original, 0, 0, Magick::DissolveCompositeOp); } From 3cf79a5c89fef78251dbaf8dcf903eb2d63aac4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Karas?= Date: Mon, 12 Oct 2026 09:34:53 +0200 Subject: [PATCH 5/7] move dependency detection to root CMakeLists.txt --- CMakeLists.txt | 50 ++++++++++++++++++++++++++++++++++++++ src/CMakeLists.txt | 60 ++++------------------------------------------ 2 files changed, 55 insertions(+), 55 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4745ad7..917467d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,57 @@ cmake_minimum_required(VERSION 3.10) project(timelapse) +list(APPEND CMAKE_MODULE_PATH "${CMAKE_HOME_DIRECTORY}/CMakeMod") +list(APPEND CMAKE_MODULE_PATH "CMakeMod") + +FIND_PACKAGE(Qt5 REQUIRED COMPONENTS Core Multimedia) +FIND_PACKAGE(ImageMagick REQUIRED COMPONENTS Magick++ MagickCore) +FIND_PACKAGE(VidStab REQUIRED) +FIND_PACKAGE(V4L REQUIRED) +FIND_PACKAGE(GPHOTO2 REQUIRED) + +# enable warnings +ADD_DEFINITIONS( -Wall -Wextra -pedantic -fPIC) +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANGXX OR CMAKE_COMPILER_IS_GNUCC) + set(TIMELAPS_WARNING_FLAGS "-Wall -pedantic -Winit-self -Wno-overloaded-virtual -Wcast-qual -Wwrite-strings -Wextra -Wno-long-long") + if(EMSCRIPTEN) + set(TIMELAPS_WARNING_FLAGS "${TIMELAPS_WARNING_FLAGS} -Wno-warn-absolute-paths") + elseif(NOT APPLE) + set(TIMELAPS_WARNING_FLAGS "${TIMELAPS_WARNING_FLAGS} -Wno-unused-but-set-parameter") + endif() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TIMELAPS_WARNING_FLAGS}") +endif() + +# QT5 definitions +ADD_DEFINITIONS(${Qt5Core_DEFINITIONS}) + +# read and setup ImageMagick cflags (these flags are not setup by FindImageMagick.cmake) +FIND_PACKAGE(PkgConfig REQUIRED) +pkg_check_modules(IM "ImageMagick") +# ImageMagick compile time configuration +# ADD_DEFINITIONS(-DMAGICKCORE_QUANTUM_DEPTH=16) # Number of bits in a pixel Quantum (8/16/32/64) +# ADD_DEFINITIONS(-DMAGICKCORE_HDRI_SUPPORT=0) # colorHistogram fails with SIGSEGV when this option is enabled +ADD_DEFINITIONS(${IM_CFLAGS}) + add_subdirectory(src) enable_testing() add_subdirectory(test) + +## for debug +message(STATUS "Module path: ${CMAKE_MODULE_PATH}") +message(STATUS "Qt5Core_INCLUDE_DIRS: ${Qt5Core_INCLUDE_DIRS}") +message(STATUS "Qt5Core_DEFINITIONS: ${Qt5Core_DEFINITIONS}") +message(STATUS "ImageMagick_INCLUDE_DIRS: ${ImageMagick_INCLUDE_DIRS}") +message(STATUS "ImageMagick_LIBRARIES: ${ImageMagick_LIBRARIES}") +message(STATUS "IM_CFLAGS: ${IM_CFLAGS}") +message(STATUS "VIDSTAB_INCLUDE_DIRS: ${VIDSTAB_INCLUDE_DIRS}") +message(STATUS "VIDSTAB_LIBRARIES: ${VIDSTAB_LIBRARIES}") +message(STATUS "VIDSTAB_FOUND: ${VIDSTAB_FOUND}") +message(STATUS "V4L_INCLUDE_DIRS: ${V4L_INCLUDE_DIRS}") +message(STATUS "V4L_LIBRARIES: ${V4L_LIBRARIES}") +message(STATUS "V4L_FOUND: ${V4L_FOUND}") +message(STATUS "V4L_DEFINITIONS: ${V4L_DEFINITIONS}") +message(STATUS "GPHOTO2_FOUND: ${GPHOTO2_FOUND}") +message(STATUS "GPHOTO2_INCLUDE_DIR: ${GPHOTO2_INCLUDE_DIR}") +message(STATUS "GPHOTO2_LIBRARIES: ${GPHOTO2_LIBRARIES}") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 281ce1f..4f2522b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,15 +2,6 @@ # Find includes in corresponding build directories set(CMAKE_INCLUDE_CURRENT_DIR ON) -list(APPEND CMAKE_MODULE_PATH "${CMAKE_HOME_DIRECTORY}/CMakeMod") -list(APPEND CMAKE_MODULE_PATH "../CMakeMod") - -FIND_PACKAGE(Qt5 REQUIRED COMPONENTS Core Multimedia) -FIND_PACKAGE(ImageMagick REQUIRED COMPONENTS Magick++ MagickCore) -FIND_PACKAGE(VidStab REQUIRED) -FIND_PACKAGE(V4L REQUIRED) -FIND_PACKAGE(GPHOTO2 REQUIRED) - set(DESCRIBE_CMD "git describe --tags --dirty=+dirty --match 'v[0-9]*' | sed -E 's/^v//' ") execute_process( COMMAND bash -c "${DESCRIBE_CMD}" @@ -35,47 +26,6 @@ include_directories( ${V4L_INCLUDE_DIRS} ${GPHOTO2_INCLUDE_DIR}) -# enable warnings -ADD_DEFINITIONS( -Wall -Wextra -pedantic -fPIC) -if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANGXX OR CMAKE_COMPILER_IS_GNUCC) - set(TIMELAPS_WARNING_FLAGS "-Wall -pedantic -Winit-self -Wno-overloaded-virtual -Wcast-qual -Wwrite-strings -Wextra -Wno-long-long") - if(EMSCRIPTEN) - set(TIMELAPS_WARNING_FLAGS "${TIMELAPS_WARNING_FLAGS} -Wno-warn-absolute-paths") - elseif(NOT APPLE) - set(TIMELAPS_WARNING_FLAGS "${TIMELAPS_WARNING_FLAGS} -Wno-unused-but-set-parameter") - endif() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TIMELAPS_WARNING_FLAGS}") -endif() - -# QT5 definitions -ADD_DEFINITIONS(${Qt5Core_DEFINITIONS}) - -# read and setup ImageMagick cflags (these flags are not setup by FindImageMagick.cmake) -FIND_PACKAGE(PkgConfig REQUIRED) -pkg_check_modules(IM "ImageMagick") -# ImageMagick compile time configuration -# ADD_DEFINITIONS(-DMAGICKCORE_QUANTUM_DEPTH=16) # Number of bits in a pixel Quantum (8/16/32/64) -# ADD_DEFINITIONS(-DMAGICKCORE_HDRI_SUPPORT=0) # colorHistogram fails with SIGSEGV when this option is enabled -ADD_DEFINITIONS(${IM_CFLAGS}) - -## for debug -message(STATUS "Module path: ${CMAKE_MODULE_PATH}") -message(STATUS "Qt5Core_INCLUDE_DIRS: ${Qt5Core_INCLUDE_DIRS}") -message(STATUS "Qt5Core_DEFINITIONS: ${Qt5Core_DEFINITIONS}") -message(STATUS "ImageMagick_INCLUDE_DIRS: ${ImageMagick_INCLUDE_DIRS}") -message(STATUS "ImageMagick_LIBRARIES: ${ImageMagick_LIBRARIES}") -message(STATUS "IM_CFLAGS: ${IM_CFLAGS}") -message(STATUS "VIDSTAB_INCLUDE_DIRS: ${VIDSTAB_INCLUDE_DIRS}") -message(STATUS "VIDSTAB_LIBRARIES: ${VIDSTAB_LIBRARIES}") -message(STATUS "VIDSTAB_FOUND: ${VIDSTAB_FOUND}") -message(STATUS "V4L_INCLUDE_DIRS: ${V4L_INCLUDE_DIRS}") -message(STATUS "V4L_LIBRARIES: ${V4L_LIBRARIES}") -message(STATUS "V4L_FOUND: ${V4L_FOUND}") -message(STATUS "V4L_DEFINITIONS: ${V4L_DEFINITIONS}") -message(STATUS "GPHOTO2_FOUND: ${GPHOTO2_FOUND}") -message(STATUS "GPHOTO2_INCLUDE_DIR: ${GPHOTO2_INCLUDE_DIR}") -message(STATUS "GPHOTO2_LIBRARIES: ${GPHOTO2_LIBRARIES}") - set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) @@ -162,7 +112,7 @@ set_property(TARGET timelapse_capture PROPERTY CXX_STANDARD 17) target_link_libraries(timelapse Qt5::Core Qt5::Multimedia - ${ImageMagick_LIBRARIES} # Magick++-6.Q16 + ${ImageMagick_LIBRARIES} # Magick++ ${VIDSTAB_LIBRARIES} ${V4L_LIBRARIES} ${GPHOTO2_LIBRARIES}) @@ -170,25 +120,25 @@ target_link_libraries(timelapse target_link_libraries(timelapse_assembly timelapse Qt5::Core - ${ImageMagick_LIBRARIES} # Magick++-6.Q16 + ${ImageMagick_LIBRARIES} # Magick++ ${GPHOTO2_LIBRARIES}) target_link_libraries(timelapse_deflicker timelapse Qt5::Core - ${ImageMagick_LIBRARIES} # Magick++-6.Q16 + ${ImageMagick_LIBRARIES} # Magick++ ) target_link_libraries(timelapse_stabilize timelapse Qt5::Core - ${ImageMagick_LIBRARIES} # Magick++-6.Q16 + ${ImageMagick_LIBRARIES} # Magick++ ${VIDSTAB_LIBRARIES}) target_link_libraries(timelapse_capture timelapse Qt5::Core - ${ImageMagick_LIBRARIES} # Magick++-6.Q16 + ${ImageMagick_LIBRARIES} # Magick++ ${V4L_LIBRARIES} ${GPHOTO2_LIBRARIES}) From 1d43846eb3715f64c7748b77f8a22a163960d718 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Karas?= Date: Mon, 12 Oct 2026 09:44:02 +0200 Subject: [PATCH 6/7] add defilcker composition test using Catch2 v3 --- .github/workflows/ubuntu-2404-cmake.yml | 2 +- .github/workflows/ubuntu-2604-cmake.yml | 2 +- CMakeLists.txt | 4 ++ test/CMakeLists.txt | 9 ++++ test/deflicker_composition_test.cpp | 65 +++++++++++++++++++++++++ 5 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 test/deflicker_composition_test.cpp diff --git a/.github/workflows/ubuntu-2404-cmake.yml b/.github/workflows/ubuntu-2404-cmake.yml index 7328391..d8f3142 100644 --- a/.github/workflows/ubuntu-2404-cmake.yml +++ b/.github/workflows/ubuntu-2404-cmake.yml @@ -24,7 +24,7 @@ jobs: shell: bash run: "sudo apt-get update && sudo apt-get -y install cmake cmake-data build-essential libmagick++-dev qtbase5-dev qtmultimedia5-dev - ffmpeg git libv4l-dev libgphoto2-dev" + ffmpeg git libv4l-dev libgphoto2-dev catch2" - name: Install upstream vidstab shell: bash diff --git a/.github/workflows/ubuntu-2604-cmake.yml b/.github/workflows/ubuntu-2604-cmake.yml index aeadc14..fd7e0a1 100644 --- a/.github/workflows/ubuntu-2604-cmake.yml +++ b/.github/workflows/ubuntu-2604-cmake.yml @@ -23,7 +23,7 @@ jobs: shell: bash run: "sudo apt-get update && sudo apt-get -y install cmake cmake-data build-essential libmagick++-dev qtbase5-dev qtmultimedia5-dev - ffmpeg git libv4l-dev libgphoto2-dev" + ffmpeg git libv4l-dev libgphoto2-dev catch2" - name: Install upstream vidstab shell: bash diff --git a/CMakeLists.txt b/CMakeLists.txt index 917467d..fbb8932 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,6 +34,9 @@ pkg_check_modules(IM "ImageMagick") # ADD_DEFINITIONS(-DMAGICKCORE_HDRI_SUPPORT=0) # colorHistogram fails with SIGSEGV when this option is enabled ADD_DEFINITIONS(${IM_CFLAGS}) +find_package(Catch2 3 QUIET) + + add_subdirectory(src) enable_testing() @@ -56,3 +59,4 @@ message(STATUS "V4L_DEFINITIONS: ${V4L_DEFINITIONS}") message(STATUS "GPHOTO2_FOUND: ${GPHOTO2_FOUND}") message(STATUS "GPHOTO2_INCLUDE_DIR: ${GPHOTO2_INCLUDE_DIR}") message(STATUS "GPHOTO2_LIBRARIES: ${GPHOTO2_LIBRARIES}") +message(STATUS "Catch2_FOUND: ${Catch2_FOUND}") diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 8b3446c..185c5ad 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -5,6 +5,15 @@ endif() include(CTest) +if(Catch2_FOUND) + add_executable(deflicker_composition_test deflicker_composition_test.cpp) + set_property(TARGET deflicker_composition_test PROPERTY CXX_STANDARD 17) + target_include_directories(deflicker_composition_test PRIVATE "${CMAKE_SOURCE_DIR}/src") + target_link_libraries(deflicker_composition_test + PRIVATE timelapse Qt5::Core ${ImageMagick_LIBRARIES} Catch2::Catch2WithMain) + add_test(NAME deflicker_composition_test COMMAND deflicker_composition_test) +endif() + add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -C Debug) diff --git a/test/deflicker_composition_test.cpp b/test/deflicker_composition_test.cpp new file mode 100644 index 0000000..e93b525 --- /dev/null +++ b/test/deflicker_composition_test.cpp @@ -0,0 +1,65 @@ +#include + +#include + +#include + +TEST_CASE("deflicker debug image composes original and corrected images") { + Magick::InitializeMagick("deflicker_composition_test"); + int argc = 1; + char applicationName[] = "deflicker_composition_test"; + char *argv[] = {applicationName, nullptr}; + QCoreApplication application(argc, argv); + QString log; + QTextStream verboseOutput(&log); + + for (size_t width : {8u, 9u}) { + const size_t height = 5; + Magick::Image original(Magick::Geometry(width, height), Magick::Color("black")); + for (size_t y = 0; y < height; y++) { + for (size_t x = 0; x < width; x++) { + original.pixelColor(x, y, Magick::ColorRGB( + 0.1 + 0.05 * x, 0.2 + 0.1 * y, 0.3 + 0.02 * (x + y))); + } + } + + std::vector> histogram; + Magick::colorHistogram(&histogram, original); + InputImageInfo info; + info.luminance = timelapse::ComputeLuminance::computeLuminance(histogram); + info.luminanceChange = info.luminance * 0.1; + + Magick::Image corrected; + Magick::Image debug; + bool correctedEmitted = false; + bool debugEmitted = false; + timelapse::AdjustLuminance normalHandler(&verboseOutput, false); + timelapse::AdjustLuminance debugHandler(&verboseOutput, true); + QObject::connect(&normalHandler, &timelapse::ImageHandler::inputImg, + [&](InputImageInfo, Magick::Image image) { + corrected = image; + correctedEmitted = true; + }); + QObject::connect(&debugHandler, &timelapse::ImageHandler::inputImg, + [&](InputImageInfo, Magick::Image image) { + debug = image; + debugEmitted = true; + }); + normalHandler.onInputImg(info, original); + debugHandler.onInputImg(info, original); + + INFO("image width: " << width); + REQUIRE(correctedEmitted); + REQUIRE(debugEmitted); + REQUIRE(debug.columns() == width); + REQUIRE(debug.rows() == height); + + for (size_t y = 0; y < height; y++) { + for (size_t x = 0; x < width; x++) { + const Magick::Image &expected = x < width / 2 ? original : corrected; + CAPTURE(x, y); + REQUIRE(debug.pixelColor(x, y) == expected.pixelColor(x, y)); + } + } + } +} From b7a8b9403ca2686ee6ffadfd213c5fe90160e808 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Karas?= Date: Mon, 12 Oct 2026 09:46:13 +0200 Subject: [PATCH 7/7] drop Github action with Ubuntu 20.04 --- .github/workflows/ubuntu-2004-cmake.yml | 62 ------------------------- 1 file changed, 62 deletions(-) delete mode 100644 .github/workflows/ubuntu-2004-cmake.yml diff --git a/.github/workflows/ubuntu-2004-cmake.yml b/.github/workflows/ubuntu-2004-cmake.yml deleted file mode 100644 index 56ef05d..0000000 --- a/.github/workflows/ubuntu-2004-cmake.yml +++ /dev/null @@ -1,62 +0,0 @@ -name: Ubuntu 20.04, CMake - -on: - pull_request: - branches: - - master - push: - branches: - - master - -env: - BUILD_TYPE: RelWithDebInfo - DEBIAN_FRONTEND: noninteractive - -jobs: - build: - # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix - runs-on: ubuntu-20.04 - - steps: - - uses: actions/checkout@v2 - - - name: Install dependencies - shell: bash - run: "sudo apt-get update && sudo apt-get -y install - cmake cmake-data build-essential libmagick++-dev qtbase5-dev qtmultimedia5-dev - ffmpeg git libv4l-dev libgphoto2-dev" - - - name: Install upstream vidstab - shell: bash - working-directory: /tmp - run: "git clone https://github.com/georgmartius/vid.stab.git vidstab && - cd vidstab && - cmake . && - make -j $(nproc) && - sudo make install && - sudo ldconfig" - - - name: Create Build Environment - run: cmake -E make_directory ${{runner.workspace}}/build - - - name: Configure CMake - shell: bash - working-directory: ${{runner.workspace}}/build - # Note the current convention is to use the -S and -B options here to specify source - # and build directories, but this is only available with CMake 3.13 and higher. - # The CMake binaries on the Github Actions machines are (as of this writing) 3.12 - run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE - # TODO: run tests with address sanitizer when vidstab will be fine: -DCMAKE_CXX_FLAGS=-fsanitize=address - - - name: Build - working-directory: ${{runner.workspace}}/build - shell: bash - # Execute the build. You can specify a specific target with "--target " - run: cmake --build . --config $BUILD_TYPE - - - name: Test - working-directory: ${{runner.workspace}}/build - shell: bash - # Execute tests defined by the CMake configuration. - # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail - run: ctest -C $BUILD_TYPE --output-on-failure