File indexing completed on 2025-01-05 03:55:18
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 * Bitwise operations. 0009 * 0010 * SPDX-FileCopyrightText: 2005 by Renchi Raju <renchi dot raju at gmail dot com> 0011 * SPDX-FileCopyrightText: 2005-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0012 * SPDX-FileCopyrightText: 2006-2013 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> 0013 * 0014 * SPDX-License-Identifier: GPL-2.0-or-later 0015 * 0016 * ============================================================ */ 0017 0018 #include "dimg_p.h" 0019 0020 namespace Digikam 0021 { 0022 0023 void DImg::bitBltImage(const DImg* const src, int dx, int dy) 0024 { 0025 bitBltImage(src, 0, 0, src->width(), src->height(), dx, dy); 0026 } 0027 0028 void DImg::bitBltImage(const DImg* const src, int sx, int sy, int dx, int dy) 0029 { 0030 bitBltImage(src, sx, sy, src->width() - sx, src->height() - sy, dx, dy); 0031 } 0032 0033 void DImg::bitBltImage(const DImg* const src, int sx, int sy, int w, int h, int dx, int dy) 0034 { 0035 if (isNull()) 0036 { 0037 return; 0038 } 0039 0040 if (src->sixteenBit() != sixteenBit()) 0041 { 0042 qCWarning(DIGIKAM_DIMG_LOG) << "Blitting from 8-bit to 16-bit or vice versa is not supported"; 0043 return; 0044 } 0045 0046 if ((w == -1) && (h == -1)) 0047 { 0048 w = src->width(); 0049 h = src->height(); 0050 } 0051 0052 bitBlt(src->bits(), bits(), sx, sy, w, h, dx, dy, 0053 src->width(), src->height(), width(), height(), sixteenBit(), src->bytesDepth(), bytesDepth()); 0054 } 0055 0056 void DImg::bitBltImage(const uchar* const src, int sx, int sy, int w, int h, int dx, int dy, 0057 uint swidth, uint sheight, int sdepth) 0058 { 0059 if (isNull()) 0060 { 0061 return; 0062 } 0063 0064 if (bytesDepth() != sdepth) 0065 { 0066 qCWarning(DIGIKAM_DIMG_LOG) << "Blitting from 8-bit to 16-bit or vice versa is not supported"; 0067 return; 0068 } 0069 0070 if ((w == -1) && (h == -1)) 0071 { 0072 w = swidth; 0073 h = sheight; 0074 } 0075 0076 bitBlt(src, bits(), sx, sy, w, h, dx, dy, swidth, sheight, width(), height(), sixteenBit(), sdepth, bytesDepth()); 0077 } 0078 0079 bool DImg::normalizeRegionArguments(int& sx, int& sy, int& w, int& h, int& dx, int& dy, 0080 uint swidth, uint sheight, uint dwidth, uint dheight) const 0081 { 0082 if (sx < 0) 0083 { 0084 // sx is negative, so + is - and - is + 0085 0086 dx -= sx; 0087 w += sx; 0088 sx = 0; 0089 } 0090 0091 if (sy < 0) 0092 { 0093 dy -= sy; 0094 h += sy; 0095 sy = 0; 0096 } 0097 0098 if (dx < 0) 0099 { 0100 sx -= dx; 0101 w += dx; 0102 dx = 0; 0103 } 0104 0105 if (dy < 0) 0106 { 0107 sy -= dy; 0108 h += dy; 0109 dy = 0; 0110 } 0111 0112 if ((sx + w) > (int)swidth) 0113 { 0114 w = swidth - sx; 0115 } 0116 0117 if ((sy + h) > (int)sheight) 0118 { 0119 h = sheight - sy; 0120 } 0121 0122 if ((dx + w) > (int)dwidth) 0123 { 0124 w = dwidth - dx; 0125 } 0126 0127 if ((dy + h) > (int)dheight) 0128 { 0129 h = dheight - dy; 0130 } 0131 0132 // Nothing left to copy 0133 0134 if ((w <= 0) || (h <= 0)) 0135 { 0136 return false; 0137 } 0138 0139 return true; 0140 } 0141 0142 void DImg::bitBlt(const uchar* const src, uchar* const dest, 0143 int sx, int sy, int w, int h, int dx, int dy, 0144 uint swidth, uint sheight, uint dwidth, uint dheight, 0145 bool /*sixteenBit*/, int sdepth, int ddepth) 0146 { 0147 // Normalize 0148 0149 if (!normalizeRegionArguments(sx, sy, w, h, dx, dy, swidth, sheight, dwidth, dheight)) 0150 { 0151 return; 0152 } 0153 0154 // Same pixels 0155 0156 if ((src == dest) && (dx == sx) && (dy == sy)) 0157 { 0158 return; 0159 } 0160 0161 const uchar* sptr = nullptr; 0162 uchar* dptr = nullptr; 0163 uint slinelength = swidth * sdepth; 0164 uint dlinelength = dwidth * ddepth; 0165 int scurY = sy; 0166 int dcurY = dy; 0167 int sdepthlength = w * sdepth; 0168 0169 for (int j = 0 ; j < h ; ++j, ++scurY, ++dcurY) 0170 { 0171 sptr = &src [ scurY * slinelength ] + sx * sdepth; 0172 dptr = &dest[ dcurY * dlinelength ] + dx * ddepth; 0173 0174 // plain and simple bitBlt 0175 0176 for (int i = 0; i < sdepthlength ; ++i, ++sptr, ++dptr) 0177 { 0178 *dptr = *sptr; 0179 } 0180 } 0181 } 0182 0183 0184 void DImg::bitBlendImage(DColorComposer* const composer, const DImg* const src, 0185 int sx, int sy, int w, int h, int dx, int dy, 0186 DColorComposer::MultiplicationFlags multiplicationFlags) 0187 { 0188 if (isNull()) 0189 { 0190 return; 0191 } 0192 0193 if (src->sixteenBit() != sixteenBit()) 0194 { 0195 qCWarning(DIGIKAM_DIMG_LOG) << "Blending from 8-bit to 16-bit or vice versa is not supported"; 0196 return; 0197 } 0198 0199 bitBlend(composer, src->bits(), bits(), sx, sy, w, h, dx, dy, 0200 src->width(), src->height(), width(), height(), sixteenBit(), 0201 src->bytesDepth(), bytesDepth(), multiplicationFlags); 0202 } 0203 0204 void DImg::bitBlend(DColorComposer* const composer, uchar* const src, uchar* const dest, 0205 int sx, int sy, int w, int h, int dx, int dy, 0206 uint swidth, uint sheight, uint dwidth, uint dheight, 0207 bool sixteenBit, int sdepth, int ddepth, 0208 DColorComposer::MultiplicationFlags multiplicationFlags) 0209 { 0210 // Normalize 0211 0212 if (!normalizeRegionArguments(sx, sy, w, h, dx, dy, swidth, sheight, dwidth, dheight)) 0213 { 0214 return; 0215 } 0216 0217 uchar* sptr = nullptr; 0218 uchar* dptr = nullptr; 0219 uint slinelength = swidth * sdepth; 0220 uint dlinelength = dwidth * ddepth; 0221 int scurY = sy; 0222 int dcurY = dy; 0223 0224 for (int j = 0 ; j < h ; ++j, ++scurY, ++dcurY) 0225 { 0226 sptr = &src [ scurY * slinelength ] + sx * sdepth; 0227 dptr = &dest[ dcurY * dlinelength ] + dx * ddepth; 0228 0229 // blend src and destination 0230 0231 for (int i = 0 ; i < w ; ++i, sptr += sdepth, dptr += ddepth) 0232 { 0233 DColor srcp(sptr, sixteenBit); 0234 DColor dstp(dptr, sixteenBit); 0235 0236 // blend colors 0237 0238 composer->compose(dstp, srcp, multiplicationFlags); 0239 0240 dstp.setPixel(dptr); 0241 } 0242 } 0243 } 0244 0245 void DImg::bitBlendImageOnColor(const DColor& color) 0246 { 0247 bitBlendImageOnColor(color, 0, 0, width(), height()); 0248 } 0249 0250 void DImg::bitBlendImageOnColor(const DColor& color, int x, int y, int w, int h) 0251 { 0252 // get composer for compositing rule 0253 0254 DColorComposer* const composer = DColorComposer::getComposer(DColorComposer::PorterDuffNone); 0255 0256 // flags would be MultiplicationFlagsDImg for anything but PorterDuffNone 0257 0258 bitBlendImageOnColor(composer, color, x, y, w, h, DColorComposer::NoMultiplication); 0259 0260 delete composer; 0261 } 0262 0263 void DImg::bitBlendImageOnColor(DColorComposer* const composer, const DColor& color, 0264 int x, int y, int w, int h, 0265 DColorComposer::MultiplicationFlags multiplicationFlags) 0266 { 0267 if (isNull()) 0268 { 0269 return; 0270 } 0271 0272 DColor c = color; 0273 0274 if (sixteenBit()) 0275 { 0276 c.convertToSixteenBit(); 0277 } 0278 else 0279 { 0280 c.convertToEightBit(); 0281 } 0282 0283 bitBlendOnColor(composer, c, bits(), x, y, w, h, 0284 width(), height(), sixteenBit(), bytesDepth(), multiplicationFlags); 0285 } 0286 0287 void DImg::bitBlendOnColor(DColorComposer* const composer, const DColor& color, 0288 uchar* const data, int x, int y, int w, int h, 0289 uint width, uint height, bool sixteenBit, int depth, 0290 DColorComposer::MultiplicationFlags multiplicationFlags) 0291 { 0292 // Normalize 0293 0294 if (!normalizeRegionArguments(x, y, w, h, x, y, width, height, width, height)) 0295 { 0296 return; 0297 } 0298 0299 uchar* ptr = nullptr; 0300 uint linelength = width * depth; 0301 int curY = y; 0302 0303 for (int j = 0 ; j < h ; ++j, ++curY) 0304 { 0305 ptr = &data[ curY * linelength ] + x * depth; 0306 0307 // blend src and destination 0308 0309 for (int i = 0 ; i < w ; ++i, ptr += depth) 0310 { 0311 DColor src(ptr, sixteenBit); 0312 DColor dst(color); 0313 0314 // blend colors 0315 0316 composer->compose(dst, src, multiplicationFlags); 0317 0318 dst.setPixel(ptr); 0319 } 0320 } 0321 } 0322 0323 } // namespace Digikam