Skip to content

Conversation

@ktro2828
Copy link
Contributor

@ktro2828 ktro2828 commented Dec 26, 2025

PR Type

  • Improvement

Related Links

TIER IV INTERNAL LINK

Description

This pull request introduces a new package, accelerated_image_processor_compression, which provides a flexible and hardware-accelerated image compression library, primarily targeting JPEG compression with support for various backends (Jetson, NVJPEG, TurboJPEG/CPU). The package is designed for ROS 2 integration and includes CMake configuration for dependency detection and platform-specific builds.

The most important changes are:

Core Library Implementation:

  • Added builder.hpp and jpeg_compressor.hpp headers, defining the compressor interface, compressor creation utilities, and backend selection logic, along with backend-specific compressor classes (JetsonJPEGCompressor, NvJPEGCompressor, CpuJPEGCompressor). [1] [2]

CMake and Build System:

  • Introduced a comprehensive CMakeLists.txt to detect platform capabilities (Jetson, NVJPEG, TurboJPEG), configure build options, and handle conditional compilation and linking for different hardware backends.
  • Added custom CMake modules (FindNVJPEG.cmake, FindLibJpegTurbo.cmake, LibFindMacros.cmake) to robustly detect and configure third-party dependencies required for hardware-accelerated JPEG compression. [1] [2] [3]

Documentation and Packaging:

  • Created a README.md detailing the supported compression backends, usage examples in ROS 2, and integration instructions.
  • Added a package.xml manifest for ROS 2, declaring dependencies, maintainers, and licensing information.

Remarks

The following demonstrates how to use the compressor on ROS 2 codebase:

#include <accelerated_image_processor_common/datatype.hpp>
#include <accelerated_image_processor_compression/builder.hpp>

#include <rclcpp/rclcpp.hpp>

using namespace accelerated_image_processor;

class SomeNode final : public rclcpp::Node
{
public:
  explicit SomeNode(const rclcpp::NodeOptions & options) : Node("some_node", options)
  {
    compressor_ = compression::create_compressor<SomeNode, &SomeNode::publish>("jpeg", this);

    // Update parameters of the compressor
    for (auto & [name, value] : compressor_->parameters()) {
      std::visit([&](auto & v) {
        using T = std::decay_t<decltype(v)>;
        v = this->get_parameter_or<T>(name, v);
      }, value);
    }

    // Create a subscription and publisher
    subscription_ = this->create_subscription<sensor_msgs::msg::Image>(
      "~/input/image", 10, [this](const sensor_msgs::msg::Image::ConstSharedPtr msg) { this->callback(msg); });
    publisher_ = this->create_publisher<sensor_msgs::msg::CompressedImage>("~/output/image", 10);
  }

private:
  void callback(const sensor_msgs::msg::Image::ConstSharedPtr msg)
  {
    common::Image image;
    // Convert the message to image...
    compressor_->process(image);
  }

  void publish(const common::Image & image)
  {
    sensor_msgs::msg::CompressedImage msg;
    // Convert the image to message...
    publisher_->publish(msg);
  }

  std::unique_ptr<compression::Compressor> compressor_; //!< Compressor

  rclcpp::Subscription<sensor_msgs::msg::Image>::SharedPtr subscription_; //!< Subscription
  rclcpp::Publisher<sensor_msgs::msg::CompressedImage>::SharedPtr publisher_; //!< Publisher
};

Pre-Review Checklist for the PR Author

PR Author should check the checkboxes below when creating the PR.

  • Assign PR to reviewer

Checklist for the PR Reviewer

Reviewers should check the checkboxes below before approval.

  • Commits are properly organized and messages are according to the guideline
  • (Optional) Unit tests have been written for new behavior
  • PR title describes the changes

Post-Review Checklist for the PR Author

PR Author should check the checkboxes below before merging.

  • All open points are addressed and tracked via issues or tickets

CI Checks

I confirmed unit testings passed with all of Jetson, NvJPEG, TurboJPEG backends:

Unit testings summary
nvidia@ANVIL:~/workspace/accelerated_image_processor$ colcon test --packages-select accelerated_image_processor_compression --event-handlers console_cohesion+ 
Starting >>> accelerated_image_processor_compression
--- output: accelerated_image_processor_compression                   
UpdateCTestConfiguration  from :/home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression/CTestConfiguration.ini
Parse Config file:/home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression/CTestConfiguration.ini
   Site: ANVIL
   Build name: (empty)
 Add coverage exclude regular expressions.
