File indexing completed on 2025-01-19 03:54:50
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2005-06-14 0007 * Description : digiKam 8/16 bits image management API. 0008 * QPixmap accessors. 0009 * 0010 * SPDX-FileCopyrightText: 2005-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0011 * SPDX-FileCopyrightText: 2006-2013 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> 0012 * 0013 * SPDX-License-Identifier: GPL-2.0-or-later 0014 * 0015 * ============================================================ */ 0016 0017 #include "dimg_p.h" 0018 0019 namespace Digikam 0020 { 0021 0022 class Q_DECL_HIDDEN PixmapPaintEngineDetector 0023 { 0024 public: 0025 0026 PixmapPaintEngineDetector() 0027 : m_isRaster(detectRasterFromPixmap()) 0028 { 0029 } 0030 0031 bool isRaster() const 0032 { 0033 return m_isRaster; 0034 } 0035 0036 private: 0037 0038 static bool detectRasterFromPixmap() 0039 { 0040 QPixmap pix(1, 1); 0041 QPainter p(&pix); 0042 return (p.paintEngine() && (p.paintEngine()->type() == QPaintEngine::Raster)); 0043 } 0044 0045 const bool m_isRaster; 0046 }; 0047 0048 Q_GLOBAL_STATIC(PixmapPaintEngineDetector, pixmapPaintEngineDetector) 0049 0050 // -------------------------------------------------------------------------------------- 0051 0052 QPixmap DImg::convertToPixmap() const 0053 { 0054 if (isNull()) 0055 { 0056 return QPixmap(); 0057 } 0058 0059 if (sixteenBit()) 0060 { 0061 // make faster... 0062 0063 return QPixmap::fromImage(copyQImage(0, 0, width(), height())); 0064 } 0065 0066 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) 0067 { 0068 QImage img(width(), height(), hasAlpha() ? QImage::Format_ARGB32 : QImage::Format_RGB32); 0069 0070 uchar* sptr = bits(); 0071 uint* dptr = reinterpret_cast<uint*>(img.bits()); 0072 uint dim = width() * height(); 0073 0074 for (uint i = 0 ; i < dim ; ++i) 0075 { 0076 *dptr++ = qRgba(sptr[2], sptr[1], sptr[0], sptr[3]); 0077 sptr += 4; 0078 } 0079 0080 // alpha channel is auto-detected during QImage->QPixmap conversion 0081 0082 return QPixmap::fromImage(img); 0083 } 0084 else 0085 { 0086 // This is a temporary image operating on the DImg buffer 0087 0088 QImage img(bits(), width(), height(), hasAlpha() ? QImage::Format_ARGB32 : QImage::Format_RGB32); 0089 0090 // For paint engines which base the QPixmap internally on a QImage, we must use a persistent QImage 0091 0092 if (pixmapPaintEngineDetector->isRaster()) 0093 { 0094 img = img.copy(); 0095 } 0096 0097 // alpha channel is auto-detected during QImage->QPixmap conversion 0098 0099 return QPixmap::fromImage(img); 0100 } 0101 } 0102 0103 QPixmap DImg::convertToPixmap(IccTransform& monitorICCtrans) const 0104 { 0105 if (isNull()) 0106 { 0107 return QPixmap(); 0108 } 0109 0110 if (monitorICCtrans.outputProfile().isNull()) 0111 { 0112 return convertToPixmap(); 0113 } 0114 0115 DImg img = copy(); 0116 monitorICCtrans.apply(img); 0117 0118 return (img.convertToPixmap()); 0119 } 0120 0121 QImage DImg::pureColorMask(ExposureSettingsContainer* const expoSettings) const 0122 { 0123 if (isNull() || (!expoSettings->underExposureIndicator && !expoSettings->overExposureIndicator)) 0124 { 0125 return QImage(); 0126 } 0127 0128 QImage img(size(), QImage::Format_ARGB32); 0129 img.fill(0x00000000); // Full transparent. 0130 0131 // NOTE: Qt4 do not provide anymore QImage::setAlphaChannel() because 0132 // alpha channel is auto-detected during QImage->QPixmap conversion 0133 0134 uchar* bits = img.bits(); 0135 0136 // NOTE: Using DImgScale before to compute Mask clamp to 65534 | 254. Why ? 0137 0138 int max = lround(sixteenBit() ? 65535.0 - (65535.0 * expoSettings->overExposurePercent / 100.0) 0139 : 255.0 - (255.0 * expoSettings->overExposurePercent / 100.0)); 0140 int min = lround(sixteenBit() ? 0.0 + (65535.0 * expoSettings->underExposurePercent / 100.0) 0141 : 0.0 + (255.0 * expoSettings->underExposurePercent / 100.0)); 0142 0143 // -------------------------------------------------------- 0144 0145 // caching 0146 0147 int u_red = expoSettings->underExposureColor.red(); 0148 int u_green = expoSettings->underExposureColor.green(); 0149 int u_blue = expoSettings->underExposureColor.blue(); 0150 0151 int o_red = expoSettings->overExposureColor.red(); 0152 int o_green = expoSettings->overExposureColor.green(); 0153 int o_blue = expoSettings->overExposureColor.blue(); 0154 0155 bool under = expoSettings->underExposureIndicator; 0156 bool over = expoSettings->overExposureIndicator; 0157 bool pure = expoSettings->exposureIndicatorMode; 0158 0159 // -------------------------------------------------------- 0160 0161 uint dim = m_priv->width * m_priv->height; 0162 uchar* dptr = bits; 0163 int s_blue, s_green, s_red; 0164 bool match = false; 0165 0166 if (sixteenBit()) 0167 { 0168 unsigned short* sptr = reinterpret_cast<unsigned short*>(m_priv->data); 0169 0170 for (uint i = 0 ; i < dim ; ++i) 0171 { 0172 s_blue = *sptr++; 0173 s_green = *sptr++; 0174 s_red = *sptr++; 0175 sptr++; 0176 match = pure ? (s_red <= min) && (s_green <= min) && (s_blue <= min) 0177 : (s_red <= min) || (s_green <= min) || (s_blue <= min); 0178 0179 if (under && match) 0180 { 0181 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) 0182 { 0183 dptr[0] = 0xFF; 0184 dptr[1] = u_red; 0185 dptr[2] = u_green; 0186 dptr[3] = u_blue; 0187 } 0188 else 0189 { 0190 dptr[0] = u_blue; 0191 dptr[1] = u_green; 0192 dptr[2] = u_red; 0193 dptr[3] = 0xFF; 0194 } 0195 } 0196 0197 match = pure ? (s_red >= max) && (s_green >= max) && (s_blue >= max) 0198 : (s_red >= max) || (s_green >= max) || (s_blue >= max); 0199 0200 if (over && match) 0201 { 0202 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) 0203 { 0204 dptr[0] = 0xFF; 0205 dptr[1] = o_red; 0206 dptr[2] = o_green; 0207 dptr[3] = o_blue; 0208 } 0209 else 0210 { 0211 dptr[0] = o_blue; 0212 dptr[1] = o_green; 0213 dptr[2] = o_red; 0214 dptr[3] = 0xFF; 0215 } 0216 } 0217 0218 dptr += 4; 0219 } 0220 } 0221 else 0222 { 0223 uchar* sptr = m_priv->data; 0224 0225 for (uint i = 0 ; i < dim ; ++i) 0226 { 0227 s_blue = *sptr++; 0228 s_green = *sptr++; 0229 s_red = *sptr++; 0230 sptr++; 0231 match = pure ? (s_red <= min) && (s_green <= min) && (s_blue <= min) 0232 : (s_red <= min) || (s_green <= min) || (s_blue <= min); 0233 0234 if (under && match) 0235 { 0236 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) 0237 { 0238 dptr[0] = 0xFF; 0239 dptr[1] = u_red; 0240 dptr[2] = u_green; 0241 dptr[3] = u_blue; 0242 } 0243 else 0244 { 0245 dptr[0] = u_blue; 0246 dptr[1] = u_green; 0247 dptr[2] = u_red; 0248 dptr[3] = 0xFF; 0249 } 0250 } 0251 0252 match = pure ? (s_red >= max) && (s_green >= max) && (s_blue >= max) 0253 : (s_red >= max) || (s_green >= max) || (s_blue >= max); 0254 0255 if (over && match) 0256 { 0257 if (QSysInfo::ByteOrder == QSysInfo::BigEndian) 0258 { 0259 dptr[0] = 0xFF; 0260 dptr[1] = o_red; 0261 dptr[2] = o_green; 0262 dptr[3] = o_blue; 0263 } 0264 else 0265 { 0266 dptr[0] = o_blue; 0267 dptr[1] = o_green; 0268 dptr[2] = o_red; 0269 dptr[3] = 0xFF; 0270 } 0271 } 0272 0273 dptr += 4; 0274 } 0275 } 0276 0277 return img; 0278 } 0279 0280 } // namespace Digikam