KImageFormats

scanlineconverter.cpp
1/*
2 SPDX-FileCopyrightText: 2023 Mirco Miranda <mircomir@outlook.com>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "scanlineconverter_p.h"
8#include <cstring>
9
10ScanLineConverter::ScanLineConverter(const QImage::Format &targetFormat)
11 : _targetFormat(targetFormat)
12{
13}
14
15ScanLineConverter::ScanLineConverter(const ScanLineConverter &other)
16 : _targetFormat(other._targetFormat)
17 , _colorSpace(other._colorSpace)
18 , _defaultColorSpace(other._defaultColorSpace)
19{
20}
21
22ScanLineConverter &ScanLineConverter::operator=(const ScanLineConverter &other)
23{
24 _targetFormat = other._targetFormat;
25 _colorSpace = other._colorSpace;
26 _defaultColorSpace = other._defaultColorSpace;
27 return (*this);
28}
29
30QImage::Format ScanLineConverter::targetFormat() const
31{
32 return _targetFormat;
33}
34
35void ScanLineConverter::setTargetColorSpace(const QColorSpace &colorSpace)
36{
37 _colorSpace = colorSpace;
38}
39
40QColorSpace ScanLineConverter::targetColorSpace() const
41{
42 return _colorSpace;
43}
44
45void ScanLineConverter::setDefaultSourceColorSpace(const QColorSpace &colorSpace)
46{
47 _defaultColorSpace = colorSpace;
48}
49
50QColorSpace ScanLineConverter::defaultSourceColorSpace() const
51{
52 return _defaultColorSpace;
53}
54
55const uchar *ScanLineConverter::convertedScanLine(const QImage &image, qint32 y)
56{
57 auto colorSpaceConversion = isColorSpaceConversionNeeded(image);
58 if (image.format() == _targetFormat && !colorSpaceConversion) {
59 return image.constScanLine(y);
60 }
61 if (image.width() != _tmpBuffer.width() || image.format() != _tmpBuffer.format()) {
62 _tmpBuffer = QImage(image.width(), 1, image.format());
63 _tmpBuffer.setColorTable(image.colorTable());
64 }
65 if (_tmpBuffer.isNull()) {
66 return nullptr;
67 }
68 std::memcpy(_tmpBuffer.bits(), image.constScanLine(y), std::min(_tmpBuffer.bytesPerLine(), image.bytesPerLine()));
69 auto tmp = _tmpBuffer;
70 if (colorSpaceConversion) {
71 auto cs = image.colorSpace();
72 if (!cs.isValid()) {
73 cs = _defaultColorSpace;
74 }
75#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
76 if (tmp.depth() < 8 && cs.colorModel() == QColorSpace::ColorModel::Gray) {
77 tmp.convertTo(QImage::Format_Grayscale8);
78 }
79 else if (tmp.depth() < 24 && cs.colorModel() == QColorSpace::ColorModel::Rgb) {
80 tmp.convertTo(tmp.hasAlphaChannel() ? QImage::Format_ARGB32 : QImage::Format_RGB32);
81 }
82#else
83 if (tmp.depth() < 24) {
84 tmp.convertTo(tmp.hasAlphaChannel() ? QImage::Format_ARGB32 : QImage::Format_RGB32);
85 }
86#endif
87 tmp.setColorSpace(cs);
88 tmp.convertToColorSpace(_colorSpace);
89 }
90
91 /*
92 * Work Around for wrong RGBA64 -> 16FPx4/32FPx4 conversion on Intel architecture.
93 * Luckily convertTo() works fine with 16FPx4 images so I can use it instead convertToFormat().
94 * See also: https://bugreports.qt.io/browse/QTBUG-120614
95 */
96 tmp.convertTo(_targetFormat);
97 _convBuffer = tmp;
98
99 if (_convBuffer.isNull()) {
100 return nullptr;
101 }
102 return _convBuffer.constBits();
103}
104
105qsizetype ScanLineConverter::bytesPerLine() const
106{
107 if (_convBuffer.isNull()) {
108 return 0;
109 }
110 return _convBuffer.bytesPerLine();
111}
112
113bool ScanLineConverter::isColorSpaceConversionNeeded(const QImage &image, const QColorSpace &targetColorSpace, const QColorSpace &defaultColorSpace)
114{
115 auto sourceColorSpace = image.colorSpace();
116 if (!sourceColorSpace.isValid()) {
117 sourceColorSpace = defaultColorSpace;
118 }
119 if (!sourceColorSpace.isValid() || !targetColorSpace.isValid()) {
120 return false;
121 }
122
123 auto stf = sourceColorSpace.transferFunction();
124 auto spr = sourceColorSpace.primaries();
125 auto ttf = targetColorSpace.transferFunction();
126 auto tpr = targetColorSpace.primaries();
127 // clang-format off
128 if (stf == QColorSpace::TransferFunction::Custom ||
129 ttf == QColorSpace::TransferFunction::Custom ||
130 spr == QColorSpace::Primaries::Custom ||
131 tpr == QColorSpace::Primaries::Custom) {
132 return true;
133 }
134 // clang-format on
135 if (stf == ttf && spr == tpr) {
136 return false;
137 }
138 return true;
139}
bool isValid() const const
Primaries primaries() const const
TransferFunction transferFunction() const const
qsizetype bytesPerLine() const const
QColorSpace colorSpace() const const
QList< QRgb > colorTable() const const
const uchar * constScanLine(int i) const const
Format format() const const
int width() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:07:21 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.