diff --git a/CMakeLists.txt b/CMakeLists.txt index 5e52e5bd..5409ad57 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -149,7 +149,7 @@ set(TEV_SOURCES include/tev/imageio/ImageLoader.h src/imageio/ImageLoader.cpp include/tev/imageio/ImageSaver.h src/imageio/ImageSaver.cpp include/tev/imageio/PfmImageLoader.h src/imageio/PfmImageLoader.cpp - include/tev/imageio/QoiImageLoader.h src/imageio/QoiImageLoader.cpp src/imageio/QoiImplementation.c + include/tev/imageio/QoiImageLoader.h src/imageio/QoiImageLoader.cpp include/tev/imageio/QoiImageSaver.h src/imageio/QoiImageSaver.cpp include/tev/imageio/StbiHdrImageSaver.h src/imageio/StbiHdrImageSaver.cpp include/tev/imageio/StbiImageLoader.h src/imageio/StbiImageLoader.cpp diff --git a/dependencies/qoi b/dependencies/qoi index fda5167d..4bc071df 160000 --- a/dependencies/qoi +++ b/dependencies/qoi @@ -1 +1 @@ -Subproject commit fda5167d76d05de67b821c787824c8d177fd22d8 +Subproject commit 4bc071df7811c9c42e4a98aca13ac3dd0c98a576 diff --git a/src/imageio/QoiImageLoader.cpp b/src/imageio/QoiImageLoader.cpp index be0639b7..fd295b93 100644 --- a/src/imageio/QoiImageLoader.cpp +++ b/src/imageio/QoiImageLoader.cpp @@ -5,6 +5,7 @@ #include #define QOI_NO_STDIO +#define QOI_IMPLEMENTATION #include using namespace filesystem; @@ -66,42 +67,27 @@ Task> QoiImageLoader::load(istream& iStream, const path&, cons resultData.channels = makeNChannels(numChannels, size); resultData.hasPremultipliedAlpha = false; - // QOI uses a bitmap 0000rgba for 'colorspace', where a bit 1 indicates linear, - // however, it is purely informative (meaning it has no effect in en/decoding). - // Thus, we interpret the default 0x0 value to mean: sRGB encoded RGB channels - // with linear encoded alpha channel: - bool isSRGBChannel[4] = {true, true, true, false}; - switch (desc.colorspace) { - case 0x0: // case QOI_SRGB: - case QOI_SRGB_LINEAR_ALPHA: - break; - case QOI_LINEAR: - isSRGBChannel[0] = false; - isSRGBChannel[1] = false; - isSRGBChannel[2] = false; - break; - default: - // FIXME: should we handle "per-channel" encoding information or just the two cases above? - // Another option is assuming all values except for QOI_LINEAR mean QOI_SRGB_LINEAR_ALPHA. - // throw invalid_argument{tfm::format("Unsupported QOI colorspace: %X", desc.colorspace)}; - isSRGBChannel[0] = (desc.colorspace & 0x8) == 0x0; // R channel => 0000rgba & 1000 = r000 - isSRGBChannel[1] = (desc.colorspace & 0x4) == 0x0; // G channel => 0000rgba & 0100 = 0g00 - isSRGBChannel[2] = (desc.colorspace & 0x2) == 0x0; // B channel => 0000rgba & 0010 = 00b0 - isSRGBChannel[3] = (desc.colorspace & 0x1) == 0x0; // A channel => 0000rgba & 0001 = 000a - break; - } - - co_await gThreadPool->parallelForAsync(0, numPixels, [&](size_t i) { - auto typedData = reinterpret_cast(decodedData); - size_t baseIdx = i * numChannels; - for (int c = 0; c < numChannels; ++c) { - if (isSRGBChannel[c]) { - resultData.channels[c].at(i) = toLinear((typedData[baseIdx + c]) / 255.0f); - } else { + if (desc.colorspace == QOI_LINEAR) { + co_await gThreadPool->parallelForAsync(0, numPixels, [&](size_t i) { + auto typedData = reinterpret_cast(decodedData); + size_t baseIdx = i * numChannels; + for (int c = 0; c < numChannels; ++c) { resultData.channels[c].at(i) = (typedData[baseIdx + c]) / 255.0f; } - } - }, priority); + }, priority); + } else { + co_await gThreadPool->parallelForAsync(0, numPixels, [&](size_t i) { + auto typedData = reinterpret_cast(decodedData); + size_t baseIdx = i * numChannels; + for (int c = 0; c < numChannels; ++c) { + if (c == 3) { + resultData.channels[c].at(i) = (typedData[baseIdx + c]) / 255.0f; + } else { + resultData.channels[c].at(i) = toLinear((typedData[baseIdx + c]) / 255.0f); + } + } + }, priority); + } co_return result; } diff --git a/src/imageio/QoiImageSaver.cpp b/src/imageio/QoiImageSaver.cpp index 959d1b89..bf1b6686 100644 --- a/src/imageio/QoiImageSaver.cpp +++ b/src/imageio/QoiImageSaver.cpp @@ -25,7 +25,7 @@ void QoiImageSaver::save(ostream& oStream, const path&, const vector& data .width = static_cast(imageSize.x()), .height = static_cast(imageSize.y()), .channels = static_cast(nChannels), - .colorspace = QOI_SRGB_LINEAR_ALPHA, + .colorspace = QOI_SRGB, }; int sizeInBytes = 0; void *encodedData = qoi_encode(data.data(), &desc, &sizeInBytes); diff --git a/src/imageio/QoiImplementation.c b/src/imageio/QoiImplementation.c deleted file mode 100644 index 89ed691d..00000000 --- a/src/imageio/QoiImplementation.c +++ /dev/null @@ -1,11 +0,0 @@ -// This file was developed by Tiago Chaves & Thomas Müller . -// It is published under the BSD 3-Clause License within the LICENSE file. - -#define QOI_NO_STDIO -#define QOI_IMPLEMENTATION -#include - -// This is kept in a separate file to make sure that qoi.h is compiled as C99 -// code instead of C++ as converting 'void*' to 'char*' would require casting. -// We define QOI_NO_STDIO because we are using qoi_decode/qoi_encode directly, -// hence, we do not need qoi_read/qoi_write to be include.