C
Qt Quick Ultralite traveo_t2g_effects Example
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial
#include "desaturation.h"
#include <qul/image.h>
#include <platform/platform.h>
#include <qul/private/texture.h>
#include <qul/private/rasterbuffer.h>
#include <platforminterface/log.h>
#include <cstring>
#include <memory>
#ifdef QUL_TVIIC_PLATFORM
#include <sm_util.h>
#include <pe_matrix.h>
#include "cygfx.h"
#else
#include <QImage>
#include <QPainter>
#include <QVector>
#include "desktop.h"
#endif
#include <qul/private/unicodestring.h>
#include <qul/private/image_p.h>
Qul::PlatformInterface::Rect DesaturationDelegate::boundingRect(Qul::PlatformInterface::Size) const
{
if (source.value().textureCount() != 1) {
Qul::PlatformInterface::log("TVII effects: desaturation: Unexpected texture count %i\r\n",
source.value().textureCount());
std::terminate();
}
auto texture = source.value().texture();
return Qul::PlatformInterface::Rect(0, 0, texture.width(), texture.height());
}
#ifndef QUL_TVIIC_PLATFORM
QImage desaturated(const QImage &source, float saturation)
{
QImage result = source.convertToFormat(QImage::Format_ARGB32_Premultiplied);
uint32_t *bits = reinterpret_cast<uint32_t *>(result.bits());
for (int y = 0; y < result.height(); ++y) {
for (int x = 0; x < result.width(); ++x) {
uint32_t pixel = bits[x];
uint32_t gray = qGray(pixel);
int red = qRed(pixel) * saturation + gray * (1 - saturation);
int green = qGreen(pixel) * saturation + gray * (1 - saturation);
int blue = qBlue(pixel) * saturation + gray * (1 - saturation);
int alpha = qAlpha(pixel);
bits[x] = qRgba(red, green, blue, alpha);
}
bits += result.bytesPerLine() / 4;
}
return result;
}
#endif
void DesaturationDelegate::saturationChanged()
{
update();
}
void DesaturationDelegate::paint(Qul::PlatformInterface::DrawingDevice *device,
const Qul::PlatformInterface::Rect &clip,
const Qul::PlatformInterface::Transform &transform,
Qul::PlatformInterface::Size,
float opacity) const
{
float saturationValue = saturation.value();
auto texture = source.value().texture();
if (!m_initialized) {
#ifdef QUL_TVIIC_PLATFORM
CyGfx::loadSurface(&m_source, texture);
#endif
m_initialized = true;
}
#ifdef QUL_TVIIC_PLATFORM
void **platformContext = static_cast<void **>(device->platformContext());
CYGFX_BE_CONTEXT ctx = static_cast<CYGFX_BE_CONTEXT>(platformContext[0]);
CYGFX_ERROR ret = CYGFX_OK;
Mat3x3 matrix{transform.m11(),
transform.m12(),
transform.m13(),
transform.m21(),
transform.m22(),
transform.m23(),
transform.dx(),
transform.dy(),
transform.m33()};
bool hasClipping = false;
if (clip != Qul::PlatformInterface::Rect(0, 0, device->width(), device->height())) {
// Blend only in clip area
UTIL_SUCCESS(ret,
CyGfx_BeSetSurfAttribute(ctx, CYGFX_BE_TARGET_STORE, CYGFX_BE_SURF_ATTR_USE_CLIPPING, CYGFX_TRUE));
UTIL_SUCCESS(ret,
CyGfx_BeActiveArea(ctx, CYGFX_BE_TARGET_STORE, clip.x(), clip.y(), clip.width(), clip.height()));
}
UTIL_SUCCESS(ret, CyGfx_BeBindSurface(ctx, CYGFX_BE_TARGET_SRC, m_source));
if (!Qul::Private::qFuzzyCompare(opacity, 1.0f)) {
UTIL_SUCCESS(ret,
CyGfx_BeSetSurfAttribute(ctx,
CYGFX_BE_TARGET_SRC,
CYGFX_BE_SURF_ATTR_COLOR,
CYGFX_SM_COLOR_TO_RGBA(255, 255, 255, int(255 * opacity))));
UTIL_SUCCESS(ret, CyGfx_BeSetSurfAttribute(ctx, CYGFX_BE_TARGET_SRC, CYGFX_BE_SURF_ATTR_ALPHAMULTI, CYGFX_TRUE));
}
Mat4x3 colorMatrix;
utMat4x3CalcColMatrix(colorMatrix, 1.0f, 0.0f, saturationValue, 0.0f);
UTIL_SUCCESS(ret, CyGfx_CmSetColorMatrix(ctx, CYGFX_CM_CMATRIX_FORMAT_4X3, colorMatrix));
UTIL_SUCCESS(ret, CyGfx_BeSetGeoMatrix(ctx, CYGFX_BE_TARGET_SRC, CYGFX_BE_GEO_MATRIX_FORMAT_3X3, matrix));
UTIL_SUCCESS(ret, CyGfx_BeBlt(ctx, 0, 0));
UTIL_SUCCESS(ret, CyGfx_CmSetColorMatrix(ctx, CYGFX_CM_CMATRIX_FORMAT_4X3, nullptr));
UTIL_SUCCESS(ret, CyGfx_BeBindSurface(ctx, CYGFX_BE_TARGET_MASK, nullptr));
if (hasClipping)
UTIL_SUCCESS(ret,
CyGfx_BeSetSurfAttribute(ctx, CYGFX_BE_TARGET_STORE, CYGFX_BE_SURF_ATTR_USE_CLIPPING, CYGFX_FALSE));
#else
QPainter *p = static_cast<QPainter *>(device->platformContext());
QImage image(texture.data(),
texture.width(),
texture.height(),
texture.bytesPerLine(),
toQImageFormat(texture.format()));
QImage desaturatedImage = desaturated(image, saturationValue);
p->save();
p->setClipRect(QRect(clip.x(), clip.y(), clip.width(), clip.height()));
p->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
p->setTransform(toQTransform(transform));
p->setOpacity(opacity);
p->drawImage(QPoint(), desaturatedImage);
p->restore();
#endif
}