From f0185eec96deb8b19f155a4a6c6af3a00afc9dc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaakko=20Ker=C3=A4nen?= Date: Wed, 30 Mar 2016 09:39:31 +0300 Subject: [PATCH] libgui|Image: Converting indexed image data to plain RGBA --- .../sdk/libgui/include/de/graphics/image.h | 20 +++++++ doomsday/sdk/libgui/src/graphics/image.cpp | 56 +++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/doomsday/sdk/libgui/include/de/graphics/image.h b/doomsday/sdk/libgui/include/de/graphics/image.h index 6fe02699bf..4e81a8e154 100644 --- a/doomsday/sdk/libgui/include/de/graphics/image.h +++ b/doomsday/sdk/libgui/include/de/graphics/image.h @@ -173,6 +173,26 @@ class LIBGUI_PUBLIC Image : public ISerializable /// @copydoc fromData() static Image fromData(Block const &data, String const &formatHint = ""); + static Image fromIndexedData(Image::Size const &size, IByteArray const &image, + IByteArray const &palette); + + /** + * Converts a color indexed 8-bit image to RGBA_8888. + * + * @param size Dimensions of the image. + * @param imageAndMask Image content. This is w*h 8-bit palette indices followed + * by w*h 8-bit alpha components, i.e., the alpha mask is + * stored as a separate layer following the indices. + * @param palette RGB palette containing 8-bit color triplets. The size of the + * palette must be big enough to contain all the color indices + * used in the image data. + * + * @return Image in RGBA_8888 format. + */ + static Image fromMaskedIndexedData(Image::Size const &size, + IByteArray const &imageAndMask, + IByteArray const &palette); + /** * Attempts to recognize if a file contains a supported image content format. * @param file File whose contents to recognize. diff --git a/doomsday/sdk/libgui/src/graphics/image.cpp b/doomsday/sdk/libgui/src/graphics/image.cpp index 3883e77b4e..33034082df 100644 --- a/doomsday/sdk/libgui/src/graphics/image.cpp +++ b/doomsday/sdk/libgui/src/graphics/image.cpp @@ -803,6 +803,62 @@ Image Image::fromData(Block const &data, String const &formatHint) return QImage::fromData(data).convertToFormat(QImage::Format_ARGB32); } +Image Image::fromIndexedData(Size const &size, IByteArray const &image, IByteArray const &palette) +{ + QImage rgba(size.x, size.y, QImage::Format_ARGB32); + + // Process the source data by row. + Block color(size.x); + for(duint y = 0; y < size.y; ++y) + { + duint32 *dest = reinterpret_cast(rgba.bits() + y * rgba.bytesPerLine()); + + image.get(size.x * y, color.data(), color.size()); + auto const *srcColor = color.dataConst(); + + for(duint x = 0; x < size.x; ++x) + { + duint8 paletteColor[3]; + palette.get(*srcColor++ * 3, paletteColor, 3); + *dest++ = qRgba(paletteColor[0], paletteColor[1], paletteColor[2], 255); + } + } + + return rgba; +} + +Image Image::fromMaskedIndexedData(Size const &size, IByteArray const &imageAndMask, + IByteArray const &palette) +{ + duint const layerSize = size.x * size.y; + + QImage rgba(size.x, size.y, QImage::Format_ARGB32); + + // Process the source data by row. + Block color(size.x); + Block alpha(size.x); + + for(duint y = 0; y < size.y; ++y) + { + duint32 *dest = reinterpret_cast(rgba.bits() + y * rgba.bytesPerLine()); + + imageAndMask.get(size.x * y, color.data(), color.size()); + imageAndMask.get(size.x * y + layerSize, alpha.data(), alpha.size()); + + auto const *srcColor = color.dataConst(); + auto const *srcAlpha = color.dataConst(); + + for(duint x = 0; x < size.x; ++x) + { + duint8 paletteColor[3]; + palette.get(*srcColor++ * 3, paletteColor, 3); + *dest++ = qRgba(paletteColor[0], paletteColor[1], paletteColor[2], *srcAlpha++); + } + } + + return rgba; +} + bool Image::recognize(File const &file) { String const ext = file.name().fileNameExtension().toLower();