/* Python-rgbcx Texture Compression Library Copyright (C) 2021 Andrew Cassidy Partially derived from rgbcx.h written by Richard Geldreich and licenced under the public domain This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #pragma once #include #include #include #include #include #include "Color.h" #include "ndebug.h" namespace rgbcx { template class RowView { public: RowView(S *start, int pixel_stride = 1) : start(start), pixel_stride(pixel_stride) {} constexpr S &operator[](size_t index) noexcept(ndebug) { assert(index < N); return start[index * pixel_stride]; } constexpr const S &operator[](size_t index) const noexcept(ndebug) { assert(index < N); return start[index * pixel_stride]; } constexpr int size() noexcept { return N; } S *const start; const int pixel_stride; }; template class BlockView { public: using Row = RowView; BlockView(S *start, int row_stride = N, int pixel_stride = 1) : start(start), row_stride(row_stride), pixel_stride(pixel_stride) {} constexpr Row operator[](unsigned index) noexcept(ndebug) { assert(index < M); return RowView(&start[row_stride * (int)index], pixel_stride); } constexpr int width() noexcept { return N; } constexpr int height() noexcept { return M; } constexpr int size() noexcept { return N * M; } constexpr S &get(unsigned x, unsigned y) noexcept(ndebug) { assert(x < N); assert(y < M); return start[(row_stride * (int)y) + (pixel_stride * (int)x)]; } constexpr S get(unsigned x, unsigned y) const noexcept(ndebug) { assert(x < N); assert(y < M); return start[(row_stride * (int)y) + (pixel_stride * (int)x)]; } constexpr void set(unsigned x, unsigned y, S value) noexcept(ndebug) { assert(x < N); assert(y < M); start[(row_stride * (int)y) + (pixel_stride * (int)x)] = value; } constexpr std::array flatten() noexcept { std::array result; for (int x = 0; x < N; x++) { for (int y = 0; y < M; y++) { result[x + (N * y)] = start[(row_stride * y) + (pixel_stride * x)]; } } return result; } S *const start; const int row_stride; const int pixel_stride; }; template class ColorBlockView : public BlockView { public: using Base = BlockView; using ChannelView = BlockView; ColorBlockView(Color *start, int row_stride = N, int pixel_stride = 1) : Base(start, row_stride, pixel_stride) {} constexpr ChannelView GetChannel(uint8_t index) noexcept(ndebug) { assert(index < 4U); auto channelStart = reinterpret_cast(Base::start) + index; return ChannelView(channelStart, Base::row_stride * 4, Base::pixel_stride * 4); } void SetRGB(unsigned x, unsigned y, Color value) noexcept(ndebug) { Base::get(x, y).SetRGB(value); } }; using Color4x4 = ColorBlockView<4, 4>; } // namespace rgbcx