Create new tag: 20251226-0427 - Experimental
UpdateCTestConfiguration  from :/home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression/CTestConfiguration.ini
Parse Config file:/home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression/CTestConfiguration.ini
Test project /home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression
Constructing a list of tests
Done constructing a list of tests
Updating test list for fixtures
Added 0 tests to meet fixture requirements
Checking test dependency graph...
Checking test dependency graph end
test 1
    Start 1: builder.cpp_accelerated_image_processor_compression

1: Test command: /usr/bin/python3 "-u" "/opt/ros/humble/share/ament_cmake_test/cmake/run_test.py" "/home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression/test_results/accelerated_image_processor_compression/builder.cpp_accelerated_image_processor_compression.gtest.xml" "--package-name" "accelerated_image_processor_compression" "--output-file" "/home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression/ament_cmake_gtest/builder.cpp_accelerated_image_processor_compression.txt" "--command" "/home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression/builder.cpp_accelerated_image_processor_compression" "--gtest_output=xml:/home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression/test_results/accelerated_image_processor_compression/builder.cpp_accelerated_image_processor_compression.gtest.xml"
1: Working Directory: /home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression
1: Test timeout computed to be: 60
1: -- run_test.py: invoking following command in '/home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression':
1:  - /home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression/builder.cpp_accelerated_image_processor_compression --gtest_output=xml:/home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression/test_results/accelerated_image_processor_compression/builder.cpp_accelerated_image_processor_compression.gtest.xml
1: Running main() from /opt/ros/humble/src/gtest_vendor/src/gtest_main.cc
1: [==========] Running 6 tests from 1 test suite.
1: [----------] Global test environment set-up.
1: [----------] 6 tests from TestCompressorBuilder
1: [ RUN      ] TestCompressorBuilder.CreateJPEGCompressor1
1: [       OK ] TestCompressorBuilder.CreateJPEGCompressor1 (195 ms)
1: [ RUN      ] TestCompressorBuilder.CreateJPEGCompressor2
1: [       OK ] TestCompressorBuilder.CreateJPEGCompressor2 (0 ms)
1: [ RUN      ] TestCompressorBuilder.CreateJPEGCompressor3
1: [       OK ] TestCompressorBuilder.CreateJPEGCompressor3 (0 ms)
1: [ RUN      ] TestCompressorBuilder.CreateJPEGCompressor4
1: [       OK ] TestCompressorBuilder.CreateJPEGCompressor4 (0 ms)
1: [ RUN      ] TestCompressorBuilder.CreateJPEGCompressor5
1: [       OK ] TestCompressorBuilder.CreateJPEGCompressor5 (0 ms)
1: [ RUN      ] TestCompressorBuilder.CreateJPEGCompressor6
1: [       OK ] TestCompressorBuilder.CreateJPEGCompressor6 (0 ms)
1: [----------] 6 tests from TestCompressorBuilder (195 ms total)
1: 
1: [----------] Global test environment tear-down
1: [==========] 6 tests from 1 test suite ran. (195 ms total)
1: [  PASSED  ] 6 tests.
1: -- run_test.py: return code 0
1: -- run_test.py: inject classname prefix into gtest result file '/home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression/test_results/accelerated_image_processor_compression/builder.cpp_accelerated_image_processor_compression.gtest.xml'
1: -- run_test.py: verify result file '/home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression/test_results/accelerated_image_processor_compression/builder.cpp_accelerated_image_processor_compression.gtest.xml'
1/4 Test #1: builder.cpp_accelerated_image_processor_compression ..................   Passed    0.39 sec
test 2
    Start 2: cpu_jpeg_compressor.cpp_accelerated_image_processor_compression

