C

Qt Quick Ultralite tvii_effects Example

/****************************************************************************** ** ** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt Quick Ultralite module. ** ** $QT_BEGIN_LICENSE:COMM$ ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see http://www.qt.io/terms-conditions. For further ** information use the contact form at http://www.qt.io/contact-us. ** ** $QT_END_LICENSE$ ** ******************************************************************************/
#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 (opacity != 1) { 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 }