From a2b056d45682b16941ffff3ac99cc97815843d28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaakko=20Kera=CC=88nen?= Date: Thu, 5 Apr 2018 22:20:11 +0300 Subject: [PATCH] libgui|Image: Added more image manipulation methods --- doomsday/libs/gui/include/de/graphics/image.h | 11 +++ doomsday/libs/gui/src/graphics/image.cpp | 71 ++++++++++++++++++- 2 files changed, 81 insertions(+), 1 deletion(-) diff --git a/doomsday/libs/gui/include/de/graphics/image.h b/doomsday/libs/gui/include/de/graphics/image.h index bb37679621..b333e5769a 100644 --- a/doomsday/libs/gui/include/de/graphics/image.h +++ b/doomsday/libs/gui/include/de/graphics/image.h @@ -93,6 +93,14 @@ class LIBGUI_PUBLIC Image : public ISerializable Image(Image const &other); Image(QImage const &image); + /** + * Constructs an image with uninitialized contents. + * + * @param size Size of the image. + * @param format Data format. + */ + Image(Size const &size, Format format); + /** * Constructs an image, taking a copy of the pixel data. * @@ -180,6 +188,9 @@ class LIBGUI_PUBLIC Image : public ISerializable Image multiplied(Image const &factorImage) const; Image multiplied(Color const &color) const; Image colorized(Color const &color) const; + Image invertedColor() const; + Image mixed(Image const &low, Image const &high) const; + Image withAlpha(Image const &grayscale) const; // Implements ISerializable. void operator >> (Writer &to) const; diff --git a/doomsday/libs/gui/src/graphics/image.cpp b/doomsday/libs/gui/src/graphics/image.cpp index 511325c50f..671d4919e5 100644 --- a/doomsday/libs/gui/src/graphics/image.cpp +++ b/doomsday/libs/gui/src/graphics/image.cpp @@ -346,7 +346,7 @@ DENG2_PIMPL(Image) size = Size(img.width(), img.height()); } - Impl(Public * i, Impl const &other) + Impl(Public *i, Impl const &other) : Base(i) , format(other.format) , size(other.size) @@ -356,6 +356,12 @@ DENG2_PIMPL(Image) , pointRatio(other.pointRatio) {} + Impl(Public *i, Size const &imgSize, Format imgFormat) + : Base(i), format(imgFormat), size(imgSize) + { + pixels.resize(i->stride() * imgSize.y); + } + Impl(Public *i, Size const &imgSize, Format imgFormat, IByteArray const &imgPixels) : Base(i), format(imgFormat), size(imgSize), pixels(imgPixels) {} @@ -375,6 +381,10 @@ Image::Image(Image const &other) Image::Image(QImage const &image) : d(new Impl(this, image)) {} +Image::Image(Size const &size, Format format) + : d(new Impl(this, size, format)) +{} + Image::Image(Size const &size, Format format, IByteArray const &pixels) : d(new Impl(this, size, format, pixels)) {} @@ -734,6 +744,65 @@ Image Image::colorized(Color const &color) const return copy; } +Image Image::invertedColor() const +{ + QImage img = toQImage().convertToFormat(QImage::Format_ARGB32); + img.invertPixels(); + return img; +} + +Image Image::mixed(Image const &low, Image const &high) const +{ + DENG2_ASSERT(size() == low.size()); + DENG2_ASSERT(size() == high.size()); + + const QImage lowImg = low.toQImage(); + const QImage highImg = high.toQImage(); + + QImage mix = toQImage().convertToFormat(QImage::Format_ARGB32); + for (duint y = 0; y < height(); ++y) + { + duint32 *ptr = reinterpret_cast(mix.bits() + y * mix.bytesPerLine()); + for (duint x = 0; x < width(); ++x) + { + duint mb = *ptr & 0xff; + duint mg = (*ptr & 0xff00) >> 8; + duint mr = (*ptr & 0xff0000) >> 16; + duint ma = (*ptr & 0xff000000) >> 24; + + const QRgb lowColor = lowImg .pixel(x, y); + const QRgb highColor = highImg.pixel(x, y); + + int red = (qRed(highColor) * mr + qRed(lowColor) * (255 - mr)) / 255; + int green = (qGreen(highColor) * mg + qGreen(lowColor) * (255 - mg)) / 255; + int blue = (qBlue(highColor) * mb + qBlue(lowColor) * (255 - mb)) / 255; + int alpha = (qAlpha(highColor) * ma + qAlpha(lowColor) * (255 - ma)) / 255; + + *ptr = blue | (green << 8) | (red << 16) | (alpha << 24); + + ptr++; + } + } + return mix; +} + +Image Image::withAlpha(Image const &grayscale) const +{ + DENG2_ASSERT(size() == grayscale.size()); + const QImage alpha = grayscale.toQImage(); + QImage img = toQImage().convertToFormat(QImage::Format_ARGB32); + for (duint y = 0; y < height(); ++y) + { + duint32 *ptr = reinterpret_cast(img.bits() + y * img.bytesPerLine()); + for (duint x = 0; x < width(); ++x) + { + *ptr &= 0x00ffffff; + *ptr++ |= qRed(alpha.pixel(x, y)) << 24; + } + } + return img; +} + void Image::operator >> (Writer &to) const { to << duint8(d->format);