2: Test command: /usr/bin/python3 "-u" "/opt/ros/humble/share/ament_cmake_test/cmake/run_test.py" "/home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression/test_results/accelerated_image_processor_compression/cpu_jpeg_compressor.cpp_accelerated_image_processor_compression.gtest.xml" "--package-name" "accelerated_image_processor_compression" "--output-file" "/home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression/ament_cmake_gtest/cpu_jpeg_compressor.cpp_accelerated_image_processor_compression.txt" "--command" "/home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression/cpu_jpeg_compressor.cpp_accelerated_image_processor_compression" "--gtest_output=xml:/home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression/test_results/accelerated_image_processor_compression/cpu_jpeg_compressor.cpp_accelerated_image_processor_compression.gtest.xml"
2: Working Directory: /home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression
2: Test timeout computed to be: 60
2: -- run_test.py: invoking following command in '/home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression':
2:  - /home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression/cpu_jpeg_compressor.cpp_accelerated_image_processor_compression --gtest_output=xml:/home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression/test_results/accelerated_image_processor_compression/cpu_jpeg_compressor.cpp_accelerated_image_processor_compression.gtest.xml
2: [==========] Running 3 tests from 1 test suite.
2: [----------] Global test environment set-up.
2: [----------] 3 tests from TestJPEGCompressor
2: [ RUN      ] TestJPEGCompressor.CpuCompressionDefault
2: [       OK ] TestJPEGCompressor.CpuCompressionDefault (20 ms)
2: [ RUN      ] TestJPEGCompressor.CpuCompressionWithLowQuality
2: [       OK ] TestJPEGCompressor.CpuCompressionWithLowQuality (17 ms)
2: [ RUN      ] TestJPEGCompressor.CpuCompressionWithHighQuality
2: [       OK ] TestJPEGCompressor.CpuCompressionWithHighQuality (18 ms)
2: [----------] 3 tests from TestJPEGCompressor (55 ms total)
2: 
2: [----------] Global test environment tear-down
2: [==========] 3 tests from 1 test suite ran. (56 ms total)
2: [  PASSED  ] 3 tests.
2: -- run_test.py: return code 0
2: -- run_test.py: inject classname prefix into gtest result file '/home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression/test_results/accelerated_image_processor_compression/cpu_jpeg_compressor.cpp_accelerated_image_processor_compression.gtest.xml'
2: -- run_test.py: verify result file '/home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression/test_results/accelerated_image_processor_compression/cpu_jpeg_compressor.cpp_accelerated_image_processor_compression.gtest.xml'
2/4 Test #2: cpu_jpeg_compressor.cpp_accelerated_image_processor_compression ......   Passed    0.23 sec
test 3
    Start 3: jetson_jpeg_compressor.cpp_accelerated_image_processor_compression

3: Test command: /usr/bin/python3 "-u" "/opt/ros/humble/share/ament_cmake_test/cmake/run_test.py" "/home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression/test_results/accelerated_image_processor_compression/jetson_jpeg_compressor.cpp_accelerated_image_processor_compression.gtest.xml" "--package-name" "accelerated_image_processor_compression" "--output-file" "/home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression/ament_cmake_gtest/jetson_jpeg_compressor.cpp_accelerated_image_processor_compression.txt" "--command" "/home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression/jetson_jpeg_compressor.cpp_accelerated_image_processor_compression" "--gtest_output=xml:/home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression/test_results/accelerated_image_processor_compression/jetson_jpeg_compressor.cpp_accelerated_image_processor_compression.gtest.xml"
3: Working Directory: /home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression
3: Test timeout computed to be: 60
3: -- run_test.py: invoking following command in '/home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression':
3:  - /home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression/jetson_jpeg_compressor.cpp_accelerated_image_processor_compression --gtest_output=xml:/home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression/test_results/accelerated_image_processor_compression/jetson_jpeg_compressor.cpp_accelerated_image_processor_compression.gtest.xml
3: [==========] Running 3 tests from 1 test suite.
3: [----------] Global test environment set-up.
3: [----------] 3 tests from TestJPEGCompressor
3: [ RUN      ] TestJPEGCompressor.JetsonCompressionDefault
3: NvMMLiteBlockCreate : Block : BlockType = 1 
3: [       OK ] TestJPEGCompressor.JetsonCompressionDefault (111 ms)
3: [ RUN      ] TestJPEGCompressor.JetsonCompressionWithLowQuality
3: NvMMLiteBlockCreate : Block : BlockType = 1 
3: [       OK ] TestJPEGCompressor.JetsonCompressionWithLowQuality (35 ms)
3: [ RUN      ] TestJPEGCompressor.JetsonCompressionWithHighQuality
3: NvMMLiteBlockCreate : Block : BlockType = 1 
3: [       OK ] TestJPEGCompressor.JetsonCompressionWithHighQuality (30 ms)
3: [----------] 3 tests from TestJPEGCompressor (176 ms total)
3: 
3: [----------] Global test environment tear-down
3: [==========] 3 tests from 1 test suite ran. (176 ms total)
3: [  PASSED  ] 3 tests.
3: -- run_test.py: return code 0
3: -- run_test.py: inject classname prefix into gtest result file '/home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression/test_results/accelerated_image_processor_compression/jetson_jpeg_compressor.cpp_accelerated_image_processor_compression.gtest.xml'
3: -- run_test.py: verify result file '/home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression/test_results/accelerated_image_processor_compression/jetson_jpeg_compressor.cpp_accelerated_image_processor_compression.gtest.xml'
3/4 Test #3: jetson_jpeg_compressor.cpp_accelerated_image_processor_compression ...   Passed    0.37 sec
test 4
    Start 4: nv_jpeg_compressor.cpp_accelerated_image_processor_compression

