Skip to content
Open
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
2 changes: 2 additions & 0 deletions aui.image/src/AUI/Image/AImage.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,14 @@ class API_AUI_IMAGE AImage : public AImageView {
AImage(AByteBuffer buffer, glm::uvec2 size, APixelFormat format) : mOwnedBuffer(std::move(buffer)) {
mSize = size;
mFormat = format;
mStride = bytesPerPixel() * width();
mData = mOwnedBuffer;
}

AImage(glm::uvec2 size, APixelFormat format) {
mSize = size;
mFormat = format;
mStride = bytesPerPixel() * width();
allocate();
}

Expand Down
44 changes: 41 additions & 3 deletions aui.image/src/AUI/Image/AImageView.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,43 @@ class API_AUI_IMAGE AImageView {
public:
using Color = AColor;

AImageView() : mSize(0, 0) {}
AImageView() : mSize(0, 0), mStride(0) {}

/**
* @brief Constructs an image view with an explicit row stride.
*
* This constructor creates a non-owning view over image data using the
* provided byte buffer and metadata. The stride (bytes per row)
* is explicitly specified, which allows the view to work with padded or
* externally aligned image memory.
*
* @param data Non-owning byte buffer that contains the image pixels.
* @param stride Number of bytes between the start of consecutive rows.
* @param size Image dimensions in pixels (width, height).
* @param format Pixel format describing how to interpret each pixel.
*/
AImageView(AByteBufferView data, size_t stride, glm::uvec2 size, APixelFormat format)
: mData(data), mStride(stride), mSize(size), mFormat(format) {}

/**
* @brief Constructs an image view with tightly packed rows.
*
* This constructor assumes the image rows are tightly packed in memory
* (no padding between rows). The stride is automatically computed as:
*
* stride = bytesPerPixel() * width()
*
* Use this overload only when the source image buffer has no row padding.
*
* @param data Non-owning byte buffer that contains the image pixels.
* @param size Image dimensions in pixels (width, height).
* @param format Pixel format describing how to interpret each pixel.
*/
AImageView(AByteBufferView data, glm::uvec2 size, APixelFormat format)
: mData(data), mSize(size), mFormat(format) {}
: mData(data), mSize(size), mFormat(format) {
mStride = bytesPerPixel() * width();
}
Comment thread
Nelonn marked this conversation as resolved.

AImageView(const AImage& v);

/**
Expand Down Expand Up @@ -150,9 +184,12 @@ class API_AUI_IMAGE AImageView {
const char& rawDataAt(glm::uvec2 position) const noexcept {
AUI_ASSERT(width() != 0);
AUI_ASSERT(height() != 0);
AUI_ASSERT(mStride != 0);
AUI_ASSERT(position.x < width());
AUI_ASSERT(position.y < height());
return mData.at<char>((position.y * width() + position.x) * bytesPerPixel());
size_t index = (position.y * mStride) + (position.x * bytesPerPixel());
AUI_ASSERT(index < mData.size());
return mData.at<char>(index);
}

[[nodiscard]]
Expand All @@ -174,6 +211,7 @@ class API_AUI_IMAGE AImageView {

protected:
AByteBufferView mData;
size_t mStride;
Comment thread
Nelonn marked this conversation as resolved.
glm::uvec2 mSize;
APixelFormat mFormat = APixelFormat::UNKNOWN;
};
Expand Down
24 changes: 24 additions & 0 deletions aui.image/tests/ImageViewTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* AUI Framework - Declarative UI toolkit for modern C++20
* Copyright (C) 2020-2025 Alex2772 and Contributors
*
* SPDX-License-Identifier: MPL-2.0
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

#include <gtest/gtest.h>
#include <AUI/Image/AImageView.h>

TEST(ImageView, Stride) {
APixelFormat pf = APixelFormat::RGBA_BYTE;
std::vector<uint8_t> some_bytes(100 * 100 * pf.bytesPerPixel());
AByteBufferView data(reinterpret_cast<const char*>(some_bytes.data()), some_bytes.size());

AImageView view_big(data, 100 * pf.bytesPerPixel(), {100, 100}, pf);
AImageView view_small(data, 100 * pf.bytesPerPixel(), {50, 50}, pf);

ASSERT_EQ(view_big.get({40, 40}), view_small.get({40, 40}));
}
Loading