File indexing completed on 2024-05-12 11:53:11
0001 /* 0002 SPDX-FileCopyrightText: 2023 Mirco Miranda <mircomir@outlook.com> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "scanlineconverter_p.h" 0008 #include <cstring> 0009 0010 ScanLineConverter::ScanLineConverter(const QImage::Format &targetFormat) 0011 : _targetFormat(targetFormat) 0012 { 0013 } 0014 0015 ScanLineConverter::ScanLineConverter(const ScanLineConverter &other) 0016 : _targetFormat(other._targetFormat) 0017 , _colorSpace(other._colorSpace) 0018 { 0019 } 0020 0021 ScanLineConverter &ScanLineConverter::operator=(const ScanLineConverter &other) 0022 { 0023 this->_targetFormat = other._targetFormat; 0024 this->_colorSpace = other._colorSpace; 0025 return (*this); 0026 } 0027 0028 QImage::Format ScanLineConverter::targetFormat() const 0029 { 0030 return _targetFormat; 0031 } 0032 0033 void ScanLineConverter::setTargetColorSpace(const QColorSpace &colorSpace) 0034 { 0035 _colorSpace = colorSpace; 0036 } 0037 0038 QColorSpace ScanLineConverter::targetColorSpace() const 0039 { 0040 return _colorSpace; 0041 } 0042 0043 const uchar *ScanLineConverter::convertedScanLine(const QImage &image, qint32 y) 0044 { 0045 auto colorSpaceConversion = isColorSpaceConversionNeeded(image, _colorSpace); 0046 if (image.format() == _targetFormat && !colorSpaceConversion) { 0047 return image.constScanLine(y); 0048 } 0049 if (image.width() != _tmpBuffer.width() || image.format() != _tmpBuffer.format()) { 0050 _tmpBuffer = QImage(image.width(), 1, image.format()); 0051 } 0052 if (_tmpBuffer.isNull()) { 0053 return nullptr; 0054 } 0055 std::memcpy(_tmpBuffer.bits(), image.constScanLine(y), std::min(_tmpBuffer.bytesPerLine(), image.bytesPerLine())); 0056 if (colorSpaceConversion) { 0057 _tmpBuffer.setColorSpace(image.colorSpace()); 0058 _tmpBuffer.convertToColorSpace(_colorSpace); 0059 } 0060 _convBuffer = _tmpBuffer.convertToFormat(_targetFormat); 0061 if (_convBuffer.isNull()) { 0062 return nullptr; 0063 } 0064 return _convBuffer.constBits(); 0065 } 0066 0067 qsizetype ScanLineConverter::bytesPerLine() const 0068 { 0069 if (_convBuffer.isNull()) { 0070 return 0; 0071 } 0072 return _convBuffer.bytesPerLine(); 0073 } 0074 0075 bool ScanLineConverter::isColorSpaceConversionNeeded(const QImage &image, const QColorSpace &targetColorSpace) const 0076 { 0077 if (image.depth() < 24) { // RGB 8 bit or grater only 0078 return false; 0079 } 0080 auto sourceColorSpace = image.colorSpace(); 0081 if (!sourceColorSpace.isValid() || !targetColorSpace.isValid()) { 0082 return false; 0083 } 0084 0085 auto stf = sourceColorSpace.transferFunction(); 0086 auto spr = sourceColorSpace.primaries(); 0087 auto ttf = targetColorSpace.transferFunction(); 0088 auto tpr = targetColorSpace.primaries(); 0089 // clang-format off 0090 if (stf == QColorSpace::TransferFunction::Custom || 0091 ttf == QColorSpace::TransferFunction::Custom || 0092 spr == QColorSpace::Primaries::Custom || 0093 tpr == QColorSpace::Primaries::Custom) { 0094 return true; 0095 } 0096 // clang-format on 0097 if (stf == ttf && spr == tpr) { 0098 return false; 0099 } 0100 return true; 0101 }