4: Test command: /usr/bin/python3 "-u" "/opt/ros/humble/share/ament_cmake_test/cmake/run_test.py" "/home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression/test_results/accelerated_image_processor_compression/nv_jpeg_compressor.cpp_accelerated_image_processor_compression.gtest.xml" "--package-name" "accelerated_image_processor_compression" "--output-file" "/home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression/ament_cmake_gtest/nv_jpeg_compressor.cpp_accelerated_image_processor_compression.txt" "--command" "/home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression/nv_jpeg_compressor.cpp_accelerated_image_processor_compression" "--gtest_output=xml:/home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression/test_results/accelerated_image_processor_compression/nv_jpeg_compressor.cpp_accelerated_image_processor_compression.gtest.xml"
4: Working Directory: /home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression
4: Test timeout computed to be: 60
4: -- run_test.py: invoking following command in '/home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression':
4:  - /home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression/nv_jpeg_compressor.cpp_accelerated_image_processor_compression --gtest_output=xml:/home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression/test_results/accelerated_image_processor_compression/nv_jpeg_compressor.cpp_accelerated_image_processor_compression.gtest.xml
4: [==========] Running 3 tests from 1 test suite.
4: [----------] Global test environment set-up.
4: [----------] 3 tests from TestJPEGCompressor
4: [ RUN      ] TestJPEGCompressor.NvJPEGCompressionDefault
4: [       OK ] TestJPEGCompressor.NvJPEGCompressionDefault (100 ms)
4: [ RUN      ] TestJPEGCompressor.NvJPEGCompressionWithLowQuality
4: [       OK ] TestJPEGCompressor.NvJPEGCompressionWithLowQuality (26 ms)
4: [ RUN      ] TestJPEGCompressor.NvJPEGCompressionWithHighQuality
4: [       OK ] TestJPEGCompressor.NvJPEGCompressionWithHighQuality (23 ms)
4: [----------] 3 tests from TestJPEGCompressor (150 ms total)
4: 
4: [----------] Global test environment tear-down
4: [==========] 3 tests from 1 test suite ran. (150 ms total)
4: [  PASSED  ] 3 tests.
4: -- run_test.py: return code 0
4: -- run_test.py: inject classname prefix into gtest result file '/home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression/test_results/accelerated_image_processor_compression/nv_jpeg_compressor.cpp_accelerated_image_processor_compression.gtest.xml'
4: -- run_test.py: verify result file '/home/nvidia/workspace/accelerated_image_processor/build/accelerated_image_processor_compression/test_results/accelerated_image_processor_compression/nv_jpeg_compressor.cpp_accelerated_image_processor_compression.gtest.xml'
4/4 Test #4: nv_jpeg_compressor.cpp_accelerated_image_processor_compression .......   Passed    0.34 sec

100% tests passed, 0 tests failed out of 4

Label Time Summary:
gtest    =   1.33 sec*proc (4 tests)

