Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ project(
include(GNUInstallDirs)
include(CTest)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

Expand All @@ -20,15 +20,15 @@ if(PIXEL_SUM_ENABLE_SANITIZERS AND CMAKE_BUILD_TYPE STREQUAL "Debug")
endif()

set(PIXEL_SUM_PUBLIC_HEADERS
${CMAKE_SOURCE_DIR}/include/pixel_sum/PixelSum.h)
${CMAKE_SOURCE_DIR}/include/pixel_sum/pixel_sum.hpp)

set(PIXEL_SUM_TEST_SUPPORT_HEADERS
${CMAKE_SOURCE_DIR}/tests/support/Common.h
${CMAKE_SOURCE_DIR}/tests/support/TestUtility.h
${CMAKE_SOURCE_DIR}/tests/support/TimeUtility.h)
${CMAKE_SOURCE_DIR}/tests/support/common.hpp
${CMAKE_SOURCE_DIR}/tests/support/test_utility.hpp
${CMAKE_SOURCE_DIR}/tests/support/time_utility.hpp)

add_library(PixelSumLib
src/PixelSum.cpp
src/pixel_sum.cpp
${PIXEL_SUM_PUBLIC_HEADERS})

target_include_directories(PixelSumLib
Expand All @@ -41,7 +41,7 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
endif()

add_executable(PixelSumTest
tests/PixelSumTest.cpp
tests/pixel_sum_test.cpp
${PIXEL_SUM_TEST_SUPPORT_HEADERS})

target_link_libraries(PixelSumTest PRIVATE PixelSumLib)
Expand All @@ -58,8 +58,8 @@ find_program(CPPCHECK cppcheck)

set(PIXEL_SUM_ALL_CPP
${PIXEL_SUM_PUBLIC_HEADERS}
${CMAKE_SOURCE_DIR}/src/PixelSum.cpp
${CMAKE_SOURCE_DIR}/tests/PixelSumTest.cpp
${CMAKE_SOURCE_DIR}/src/pixel_sum.cpp
${CMAKE_SOURCE_DIR}/tests/pixel_sum_test.cpp
${PIXEL_SUM_TEST_SUPPORT_HEADERS})

if(CLANG_FORMAT)
Expand All @@ -78,7 +78,7 @@ endif()

if(CLANG_TIDY)
add_custom_target(tidy
COMMAND ${CLANG_TIDY} -p ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/src/PixelSum.cpp ${CMAKE_SOURCE_DIR}/tests/PixelSumTest.cpp
COMMAND ${CLANG_TIDY} -p ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/src/pixel_sum.cpp ${CMAKE_SOURCE_DIR}/tests/pixel_sum_test.cpp
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Running clang-tidy"
VERBATIM)
Expand All @@ -87,7 +87,7 @@ endif()
if(CPPCHECK)
set(PIXEL_SUM_CPPCHECK_ARGS
--enable=warning,style,performance,portability
--std=c++17
--std=c++20
--language=c++
--inline-suppr)

Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# PixelSum

A tiny C++17 library that builds summed-area tables (integral images) so rectangular queries over pixel buffers are O(1). It supports 8- and 16-bit pixels via a templated `PixelSum<T, S>` that stores both the raw pixels and two integral images: one for sums and one for non-zero counts.
A tiny C++20 library that builds summed-area tables (integral images) so rectangular queries over pixel buffers are O(1). It supports 8- and 16-bit pixels via a templated `PixelSum<T, S>` that stores both the raw pixels and two integral images: one for sums and one for non-zero counts.

## Features
- Constant-time sum, average, non-zero count, and non-zero average for any axis-aligned window
Expand All @@ -25,7 +25,7 @@ cmake --build build --parallel

## Usage
```cpp
#include <pixel_sum/PixelSum.h>
#include <pixel_sum/pixel_sum.hpp>

std::vector<std::uint8_t> pixels(width * height, 128);
PixelSumU8 ps(pixels.data(), width, height);
Expand Down Expand Up @@ -65,4 +65,4 @@ GitHub Actions (`.github/workflows/ci.yml`) runs:

## Notes
- Dimensions are limited to 4096 x 4096 to keep intermediate sums within `uint32_t` for 8-bit pixels; switch to `PixelSumU16` for larger ranges or higher bit depth.
- The minimal test harness in `tests/PixelSumTest.cpp` exercises edge cases and can be extended with additional `TEST` blocks.
- The minimal test harness in `tests/pixel_sum_test.cpp` exercises edge cases and can be extended with additional `TEST` blocks.
40 changes: 15 additions & 25 deletions include/pixel_sum/PixelSum.h → include/pixel_sum/pixel_sum.hpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
#pragma once

#include <cstddef>
#include <cstdint>
#include <utility>
#include <span>
#include <vector>

template <typename T, typename S>
class PixelSum {
static constexpr int MAX_WIDTH = 4096;
static constexpr int MAX_HEIGHT = 4096;
static constexpr int kMaxWidth = 4096;
static constexpr int kMaxHeight = 4096;

public:
explicit PixelSum(const T* buffer, int width, int height);
explicit PixelSum(std::span<const T> buffer, int width, int height);

~PixelSum() = default;
PixelSum(const PixelSum&) = default;
PixelSum(PixelSum&&) noexcept = default;
Expand All @@ -25,31 +28,18 @@ class PixelSum {
explicit operator bool() const noexcept;

private:
int width_ { 0 };
int height_ { 0 };

// pixel data
std::vector<T> pixel_data_ {};
int width_{0};
int height_{0};

// sparse matrix for existent flags
std::vector<S> nonzero_data_ {};
std::vector<T> pixel_data_{};
std::vector<S> nonzero_data_{};
std::vector<S> summed_data_{};

// each pixel represents the cumulative sum of corresponding input pixel with
// all pixels above and to the left of input pixel.
std::vector<S> summed_data_ {};

void swap(int& x0, int& y0, int& x1, int& y1) const;
bool clampBound(int& x0, int& y0, int& x1, int& y1) const;
[[nodiscard]] S getSummedArea(const std::vector<S>& data, int x0, int y0, int x1, int y1) const;
static void normalizeBounds(int& x0, int& y0, int& x1, int& y1);
[[nodiscard]] bool clampBounds(int& x0, int& y0, int& x1, int& y1) const;
[[nodiscard]] static std::size_t indexOf(int x, int y, int width) noexcept;
[[nodiscard]] S getSummedArea(std::span<const S> data, int x0, int y0, int x1, int y1) const;
};

using PixelSumU8 = PixelSum<std::uint8_t, std::uint32_t>;
using PixelSumU16 = PixelSum<std::uint16_t, std::uint64_t>;

template <typename T>
inline void swap_if_a_greater_than_b(T& a, T& b)
{
if (a > b) {
std::swap(a, b);
}
}
179 changes: 0 additions & 179 deletions src/PixelSum.cpp

This file was deleted.

Loading
Loading