/* Copyright 2006-2026 The QElectroTech Team This file is part of QElectroTech. QElectroTech is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. QElectroTech is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with QElectroTech. If not, see . */ #ifndef QET_TEST_INKCONTRAST_H #define QET_TEST_INKCONTRAST_H #include #include #include #include #include #include #include "qetpalette.h" /** Shared helpers for the rendering tests: paint a widget on the offscreen platform and measure the ink against the background. */ namespace QET { namespace Test { /** Grab a widget for measuring. With QET_TEST_DUMP_DIR set, the image is also written there as -.png so a failure can be looked at. */ inline QImage dump(const QImage &image, const char *name) { const QByteArray dir = qgetenv("QET_TEST_DUMP_DIR"); if (!dir.isEmpty()) image.save(QString("%1/%2-%3.png").arg(QString::fromLocal8Bit(dir), QTest::currentDataTag(), name)); return image; } inline QImage grab(QWidget *widget, const char *name) { return dump(widget->grab().toImage(), name); } /** Contrast between the background of a rendered widget (its most frequent color) and the ink drawn on it (the pixel whose luminance differs most from the background), inside rect. */ inline QHash histogram(const QImage &image, const QRect &rect) { QHash counts; for (int y = rect.top(); y <= rect.bottom(); ++y) for (int x = rect.left(); x <= rect.right(); ++x) ++counts[image.pixel(x, y)]; return counts; } /// The most frequent color inside rect. inline QRgb background(const QImage &image, const QRect &rect) { const QHash counts = histogram(image, rect); QRgb color = 0; int best = -1; for (auto it = counts.cbegin(); it != counts.cend(); ++it) if (it.value() > best) { best = it.value(); color = it.key(); } return color; } /// The color inside rect that contrasts most with the background: the ink. inline QRgb ink(const QImage &image, const QRect &rect) { const QHash counts = histogram(image, rect); const QColor bg(background(image, rect)); QRgb color = bg.rgb(); double contrast = 1.0; for (auto it = counts.cbegin(); it != counts.cend(); ++it) { const double c = QET::Palette::contrastRatio(bg, QColor(it.key())); if (c > contrast) { contrast = c; color = it.key(); } } return color; } inline double inkContrast(const QImage &image, const QRect &rect) { return QET::Palette::contrastRatio(QColor(background(image, rect)), QColor(ink(image, rect))); } } } #endif