Total Test time (real) =   1.34 sec
---
Finished <<< accelerated_image_processor_compression [1.64s]

Summary: 1 package finished [2.20s]

Signed-off-by: ktro2828 <kotaro.uetake@tier4.jp>
Signed-off-by: ktro2828 <kotaro.uetake@tier4.jp>
Signed-off-by: ktro2828 <kotaro.uetake@tier4.jp>
Signed-off-by: ktro2828 <kotaro.uetake@tier4.jp>
Signed-off-by: ktro2828 <kotaro.uetake@tier4.jp>
Signed-off-by: ktro2828 <kotaro.uetake@tier4.jp>
Signed-off-by: ktro2828 <kotaro.uetake@tier4.jp>
@ktro2828 ktro2828 requested review from Copilot and manato December 26, 2025 04:58
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new ROS 2 package accelerated_image_processor_compression that provides hardware-accelerated image compression capabilities, primarily targeting JPEG compression. The package supports multiple backends (Jetson, NVJPEG, TurboJPEG/CPU) with automatic detection and selection based on platform capabilities.

Key changes:

  • Implements a flexible compression library with support for Jetson, NVJPEG, and CPU (TurboJPEG) backends
  • Provides CMake infrastructure for conditional compilation based on available hardware acceleration libraries
  • Includes comprehensive unit tests for each backend implementation

Reviewed changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
include/accelerated_image_processor_compression/builder.hpp Defines compressor creation API and type conversions
include/accelerated_image_processor_compression/jpeg_compressor.hpp Declares JPEG compressor base class and backend enum
src/builder.cpp Implements compressor factory functions with backend selection logic
src/jpeg_compressor/cpu.cpp Implements CPU-based JPEG compression using TurboJPEG
src/jpeg_compressor/nvjpeg.cpp Implements GPU-based JPEG compression using NVJPEG
src/jpeg_compressor/jetson.cpp Implements Jetson-specific JPEG compression
test/test_utility.hpp Provides test fixture for JPEG compressor tests
test/builder.cpp Tests compressor factory functions
test/cpu_jpeg_compressor.cpp Tests CPU JPEG compressor implementation
test/nv_jpeg_compressor.cpp Tests NVJPEG compressor implementation
test/jetson_jpeg_compressor.cpp Tests Jetson JPEG compressor implementation
CMakeLists.txt Configures build system with conditional backend compilation
cmake/FindNVJPEG.cmake CMake module for detecting NVJPEG library
cmake/FindLibJpegTurbo.cmake CMake module for detecting TurboJPEG library
cmake/LibFindMacros.cmake Helper macros for library detection
package.xml ROS 2 package manifest
README.md Documentation for package usage and supported backends

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

CHECK_CUDA(cudaStreamSynchronize(stream_));

size_t out_buf_size = image.width * image.height * 3 / 2;
unsigned char * out_data = new unsigned char[out_buf_size];
Copy link

Copilot AI Dec 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using raw new without corresponding exception safety. Consider using std::vector<unsigned char> or std::unique_ptr<unsigned char[]> to ensure automatic cleanup even if an exception occurs before the delete statement.

Copilot uses AI. Check for mistakes.
Signed-off-by: ktro2828 <kotaro.uetake@tier4.jp>
Signed-off-by: ktro2828 <kotaro.uetake@tier4.jp>
manato

This comment was marked as duplicate.

manato

This comment was marked as duplicate.

Copy link
Collaborator

@manato manato left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ktro2828

Thank you very much for the PR! It looks more than good to me! (Especially, adding tests is highly appreciated)
I left small comments regarding ifdef scope. I guess they will rarely cause problems, but it's just for completeness.

Signed-off-by: ktro2828 <kotaro.uetake@tier4.jp>
Signed-off-by: ktro2828 <kotaro.uetake@tier4.jp>
@ktro2828 ktro2828 force-pushed the refactor/compression-package branch from d56fc2e to 2e0a944 Compare January 5, 2026 23:41
Copy link
Collaborator

@manato manato left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ktro2828
Awesome! LGTM!

@ktro2828 ktro2828 merged commit 3075d7d into main Jan 6, 2026
@ktro2828 ktro2828 deleted the refactor/compression-package branch January 6, 2026 05:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants