diff --git a/fleximg/CHANGELOG.md b/fleximg/CHANGELOG.md index b8ae13f3..b79dba53 100644 --- a/fleximg/CHANGELOG.md +++ b/fleximg/CHANGELOG.md @@ -12,6 +12,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Changed +- **コーディングスタイル違反の包括的修正** + - 固定小数点Q16.16メンバを `int32_t` → `int_fixed` に統一(AffinePrecomputed, SinkNode, SourceNode) + - 関数引数を `int` → `int_fast16_t` に修正(viewport, image_buffer, pixel_format, render_types 等14ファイル) + - 構造体メンバを `int` → `int16_t` に修正(RendererNode, BlurNode, MatteNode, PerfMetrics 等) + - ローカル変数・ループカウンタの型を終端変数に一致させる修正(auto + static_castパターン) + - 配列インデックスの型を `uint_fast8_t` / `size_t` に整理(EntryPool, RenderContext, FormatMetrics 等) + - PerfMetrics の count/allocCount メンバを `uint32_t` に統一 + - **関数ポインタ型の `int` 引数を `size_t` / `int_fast16_t` に修正** - `ConvertFunc` 系(ピクセル変換関数): `int pixelCount` → `size_t pixelCount` - `CopyRowDDA_Func` / `CopyQuadDDA_Func`(DDA転送関数): `int count` → `int_fast16_t count` diff --git a/fleximg/demo/bindings.cpp b/fleximg/demo/bindings.cpp index 800e19d9..4a6a5a32 100644 --- a/fleximg/demo/bindings.cpp +++ b/fleximg/demo/bindings.cpp @@ -838,12 +838,12 @@ class NodeGraphEvaluatorWrapper { // フォーマット別データ val formats = val::array(); - for (int f = 0; f < FormatIdx::Count; f++) { + for (uint_fast8_t f = 0; f < FormatIdx::Count; f++) { val fmtData = val::object(); fmtData.set("name", formatNames[f]); val ops = val::array(); - for (int o = 0; o < OpType::Count; o++) { + for (uint_fast8_t o = 0; o < OpType::Count; o++) { val opData = val::object(); opData.set("name", opNames[o]); opData.set("callCount", metrics.data[f][o].callCount); @@ -863,7 +863,7 @@ class NodeGraphEvaluatorWrapper { // 操作別合計 val opTotals = val::array(); - for (int o = 0; o < OpType::Count; o++) { + for (uint_fast8_t o = 0; o < OpType::Count; o++) { val opTotal = val::object(); opTotal.set("name", opNames[o]); auto t = metrics.totalByOp(o); diff --git a/fleximg/src/fleximg/core/format_metrics.h b/fleximg/src/fleximg/core/format_metrics.h index 5b471101..41fa354d 100644 --- a/fleximg/src/fleximg/core/format_metrics.h +++ b/fleximg/src/fleximg/core/format_metrics.h @@ -36,16 +36,16 @@ namespace core { // namespace FormatIdx { - constexpr int RGBA8_Straight = 0; - constexpr int RGB565_LE = 1; - constexpr int RGB565_BE = 2; - constexpr int RGB332 = 3; - constexpr int RGB888 = 4; - constexpr int BGR888 = 5; - constexpr int Alpha8 = 6; - constexpr int Grayscale8 = 7; - constexpr int Index8 = 8; - constexpr int Count = 9; + constexpr uint_fast8_t RGBA8_Straight = 0; + constexpr uint_fast8_t RGB565_LE = 1; + constexpr uint_fast8_t RGB565_BE = 2; + constexpr uint_fast8_t RGB332 = 3; + constexpr uint_fast8_t RGB888 = 4; + constexpr uint_fast8_t BGR888 = 5; + constexpr uint_fast8_t Alpha8 = 6; + constexpr uint_fast8_t Grayscale8 = 7; + constexpr uint_fast8_t Index8 = 8; + constexpr uint_fast8_t Count = 9; } // ======================================================================== @@ -53,10 +53,10 @@ namespace FormatIdx { // ======================================================================== namespace OpType { - constexpr int ToStraight = 0; // 各フォーマット → RGBA8_Straight - constexpr int FromStraight = 1; // RGBA8_Straight → 各フォーマット - constexpr int BlendUnder = 2; // 各フォーマット → Straight dst (under合成) - constexpr int Count = 3; + constexpr uint_fast8_t ToStraight = 0; // 各フォーマット → RGBA8_Straight + constexpr uint_fast8_t FromStraight = 1; // RGBA8_Straight → 各フォーマット + constexpr uint_fast8_t BlendUnder = 2; // 各フォーマット → Straight dst (under合成) + constexpr uint_fast8_t Count = 3; } // ======================================================================== @@ -74,7 +74,7 @@ struct FormatOpEntry { pixelCount = 0; } - void record(int pixels) { + void record(size_t pixels) { callCount++; pixelCount += static_cast(pixels); } @@ -90,25 +90,25 @@ struct FormatMetrics { } void reset() { - for (int f = 0; f < FormatIdx::Count; ++f) { - for (int o = 0; o < OpType::Count; ++o) { + for (uint_fast8_t f = 0; f < FormatIdx::Count; ++f) { + for (uint_fast8_t o = 0; o < OpType::Count; ++o) { data[f][o].reset(); } } } - void record(int formatIdx, int opType, int pixels) { - if (formatIdx >= 0 && formatIdx < FormatIdx::Count && - opType >= 0 && opType < OpType::Count) { + void record(uint_fast8_t formatIdx, uint_fast8_t opType, size_t pixels) { + if (formatIdx < FormatIdx::Count && + opType < OpType::Count) { data[formatIdx][opType].record(pixels); } } // 全フォーマットの合計(操作タイプ別) - FormatOpEntry totalByOp(int opType) const { + FormatOpEntry totalByOp(uint_fast8_t opType) const { FormatOpEntry total; - if (opType >= 0 && opType < OpType::Count) { - for (int f = 0; f < FormatIdx::Count; ++f) { + if (opType < OpType::Count) { + for (uint_fast8_t f = 0; f < FormatIdx::Count; ++f) { total.callCount += data[f][opType].callCount; total.pixelCount += data[f][opType].pixelCount; } @@ -117,10 +117,10 @@ struct FormatMetrics { } // 全操作の合計(フォーマット別) - FormatOpEntry totalByFormat(int formatIdx) const { + FormatOpEntry totalByFormat(uint_fast8_t formatIdx) const { FormatOpEntry total; - if (formatIdx >= 0 && formatIdx < FormatIdx::Count) { - for (int o = 0; o < OpType::Count; ++o) { + if (formatIdx < FormatIdx::Count) { + for (uint_fast8_t o = 0; o < OpType::Count; ++o) { total.callCount += data[formatIdx][o].callCount; total.pixelCount += data[formatIdx][o].pixelCount; } @@ -131,8 +131,8 @@ struct FormatMetrics { // 全体合計 FormatOpEntry total() const { FormatOpEntry t; - for (int f = 0; f < FormatIdx::Count; ++f) { - for (int o = 0; o < OpType::Count; ++o) { + for (uint_fast8_t f = 0; f < FormatIdx::Count; ++f) { + for (uint_fast8_t o = 0; o < OpType::Count; ++o) { t.callCount += data[f][o].callCount; t.pixelCount += data[f][o].pixelCount; } @@ -142,8 +142,8 @@ struct FormatMetrics { // スナップショット(現在の状態を保存) void saveSnapshot(FormatOpEntry snapshot[FormatIdx::Count][OpType::Count]) const { - for (int f = 0; f < FormatIdx::Count; ++f) { - for (int o = 0; o < OpType::Count; ++o) { + for (uint_fast8_t f = 0; f < FormatIdx::Count; ++f) { + for (uint_fast8_t o = 0; o < OpType::Count; ++o) { snapshot[f][o] = data[f][o]; } } @@ -151,8 +151,8 @@ struct FormatMetrics { // スナップショットから復元 void restoreSnapshot(const FormatOpEntry snapshot[FormatIdx::Count][OpType::Count]) { - for (int f = 0; f < FormatIdx::Count; ++f) { - for (int o = 0; o < OpType::Count; ++o) { + for (uint_fast8_t f = 0; f < FormatIdx::Count; ++f) { + for (uint_fast8_t o = 0; o < OpType::Count; ++o) { data[f][o] = snapshot[f][o]; } } @@ -179,9 +179,9 @@ struct FormatMetrics { return s_instance; } void reset() {} - void record(int, int, int) {} - FormatOpEntry totalByOp(int) const { return FormatOpEntry{}; } - FormatOpEntry totalByFormat(int) const { return FormatOpEntry{}; } + void record(uint_fast8_t, uint_fast8_t, size_t) {} + FormatOpEntry totalByOp(uint_fast8_t) const { return FormatOpEntry{}; } + FormatOpEntry totalByFormat(uint_fast8_t) const { return FormatOpEntry{}; } FormatOpEntry total() const { return FormatOpEntry{}; } void saveSnapshot(FormatOpEntry[FormatIdx::Count][OpType::Count]) const {} void restoreSnapshot(const FormatOpEntry[FormatIdx::Count][OpType::Count]) {} diff --git a/fleximg/src/fleximg/core/memory/pool_allocator.h b/fleximg/src/fleximg/core/memory/pool_allocator.h index 9186150d..4bd60780 100644 --- a/fleximg/src/fleximg/core/memory/pool_allocator.h +++ b/fleximg/src/fleximg/core/memory/pool_allocator.h @@ -277,14 +277,15 @@ void* PoolAllocator::allocate(size_t size) { uint32_t needBitmap = (1U << blocksNeeded) - 1; // 探索方向を決定(交互に切り替えてフラグメンテーション軽減) - int start = searchFromHead_ ? 0 : static_cast(blockCount_ - blocksNeeded); - int end = searchFromHead_ ? static_cast(blockCount_ - blocksNeeded + 1) : -1; - int step = searchFromHead_ ? 1 : -1; + size_t start = searchFromHead_ ? 0 : blockCount_ - blocksNeeded; + size_t end = blockCount_ - blocksNeeded + 1; + bool forward = searchFromHead_; searchFromHead_ = !searchFromHead_; // 次回は逆方向 // ビットマップで連続空きブロックを探索 - for (int i = start; i != end; i += step) { + for (size_t idx = 0; idx < end; ++idx) { + size_t i = forward ? idx : (start - idx); uint32_t shiftedNeed = needBitmap << i; if ((allocatedBitmap_ & shiftedNeed) == 0) { diff --git a/fleximg/src/fleximg/core/node.h b/fleximg/src/fleximg/core/node.h index 76bc7a8a..8b25408d 100644 --- a/fleximg/src/fleximg/core/node.h +++ b/fleximg/src/fleximg/core/node.h @@ -54,8 +54,8 @@ class Node { : context_(nullptr) { prepareResponse_.status = PrepareStatus::Idle; - initPorts(static_cast(other.inputs_.size()), - static_cast(other.outputs_.size())); + initPorts(static_cast(other.inputs_.size()), + static_cast(other.outputs_.size())); } // ムーブコンストラクタ: ポート構造をムーブし、ownerを修正 @@ -78,8 +78,8 @@ class Node { Node& operator=(const Node& other) { if (this != &other) { disconnectAll(); - initPorts(static_cast(other.inputs_.size()), - static_cast(other.outputs_.size())); + initPorts(static_cast(other.inputs_.size()), + static_cast(other.outputs_.size())); prepareResponse_.status = PrepareStatus::Idle; context_ = nullptr; } @@ -539,7 +539,7 @@ class Node { const FormatConverter* converter = nullptr); // 派生クラス用:ポート初期化 - void initPorts(int inputCount, int outputCount); + void initPorts(int_fast16_t inputCount, int_fast16_t outputCount); }; } // namespace core @@ -613,13 +613,13 @@ ImageBuffer Node::convertFormat(ImageBuffer&& buffer, PixelFormatID target, } // 派生クラス用:ポート初期化 -void Node::initPorts(int inputCount, int outputCount) { +void Node::initPorts(int_fast16_t inputCount, int_fast16_t outputCount) { inputs_.resize(static_cast(inputCount)); outputs_.resize(static_cast(outputCount)); - for (int i = 0; i < inputCount; ++i) { + for (int_fast16_t i = 0; i < inputCount; ++i) { inputs_[static_cast(i)] = Port(this, i); } - for (int i = 0; i < outputCount; ++i) { + for (int_fast16_t i = 0; i < outputCount; ++i) { outputs_[static_cast(i)] = Port(this, i); } } diff --git a/fleximg/src/fleximg/core/perf_metrics.h b/fleximg/src/fleximg/core/perf_metrics.h index 63a2e13e..83f8781a 100644 --- a/fleximg/src/fleximg/core/perf_metrics.h +++ b/fleximg/src/fleximg/core/perf_metrics.h @@ -78,15 +78,15 @@ static_assert(NodeType::VerticalBlur == 11, // ノード別メトリクス struct NodeMetrics { uint32_t time_us = 0; // 処理時間(マイクロ秒) - int count = 0; // 呼び出し回数 - uint32_t requestedPixels = 0; // 上流に要求したピクセル数 - uint32_t usedPixels = 0; // 実際に使用したピクセル数 + uint32_t count = 0; // 呼び出し回数 + uint32_t requestedPixels = 0; // 上流に要求したピクセル数 + uint32_t usedPixels = 0; // 実際に使用したピクセル数 uint32_t theoreticalMinPixels = 0; // 理論最小ピクセル数(分割時の推定値) - uint32_t allocatedBytes = 0; // このノードが確保したバイト数 - int allocCount = 0; // 確保回数 + uint32_t allocatedBytes = 0; // このノードが確保したバイト数 + uint32_t allocCount = 0; // 確保回数 uint32_t maxAllocBytes = 0; // 一回の最大確保バイト数 - int maxAllocWidth = 0; // その時の幅 - int maxAllocHeight = 0; // その時の高さ + int16_t maxAllocWidth = 0; // その時の幅 + int16_t maxAllocHeight = 0; // その時の高さ void reset() { *this = NodeMetrics{}; @@ -112,13 +112,13 @@ struct NodeMetrics { } // メモリ確保を記録 - void recordAlloc(size_t bytes, int width, int height) { + void recordAlloc(size_t bytes, int_fast16_t width, int_fast16_t height) { allocatedBytes += static_cast(bytes); allocCount++; if (static_cast(bytes) > maxAllocBytes) { maxAllocBytes = static_cast(bytes); - maxAllocWidth = width; - maxAllocHeight = height; + maxAllocWidth = static_cast(width); + maxAllocHeight = static_cast(height); } } }; diff --git a/fleximg/src/fleximg/core/render_context.h b/fleximg/src/fleximg/core/render_context.h index c70c78ad..05038da7 100644 --- a/fleximg/src/fleximg/core/render_context.h +++ b/fleximg/src/fleximg/core/render_context.h @@ -102,7 +102,7 @@ class RenderContext { RenderResponse& acquireResponse() { // nextHint_から開始して循環探索 uint_fast8_t idx = nextHint_; - for (int i = 0; i < MAX_RESPONSES; ++i) { + for (uint_fast8_t i = 0; i < MAX_RESPONSES; ++i) { idx = (idx + 1) & (MAX_RESPONSES - 1); if (!responsePool_[idx].inUse) { responsePool_[idx].inUse = true; @@ -154,8 +154,8 @@ class RenderContext { void resetScanlineResources() { #ifdef FLEXIMG_DEBUG // 未返却チェック - int inUseCount = 0; - for (int i = 0; i < MAX_RESPONSES; ++i) { + uint_fast8_t inUseCount = 0; + for (uint_fast8_t i = 0; i < MAX_RESPONSES; ++i) { if (responsePool_[i].inUse) ++inUseCount; } if (inUseCount > 1) { @@ -167,7 +167,7 @@ class RenderContext { #endif } #endif - for (int i = 0; i < MAX_RESPONSES; ++i) { + for (uint_fast8_t i = 0; i < MAX_RESPONSES; ++i) { if (responsePool_[i].inUse) { responsePool_[i].clear(); responsePool_[i].inUse = false; diff --git a/fleximg/src/fleximg/core/types.h b/fleximg/src/fleximg/core/types.h index b3b1d5a8..7de89fa3 100644 --- a/fleximg/src/fleximg/core/types.h +++ b/fleximg/src/fleximg/core/types.h @@ -229,12 +229,12 @@ inline Matrix2x2_fixed inverseFixed(const AffineMatrix& m) { struct AffinePrecomputed { Matrix2x2_fixed invMatrix; // 逆行列(2x2部分) - int32_t invTxFixed = 0; // 逆変換オフセットX(Q16.16) - int32_t invTyFixed = 0; // 逆変換オフセットY(Q16.16) - int32_t rowOffsetX = 0; // ピクセル中心オフセット: invMatrix.b >> 1 - int32_t rowOffsetY = 0; // ピクセル中心オフセット: invMatrix.d >> 1 - int32_t dxOffsetX = 0; // ピクセル中心オフセット: invMatrix.a >> 1 - int32_t dxOffsetY = 0; // ピクセル中心オフセット: invMatrix.c >> 1 + int_fixed invTxFixed = 0; // 逆変換オフセットX(Q16.16) + int_fixed invTyFixed = 0; // 逆変換オフセットY(Q16.16) + int_fixed rowOffsetX = 0; // ピクセル中心オフセット: invMatrix.b >> 1 + int_fixed rowOffsetY = 0; // ピクセル中心オフセット: invMatrix.d >> 1 + int_fixed dxOffsetX = 0; // ピクセル中心オフセット: invMatrix.a >> 1 + int_fixed dxOffsetY = 0; // ピクセル中心オフセット: invMatrix.c >> 1 bool isValid() const { return invMatrix.valid; } }; diff --git a/fleximg/src/fleximg/image/image_buffer.h b/fleximg/src/fleximg/image/image_buffer.h index bfe135f5..7909541d 100644 --- a/fleximg/src/fleximg/image/image_buffer.h +++ b/fleximg/src/fleximg/image/image_buffer.h @@ -65,7 +65,7 @@ class ImageBuffer { // サイズ指定コンストラクタ // alloc = nullptr の場合、DefaultAllocator を使用 - ImageBuffer(int w, int h, PixelFormatID fmt = PixelFormatIDs::RGBA8_Straight, + ImageBuffer(int_fast16_t w, int_fast16_t h, PixelFormatID fmt = PixelFormatIDs::RGBA8_Straight, InitPolicy init = DefaultInitPolicy, core::memory::IAllocator* alloc = nullptr) : view_(nullptr, fmt, 0, static_cast(w), static_cast(h)) @@ -296,7 +296,7 @@ class ImageBuffer { resolved = resolveConverter(view_.formatID, target, auxPtr); } if (resolved) { - for (int y = 0; y < view_.height; ++y) { + for (int_fast16_t y = 0; y < view_.height; ++y) { // ViewPortのx,yオフセットを考慮 const uint8_t* srcRow = static_cast(view_.data) + (view_.y + y) * view_.stride diff --git a/fleximg/src/fleximg/image/image_buffer_entry_pool.h b/fleximg/src/fleximg/image/image_buffer_entry_pool.h index df30a2dc..4a5f9f72 100644 --- a/fleximg/src/fleximg/image/image_buffer_entry_pool.h +++ b/fleximg/src/fleximg/image/image_buffer_entry_pool.h @@ -58,7 +58,7 @@ class ImageBufferEntryPool { /// @brief デフォルトコンストラクタ ImageBufferEntryPool() : nextHint_(0) { // エントリを初期化 - for (int i = 0; i < POOL_SIZE; ++i) { + for (uint_fast8_t i = 0; i < POOL_SIZE; ++i) { entries_[i].inUse = false; } } @@ -87,7 +87,7 @@ class ImageBufferEntryPool { Entry* acquire() { // nextHint_から開始して循環探索 uint_fast8_t idx = nextHint_; - for (int i = 0; i < POOL_SIZE; ++i) { + for (uint_fast8_t i = 0; i < POOL_SIZE; ++i) { idx = (idx + 1) & (POOL_SIZE - 1); if (!entries_[idx].inUse) { entries_[idx].inUse = true; @@ -124,7 +124,7 @@ class ImageBufferEntryPool { /// @brief 全エントリを一括解放(フレーム終了時) void releaseAll() { - for (int i = 0; i < POOL_SIZE; ++i) { + for (uint_fast8_t i = 0; i < POOL_SIZE; ++i) { if (entries_[i].inUse) { entries_[i].buffer.reset(); // 軽量リセット entries_[i].inUse = false; @@ -138,22 +138,22 @@ class ImageBufferEntryPool { // ======================================== /// @brief 使用中のエントリ数を取得 - int usedCount() const { - int count = 0; - for (int i = 0; i < POOL_SIZE; ++i) { + uint_fast8_t usedCount() const { + uint_fast8_t count = 0; + for (uint_fast8_t i = 0; i < POOL_SIZE; ++i) { if (entries_[i].inUse) ++count; } return count; } /// @brief 空きエントリ数を取得 - int freeCount() const { - return POOL_SIZE - usedCount(); + uint_fast8_t freeCount() const { + return static_cast(POOL_SIZE - usedCount()); } /// @brief 空きがあるか bool hasAvailable() const { - for (int i = 0; i < POOL_SIZE; ++i) { + for (uint_fast8_t i = 0; i < POOL_SIZE; ++i) { if (!entries_[i].inUse) return true; } return false; diff --git a/fleximg/src/fleximg/image/pixel_format.h b/fleximg/src/fleximg/image/pixel_format.h index 6190401c..675d4b50 100644 --- a/fleximg/src/fleximg/image/pixel_format.h +++ b/fleximg/src/fleximg/image/pixel_format.h @@ -476,7 +476,7 @@ FormatConverter resolveConverter( // 中間バッファが必要な場合は DefaultAllocator 経由で一時確保される。 inline void convertFormat(const void* src, PixelFormatID srcFormat, void* dst, PixelFormatID dstFormat, - int pixelCount, + int_fast16_t pixelCount, const PixelAuxInfo* srcAux = nullptr, const PixelAuxInfo* dstAux = nullptr) { (void)dstAux; // 現在の全呼び出し箇所で未使用 diff --git a/fleximg/src/fleximg/image/render_types.h b/fleximg/src/fleximg/image/render_types.h index 9f1179cb..d6fc1a04 100644 --- a/fleximg/src/fleximg/image/render_types.h +++ b/fleximg/src/fleximg/image/render_types.h @@ -53,7 +53,7 @@ struct TileConfig { int16_t tileHeight = 0; TileConfig() = default; - TileConfig(int w, int h) + TileConfig(int_fast16_t w, int_fast16_t h) : tileWidth(static_cast(w)) , tileHeight(static_cast(h)) {} @@ -74,7 +74,7 @@ struct RenderRequest { // マージン分拡大(フィルタ用) // 左右上下に適用されるため width/height は margin*2 増加 // origin は左上に移動(ワールド座標なので減算) - RenderRequest expand(int margin) const { + RenderRequest expand(int_fast16_t margin) const { int_fixed marginFixed = to_fixed(margin); return { static_cast(width + margin * 2), @@ -276,7 +276,7 @@ inline void calcAffineAABB( // matrix: 順方向のアフィン変換(内部で逆行列を計算) // 戻り値: 入力側で必要なAABB(width, height, origin) inline void calcInverseAffineAABB( - int outputWidth, int outputHeight, + int_fast16_t outputWidth, int_fast16_t outputHeight, Point outputOrigin, const AffineMatrix& matrix, int16_t& outWidth, int16_t& outHeight, Point& outOrigin) @@ -382,7 +382,7 @@ struct RenderResponse { /// @brief 新しいバッファを直接作成 /// @return 作成されたバッファへのポインタ(失敗時はnullptr) - ImageBuffer* createBuffer(int width, int height, PixelFormatID format, + ImageBuffer* createBuffer(int_fast16_t width, int_fast16_t height, PixelFormatID format, InitPolicy policy) { if (width <= 0 || height <= 0 || !format) return nullptr; // 既存エントリがあれば解放 @@ -428,8 +428,8 @@ struct RenderResponse { PixelFormatID srcFmt = entry_->buffer.view().formatID; if (srcFmt == format) return; - int width = entry_->buffer.width(); - ImageBuffer converted(width, 1, format, InitPolicy::Uninitialized, allocator_); + auto width = entry_->buffer.width(); + ImageBuffer converted(width, static_cast(1), format, InitPolicy::Uninitialized, allocator_); if (!converted.isValid()) return; const void* srcRow = entry_->buffer.view().pixelAt(0, 0); diff --git a/fleximg/src/fleximg/image/viewport.h b/fleximg/src/fleximg/image/viewport.h index 70f56471..b1a6e350 100644 --- a/fleximg/src/fleximg/image/viewport.h +++ b/fleximg/src/fleximg/image/viewport.h @@ -88,12 +88,12 @@ inline ViewPort subView(const ViewPort& v, int_fast16_t dx, int_fast16_t dy, } // 矩形コピー -void copy(ViewPort& dst, int dstX, int dstY, - const ViewPort& src, int srcX, int srcY, - int width, int height); +void copy(ViewPort& dst, int_fast16_t dstX, int_fast16_t dstY, + const ViewPort& src, int_fast16_t srcX, int_fast16_t srcY, + int_fast16_t width, int_fast16_t height); // 矩形クリア -void clear(ViewPort& dst, int x, int y, int width, int height); +void clear(ViewPort& dst, int_fast16_t x, int_fast16_t y, int_fast16_t width, int_fast16_t height); // ======================================================================== // DDA転写関数 @@ -180,9 +180,9 @@ inline bool canUseSingleChannelBilinear(PixelFormatID formatID, uint8_t edgeFade namespace FLEXIMG_NAMESPACE { namespace view_ops { -void copy(ViewPort& dst, int dstX, int dstY, - const ViewPort& src, int srcX, int srcY, - int width, int height) { +void copy(ViewPort& dst, int_fast16_t dstX, int_fast16_t dstY, + const ViewPort& src, int_fast16_t srcX, int_fast16_t srcY, + int_fast16_t width, int_fast16_t height) { if (!dst.isValid() || !src.isValid()) return; // クリッピング @@ -190,8 +190,8 @@ void copy(ViewPort& dst, int dstX, int dstY, if (srcY < 0) { dstY -= srcY; height += srcY; srcY = 0; } if (dstX < 0) { srcX -= dstX; width += dstX; dstX = 0; } if (dstY < 0) { srcY -= dstY; height += dstY; dstY = 0; } - width = std::min(width, std::min(src.width - srcX, dst.width - dstX)); - height = std::min(height, std::min(src.height - srcY, dst.height - dstY)); + width = std::min(width, std::min(src.width - srcX, dst.width - dstX)); + height = std::min(height, std::min(src.height - srcY, dst.height - dstY)); if (width <= 0 || height <= 0) return; // view_ops::copy は同一フォーマット間の矩形コピー専用。 @@ -200,7 +200,7 @@ void copy(ViewPort& dst, int dstX, int dstY, "view_ops::copy requires matching formats; use convertFormat for conversion"); size_t bytesPerPixel = static_cast(dst.bytesPerPixel()); - for (int y = 0; y < height; ++y) { + for (int_fast16_t y = 0; y < height; ++y) { const uint8_t* srcRow = static_cast(src.pixelAt(srcX, srcY + y)); uint8_t* dstRow = static_cast(dst.pixelAt(dstX, dstY + y)); std::memcpy(dstRow, srcRow, static_cast(width) * bytesPerPixel); @@ -208,12 +208,12 @@ void copy(ViewPort& dst, int dstX, int dstY, } -void clear(ViewPort& dst, int x, int y, int width, int height) { +void clear(ViewPort& dst, int_fast16_t x, int_fast16_t y, int_fast16_t width, int_fast16_t height) { if (!dst.isValid()) return; size_t bytesPerPixel = static_cast(dst.bytesPerPixel()); - for (int row = 0; row < height; ++row) { - int dy = y + row; + for (int_fast16_t row = 0; row < height; ++row) { + auto dy = static_cast(y + row); if (dy < 0 || dy >= dst.height) continue; uint8_t* dstRow = static_cast(dst.pixelAt(x, dy)); std::memset(dstRow, 0, static_cast(width) * bytesPerPixel); diff --git a/fleximg/src/fleximg/nodes/composite_node.h b/fleximg/src/fleximg/nodes/composite_node.h index 2aa64b3c..b417c2e5 100644 --- a/fleximg/src/fleximg/nodes/composite_node.h +++ b/fleximg/src/fleximg/nodes/composite_node.h @@ -43,7 +43,7 @@ namespace FLEXIMG_NAMESPACE { class CompositeNode : public Node, public AffineCapability { public: explicit CompositeNode(int_fast16_t inputCount = 2) { - initPorts(static_cast(inputCount), 1); // 入力N、出力1 + initPorts(inputCount, 1); // 入力N、出力1 } // ======================================== diff --git a/fleximg/src/fleximg/nodes/distributor_node.h b/fleximg/src/fleximg/nodes/distributor_node.h index c86b5fbf..ee0aca56 100644 --- a/fleximg/src/fleximg/nodes/distributor_node.h +++ b/fleximg/src/fleximg/nodes/distributor_node.h @@ -47,7 +47,7 @@ class DistributorNode : public Node, public AffineCapability { // ======================================== // 出力数を変更(既存接続は維持) - void setOutputCount(int count) { + void setOutputCount(int_fast16_t count) { if (count < 1) count = 1; outputs_.resize(static_cast(count)); for (int i = 0; i < count; ++i) { diff --git a/fleximg/src/fleximg/nodes/horizontal_blur_node.h b/fleximg/src/fleximg/nodes/horizontal_blur_node.h index 1699d406..a513ed0e 100644 --- a/fleximg/src/fleximg/nodes/horizontal_blur_node.h +++ b/fleximg/src/fleximg/nodes/horizontal_blur_node.h @@ -51,17 +51,17 @@ class HorizontalBlurNode : public Node { static constexpr int kMaxRadius = 127; // 実用上十分、メモリ消費も許容範囲 static constexpr int kMaxPasses = 3; // ガウシアン近似に十分 - void setRadius(int radius) { - radius_ = (radius < 0) ? 0 : (radius > kMaxRadius) ? kMaxRadius : radius; + void setRadius(int_fast16_t radius) { + radius_ = static_cast((radius < 0) ? 0 : (radius > kMaxRadius) ? kMaxRadius : radius); } - void setPasses(int passes) { - passes_ = (passes < 1) ? 1 : (passes > kMaxPasses) ? kMaxPasses : passes; + void setPasses(int_fast16_t passes) { + passes_ = static_cast((passes < 1) ? 1 : (passes > kMaxPasses) ? kMaxPasses : passes); } - int radius() const { return radius_; } - int passes() const { return passes_; } - int kernelSize() const { return radius_ * 2 + 1; } + int16_t radius() const { return radius_; } + int16_t passes() const { return passes_; } + int_fast16_t kernelSize() const { return radius_ * 2 + 1; } // ======================================== // Node インターフェース @@ -81,7 +81,7 @@ class HorizontalBlurNode : public Node { } // 上流への拡張リクエストを作成(左方向に拡大) - int totalMargin = radius_ * passes_; + auto totalMargin = static_cast(radius_ * passes_); RenderRequest inputReq; inputReq.width = static_cast(request.width + totalMargin * 2); inputReq.height = 1; @@ -134,16 +134,16 @@ class HorizontalBlurNode : public Node { void onPushProcess(RenderResponse& input, const RenderRequest& request) override; private: - int radius_ = 5; - int passes_ = 1; // 1-3の範囲、デフォルト1 + int16_t radius_ = 5; + int16_t passes_ = 1; // 1-3の範囲、デフォルト1 // 水平方向ブラー処理(共通) - void applyHorizontalBlur(const ViewPort& srcView, int inputOffset, ImageBuffer& output); + void applyHorizontalBlur(const ViewPort& srcView, int_fast16_t inputOffset, ImageBuffer& output); // ブラー済みピクセルを書き込み - void writeBlurredPixel(uint8_t* row, int x, uint32_t sumR, uint32_t sumG, + void writeBlurredPixel(uint8_t* row, int_fast16_t x, uint32_t sumR, uint32_t sumG, uint32_t sumB, uint32_t sumA) { - int off = x * 4; + auto off = static_cast(x * 4); uint32_t ks = static_cast(kernelSize()); if (sumA > 0) { row[off] = static_cast(sumR / sumA); @@ -191,7 +191,7 @@ PrepareResponse HorizontalBlurNode::onPullPrepare(const PrepareRequest& request) // 水平ぼかしはX方向に radius * passes 分拡張する // AABBの幅を拡張し、originのXをシフト(左方向に拡大) - int expansion = radius_ * passes_; + auto expansion = static_cast(radius_ * passes_); upstreamResult.width = static_cast(upstreamResult.width + expansion * 2); upstreamResult.origin.x = upstreamResult.origin.x - to_fixed(expansion); @@ -208,7 +208,7 @@ RenderResponse& HorizontalBlurNode::onPullProcess(const RenderRequest& request) } // マージンを計算して上流への要求を拡大 - int totalMargin = radius_ * passes_; // 片側のマージン + auto totalMargin = static_cast(radius_ * passes_); // 片側のマージン RenderRequest inputReq; inputReq.width = static_cast(request.width + totalMargin * 2); // 両側にマージンを追加 inputReq.height = 1; @@ -243,10 +243,10 @@ RenderResponse& HorizontalBlurNode::onPullProcess(const RenderRequest& request) Point currentOrigin = input.origin; // passes回、水平ブラーを適用(各パスで拡張+origin調整) - for (int pass = 0; pass < passes_; pass++) { + for (int_fast16_t pass = 0; pass < passes_; pass++) { ViewPort srcView = buffer.view(); - int inputWidth = srcView.width; - int outputWidth = inputWidth + radius_ * 2; + auto inputWidth = static_cast(srcView.width); + auto outputWidth = static_cast(inputWidth + radius_ * 2); #ifdef FLEXIMG_DEBUG_PERF_METRICS if (pass == 0) { @@ -286,7 +286,7 @@ RenderResponse& HorizontalBlurNode::onPullProcess(const RenderRequest& request) // origin座標を基準にクロップ位置を計算 int_fixed offsetX = currentOrigin.x - request.origin.x; - int cropOffset = from_fixed(offsetX); + auto cropOffset = static_cast(from_fixed(offsetX)); // 出力バッファを確保(必要幅のみ、ゼロ初期化) // 出力バッファ左端のワールド座標 = リクエスト左端 + blurredStartX @@ -300,10 +300,10 @@ RenderResponse& HorizontalBlurNode::onPullProcess(const RenderRequest& request) // cropOffset = ブラー後バッファ左端 - リクエスト左端(ワールド座標差) // blurredStartX = 出力範囲の開始位置(リクエスト座標系) // ブラー後バッファ内での位置 = blurredStartX - cropOffset - int srcStartX = std::max(0, blurredStartX - cropOffset); - int dstStartX = std::max(0, cropOffset - blurredStartX); - int copyWidth = std::min(static_cast(buffer.width()) - srcStartX, - static_cast(outputWidth) - dstStartX); + auto srcStartX = std::max(0, blurredStartX - cropOffset); + auto dstStartX = std::max(0, cropOffset - blurredStartX); + auto copyWidth = std::min(static_cast(buffer.width()) - srcStartX, + static_cast(outputWidth) - dstStartX); // 有効な範囲をコピー(範囲外は既にゼロ初期化済み) if (copyWidth > 0) { @@ -344,10 +344,10 @@ void HorizontalBlurNode::onPushProcess(RenderResponse& input, const RenderReques Point currentOrigin = input.origin; // passes回、水平ブラーを適用 - for (int pass = 0; pass < passes_; pass++) { + for (int_fast16_t pass = 0; pass < passes_; pass++) { ViewPort srcView = buffer.view(); - int inputWidth = srcView.width; - int outputWidth = inputWidth + radius_ * 2; + auto inputWidth = static_cast(srcView.width); + auto outputWidth = static_cast(inputWidth + radius_ * 2); // 出力バッファを確保 ImageBuffer output(outputWidth, 1, PixelFormatIDs::RGBA8_Straight, @@ -379,11 +379,11 @@ void HorizontalBlurNode::onPushProcess(RenderResponse& input, const RenderReques // 水平方向ブラー処理(共通) // inputOffset: 出力x=0に対応する入力のカーネル中心位置 -void HorizontalBlurNode::applyHorizontalBlur(const ViewPort& srcView, int inputOffset, ImageBuffer& output) { +void HorizontalBlurNode::applyHorizontalBlur(const ViewPort& srcView, int_fast16_t inputOffset, ImageBuffer& output) { const uint8_t* srcRow = static_cast(srcView.data); uint8_t* dstRow = static_cast(output.view().data); - int inputWidth = srcView.width; - int outputWidth = output.width(); + auto inputWidth = static_cast(srcView.width); + auto outputWidth = static_cast(output.width()); // 初期ウィンドウの合計(出力x=0に対応) uint32_t sumR = 0, sumG = 0, sumB = 0, sumA = 0; diff --git a/fleximg/src/fleximg/nodes/matte_node.h b/fleximg/src/fleximg/nodes/matte_node.h index 27babf98..db9b9ccc 100644 --- a/fleximg/src/fleximg/nodes/matte_node.h +++ b/fleximg/src/fleximg/nodes/matte_node.h @@ -93,14 +93,15 @@ class MatteNode : public Node { // 入力画像のビュー情報(座標変換済み) struct InputView { const uint8_t* ptr = nullptr; - int width = 0, height = 0, stride = 0; - int offsetX = 0, offsetY = 0; + int16_t width = 0, height = 0; + int32_t stride = 0; + int16_t offsetX = 0, offsetY = 0; bool valid() const { return ptr != nullptr; } // 指定Y座標の行ポインタ(範囲外ならnullptr) - const uint8_t* rowAt(int y) const { - int srcY = y - offsetY; + const uint8_t* rowAt(int_fast16_t y) const { + auto srcY = static_cast(y - offsetY); if (static_cast(srcY) >= static_cast(height)) return nullptr; return ptr + srcY * stride; } @@ -116,16 +117,16 @@ class MatteNode : public Node { v.width = vp.width; v.height = vp.height; v.stride = vp.stride; - v.offsetX = from_fixed(resp.origin.x - outOriginX); - v.offsetY = from_fixed(resp.origin.y - outOriginY); + v.offsetX = static_cast(from_fixed(resp.origin.x - outOriginX)); + v.offsetY = static_cast(from_fixed(resp.origin.y - outOriginY)); return v; } }; // マスクの左右0スキップ範囲をスキャン(4バイト単位、アライメント対応) // 戻り値: 有効範囲の幅(0なら全面0) - static int scanMaskZeroRanges(const uint8_t* maskData, int maskWidth, - int& outLeftSkip, int& outRightSkip); + static int_fast16_t scanMaskZeroRanges(const uint8_t* maskData, int_fast16_t maskWidth, + int_fast16_t& outLeftSkip, int_fast16_t& outRightSkip); // ======================================== // 合成処理 @@ -135,7 +136,7 @@ class MatteNode : public Node { // alpha=0: 何もしない(出力に既にbgがある) // alpha=255: fgをコピー // 中間alpha: out = out*(1-a) + fg*a - void applyMatteOverlay(ImageBuffer& output, int outWidth, + void applyMatteOverlay(ImageBuffer& output, int_fast16_t outWidth, const InputView& fg, const InputView& mask); // ======================================== @@ -177,7 +178,7 @@ PrepareResponse MatteNode::onPullPrepare(const PrepareRequest& request) { float minX = 0, minY = 0, maxX = 0, maxY = 0; // 全上流へ伝播し、結果をマージ(AABB和集合) - for (int i = 0; i < 3; ++i) { + for (int_fast16_t i = 0; i < 3; ++i) { Node* upstream = upstreamNode(i); if (upstream) { PrepareResponse result = upstream->pullPrepare(request); @@ -234,7 +235,7 @@ PrepareResponse MatteNode::onPullPrepare(const PrepareRequest& request) { void MatteNode::onPullFinalize() { finalize(); - for (int i = 0; i < 3; ++i) { + for (int_fast16_t i = 0; i < 3; ++i) { Node* upstream = upstreamNode(i); if (upstream) { upstream->pullFinalize(); @@ -374,8 +375,8 @@ RenderResponse& MatteNode::onPullProcess(const RenderRequest& request) { // 全面0判定(行スキャン)+ 有効範囲へのcrop ViewPort maskView = maskResult.view(); const uint8_t* maskData = static_cast(maskView.data); - int maskLeftSkip = 0, maskRightSkip = 0; - int maskEffectiveWidth = scanMaskZeroRanges(maskData, maskView.width, + int_fast16_t maskLeftSkip = 0, maskRightSkip = 0; + auto maskEffectiveWidth = scanMaskZeroRanges(maskData, maskView.width, maskLeftSkip, maskRightSkip); // 全面0 → bg fallback @@ -423,8 +424,8 @@ RenderResponse& MatteNode::onPullProcess(const RenderRequest& request) { if (bgMaxY > unionMaxY) unionMaxY = bgMaxY; } - int unionWidth = from_fixed(unionMaxX - unionMinX); - int unionHeight = from_fixed(unionMaxY - unionMinY); + auto unionWidth = static_cast(from_fixed(unionMaxX - unionMinX)); + auto unionHeight = static_cast(from_fixed(unionMaxY - unionMinY)); // ======================================================================== // Step 3: 出力バッファ作成(ゼロクリア)+ bgコピー @@ -441,8 +442,8 @@ RenderResponse& MatteNode::onPullProcess(const RenderRequest& request) { // bgがあればコピー if (bgResultPtr) { - int bgOffsetX = from_fixed(bgResultPtr->origin.x - unionMinX); - int bgOffsetY = from_fixed(bgResultPtr->origin.y - unionMinY); + auto bgOffsetX = static_cast(from_fixed(bgResultPtr->origin.x - unionMinX)); + auto bgOffsetY = static_cast(from_fixed(bgResultPtr->origin.y - unionMinY)); auto converter = resolveConverter(bgResultPtr->buffer().formatID(), PixelFormatIDs::RGBA8_Straight, @@ -450,19 +451,19 @@ RenderResponse& MatteNode::onPullProcess(const RenderRequest& request) { if (converter) { ViewPort bgViewPort = bgResultPtr->view(); ViewPort outView = outputBuf.view(); - int srcBytesPerPixel = bgViewPort.bytesPerPixel(); + auto srcBytesPerPixel = static_cast(bgViewPort.bytesPerPixel()); // bgの有効範囲を計算(出力座標系) - int copyStartX = std::max(0, bgOffsetX); - int copyEndX = std::min(unionWidth, bgOffsetX + bgViewPort.width); - int copyStartY = std::max(0, bgOffsetY); - int copyEndY = std::min(unionHeight, bgOffsetY + bgViewPort.height); - int copyWidth = copyEndX - copyStartX; + auto copyStartX = std::max(0, bgOffsetX); + auto copyEndX = std::min(unionWidth, bgOffsetX + bgViewPort.width); + auto copyStartY = std::max(0, bgOffsetY); + auto copyEndY = std::min(unionHeight, bgOffsetY + bgViewPort.height); + auto copyWidth = static_cast(copyEndX - copyStartX); if (copyWidth > 0) { - int srcStartX = copyStartX - bgOffsetX; - for (int y = copyStartY; y < copyEndY; ++y) { - int srcY = y - bgOffsetY; + auto srcStartX = static_cast(copyStartX - bgOffsetX); + for (auto y = copyStartY; y < copyEndY; ++y) { + auto srcY = static_cast(y - bgOffsetY); const uint8_t* srcRow = static_cast(bgViewPort.data) + srcY * bgViewPort.stride + srcStartX * srcBytesPerPixel; @@ -525,16 +526,16 @@ RenderResponse& MatteNode::onPullProcess(const RenderRequest& request) { // MatteNode - ヘルパー関数実装 // ============================================================================ -int MatteNode::scanMaskZeroRanges(const uint8_t* maskData, int maskWidth, - int& outLeftSkip, int& outRightSkip) { +int_fast16_t MatteNode::scanMaskZeroRanges(const uint8_t* maskData, int_fast16_t maskWidth, + int_fast16_t& outLeftSkip, int_fast16_t& outRightSkip) { // 左端からの0スキップ(4バイト単位、アライメント対応) - int leftSkip = 0; + int_fast16_t leftSkip = 0; { // Phase 1: アライメントまで1バイトずつ uintptr_t addr = reinterpret_cast(maskData); - int misalign = static_cast(addr & 3); + int_fast16_t misalign = static_cast(addr & 3); if (misalign != 0) { - int alignBytes = 4 - misalign; + int_fast16_t alignBytes = static_cast(4 - misalign); if (alignBytes > maskWidth) { alignBytes = maskWidth; } @@ -557,7 +558,7 @@ int MatteNode::scanMaskZeroRanges(const uint8_t* maskData, int maskWidth, while (p32 < p32_end && *p32 == 0) { ++p32; } - leftSkip = static_cast(reinterpret_cast(p32) - maskData); + leftSkip = static_cast(reinterpret_cast(p32) - maskData); } // Phase 3: 残りを1バイトずつ @@ -577,13 +578,13 @@ int MatteNode::scanMaskZeroRanges(const uint8_t* maskData, int maskWidth, outLeftSkip = leftSkip; // 右端からの0スキップ(4バイト単位、アライメント対応) - int rightSkip = 0; + int_fast16_t rightSkip = 0; { - const int limit = maskWidth - leftSkip; + const int_fast16_t limit = static_cast(maskWidth - leftSkip); // Phase 1: アライメントまで1バイトずつ uintptr_t endAddr = reinterpret_cast(maskData + maskWidth); - int misalign = static_cast(endAddr & 3); + int_fast16_t misalign = static_cast(endAddr & 3); if (misalign > limit) { misalign = limit; } @@ -602,7 +603,7 @@ int MatteNode::scanMaskZeroRanges(const uint8_t* maskData, int maskWidth, while (p32 > p32_end && *p32 == 0) { --p32; } - rightSkip = static_cast(maskData + maskWidth - reinterpret_cast(p32 + 1)); + rightSkip = static_cast(maskData + maskWidth - reinterpret_cast(p32 + 1)); } // Phase 3: 残りを1バイトずつ @@ -683,9 +684,9 @@ static inline void processRowNoFg( m += 4; } while (--plimit); if (m != m_start) { - auto len = static_cast(m - m_start); + auto len = static_cast(m - m_start); std::memset(d, 0, static_cast(len) * 4); - pixelCount -= static_cast(len); + pixelCount -= len; if (pixelCount <= 0) return; alpha = static_cast(m32); d += len * 4; @@ -712,8 +713,8 @@ static inline void processRowNoFg( m += 4; } while (--plimit); if (m != m_start) { - int skipped = static_cast(m - m_start); - pixelCount -= static_cast(skipped); + auto skipped = static_cast(m - m_start); + pixelCount -= skipped; if (pixelCount <= 0) return; alpha = static_cast(m32); d += skipped * 4; @@ -796,9 +797,9 @@ static inline void processRowWithFg( m += 4; } while (--plimit); if (m != m_start) { - auto len = static_cast(m - m_start); + auto len = static_cast(m - m_start); memcpy(d, s, static_cast(len) * 4); - pixelCount -= static_cast(len); + pixelCount -= len; if (pixelCount <= 0) return; alpha = static_cast(m32); d += len * 4; @@ -826,8 +827,8 @@ static inline void processRowWithFg( m += 4; } while (--plimit); if (m != m_start) { - int skipped = static_cast(m - m_start); - pixelCount -= static_cast(skipped); + auto skipped = static_cast(m - m_start); + pixelCount -= skipped; if (pixelCount <= 0) return; alpha = static_cast(m32); d += skipped * 4; @@ -842,32 +843,32 @@ static inline void processRowWithFg( // ---------------------------------------------------------------------------- -void MatteNode::applyMatteOverlay(ImageBuffer& output, int outWidth, +void MatteNode::applyMatteOverlay(ImageBuffer& output, int_fast16_t outWidth, const InputView& fg, const InputView& mask) { ViewPort outView = output.view(); uint8_t* __restrict__ outData = static_cast(outView.data); - const int outHeight = outView.height; - const int outStride = outView.stride; + const auto outHeight = static_cast(outView.height); + const int32_t outStride = outView.stride; // マスクの有効X範囲(出力座標系) - const int maskXStart = std::max(0, mask.offsetX); - const int maskXEnd = std::min(outWidth, mask.width + mask.offsetX); + const auto maskXStart = std::max(0, mask.offsetX); + const auto maskXEnd = std::min(outWidth, mask.width + mask.offsetX); if (maskXStart >= maskXEnd) return; - const int maskSrcOffsetX = maskXStart - mask.offsetX; + const auto maskSrcOffsetX = static_cast(maskXStart - mask.offsetX); // 前景の有効X範囲(事前計算) - const int fgXStart = fg.valid() ? std::max(maskXStart, fg.offsetX) : maskXEnd; - const int fgXEnd = fg.valid() ? std::min(maskXEnd, fg.width + fg.offsetX) : maskXStart; - const int fgSrcOffsetX = fgXStart - fg.offsetX; + const auto fgXStart = fg.valid() ? std::max(maskXStart, fg.offsetX) : maskXEnd; + const auto fgXEnd = fg.valid() ? std::min(maskXEnd, fg.width + fg.offsetX) : maskXStart; + const auto fgSrcOffsetX = static_cast(fgXStart - fg.offsetX); // 3領域の幅を事前計算 - const int leftWidth = fgXStart - maskXStart; // 左領域(fgなし) - const int midWidth = fgXEnd - fgXStart; // 中央領域(fg/bg両方) - const int rightWidth = maskXEnd - fgXEnd; // 右領域(fgなし) + const auto leftWidth = static_cast(fgXStart - maskXStart); // 左領域(fgなし) + const auto midWidth = static_cast(fgXEnd - fgXStart); // 中央領域(fg/bg両方) + const auto rightWidth = static_cast(maskXEnd - fgXEnd); // 右領域(fgなし) // 行ごとに処理 - for (int y = 0; y < outHeight; ++y) { + for (int_fast16_t y = 0; y < outHeight; ++y) { // マスクがない行 → スキップ const uint8_t* maskRowBase = mask.rowAt(y); if (!maskRowBase) continue; diff --git a/fleximg/src/fleximg/nodes/ninepatch_source_node.h b/fleximg/src/fleximg/nodes/ninepatch_source_node.h index b907e77e..bdccc934 100644 --- a/fleximg/src/fleximg/nodes/ninepatch_source_node.h +++ b/fleximg/src/fleximg/nodes/ninepatch_source_node.h @@ -241,7 +241,7 @@ class NinePatchSourceNode : public Node, public AffineCapability { // 内部メソッド // ======================================== - int getPatchIndex(int col, int row) const { + int_fast16_t getPatchIndex(int_fast16_t col, int_fast16_t row) const { return row * 3 + col; } diff --git a/fleximg/src/fleximg/nodes/renderer_node.h b/fleximg/src/fleximg/nodes/renderer_node.h index 3b37e5c1..a9d6338d 100644 --- a/fleximg/src/fleximg/nodes/renderer_node.h +++ b/fleximg/src/fleximg/nodes/renderer_node.h @@ -47,9 +47,9 @@ class RendererNode : public Node { // 仮想スクリーン設定 // サイズを指定。pivot は setPivot() または setPivotCenter() で別途設定 - void setVirtualScreen(int width, int height) { - virtualWidth_ = width; - virtualHeight_ = height; + void setVirtualScreen(int_fast16_t width, int_fast16_t height) { + virtualWidth_ = static_cast(width); + virtualHeight_ = static_cast(height); } // pivot設定(スクリーン座標でワールド原点の表示位置を指定) @@ -78,7 +78,7 @@ class RendererNode : public Node { tileConfig_ = config; } - void setTileConfig(int tileWidth, int tileHeight) { + void setTileConfig(int_fast16_t tileWidth, int_fast16_t tileHeight) { tileConfig_ = TileConfig(tileWidth, tileHeight); } @@ -165,7 +165,7 @@ class RendererNode : public Node { // タイル処理(派生クラスでカスタマイズ可能) // 注: exec()全体の時間はnodes[NodeType::Renderer]に記録される // 各ノードの合計との差分がオーバーヘッド(タイル管理、データ受け渡し等) - virtual void processTile(int tileX, int tileY) { + virtual void processTile(int_fast16_t tileX, int_fast16_t tileY) { RenderRequest request = createTileRequest(tileX, tileY); // 上流からプル @@ -197,8 +197,8 @@ class RendererNode : public Node { RenderResponse& result); private: - int virtualWidth_ = 0; - int virtualHeight_ = 0; + int16_t virtualWidth_ = 0; + int16_t virtualHeight_ = 0; int_fixed pivotX_ = 0; int_fixed pivotY_ = 0; TileConfig tileConfig_; @@ -211,25 +211,25 @@ class RendererNode : public Node { // タイルサイズ取得 // 注: パイプライン上のリクエストは必ずスキャンライン(height=1) // これにより各ノードの最適化が可能になる - int effectiveTileWidth() const { + int_fast16_t effectiveTileWidth() const { return tileConfig_.isEnabled() ? tileConfig_.tileWidth : virtualWidth_; } - int effectiveTileHeight() const { + int_fast16_t effectiveTileHeight() const { // スキャンライン必須(height=1) // TileConfig の tileHeight は無視される return 1; } // タイル数取得 - int calcTileCountX() const { - int tw = effectiveTileWidth(); - return (tw > 0) ? (virtualWidth_ + tw - 1) / tw : 1; + int_fast16_t calcTileCountX() const { + auto tw = effectiveTileWidth(); + return (tw > 0) ? static_cast((virtualWidth_ + tw - 1) / tw) : 1; } - int calcTileCountY() const { - int th = effectiveTileHeight(); - return (th > 0) ? (virtualHeight_ + th - 1) / th : 1; + int_fast16_t calcTileCountY() const { + auto th = effectiveTileHeight(); + return (th > 0) ? static_cast((virtualHeight_ + th - 1) / th) : 1; } // スクリーン全体のRenderRequestを作成 @@ -244,15 +244,15 @@ class RendererNode : public Node { } // タイル用のRenderRequestを作成 - RenderRequest createTileRequest(int tileX, int tileY) const { - int tw = effectiveTileWidth(); - int th = effectiveTileHeight(); - int tileLeft = tileX * tw; - int tileTop = tileY * th; + RenderRequest createTileRequest(int_fast16_t tileX, int_fast16_t tileY) const { + auto tw = effectiveTileWidth(); + auto th = effectiveTileHeight(); + auto tileLeft = static_cast(tileX * tw); + auto tileTop = static_cast(tileY * th); // タイルサイズ(端の処理) - int tileW = std::min(tw, virtualWidth_ - tileLeft); - int tileH = std::min(th, virtualHeight_ - tileTop); + auto tileW = std::min(tw, virtualWidth_ - tileLeft); + auto tileH = std::min(th, virtualHeight_ - tileTop); RenderRequest req; req.width = static_cast(tileW); @@ -349,11 +349,11 @@ PrepareStatus RendererNode::execPrepare() { } void RendererNode::execProcess() { - int tileCountX = calcTileCountX(); - int tileCountY = calcTileCountY(); + auto tileCountX = calcTileCountX(); + auto tileCountY = calcTileCountY(); - for (int ty = 0; ty < tileCountY; ++ty) { - for (int tx = 0; tx < tileCountX; ++tx) { + for (int_fast16_t ty = 0; ty < tileCountY; ++ty) { + for (int_fast16_t tx = 0; tx < tileCountX; ++tx) { // デバッグ用チェッカーボード: 市松模様でタイルをスキップ if (debugCheckerboard_ && ((tx + ty) % 2 == 1)) { continue; diff --git a/fleximg/src/fleximg/nodes/sink_node.h b/fleximg/src/fleximg/nodes/sink_node.h index 759422e5..00a6d75b 100644 --- a/fleximg/src/fleximg/nodes/sink_node.h +++ b/fleximg/src/fleximg/nodes/sink_node.h @@ -96,8 +96,8 @@ class SinkNode : public Node, public AffineCapability { // アフィン伝播用メンバ変数(事前計算済み) Matrix2x2_fixed invMatrix_; // 逆行列(固定小数点) - int32_t baseTx_ = 0; // 事前計算済みオフセットX(Q16.16、pivot込み) - int32_t baseTy_ = 0; // 事前計算済みオフセットY(Q16.16、pivot込み) + int_fixed baseTx_ = 0; // 事前計算済みオフセットX(Q16.16、pivot込み) + int_fixed baseTy_ = 0; // 事前計算済みオフセットY(Q16.16、pivot込み) bool hasAffine_ = false; // アフィン変換が伝播されているか // アフィン変換付きプッシュ処理 @@ -221,11 +221,11 @@ void SinkNode::onPushProcess(RenderResponse& input, ViewPort inputView = input.view(); int_fixed txFixed = float_to_fixed(localMatrix_.tx); int_fixed tyFixed = float_to_fixed(localMatrix_.ty); - int dstX = from_fixed(input.origin.x + txFixed + pivotX_); - int dstY = from_fixed(input.origin.y + tyFixed + pivotY_); + auto dstX = static_cast(from_fixed(input.origin.x + txFixed + pivotX_)); + auto dstY = static_cast(from_fixed(input.origin.y + tyFixed + pivotY_)); // クリッピング処理 - int srcX = 0, srcY = 0; + int_fast16_t srcX = 0, srcY = 0; if (dstX < 0) { srcX = -dstX; dstX = 0; } if (dstY < 0) { srcY = -dstY; dstY = 0; } @@ -286,8 +286,8 @@ void SinkNode::applyAffine(ViewPort& dst, // baseTx_はすでにworldオフセットを含む // srcOriginは入力バッファの左上のworld座標なので減算 - const int32_t fixedTx = baseTx_ - (srcOriginXInt << INT_FIXED_SHIFT); - const int32_t fixedTy = baseTy_ - (srcOriginYInt << INT_FIXED_SHIFT); + const int_fixed fixedTx = baseTx_ - (srcOriginXInt << INT_FIXED_SHIFT); + const int_fixed fixedTy = baseTy_ - (srcOriginYInt << INT_FIXED_SHIFT); // ピクセル中心オフセット(逆行列用) int_fixed rowOffsetX = invMatrix_.b >> 1; diff --git a/fleximg/src/fleximg/nodes/source_node.h b/fleximg/src/fleximg/nodes/source_node.h index 2a6e9505..d586f46a 100644 --- a/fleximg/src/fleximg/nodes/source_node.h +++ b/fleximg/src/fleximg/nodes/source_node.h @@ -139,12 +139,12 @@ class SourceNode : public Node, public AffineCapability { PixelFormatID preferredFormat_ = PixelFormatIDs::RGBA8_Straight; // LovyanGFX方式の範囲計算用事前計算値 - int32_t xs1_ = 0, xs2_ = 0; // X方向の範囲境界(invAに依存) - int32_t ys1_ = 0, ys2_ = 0; // Y方向の範囲境界(invCに依存) - int32_t fpWidth_ = 0; // ソース幅(Q16.16固定小数点) - int32_t fpHeight_ = 0; // ソース高さ(Q16.16固定小数点) - int32_t baseTxWithOffsets_ = 0; // 事前計算統合: invTx + srcPivot + rowOffset + dxOffset - int32_t baseTyWithOffsets_ = 0; // 事前計算統合: invTy + srcPivot + rowOffset + dxOffset + int_fixed xs1_ = 0, xs2_ = 0; // X方向の範囲境界(invAに依存) + int_fixed ys1_ = 0, ys2_ = 0; // Y方向の範囲境界(invCに依存) + int_fixed fpWidth_ = 0; // ソース幅(Q16.16固定小数点) + int_fixed fpHeight_ = 0; // ソース高さ(Q16.16固定小数点) + int_fixed baseTxWithOffsets_ = 0; // 事前計算統合: invTx + srcPivot + rowOffset + dxOffset + int_fixed baseTyWithOffsets_ = 0; // 事前計算統合: invTy + srcPivot + rowOffset + dxOffset // Prepare時のorigin(Process時の差分計算用) int_fixed prepareOriginX_ = 0; @@ -241,7 +241,7 @@ PrepareResponse SourceNode::onPullPrepare(const PrepareRequest& request) { // バイリニア: edgeFadeFlagsに応じて各辺の範囲を拡張 // フェード有効な辺のみ halfPixel 分拡張(フェードアウト領域用) // invA/invCの符号によって、どの辺がstart/endに対応するか変わる - constexpr int32_t halfPixel = 1 << (INT_FIXED_SHIFT - 1); + constexpr int_fixed halfPixel = 1 << (INT_FIXED_SHIFT - 1); // X方向のフェード拡張 int32_t hpAStart = 0, hpAEnd = 0; @@ -300,7 +300,7 @@ PrepareResponse SourceNode::onPullPrepare(const PrepareRequest& request) { // 等倍表示相当(逆行列2x2部分が単位行列)かつ最近傍の場合、 // DDA をスキップし、高速な非アフィンパス(subView参照)を使用 // バイリニア補間時はedgeFade等の処理にDDAが必要なためスキップしない - constexpr int32_t one = 1 << INT_FIXED_SHIFT; + constexpr int_fixed one = 1 << INT_FIXED_SHIFT; bool isTranslationOnly = !useBilinear_ && invA == one && @@ -562,13 +562,13 @@ RenderResponse& SourceNode::pullProcessWithAffine(const RenderRequest& request) void* dstRow = output->data(); // ViewPortのx,yオフセットをQ16.16固定小数点に変換 - int32_t offsetX = static_cast(source_.x) << INT_FIXED_SHIFT; - int32_t offsetY = static_cast(source_.y) << INT_FIXED_SHIFT; + int_fixed offsetX = static_cast(source_.x) << INT_FIXED_SHIFT; + int_fixed offsetY = static_cast(source_.y) << INT_FIXED_SHIFT; if (useBilinear_) { // バイリニア補間(出力はRGBA8_Straight) // 0.5ピクセル減算(ピクセル中心→左上基準への変換) - constexpr int32_t halfPixel = 1 << (INT_FIXED_SHIFT - 1); + constexpr int_fixed halfPixel = 1 << (INT_FIXED_SHIFT - 1); // パレット情報をPixelAuxInfoとして渡す(Index8のパレット展開用) PixelAuxInfo auxInfo; if (palette_) { diff --git a/fleximg/src/fleximg/nodes/vertical_blur_node.h b/fleximg/src/fleximg/nodes/vertical_blur_node.h index 1a85294e..66a64c78 100644 --- a/fleximg/src/fleximg/nodes/vertical_blur_node.h +++ b/fleximg/src/fleximg/nodes/vertical_blur_node.h @@ -58,18 +58,18 @@ class VerticalBlurNode : public Node { static constexpr int kMaxRadius = 127; // 実用上十分、メモリ消費も許容範囲 static constexpr int kMaxPasses = 3; // ガウシアン近似に十分 - void setRadius(int radius) { - radius_ = (radius < 0) ? 0 : (radius > kMaxRadius) ? kMaxRadius : radius; + void setRadius(int_fast16_t radius) { + radius_ = static_cast((radius < 0) ? 0 : (radius > kMaxRadius) ? kMaxRadius : radius); } - void setPasses(int passes) { - passes_ = (passes < 1) ? 1 : (passes > kMaxPasses) ? kMaxPasses : passes; + void setPasses(int_fast16_t passes) { + passes_ = static_cast((passes < 1) ? 1 : (passes > kMaxPasses) ? kMaxPasses : passes); } - int radius() const { return radius_; } - int passes() const { return passes_; } - int kernelSize() const { return radius_ * 2 + 1; } - int totalKernelSize() const { return radius_ * 2 * passes_ + 1; } + int16_t radius() const { return radius_; } + int16_t passes() const { return passes_; } + int_fast16_t kernelSize() const { return radius_ * 2 + 1; } + int_fast16_t totalKernelSize() const { return radius_ * 2 * passes_ + 1; } // ======================================== // Node インターフェース @@ -95,12 +95,12 @@ class VerticalBlurNode : public Node { RenderResponse& onPullProcess(const RenderRequest& request) override; private: - int radius_ = 5; - int passes_ = 1; // 1-3の範囲、デフォルト1 + int16_t radius_ = 5; + int16_t passes_ = 1; // 1-3の範囲、デフォルト1 // スクリーン情報 - int screenWidth_ = 0; - int screenHeight_ = 0; + int16_t screenWidth_ = 0; + int16_t screenHeight_ = 0; Point screenOrigin_; // ======================================== @@ -116,12 +116,12 @@ class VerticalBlurNode : public Node { std::vector colSumG; // 列合計(G×A) std::vector colSumB; // 列合計(B×A) std::vector colSumA; // 列合計(A) - int currentY = 0; // 現在のY座標(pull型用) + int32_t currentY = 0; // 現在のY座標(pull型用) bool cacheReady = false; // キャッシュ初期化済みフラグ // push型用の状態 - int pushInputY = 0; // 入力行カウント - int pushOutputY = 0; // 出力行カウント + int32_t pushInputY = 0; // 入力行カウント + int32_t pushOutputY = 0; // 出力行カウント void clear() { rowCache.clear(); @@ -140,7 +140,7 @@ class VerticalBlurNode : public Node { // パイプラインステージ(passes個、passes=1でもstages_[0]を使用) std::vector stages_; - int cacheWidth_ = 0; + int16_t cacheWidth_ = 0; int_fixed cacheOriginX_ = 0; // キャッシュの基準X座標(pull型用) int_fixed upstreamOriginX_ = 0; // 上流pullProcessのorigin.x(radius=0と同じ出力用) bool upstreamOriginXSet_ = false; // upstreamOriginX_が設定済みかどうか @@ -150,11 +150,11 @@ class VerticalBlurNode : public Node { int16_t sourceHeight_ = 0; // 上流の高さ(拡張前) // push型処理用の状態 - int pushInputY_ = 0; - int pushOutputY_ = 0; - int pushInputWidth_ = 0; - int pushInputHeight_ = 0; - int pushOutputHeight_ = 0; + int32_t pushInputY_ = 0; + int32_t pushOutputY_ = 0; + int16_t pushInputWidth_ = 0; + int16_t pushInputHeight_ = 0; + int16_t pushOutputHeight_ = 0; int_fixed baseOriginX_ = 0; // 基準origin.x(pushPrepareで設定) int_fixed pushInputOriginY_ = 0; int_fixed lastInputOriginY_ = 0; @@ -169,16 +169,16 @@ class VerticalBlurNode : public Node { // 内部実装(宣言のみ) RenderResponse& pullProcessPipeline(Node* upstream, const RenderRequest& request); - void updateStageCache(int stageIndex, Node* upstream, const RenderRequest& request, int newY); - void fetchRowToStageCache(BlurStage& stage, Node* upstream, const RenderRequest& request, int srcY, int cacheIndex); - void fetchRowFromPrevStage(int stageIndex, Node* upstream, const RenderRequest& request, int srcY, int cacheIndex); - void updateStageColSum(BlurStage& stage, int cacheIndex, bool add); - void computeStageOutputRow(BlurStage& stage, ImageBuffer& output, int width); - void initializeStage(BlurStage& stage, int width); - void initializeStages(int width); + void updateStageCache(int_fast16_t stageIndex, Node* upstream, const RenderRequest& request, int_fast16_t newY); + void fetchRowToStageCache(BlurStage& stage, Node* upstream, const RenderRequest& request, int_fast16_t srcY, int_fast16_t cacheIndex); + void fetchRowFromPrevStage(int_fast16_t stageIndex, Node* upstream, const RenderRequest& request, int_fast16_t srcY, int_fast16_t cacheIndex); + void updateStageColSum(BlurStage& stage, int_fast16_t cacheIndex, bool add); + void computeStageOutputRow(BlurStage& stage, ImageBuffer& output, int_fast16_t width); + void initializeStage(BlurStage& stage, int_fast16_t width); + void initializeStages(int_fast16_t width); void propagatePipelineStages(); void emitBlurredLinePipeline(); - void storeInputRowToStageCache(BlurStage& stage, const ImageBuffer& input, int cacheIndex, int xOffset = 0); + void storeInputRowToStageCache(BlurStage& stage, const ImageBuffer& input, int_fast16_t cacheIndex, int_fast16_t xOffset = 0); }; } // namespace FLEXIMG_NAMESPACE @@ -258,7 +258,7 @@ DataRange VerticalBlurNode::getDataRange(const RenderRequest& request) const { // 垂直ブラーでは、出力行Yに対して入力行 Y-expansion から Y+expansion の // X範囲の和集合が必要(expansion = radius * passes) // 特にアフィン変換された画像では、各行のX範囲が異なる可能性がある - int expansion = radius_ * passes_; + int_fast16_t expansion = radius_ * passes_; int16_t startX = INT16_MAX; int16_t endX = INT16_MIN; @@ -332,7 +332,7 @@ PrepareResponse VerticalBlurNode::onPullPrepare(const PrepareRequest& request) { // 垂直ぼかしはY方向に radius * passes 分拡張する // AABBの高さを拡張し、originのYをシフト(上方向に拡大) - int expansion = radius_ * passes_; + int_fast16_t expansion = radius_ * passes_; upstreamResult.height = static_cast(upstreamResult.height + expansion * 2); upstreamResult.origin.y = upstreamResult.origin.y - to_fixed(expansion); @@ -394,11 +394,11 @@ void VerticalBlurNode::onPushProcess(RenderResponse& input, const RenderRequest& // パイプライン方式で処理(passes=1でもstages_[0]を使用) Point inputOrigin = input.origin; - int ks = kernelSize(); + int_fast16_t ks = kernelSize(); // Stage 0に入力行を格納 BlurStage& stage0 = stages_[0]; - int slot0 = stage0.pushInputY % ks; + int_fast16_t slot0 = static_cast(stage0.pushInputY % ks); // 古い行を列合計から減算 if (stage0.pushInputY >= ks) { @@ -413,7 +413,7 @@ void VerticalBlurNode::onPushProcess(RenderResponse& input, const RenderRequest& inputOrigin = input.origin; // consolidate後のoriginを反映 ImageBuffer converted = convertFormat(ImageBuffer(input.buffer()), PixelFormatIDs::RGBA8_Straight); - int xOffset = from_fixed(inputOrigin.x - baseOriginX_); + int_fast16_t xOffset = static_cast(from_fixed(inputOrigin.x - baseOriginX_)); storeInputRowToStageCache(stage0, converted, slot0, xOffset); } stage0.rowOriginX[static_cast(slot0)] = inputOrigin.x; @@ -442,13 +442,13 @@ void VerticalBlurNode::onPushFinalize() { } // パイプライン方式で残りの行を出力(passes=1でもstages_[0]を使用) - int ks = kernelSize(); + int_fast16_t ks = kernelSize(); // 残りの行を出力(下端はゼロパディング扱い) while (pushOutputY_ < pushOutputHeight_) { // Stage 0にゼロ行を追加 BlurStage& stage0 = stages_[0]; - int slot0 = stage0.pushInputY % ks; + int_fast16_t slot0 = static_cast(stage0.pushInputY % ks); if (stage0.pushInputY >= ks) { updateStageColSum(stage0, slot0, false); @@ -489,7 +489,7 @@ RenderResponse& VerticalBlurNode::onPullProcess(const RenderRequest& request) { // ======================================== RenderResponse& VerticalBlurNode::pullProcessPipeline(Node* upstream, const RenderRequest& request) { - int requestY = from_fixed(request.origin.y); + int_fast16_t requestY = static_cast(from_fixed(request.origin.y)); // 注: 各ステージの初期化はupdateStageCache内で行われる // 最終ステージのキャッシュを更新(再帰的に前段ステージも更新される) @@ -531,8 +531,8 @@ RenderResponse& VerticalBlurNode::pullProcessPipeline(Node* upstream, const Rend } // キャッシュ内のオフセットと出力幅を計算(SourceNodeと同じ丸め方式) - int srcStartX = from_fixed_floor(interLeft - cacheLeft); - int srcEndX = from_fixed_ceil(interRight - cacheLeft); + int_fast16_t srcStartX = static_cast(from_fixed_floor(interLeft - cacheLeft)); + int_fast16_t srcEndX = static_cast(from_fixed_ceil(interRight - cacheLeft)); int16_t outputWidth = static_cast(srcEndX - srcStartX); #ifdef FLEXIMG_DEBUG_PERF_METRICS @@ -551,9 +551,9 @@ RenderResponse& VerticalBlurNode::pullProcessPipeline(Node* upstream, const Rend // 最終ステージの列合計から出力行を計算(有効範囲のみ) BlurStage& lastStage = stages_[static_cast(passes_ - 1)]; uint8_t* outRow = static_cast(output.view().data); - int ks = kernelSize(); + int_fast16_t ks = kernelSize(); - for (auto cacheX = static_cast(srcStartX); cacheX < srcEndX; cacheX++) { + for (int_fast16_t cacheX = srcStartX; cacheX < srcEndX; cacheX++) { size_t outOff = static_cast(cacheX - srcStartX) * 4; if (lastStage.colSumA[static_cast(cacheX)] > 0) { @@ -575,9 +575,9 @@ RenderResponse& VerticalBlurNode::pullProcessPipeline(Node* upstream, const Rend return makeResponse(std::move(output), outputOrigin); } -void VerticalBlurNode::updateStageCache(int stageIndex, Node* upstream, const RenderRequest& request, int newY) { +void VerticalBlurNode::updateStageCache(int_fast16_t stageIndex, Node* upstream, const RenderRequest& request, int_fast16_t newY) { BlurStage& stage = stages_[static_cast(stageIndex)]; - int ks = kernelSize(); + int_fast16_t ks = kernelSize(); // このステージへの最初の呼び出し時、currentYを調整してキャッシュを完全に充填 // newY - kernelSize() から開始することで、kernelSize()回のループでキャッシュが充填される @@ -588,11 +588,11 @@ void VerticalBlurNode::updateStageCache(int stageIndex, Node* upstream, const Re if (stage.currentY == newY) return; - int step = (stage.currentY < newY) ? 1 : -1; + int_fast16_t step = (stage.currentY < newY) ? 1 : -1; while (stage.currentY != newY) { - int newSrcY = stage.currentY + step * (radius_ + 1); - int slot = newSrcY % ks; + int_fast16_t newSrcY = static_cast(stage.currentY + step * (radius_ + 1)); + int_fast16_t slot = static_cast(newSrcY % ks); if (slot < 0) slot += ks; // 古い行を列合計から減算 @@ -615,7 +615,7 @@ void VerticalBlurNode::updateStageCache(int stageIndex, Node* upstream, const Re } void VerticalBlurNode::fetchRowToStageCache(BlurStage& stage, Node* upstream, const RenderRequest& request, - int srcY, int cacheIndex) { + int_fast16_t srcY, int_fast16_t cacheIndex) { // キャッシュ幅・原点を使用してリクエスト作成 RenderRequest upstreamReq; upstreamReq.width = static_cast(cacheWidth_); @@ -658,10 +658,10 @@ void VerticalBlurNode::fetchRowToStageCache(BlurStage& stage, Node* upstream, co // 入力データをキャッシュにコピー(オフセット考慮) // cacheOriginX_(更新済み)を使用して正しい座標でコピーする // result.origin.x - cacheOriginX_ = 入力バッファ左端 - キャッシュ左端 - int srcOffsetX = from_fixed(result.origin.x - cacheOriginX_); - int dstStartX = std::max(0, srcOffsetX); - int srcStartX = std::max(0, -srcOffsetX); - int copyWidth = std::min(static_cast(srcView.width) - srcStartX, cacheWidth_ - dstStartX); + int_fast16_t srcOffsetX = static_cast(from_fixed(result.origin.x - cacheOriginX_)); + int_fast16_t dstStartX = std::max(0, srcOffsetX); + int_fast16_t srcStartX = std::max(0, -srcOffsetX); + int_fast16_t copyWidth = std::min(static_cast(srcView.width) - srcStartX, cacheWidth_ - dstStartX); if (copyWidth > 0) { const uint8_t* srcPtr = static_cast(srcView.data) + srcStartX * 4; std::memcpy(static_cast(dstView.data) + dstStartX * 4, srcPtr, static_cast(copyWidth) * 4); @@ -670,8 +670,8 @@ void VerticalBlurNode::fetchRowToStageCache(BlurStage& stage, Node* upstream, co (void)request; // 現在は未使用(将来の拡張用) } -void VerticalBlurNode::fetchRowFromPrevStage(int stageIndex, Node* upstream, const RenderRequest& request, - int srcY, int cacheIndex) { +void VerticalBlurNode::fetchRowFromPrevStage(int_fast16_t stageIndex, Node* upstream, const RenderRequest& request, + int_fast16_t srcY, int_fast16_t cacheIndex) { BlurStage& stage = stages_[static_cast(stageIndex)]; BlurStage& prevStage = stages_[static_cast(stageIndex - 1)]; @@ -686,7 +686,7 @@ void VerticalBlurNode::fetchRowFromPrevStage(int stageIndex, Node* upstream, con int16_t startX = static_cast(cacheWidth_); int16_t endX = 0; - int ks = kernelSize(); + int_fast16_t ks = kernelSize(); for (size_t x = 0; x < static_cast(cacheWidth_); x++) { size_t off = x * 4; if (prevStage.colSumA[x] > 0) { @@ -706,9 +706,9 @@ void VerticalBlurNode::fetchRowFromPrevStage(int stageIndex, Node* upstream, con stage.rowDataRange[static_cast(cacheIndex)] = DataRange{startX, endX}; } -void VerticalBlurNode::updateStageColSum(BlurStage& stage, int cacheIndex, bool add) { +void VerticalBlurNode::updateStageColSum(BlurStage& stage, int_fast16_t cacheIndex, bool add) { const uint8_t* row = static_cast(stage.rowCache[static_cast(cacheIndex)].view().data); - int sign = add ? 1 : -1; + int_fast16_t sign = add ? 1 : -1; for (size_t x = 0; x < static_cast(cacheWidth_); x++) { size_t off = x * 4; int32_t a = row[off + 3] * sign; @@ -722,9 +722,9 @@ void VerticalBlurNode::updateStageColSum(BlurStage& stage, int cacheIndex, bool } } -void VerticalBlurNode::computeStageOutputRow(BlurStage& stage, ImageBuffer& output, int width) { +void VerticalBlurNode::computeStageOutputRow(BlurStage& stage, ImageBuffer& output, int_fast16_t width) { uint8_t* outRow = static_cast(output.view().data); - int ks = kernelSize(); + int_fast16_t ks = kernelSize(); for (size_t x = 0; x < static_cast(width); x++) { size_t off = x * 4; if (stage.colSumA[x] > 0) { @@ -742,7 +742,7 @@ void VerticalBlurNode::computeStageOutputRow(BlurStage& stage, ImageBuffer& outp // キャッシュ管理 // ======================================== -void VerticalBlurNode::initializeStage(BlurStage& stage, int width) { +void VerticalBlurNode::initializeStage(BlurStage& stage, int_fast16_t width) { size_t cacheRows = static_cast(kernelSize()); // radius*2+1 stage.rowCache.resize(cacheRows); stage.rowOriginX.assign(cacheRows, 0); @@ -759,8 +759,8 @@ void VerticalBlurNode::initializeStage(BlurStage& stage, int width) { stage.cacheReady = false; } -void VerticalBlurNode::initializeStages(int width) { - cacheWidth_ = width; +void VerticalBlurNode::initializeStages(int_fast16_t width) { + cacheWidth_ = static_cast(width); stages_.resize(static_cast(passes_)); for (size_t i = 0; i < static_cast(passes_); i++) { initializeStage(stages_[i], width); @@ -772,7 +772,7 @@ void VerticalBlurNode::initializeStages(int width) { // ======================================== void VerticalBlurNode::propagatePipelineStages() { - int ks = kernelSize(); + int_fast16_t ks = kernelSize(); // Stage 0の出力を計算してStage 1以降に伝播 for (int_fast16_t s = 1; s < passes_; s++) { @@ -800,7 +800,7 @@ void VerticalBlurNode::propagatePipelineStages() { prevStage.pushOutputY++; // 現段ステージのキャッシュに格納 - int slot = stage.pushInputY % ks; + int_fast16_t slot = static_cast(stage.pushInputY % ks); // 古い行を列合計から減算 if (stage.pushInputY >= ks) { @@ -829,7 +829,7 @@ void VerticalBlurNode::propagatePipelineStages() { void VerticalBlurNode::emitBlurredLinePipeline() { BlurStage& lastStage = stages_[static_cast(passes_ - 1)]; - int ks = kernelSize(); + int_fast16_t ks = kernelSize(); ImageBuffer output(cacheWidth_, 1, PixelFormatIDs::RGBA8_Straight, InitPolicy::Uninitialized); @@ -853,7 +853,7 @@ void VerticalBlurNode::emitBlurredLinePipeline() { // lastInputOriginY_は最後に受信した入力行のorigin.y // 出力行のorigin.yは、入力行との差分を減算して求める int_fixed originX = baseOriginX_; - int rowDiff = (stages_[0].pushInputY - 1) - pushOutputY_; + int32_t rowDiff = (stages_[0].pushInputY - 1) - pushOutputY_; int_fixed originY = lastInputOriginY_ - to_fixed(rowDiff); RenderRequest outReq; @@ -871,12 +871,12 @@ void VerticalBlurNode::emitBlurredLinePipeline() { } } -void VerticalBlurNode::storeInputRowToStageCache(BlurStage& stage, const ImageBuffer& input, int cacheIndex, int xOffset) { +void VerticalBlurNode::storeInputRowToStageCache(BlurStage& stage, const ImageBuffer& input, int_fast16_t cacheIndex, int_fast16_t xOffset) { ViewPort srcView = input.view(); ViewPort dstView = stage.rowCache[static_cast(cacheIndex)].view(); const uint8_t* srcData = static_cast(srcView.data); uint8_t* dstData = static_cast(dstView.data); - int srcWidth = static_cast(srcView.width); + int_fast16_t srcWidth = static_cast(srcView.width); // キャッシュをゼロクリア std::memset(dstData, 0, static_cast(cacheWidth_) * 4); @@ -884,9 +884,9 @@ void VerticalBlurNode::storeInputRowToStageCache(BlurStage& stage, const ImageBu // コピー範囲の計算(pull pathのfetchRowToStageCacheと同じロジック) // xOffset > 0: 入力がキャッシュより右にある → cache[xOffset]に書き込み // xOffset < 0: 入力がキャッシュより左にある → source[-xOffset]から読み込み - int dstStart = std::max(0, xOffset); - int srcStart = std::max(0, -xOffset); - int copyWidth = std::min(srcWidth - srcStart, cacheWidth_ - dstStart); + int_fast16_t dstStart = std::max(0, xOffset); + int_fast16_t srcStart = std::max(0, -xOffset); + int_fast16_t copyWidth = std::min(srcWidth - srcStart, cacheWidth_ - dstStart); if (copyWidth > 0) { std::memcpy(dstData + dstStart * 4, srcData + srcStart * 4, static_cast(copyWidth) * 4); diff --git a/fleximg/src/fleximg/operations/canvas_utils.h b/fleximg/src/fleximg/operations/canvas_utils.h index dc41564a..1a891b64 100644 --- a/fleximg/src/fleximg/operations/canvas_utils.h +++ b/fleximg/src/fleximg/operations/canvas_utils.h @@ -24,7 +24,7 @@ namespace canvas_utils { // - 全面を画像で埋める場合: DefaultInitPolicy(初期化スキップ可) // - 部分的な描画の場合: InitPolicy::Zero(透明で初期化) // alloc: メモリアロケータ(nullptrの場合はDefaultAllocator使用) -inline ImageBuffer createCanvas(int width, int height, +inline ImageBuffer createCanvas(int_fast16_t width, int_fast16_t height, InitPolicy init = DefaultInitPolicy, core::memory::IAllocator* alloc = nullptr) { return ImageBuffer(width, height, PixelFormatIDs::RGBA8_Straight, init, alloc); @@ -39,25 +39,25 @@ inline void placeFirst(ViewPort& canvas, int_fixed canvasOriginX, int_fixed canv // 新座標系: originはバッファ左上のワールド座標 // srcをcanvasに配置する際のオフセット = src左端 - canvas左端 - int offsetX = from_fixed(srcOriginX - canvasOriginX); - int offsetY = from_fixed(srcOriginY - canvasOriginY); + auto offsetX = static_cast(from_fixed(srcOriginX - canvasOriginX)); + auto offsetY = static_cast(from_fixed(srcOriginY - canvasOriginY)); // クリッピング範囲を計算 // offsetX > 0: srcがcanvasより右にある → canvas[offsetX]に書き込み // offsetX < 0: srcがcanvasより左にある → src[-offsetX]から読み込み - int srcStartX = std::max(0, -offsetX); - int srcStartY = std::max(0, -offsetY); - int dstStartX = std::max(0, offsetX); - int dstStartY = std::max(0, offsetY); - int copyWidth = std::min(src.width - srcStartX, canvas.width - dstStartX); - int copyHeight = std::min(src.height - srcStartY, canvas.height - dstStartY); + auto srcStartX = std::max(0, -offsetX); + auto srcStartY = std::max(0, -offsetY); + auto dstStartX = std::max(0, offsetX); + auto dstStartY = std::max(0, offsetY); + auto copyWidth = std::min(src.width - srcStartX, canvas.width - dstStartX); + auto copyHeight = std::min(src.height - srcStartY, canvas.height - dstStartY); if (copyWidth <= 0 || copyHeight <= 0) return; // 同一フォーマット → memcpy if (src.formatID == canvas.formatID) { size_t bytesPerPixel = static_cast(src.formatID->bytesPerPixel); - for (int y = 0; y < copyHeight; y++) { + for (int_fast16_t y = 0; y < copyHeight; y++) { const void* srcRow = src.pixelAt(srcStartX, srcStartY + y); void* dstRow = canvas.pixelAt(dstStartX, dstStartY + y); std::memcpy(dstRow, srcRow, static_cast(copyWidth) * bytesPerPixel); @@ -67,10 +67,10 @@ inline void placeFirst(ViewPort& canvas, int_fixed canvasOriginX, int_fixed canv // キャンバスがRGBA8_Straight → toStraight関数を使用 if (canvas.formatID == PixelFormatIDs::RGBA8_Straight && src.formatID->toStraight) { - for (int y = 0; y < copyHeight; y++) { + for (int_fast16_t y = 0; y < copyHeight; y++) { const void* srcRow = src.pixelAt(srcStartX, srcStartY + y); void* dstRow = canvas.pixelAt(dstStartX, dstStartY + y); - src.formatID->toStraight(dstRow, srcRow, copyWidth, nullptr); + src.formatID->toStraight(dstRow, srcRow, static_cast(copyWidth), nullptr); } return; } diff --git a/fleximg/src/fleximg/operations/filters.h b/fleximg/src/fleximg/operations/filters.h index 417f2f50..d270738b 100644 --- a/fleximg/src/fleximg/operations/filters.h +++ b/fleximg/src/fleximg/operations/filters.h @@ -63,14 +63,14 @@ namespace filters { // ======================================================================== void brightness_line(uint8_t* pixels, int_fast16_t count, const LineFilterParams& params) { - int adjustment = static_cast(params.value1 * 255.0f); + auto adjustment = static_cast(params.value1 * 255.0f); for (int_fast16_t x = 0; x < count; x++) { int_fast16_t pixelOffset = x * 4; // RGB各チャンネルに明るさ調整を適用 - for (int c = 0; c < 3; c++) { - int value = static_cast(pixels[pixelOffset + c]) + adjustment; - pixels[pixelOffset + c] = static_cast(std::max(0, std::min(255, value))); + for (int_fast16_t c = 0; c < 3; c++) { + auto value = static_cast(pixels[pixelOffset + c] + adjustment); + pixels[pixelOffset + c] = static_cast(std::max(0, std::min(255, value))); } // Alphaはそのまま維持 }