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