/* Python-rgbcx Texture Compression Library Copyright (C) 2021 Andrew Cassidy Partially derived from rgbcx.h written by Richard Geldreich 2020 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 "BlockView.h" #include "ndebug.h" #include "util.h" namespace rgbcx { template class BlockDecoder { public: using DecodedBlock = ColorBlockView; using EncodedBlock = B; BlockDecoder() noexcept = default; virtual ~BlockDecoder() noexcept = default; virtual void DecodeBlock(DecodedBlock dest, EncodedBlock *const block) const noexcept(ndebug) = 0; std::vector DecodeImage(uint8_t *bytes, unsigned image_width, unsigned image_height) { unsigned block_width = maximum(1U, ((image_width + 3) / 4)); unsigned block_height = maximum(1U, ((image_height + 3) / 4)); using Row = typename DecodedBlock::Row; auto image = std::vector(block_width * block_height * N * M); auto blocks = reinterpret_cast(bytes); // from experimentation, multithreading this using OpenMP actually makes decoding slower // due to thread creation/teardown taking longer than the decoding process itself. // As a result, this is left as a serial operation despite being embarassingly parallelizable for (unsigned y = 0; y < block_height; y++) { for (unsigned x = 0; x < block_width; x++) { unsigned pixel_x = x * N; unsigned pixel_y = y * M; assert(pixel_x >= 0); assert(pixel_y >= 0); assert(pixel_y + M <= image_height); assert(pixel_x + N <= image_width); unsigned top_left = pixel_x + (pixel_y * image_width); auto rows = std::array(); for (unsigned i = 0; i < M; i++) { rows[i] = reinterpret_cast(&image[top_left + i * image_width]); } auto dest = DecodedBlock(&image[top_left], image_width); DecodeBlock(dest, &blocks[x + block_width * y]); } } return image; } }; } // namespace rgbcx