~ubuntu-branches/ubuntu/precise/koffice/precise

« back to all changes in this revision

Viewing changes to libs/pigment/colorspaces/KoRgbU8CompositeOp.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2010-09-21 15:36:35 UTC
  • mfrom: (1.4.1 upstream) (60.2.11 maverick)
  • Revision ID: james.westby@ubuntu.com-20100921153635-6tejqkiro2u21ydi
Tags: 1:2.2.2-0ubuntu3
Add kubuntu_03_fix-crash-on-closing-sqlite-connection-2.2.2.diff and
kubuntu_04_support-large-memo-values-for-msaccess-2.2.2.diff as
recommended by upstream http://kexi-
project.org/wiki/wikiview/index.php@Kexi2.2_Patches.html#sqlite_stab
ility

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  Copyright (c) 2006 Boudewijn Rempt <boud@valdyas.org>
3
 
 *
4
 
 *  This program is free software; you can redistribute it and/or modify
5
 
 *  it under the terms of the GNU Lesser General Public License as published by
6
 
 *  the Free Software Foundation; either version 2 of the License, or
7
 
 *  (at your option) any later version.
8
 
 *
9
 
 *  This program is distributed in the hope that it will be useful,
10
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 
 *  GNU Lesser General Public License for more details.
13
 
 *
14
 
 *  You should have received a copy of the GNU Lesser General Public License
15
 
 *  along with this program; if not, write to the Free Software
16
 
 *
17
 
 */
18
 
 
19
 
#include <KoColorSpace.h>
20
 
#include <KoIntegerMaths.h>
21
 
 
22
 
#include "KoRgbU8CompositeOp.h"
23
 
#include "KoRgbU8ColorSpace.h"
24
 
#include "KoColorConversions.h"
25
 
 
26
 
#define PixelIntensity(pixel) ((unsigned int)                           \
27
 
                               (((qreal)306.0 * (pixel[RgbU8Traits::red_pos]) + \
28
 
                                 (qreal)601.0 * (pixel[RgbU8Traits::green_pos]) + \
29
 
                                 (qreal)117.0 * (pixel[RgbU8Traits::blue_pos)) \
30
 
                                 / 1024.0))
31
 
 
32
 
#define PixelIntensityToQuantum(pixel) ((quint8)PixelIntensity(pixel))
33
 
 
34
 
#define PixelIntensityToDouble(pixel) ((qreal)PixelIntensity(pixel))
35
 
 
36
 
#define RoundSignedToQuantum(value) ((quint8) (value < 0 ? 0 :          \
37
 
                                               (value > UINT8_MAX) ? UINT8_MAX : value + 0.5))
38
 
 
39
 
#define RoundToQuantum(value) ((quint8) (value > UINT8_MAX ? UINT8_MAX : \
40
 
                                         value + 0.5))
41
 
 
42
 
// And from studio.h
43
 
#define AbsoluteValue(x)  ((x) < 0 ? -(x) : (x))
44
 
 
45
 
 
46
 
KoRgbU8CompositeOp::KoRgbU8CompositeOp(KoColorSpace * cs, const QString& id, const QString& description, const bool userVisible)
47
 
    : KoCompositeOp(cs, id, description, "", userVisible)
48
 
{
49
 
    m_pixelSize = cs->pixelSize();
50
 
}
51
 
 
52
 
 
53
 
void KoRgbU8CompositeOp::composite(quint8 *dst, qint32 dstRowStride,
54
 
                                    const quint8 *src, qint32 srcRowStride,
55
 
                                    const quint8 *mask, qint32 maskRowStride,
56
 
                                    qint32 rows, qint32 cols,
57
 
                                    quint8 opacity,
58
 
                                    const QBitArray & channelFlags) const
59
 
{
60
 
    Q_ASSERT( channelFlags.size() == 4 || channelFlags.isEmpty() );
61
 
 
62
 
    if ( id() == COMPOSITE_UNDEF ) {
63
 
        // Undefined == no composition
64
 
    }
65
 
    else if ( id() == COMPOSITE_IN ) {
66
 
        compositeIn(m_pixelSize, dst, dstRowStride, src, srcRowStride, rows, cols, opacity, channelFlags);
67
 
    }
68
 
    else if ( id() == COMPOSITE_OUT ) {
69
 
        compositeOut(m_pixelSize, dst, dstRowStride, src, srcRowStride, rows, cols, opacity, channelFlags);
70
 
    }
71
 
    else if ( id() == COMPOSITE_ATOP ) {
72
 
        compositeAtop(m_pixelSize, dst, dstRowStride, src, srcRowStride, rows, cols, opacity, channelFlags);
73
 
    }
74
 
    else if ( id() == COMPOSITE_XOR ) {
75
 
        compositeXor(m_pixelSize, dst, dstRowStride, src, srcRowStride, rows, cols, opacity, channelFlags);
76
 
    }
77
 
    else if ( id() == COMPOSITE_PLUS ) {
78
 
        compositePlus(m_pixelSize, dst, dstRowStride, src, srcRowStride, rows, cols, opacity, channelFlags);
79
 
    }
80
 
    else if (id() == COMPOSITE_MINUS) {
81
 
        compositeMinus(m_pixelSize, dst, dstRowStride, src, srcRowStride, rows, cols, opacity, channelFlags);
82
 
    }
83
 
    else if (id() == COMPOSITE_DIFF) {
84
 
        compositeDiff(m_pixelSize, dst, dstRowStride, src, srcRowStride, rows, cols, opacity, channelFlags);
85
 
    }
86
 
    else if (id() == COMPOSITE_BUMPMAP) {
87
 
        compositeBumpmap(m_pixelSize, dst, dstRowStride, src, srcRowStride, rows, cols, opacity, channelFlags);
88
 
    }
89
 
    else if (id() == COMPOSITE_COPY) {
90
 
        compositeCopy(m_pixelSize, dst, dstRowStride, src, srcRowStride, mask, maskRowStride, rows, cols, opacity, channelFlags);
91
 
    }
92
 
    else if (id() == COMPOSITE_COPY_RED) {
93
 
        compositeCopyRed(m_pixelSize, dst, dstRowStride, src, srcRowStride, rows, cols, opacity, channelFlags);
94
 
    }
95
 
    else if (id() == COMPOSITE_COPY_GREEN) {
96
 
        compositeCopyGreen(m_pixelSize, dst, dstRowStride, src, srcRowStride, rows, cols, opacity, channelFlags);
97
 
    }
98
 
    else if (id() == COMPOSITE_COPY_BLUE) {
99
 
        compositeCopyBlue(m_pixelSize, dst, dstRowStride, src, srcRowStride, rows, cols, opacity, channelFlags);
100
 
    }
101
 
    else if (id() == COMPOSITE_COPY_OPACITY) {
102
 
        compositeCopyOpacity(m_pixelSize, dst, dstRowStride, src, srcRowStride, rows, cols, opacity, channelFlags);
103
 
    }
104
 
    else if (id() == COMPOSITE_CLEAR) {
105
 
        compositeClear(m_pixelSize, dst, dstRowStride, src, srcRowStride, rows, cols, opacity, channelFlags);
106
 
    }
107
 
    else if (id() == COMPOSITE_DISSOLVE) {
108
 
        compositeDissolve(m_pixelSize, dst, dstRowStride, src, srcRowStride, rows, cols, opacity, channelFlags);
109
 
    }
110
 
    else if (id() == COMPOSITE_NO) {
111
 
        // No composition.
112
 
    }
113
 
    else if (id() == COMPOSITE_DARKEN) {
114
 
        compositeDarken(dst, dstRowStride, src, srcRowStride, mask, maskRowStride, rows, cols, opacity, channelFlags);
115
 
    }
116
 
    else if (id() == COMPOSITE_LIGHTEN) {
117
 
        compositeLighten(dst, dstRowStride, src, srcRowStride, mask, maskRowStride, rows, cols, opacity, channelFlags);
118
 
    }
119
 
    else if (id() == COMPOSITE_HUE) {
120
 
        compositeHue(dst, dstRowStride, src, srcRowStride, mask, maskRowStride, rows, cols, opacity, channelFlags);
121
 
    }
122
 
    else if (id() == COMPOSITE_SATURATION) {
123
 
        compositeSaturation(dst, dstRowStride, src, srcRowStride, mask, maskRowStride, rows, cols, opacity, channelFlags);
124
 
    }
125
 
    else if (id() == COMPOSITE_VALUE) {
126
 
        compositeValue(dst, dstRowStride, src, srcRowStride, mask, maskRowStride, rows, cols, opacity, channelFlags);
127
 
    }
128
 
    else if (id() == COMPOSITE_COLOR) {
129
 
        compositeColor(dst, dstRowStride, src, srcRowStride, mask, maskRowStride, rows, cols, opacity, channelFlags);
130
 
    }
131
 
}
132
 
 
133
 
 
134
 
void KoRgbU8CompositeOp::compositeDarken(quint8 *dstRowStart, qint32 dstRowStride, const quint8 *srcRowStart, qint32 srcRowStride, const quint8 *maskRowStart, qint32 maskRowStride, qint32 rows, qint32 numColumns, quint8 opacity, const QBitArray & channelFlags) const
135
 
{
136
 
    while (rows > 0) {
137
 
 
138
 
        const quint8 *src = srcRowStart;
139
 
        quint8 *dst = dstRowStart;
140
 
        qint32 columns = numColumns;
141
 
        const quint8 *mask = maskRowStart;
142
 
 
143
 
        while (columns > 0) {
144
 
 
145
 
            quint8 srcAlpha = src[RgbU8Traits::alpha_pos];
146
 
            quint8 dstAlpha = dst[RgbU8Traits::alpha_pos];
147
 
 
148
 
            srcAlpha = qMin(srcAlpha, dstAlpha);
149
 
 
150
 
            // apply the alphamask
151
 
            if(mask != 0)
152
 
            {
153
 
                if(*mask != OPACITY_OPAQUE)
154
 
                    srcAlpha = UINT8_MULT(srcAlpha, *mask);
155
 
                mask++;
156
 
            }
157
 
 
158
 
            if (srcAlpha != OPACITY_TRANSPARENT) {
159
 
 
160
 
                if (opacity != OPACITY_OPAQUE) {
161
 
                    srcAlpha = UINT8_MULT(src[RgbU8Traits::alpha_pos], opacity);
162
 
                }
163
 
 
164
 
                quint8 srcBlend;
165
 
 
166
 
                if (dstAlpha == OPACITY_OPAQUE) {
167
 
                    srcBlend = srcAlpha;
168
 
                } else {
169
 
                    quint8 newAlpha = dstAlpha + UINT8_MULT(OPACITY_OPAQUE - dstAlpha, srcAlpha);
170
 
                    dst[RgbU8Traits::alpha_pos] = newAlpha;
171
 
 
172
 
                    if (newAlpha != 0) {
173
 
                        srcBlend = UINT8_DIVIDE(srcAlpha, newAlpha);
174
 
                    } else {
175
 
                        srcBlend = srcAlpha;
176
 
                    }
177
 
                }
178
 
 
179
 
                for (int channel = 0; channel < MAX_CHANNEL_RGB; channel++) {
180
 
 
181
 
                    if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::alpha_pos ) ) {
182
 
                        quint8 srcColor = src[channel];
183
 
                        quint8 dstColor = dst[channel];
184
 
 
185
 
                        srcColor = qMin(srcColor, dstColor);
186
 
 
187
 
                        quint8 newColor = UINT8_BLEND(srcColor, dstColor, srcBlend);
188
 
 
189
 
                        dst[channel] = newColor;
190
 
                    }
191
 
                }
192
 
            }
193
 
 
194
 
            columns--;
195
 
            src += RgbU8Traits::channels_nb;
196
 
            dst += RgbU8Traits::channels_nb;
197
 
        }
198
 
 
199
 
        rows--;
200
 
        srcRowStart += srcRowStride;
201
 
        dstRowStart += dstRowStride;
202
 
        if(maskRowStart)
203
 
            maskRowStart += maskRowStride;
204
 
    }
205
 
}
206
 
 
207
 
void KoRgbU8CompositeOp::compositeLighten(quint8 *dstRowStart, qint32 dstRowStride, const quint8 *srcRowStart, qint32 srcRowStride, const quint8 *maskRowStart, qint32 maskRowStride, qint32 rows, qint32 numColumns, quint8 opacity, const QBitArray & channelFlags) const
208
 
{
209
 
    while (rows > 0) {
210
 
 
211
 
        const quint8 *src = srcRowStart;
212
 
        quint8 *dst = dstRowStart;
213
 
        qint32 columns = numColumns;
214
 
        const quint8 *mask = maskRowStart;
215
 
 
216
 
        while (columns > 0) {
217
 
 
218
 
            quint8 srcAlpha = src[RgbU8Traits::alpha_pos];
219
 
            quint8 dstAlpha = dst[RgbU8Traits::alpha_pos];
220
 
 
221
 
            srcAlpha = qMin(srcAlpha, dstAlpha);
222
 
 
223
 
            // apply the alphamask
224
 
            if(mask != 0)
225
 
            {
226
 
                if(*mask != OPACITY_OPAQUE)
227
 
                    srcAlpha = UINT8_MULT(srcAlpha, *mask);
228
 
                mask++;
229
 
            }
230
 
 
231
 
            if (srcAlpha != OPACITY_TRANSPARENT) {
232
 
 
233
 
                if (opacity != OPACITY_OPAQUE) {
234
 
                    srcAlpha = UINT8_MULT(src[RgbU8Traits::alpha_pos], opacity);
235
 
                }
236
 
 
237
 
                quint8 srcBlend;
238
 
 
239
 
                if (dstAlpha == OPACITY_OPAQUE) {
240
 
                    srcBlend = srcAlpha;
241
 
                } else {
242
 
                    quint8 newAlpha = dstAlpha + UINT8_MULT(OPACITY_OPAQUE - dstAlpha, srcAlpha);
243
 
                    dst[RgbU8Traits::alpha_pos] = newAlpha;
244
 
 
245
 
                    if (newAlpha != 0) {
246
 
                        srcBlend = UINT8_DIVIDE(srcAlpha, newAlpha);
247
 
                    } else {
248
 
                        srcBlend = srcAlpha;
249
 
                    }
250
 
                }
251
 
 
252
 
                for (int channel = 0; channel < MAX_CHANNEL_RGB; channel++) {
253
 
                    if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::alpha_pos ) ) {
254
 
                        quint8 srcColor = src[channel];
255
 
                        quint8 dstColor = dst[channel];
256
 
 
257
 
                        srcColor = qMax(srcColor, dstColor);
258
 
 
259
 
                        quint8 newColor = UINT8_BLEND(srcColor, dstColor, srcBlend);
260
 
 
261
 
                        dst[channel] = newColor;
262
 
                    }
263
 
                }
264
 
            }
265
 
 
266
 
            columns--;
267
 
            src += RgbU8Traits::channels_nb;
268
 
            dst += RgbU8Traits::channels_nb;
269
 
        }
270
 
 
271
 
        rows--;
272
 
        srcRowStart += srcRowStride;
273
 
        dstRowStart += dstRowStride;
274
 
        if(maskRowStart)
275
 
            maskRowStart += maskRowStride;
276
 
    }
277
 
}
278
 
 
279
 
void KoRgbU8CompositeOp::compositeHue(quint8 *dstRowStart, qint32 dstRowStride, const quint8 *srcRowStart, qint32 srcRowStride, const quint8 *maskRowStart, qint32 maskRowStride, qint32 rows, qint32 numColumns, quint8 opacity, const QBitArray & channelFlags) const
280
 
{
281
 
    while (rows > 0) {
282
 
 
283
 
        const quint8 *src = srcRowStart;
284
 
        quint8 *dst = dstRowStart;
285
 
        qint32 columns = numColumns;
286
 
        const quint8 *mask = maskRowStart;
287
 
 
288
 
        while (columns > 0) {
289
 
 
290
 
            quint8 srcAlpha = src[RgbU8Traits::alpha_pos];
291
 
            quint8 dstAlpha = dst[RgbU8Traits::alpha_pos];
292
 
 
293
 
            srcAlpha = qMin(srcAlpha, dstAlpha);
294
 
 
295
 
            // apply the alphamask
296
 
            if(mask != 0)
297
 
            {
298
 
                if(*mask != OPACITY_OPAQUE)
299
 
                    srcAlpha = UINT8_MULT(srcAlpha, *mask);
300
 
                mask++;
301
 
            }
302
 
 
303
 
            if (srcAlpha != OPACITY_TRANSPARENT) {
304
 
 
305
 
                if (opacity != OPACITY_OPAQUE) {
306
 
                    srcAlpha = UINT8_MULT(src[RgbU8Traits::alpha_pos], opacity);
307
 
                }
308
 
 
309
 
                quint8 srcBlend;
310
 
 
311
 
                if (dstAlpha == OPACITY_OPAQUE) {
312
 
                    srcBlend = srcAlpha;
313
 
                } else {
314
 
                    quint8 newAlpha = dstAlpha + UINT8_MULT(OPACITY_OPAQUE - dstAlpha, srcAlpha);
315
 
                    dst[RgbU8Traits::alpha_pos] = newAlpha;
316
 
 
317
 
                    if (newAlpha != 0) {
318
 
                        srcBlend = UINT8_DIVIDE(srcAlpha, newAlpha);
319
 
                    } else {
320
 
                        srcBlend = srcAlpha;
321
 
                    }
322
 
                }
323
 
 
324
 
                int dstRed = dst[RgbU8Traits::red_pos];
325
 
                int dstGreen = dst[RgbU8Traits::green_pos];
326
 
                int dstBlue = dst[RgbU8Traits::blue_pos];
327
 
 
328
 
                int srcHue;
329
 
                int srcSaturation;
330
 
                int srcValue;
331
 
                int dstHue;
332
 
                int dstSaturation;
333
 
                int dstValue;
334
 
 
335
 
                rgb_to_hsv(src[RgbU8Traits::red_pos], src[RgbU8Traits::green_pos], src[RgbU8Traits::blue_pos], &srcHue, &srcSaturation, &srcValue);
336
 
                rgb_to_hsv(dstRed, dstGreen, dstBlue, &dstHue, &dstSaturation, &dstValue);
337
 
 
338
 
                int srcRed;
339
 
                int srcGreen;
340
 
                int srcBlue;
341
 
 
342
 
                hsv_to_rgb(srcHue, dstSaturation, dstValue, &srcRed, &srcGreen, &srcBlue);
343
 
 
344
 
                if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::red_pos ) )
345
 
                    dst[RgbU8Traits::red_pos] = UINT8_BLEND(srcRed, dstRed, srcBlend);
346
 
                if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::green_pos ) )
347
 
                    dst[RgbU8Traits::green_pos] = UINT8_BLEND(srcGreen, dstGreen, srcBlend);
348
 
                if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::blue_pos ) )
349
 
                    dst[RgbU8Traits::blue_pos] = UINT8_BLEND(srcBlue, dstBlue, srcBlend);
350
 
            }
351
 
 
352
 
            columns--;
353
 
            src += RgbU8Traits::channels_nb;
354
 
            dst += RgbU8Traits::channels_nb;
355
 
        }
356
 
 
357
 
        rows--;
358
 
        srcRowStart += srcRowStride;
359
 
        dstRowStart += dstRowStride;
360
 
        if(maskRowStart)
361
 
            maskRowStart += maskRowStride;
362
 
    }
363
 
}
364
 
 
365
 
void KoRgbU8CompositeOp::compositeSaturation(quint8 *dstRowStart, qint32 dstRowStride, const quint8 *srcRowStart, qint32 srcRowStride, const quint8 *maskRowStart, qint32 maskRowStride, qint32 rows, qint32 numColumns, quint8 opacity, const QBitArray & channelFlags) const
366
 
{
367
 
    while (rows > 0) {
368
 
 
369
 
        const quint8 *src = srcRowStart;
370
 
        quint8 *dst = dstRowStart;
371
 
        qint32 columns = numColumns;
372
 
        const quint8 *mask = maskRowStart;
373
 
 
374
 
        while (columns > 0) {
375
 
 
376
 
            quint8 srcAlpha = src[RgbU8Traits::alpha_pos];
377
 
            quint8 dstAlpha = dst[RgbU8Traits::alpha_pos];
378
 
 
379
 
            srcAlpha = qMin(srcAlpha, dstAlpha);
380
 
 
381
 
            // apply the alphamask
382
 
            if(mask != 0)
383
 
            {
384
 
                if(*mask != OPACITY_OPAQUE)
385
 
                    srcAlpha = UINT8_MULT(srcAlpha, *mask);
386
 
                mask++;
387
 
            }
388
 
 
389
 
            if (srcAlpha != OPACITY_TRANSPARENT) {
390
 
 
391
 
                if (opacity != OPACITY_OPAQUE) {
392
 
                    srcAlpha = UINT8_MULT(src[RgbU8Traits::alpha_pos], opacity);
393
 
                }
394
 
 
395
 
                quint8 srcBlend;
396
 
 
397
 
                if (dstAlpha == OPACITY_OPAQUE) {
398
 
                    srcBlend = srcAlpha;
399
 
                } else {
400
 
                    quint8 newAlpha = dstAlpha + UINT8_MULT(OPACITY_OPAQUE - dstAlpha, srcAlpha);
401
 
                    dst[RgbU8Traits::alpha_pos] = newAlpha;
402
 
 
403
 
                    if (newAlpha != 0) {
404
 
                        srcBlend = UINT8_DIVIDE(srcAlpha, newAlpha);
405
 
                    } else {
406
 
                        srcBlend = srcAlpha;
407
 
                    }
408
 
                }
409
 
 
410
 
                int dstRed = dst[RgbU8Traits::red_pos];
411
 
                int dstGreen = dst[RgbU8Traits::green_pos];
412
 
                int dstBlue = dst[RgbU8Traits::blue_pos];
413
 
 
414
 
                int srcHue;
415
 
                int srcSaturation;
416
 
                int srcValue;
417
 
                int dstHue;
418
 
                int dstSaturation;
419
 
                int dstValue;
420
 
 
421
 
                rgb_to_hsv(src[RgbU8Traits::red_pos], src[RgbU8Traits::green_pos], src[RgbU8Traits::blue_pos], &srcHue, &srcSaturation, &srcValue);
422
 
                rgb_to_hsv(dstRed, dstGreen, dstBlue, &dstHue, &dstSaturation, &dstValue);
423
 
 
424
 
                int srcRed;
425
 
                int srcGreen;
426
 
                int srcBlue;
427
 
 
428
 
                hsv_to_rgb(dstHue, srcSaturation, dstValue, &srcRed, &srcGreen, &srcBlue);
429
 
                if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::red_pos ) )
430
 
                    dst[RgbU8Traits::red_pos] = UINT8_BLEND(srcRed, dstRed, srcBlend);
431
 
                if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::green_pos ) )
432
 
                    dst[RgbU8Traits::green_pos] = UINT8_BLEND(srcGreen, dstGreen, srcBlend);
433
 
                if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::blue_pos ) )
434
 
                    dst[RgbU8Traits::blue_pos] = UINT8_BLEND(srcBlue, dstBlue, srcBlend);
435
 
            }
436
 
 
437
 
            columns--;
438
 
            src += RgbU8Traits::channels_nb;
439
 
            dst += RgbU8Traits::channels_nb;
440
 
        }
441
 
 
442
 
        rows--;
443
 
        srcRowStart += srcRowStride;
444
 
        dstRowStart += dstRowStride;
445
 
        if(maskRowStart)
446
 
            maskRowStart += maskRowStride;
447
 
    }
448
 
}
449
 
 
450
 
void KoRgbU8CompositeOp::compositeValue(quint8 *dstRowStart, qint32 dstRowStride, const quint8 *srcRowStart, qint32 srcRowStride, const quint8 *maskRowStart, qint32 maskRowStride, qint32 rows, qint32 numColumns, quint8 opacity, const QBitArray & channelFlags) const
451
 
{
452
 
    while (rows > 0) {
453
 
 
454
 
        const quint8 *src = srcRowStart;
455
 
        quint8 *dst = dstRowStart;
456
 
        qint32 columns = numColumns;
457
 
        const quint8 *mask = maskRowStart;
458
 
 
459
 
        while (columns > 0) {
460
 
 
461
 
            quint8 srcAlpha = src[RgbU8Traits::alpha_pos];
462
 
            quint8 dstAlpha = dst[RgbU8Traits::alpha_pos];
463
 
 
464
 
            srcAlpha = qMin(srcAlpha, dstAlpha);
465
 
 
466
 
            // apply the alphamask
467
 
            if(mask != 0)
468
 
            {
469
 
                if(*mask != OPACITY_OPAQUE)
470
 
                    srcAlpha = UINT8_MULT(srcAlpha, *mask);
471
 
                mask++;
472
 
            }
473
 
 
474
 
            if (srcAlpha != OPACITY_TRANSPARENT) {
475
 
 
476
 
                if (opacity != OPACITY_OPAQUE) {
477
 
                    srcAlpha = UINT8_MULT(src[RgbU8Traits::alpha_pos], opacity);
478
 
                }
479
 
 
480
 
                quint8 srcBlend;
481
 
 
482
 
                if (dstAlpha == OPACITY_OPAQUE) {
483
 
                    srcBlend = srcAlpha;
484
 
                } else {
485
 
                    quint8 newAlpha = dstAlpha + UINT8_MULT(OPACITY_OPAQUE - dstAlpha, srcAlpha);
486
 
                    dst[RgbU8Traits::alpha_pos] = newAlpha;
487
 
 
488
 
                    if (newAlpha != 0) {
489
 
                        srcBlend = UINT8_DIVIDE(srcAlpha, newAlpha);
490
 
                    } else {
491
 
                        srcBlend = srcAlpha;
492
 
                    }
493
 
                }
494
 
 
495
 
                int dstRed = dst[RgbU8Traits::red_pos];
496
 
                int dstGreen = dst[RgbU8Traits::green_pos];
497
 
                int dstBlue = dst[RgbU8Traits::blue_pos];
498
 
 
499
 
                int srcHue;
500
 
                int srcSaturation;
501
 
                int srcValue;
502
 
                int dstHue;
503
 
                int dstSaturation;
504
 
                int dstValue;
505
 
 
506
 
                rgb_to_hsv(src[RgbU8Traits::red_pos], src[RgbU8Traits::green_pos], src[RgbU8Traits::blue_pos], &srcHue, &srcSaturation, &srcValue);
507
 
                rgb_to_hsv(dstRed, dstGreen, dstBlue, &dstHue, &dstSaturation, &dstValue);
508
 
 
509
 
                int srcRed;
510
 
                int srcGreen;
511
 
                int srcBlue;
512
 
 
513
 
                hsv_to_rgb(dstHue, dstSaturation, srcValue, &srcRed, &srcGreen, &srcBlue);
514
 
                if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::red_pos ) )
515
 
                    dst[RgbU8Traits::red_pos] = UINT8_BLEND(srcRed, dstRed, srcBlend);
516
 
                if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::green_pos ) )
517
 
                    dst[RgbU8Traits::green_pos] = UINT8_BLEND(srcGreen, dstGreen, srcBlend);
518
 
                if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::blue_pos ) )
519
 
                    dst[RgbU8Traits::blue_pos] = UINT8_BLEND(srcBlue, dstBlue, srcBlend);
520
 
            }
521
 
 
522
 
            columns--;
523
 
            src += RgbU8Traits::channels_nb;
524
 
            dst += RgbU8Traits::channels_nb;
525
 
        }
526
 
 
527
 
        rows--;
528
 
        srcRowStart += srcRowStride;
529
 
        dstRowStart += dstRowStride;
530
 
        if(maskRowStart)
531
 
            maskRowStart += maskRowStride;
532
 
    }
533
 
}
534
 
 
535
 
void KoRgbU8CompositeOp::compositeColor(quint8 *dstRowStart, qint32 dstRowStride, const quint8 *srcRowStart, qint32 srcRowStride, const quint8 *maskRowStart, qint32 maskRowStride, qint32 rows, qint32 numColumns, quint8 opacity, const QBitArray & channelFlags) const
536
 
{
537
 
 
538
 
    while (rows > 0) {
539
 
 
540
 
        const quint8 *src = srcRowStart;
541
 
        quint8 *dst = dstRowStart;
542
 
        qint32 columns = numColumns;
543
 
        const quint8 *mask = maskRowStart;
544
 
 
545
 
        while (columns > 0) {
546
 
 
547
 
            quint8 srcAlpha = src[RgbU8Traits::alpha_pos];
548
 
            quint8 dstAlpha = dst[RgbU8Traits::alpha_pos];
549
 
 
550
 
            srcAlpha = qMin(srcAlpha, dstAlpha);
551
 
 
552
 
            // apply the alphamask
553
 
            if(mask != 0)
554
 
            {
555
 
                if(*mask != OPACITY_OPAQUE)
556
 
                    srcAlpha = UINT8_MULT(srcAlpha, *mask);
557
 
                mask++;
558
 
            }
559
 
 
560
 
            if (srcAlpha != OPACITY_TRANSPARENT) {
561
 
 
562
 
                if (opacity != OPACITY_OPAQUE) {
563
 
                    srcAlpha = UINT8_MULT(src[RgbU8Traits::alpha_pos], opacity);
564
 
                }
565
 
 
566
 
                quint8 srcBlend;
567
 
 
568
 
                if (dstAlpha == OPACITY_OPAQUE) {
569
 
                    srcBlend = srcAlpha;
570
 
                } else {
571
 
                    quint8 newAlpha = dstAlpha + UINT8_MULT(OPACITY_OPAQUE - dstAlpha, srcAlpha);
572
 
                    dst[RgbU8Traits::alpha_pos] = newAlpha;
573
 
 
574
 
                    if (newAlpha != 0) {
575
 
                        srcBlend = UINT8_DIVIDE(srcAlpha, newAlpha);
576
 
                    } else {
577
 
                        srcBlend = srcAlpha;
578
 
                    }
579
 
                }
580
 
 
581
 
                int dstRed = dst[RgbU8Traits::red_pos];
582
 
                int dstGreen = dst[RgbU8Traits::green_pos];
583
 
                int dstBlue = dst[RgbU8Traits::blue_pos];
584
 
 
585
 
                int srcHue;
586
 
                int srcSaturation;
587
 
                int srcLightness;
588
 
                int dstHue;
589
 
                int dstSaturation;
590
 
                int dstLightness;
591
 
 
592
 
                rgb_to_hls(src[RgbU8Traits::red_pos], src[RgbU8Traits::green_pos], src[RgbU8Traits::blue_pos], &srcHue, &srcLightness, &srcSaturation);
593
 
                rgb_to_hls(dstRed, dstGreen, dstBlue, &dstHue, &dstLightness, &dstSaturation);
594
 
 
595
 
                quint8 srcRed;
596
 
                quint8 srcGreen;
597
 
                quint8 srcBlue;
598
 
 
599
 
                hls_to_rgb(srcHue, dstLightness, srcSaturation, &srcRed, &srcGreen, &srcBlue);
600
 
 
601
 
                if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::red_pos ) )
602
 
                    dst[RgbU8Traits::red_pos] = UINT8_BLEND(srcRed, dstRed, srcBlend);
603
 
                if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::green_pos ) )
604
 
                    dst[RgbU8Traits::green_pos] = UINT8_BLEND(srcGreen, dstGreen, srcBlend);
605
 
                if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::blue_pos ) )
606
 
                    dst[RgbU8Traits::blue_pos] = UINT8_BLEND(srcBlue, dstBlue, srcBlend);
607
 
            }
608
 
 
609
 
            columns--;
610
 
            src += RgbU8Traits::channels_nb;
611
 
            dst += RgbU8Traits::channels_nb;
612
 
        }
613
 
 
614
 
        rows--;
615
 
        srcRowStart += srcRowStride;
616
 
        dstRowStart += dstRowStride;
617
 
        if(maskRowStart)
618
 
            maskRowStart += maskRowStride;
619
 
    }
620
 
 
621
 
}
622
 
 
623
 
 
624
 
void KoRgbU8CompositeOp::compositeIn(qint32 pixelSize,
625
 
                                      quint8 *dst,
626
 
                                      qint32 dstRowSize,
627
 
                                      const quint8 *src,
628
 
                                      qint32 srcRowSize,
629
 
                                      qint32 rows,
630
 
                                      qint32 cols,
631
 
                                      quint8 opacity, const QBitArray & channelFlags) const
632
 
{
633
 
 
634
 
    if (opacity == OPACITY_TRANSPARENT)
635
 
        return;
636
 
 
637
 
    quint8 *d;
638
 
    const quint8 *s;
639
 
 
640
 
    qint32 i;
641
 
 
642
 
    qreal sAlpha, dAlpha;
643
 
    qreal alpha;
644
 
 
645
 
    while (rows-- > 0) {
646
 
        d = dst;
647
 
        s = src;
648
 
        for (i = cols; i > 0; i--, d += pixelSize, s += pixelSize) {
649
 
 
650
 
            if (s[RgbU8Traits::alpha_pos] == OPACITY_TRANSPARENT)
651
 
            {
652
 
                memcpy(d, s, pixelSize * sizeof(quint8));
653
 
                continue;
654
 
            }
655
 
            if (d[RgbU8Traits::alpha_pos] == OPACITY_TRANSPARENT)
656
 
                continue;
657
 
 
658
 
            sAlpha = UINT8_MAX - s[RgbU8Traits::alpha_pos];
659
 
            dAlpha = UINT8_MAX - d[RgbU8Traits::alpha_pos];
660
 
 
661
 
            alpha=(qreal) (((qreal) UINT8_MAX - sAlpha) * (UINT8_MAX - dAlpha) / UINT8_MAX);
662
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::red_pos ) )
663
 
                d[RgbU8Traits::red_pos]=(quint8) (((qreal) UINT8_MAX - sAlpha) *
664
 
                                                  (UINT8_MAX-dAlpha) * s[RgbU8Traits::red_pos] / UINT8_MAX / alpha + 0.5);
665
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::green_pos ) )
666
 
                d[RgbU8Traits::green_pos]=(quint8) (((qreal) UINT8_MAX - sAlpha)*
667
 
                                                    (UINT8_MAX-dAlpha) * s[RgbU8Traits::green_pos] / UINT8_MAX / alpha + 0.5);
668
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::blue_pos ) )
669
 
                d[RgbU8Traits::blue_pos]=(quint8) (((qreal) UINT8_MAX - sAlpha)*
670
 
                                                   (UINT8_MAX - dAlpha) * s[RgbU8Traits::blue_pos] / UINT8_MAX / alpha + 0.5);
671
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::alpha_pos ) )
672
 
                d[RgbU8Traits::alpha_pos]=(quint8) ((d[RgbU8Traits::alpha_pos] * (UINT8_MAX - alpha) / UINT8_MAX) + 0.5);
673
 
 
674
 
        }
675
 
        dst += dstRowSize;
676
 
        src += srcRowSize;
677
 
    }
678
 
}
679
 
 
680
 
void KoRgbU8CompositeOp::compositeOut(qint32 pixelSize,
681
 
                                       quint8 *dst,
682
 
                                       qint32 dstRowSize,
683
 
                                       const quint8 *src,
684
 
                                       qint32 srcRowSize,
685
 
                                       qint32 rows,
686
 
                                       qint32 cols,
687
 
                                       quint8 opacity, const QBitArray & channelFlags) const
688
 
{
689
 
    if (opacity == OPACITY_TRANSPARENT)
690
 
        return;
691
 
 
692
 
    quint8 *d;
693
 
    const quint8 *s;
694
 
 
695
 
    qint32 i;
696
 
 
697
 
    qreal sAlpha, dAlpha;
698
 
    qreal alpha;
699
 
 
700
 
    while (rows-- > 0) {
701
 
        d = dst;
702
 
        s = src;
703
 
        for (i = cols; i > 0; i--, d += pixelSize, s += pixelSize) {
704
 
            if (s[RgbU8Traits::alpha_pos] == OPACITY_TRANSPARENT)
705
 
            {
706
 
                memcpy(d, s, pixelSize * sizeof(quint8));
707
 
                break;
708
 
            }
709
 
            if (d[RgbU8Traits::alpha_pos] == OPACITY_OPAQUE)
710
 
            {
711
 
                d[RgbU8Traits::alpha_pos]=OPACITY_TRANSPARENT;
712
 
                break;
713
 
            }
714
 
            sAlpha = UINT8_MAX - s[RgbU8Traits::alpha_pos];
715
 
            dAlpha = UINT8_MAX - d[RgbU8Traits::alpha_pos];
716
 
 
717
 
            alpha=(qreal) (UINT8_MAX - sAlpha) * d[RgbU8Traits::alpha_pos]/UINT8_MAX;
718
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::red_pos ) )
719
 
                d[RgbU8Traits::red_pos] = (quint8) (((qreal) UINT8_MAX - sAlpha) * dAlpha * s[RgbU8Traits::red_pos] / UINT8_MAX / alpha + 0.5);
720
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::green_pos ) )
721
 
                d[RgbU8Traits::green_pos] = (quint8) (((qreal) UINT8_MAX - sAlpha) * dAlpha * s[RgbU8Traits::green_pos] / UINT8_MAX / alpha + 0.5);
722
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::blue_pos ) )
723
 
                d[RgbU8Traits::blue_pos] = (quint8) (((qreal) UINT8_MAX - sAlpha) * dAlpha * s[RgbU8Traits::blue_pos] / UINT8_MAX / alpha + 0.5);
724
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::alpha_pos ) )
725
 
                d[RgbU8Traits::alpha_pos]=(quint8) ((d[RgbU8Traits::alpha_pos] * (UINT8_MAX - alpha) / UINT8_MAX) + 0.5);
726
 
        }
727
 
        dst += dstRowSize;
728
 
        src += srcRowSize;
729
 
    }
730
 
 
731
 
}
732
 
 
733
 
void KoRgbU8CompositeOp::compositeAtop(qint32 pixelSize,
734
 
                                        quint8 *dst,
735
 
                                        qint32 dstRowSize,
736
 
                                        const quint8 *src,
737
 
                                        qint32 srcRowSize,
738
 
                                        qint32 rows,
739
 
                                        qint32 cols,
740
 
                                        quint8 opacity, const QBitArray & channelFlags) const
741
 
{
742
 
 
743
 
    if (opacity == OPACITY_TRANSPARENT)
744
 
        return;
745
 
 
746
 
    quint8 *d;
747
 
    const quint8 *s;
748
 
 
749
 
    qint32 i;
750
 
 
751
 
    qreal sAlpha, dAlpha;
752
 
    qreal alpha, red, green, blue;
753
 
 
754
 
    while (rows-- > 0) {
755
 
        d = dst;
756
 
        s = src;
757
 
        for (i = cols; i > 0; i--, d += pixelSize, s += pixelSize) {
758
 
            sAlpha = UINT8_MAX - s[RgbU8Traits::alpha_pos];
759
 
            dAlpha = UINT8_MAX - d[RgbU8Traits::alpha_pos];
760
 
 
761
 
            alpha = ((qreal)(UINT8_MAX - sAlpha) *
762
 
                     (UINT8_MAX - dAlpha) + (qreal) sAlpha *
763
 
                     (UINT8_MAX - dAlpha)) / UINT8_MAX;
764
 
 
765
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::red_pos ) ) {
766
 
                red = ((qreal)(UINT8_MAX - sAlpha) * (UINT8_MAX - dAlpha) *  s[RgbU8Traits::red_pos] / UINT8_MAX +
767
 
                       (qreal) sAlpha * (UINT8_MAX-dAlpha) * d[RgbU8Traits::red_pos]/UINT8_MAX) / alpha;
768
 
                d[RgbU8Traits::red_pos] = (quint8) (red > UINT8_MAX ? UINT8_MAX : red + 0.5);
769
 
            }
770
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::green_pos ) ) {
771
 
                green = ((qreal) (UINT8_MAX - sAlpha) * (UINT8_MAX - dAlpha) * s[RgbU8Traits::green_pos] / UINT8_MAX +
772
 
                         (qreal) sAlpha * (UINT8_MAX-dAlpha) * d[RgbU8Traits::green_pos]/UINT8_MAX)/alpha;
773
 
                d[RgbU8Traits::green_pos] = (quint8) (green > UINT8_MAX ? UINT8_MAX : green + 0.5);
774
 
            }
775
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::blue_pos ) ) {
776
 
                blue = ((qreal) (UINT8_MAX - sAlpha) * (UINT8_MAX- dAlpha) * s[RgbU8Traits::blue_pos] / UINT8_MAX +
777
 
                        (qreal) sAlpha * (UINT8_MAX - dAlpha) * d[RgbU8Traits::blue_pos]/UINT8_MAX) / alpha;
778
 
                d[RgbU8Traits::blue_pos] = (quint8) (blue > UINT8_MAX ? UINT8_MAX : blue + 0.5);
779
 
            }
780
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::alpha_pos ) )
781
 
                d[RgbU8Traits::alpha_pos]=(quint8) (UINT8_MAX - (alpha > UINT8_MAX ? UINT8_MAX : alpha) + 0.5);
782
 
        }
783
 
        dst += dstRowSize;
784
 
        src += srcRowSize;
785
 
    }
786
 
 
787
 
}
788
 
 
789
 
 
790
 
void KoRgbU8CompositeOp::compositeXor(qint32 pixelSize,
791
 
                                       quint8 *dst,
792
 
                                       qint32 dstRowSize,
793
 
                                       const quint8 *src,
794
 
                                       qint32 srcRowSize,
795
 
                                       qint32 rows,
796
 
                                       qint32 cols,
797
 
                                       quint8 opacity, const QBitArray & channelFlags) const
798
 
{
799
 
    if (opacity == OPACITY_TRANSPARENT)
800
 
        return;
801
 
 
802
 
    quint8 *d;
803
 
    const quint8 *s;
804
 
 
805
 
    qint32 i;
806
 
 
807
 
    qreal sAlpha, dAlpha;
808
 
    qreal alpha, red, green, blue;
809
 
 
810
 
    while (rows-- > 0) {
811
 
        d = dst;
812
 
        s = src;
813
 
        for (i = cols; i > 0; i--, d += pixelSize, s += pixelSize) {
814
 
            sAlpha = UINT8_MAX - s[RgbU8Traits::alpha_pos];
815
 
            dAlpha = UINT8_MAX - d[RgbU8Traits::alpha_pos];
816
 
 
817
 
            alpha =((qreal) (UINT8_MAX -sAlpha)*
818
 
                    dAlpha+(qreal) (UINT8_MAX -dAlpha)*
819
 
                    sAlpha)/UINT8_MAX ;
820
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::red_pos ) ) {
821
 
                red=((qreal) (UINT8_MAX -sAlpha)*dAlpha*
822
 
                     s[RgbU8Traits::red_pos]/UINT8_MAX +(qreal) (UINT8_MAX -dAlpha)*
823
 
                     sAlpha*d[RgbU8Traits::red_pos]/UINT8_MAX )/alpha ;
824
 
                d[RgbU8Traits::red_pos]=RoundSignedToQuantum(Qt::red);
825
 
            }
826
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::green_pos ) ) {
827
 
                green=((qreal) (UINT8_MAX -sAlpha)*dAlpha*
828
 
                       s[RgbU8Traits::green_pos]/UINT8_MAX +(qreal) (UINT8_MAX -dAlpha)*
829
 
                       sAlpha*d[RgbU8Traits::green_pos]/UINT8_MAX )/alpha ;
830
 
                d[RgbU8Traits::green_pos]=RoundSignedToQuantum(Qt::green);
831
 
            }
832
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::blue_pos ) ) {
833
 
                blue=((qreal) (UINT8_MAX -sAlpha)*dAlpha*
834
 
                      s[RgbU8Traits::blue_pos]/UINT8_MAX +(qreal) (UINT8_MAX -dAlpha)*
835
 
                      sAlpha*d[RgbU8Traits::blue_pos]/UINT8_MAX )/alpha ;
836
 
                d[RgbU8Traits::blue_pos]=RoundSignedToQuantum(Qt::blue);
837
 
            }
838
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::alpha_pos ) )
839
 
                d[RgbU8Traits::alpha_pos]=UINT8_MAX -RoundSignedToQuantum(alpha );
840
 
        }
841
 
        dst += dstRowSize;
842
 
        src += srcRowSize;
843
 
    }
844
 
 
845
 
}
846
 
 
847
 
 
848
 
void KoRgbU8CompositeOp::compositePlus(qint32 pixelSize,
849
 
                                        quint8 *dst,
850
 
                                        qint32 dstRowSize,
851
 
                                        const quint8 *src,
852
 
                                        qint32 srcRowSize,
853
 
                                        qint32 rows,
854
 
                                        qint32 cols,
855
 
                                        quint8 opacity, const QBitArray & channelFlags) const
856
 
{
857
 
    if (opacity == OPACITY_TRANSPARENT)
858
 
        return;
859
 
 
860
 
    quint8 *d;
861
 
    const quint8 *s;
862
 
 
863
 
    qint32 i;
864
 
 
865
 
    qreal sAlpha, dAlpha;
866
 
    qreal alpha, red, green, blue;
867
 
 
868
 
    while (rows-- > 0) {
869
 
        d = dst;
870
 
        s = src;
871
 
        for (i = cols; i > 0; i--, d += pixelSize, s += pixelSize) {
872
 
            sAlpha = UINT8_MAX - s[RgbU8Traits::alpha_pos];
873
 
            dAlpha = UINT8_MAX - d[RgbU8Traits::alpha_pos];
874
 
 
875
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::red_pos ) ) {
876
 
                red=((qreal) (UINT8_MAX -sAlpha)*s[RgbU8Traits::red_pos]+(qreal)
877
 
                     (UINT8_MAX -dAlpha)*d[RgbU8Traits::red_pos])/UINT8_MAX ;
878
 
                d[RgbU8Traits::red_pos]=RoundSignedToQuantum(Qt::red);
879
 
            }
880
 
 
881
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::green_pos ) ) {
882
 
                green=((qreal) (UINT8_MAX -sAlpha)*s[RgbU8Traits::green_pos]+(qreal)
883
 
                       (UINT8_MAX -dAlpha)*d[RgbU8Traits::green_pos])/UINT8_MAX ;
884
 
                d[RgbU8Traits::green_pos]=RoundSignedToQuantum(Qt::green);
885
 
            }
886
 
 
887
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::blue_pos ) ) {
888
 
                blue=((qreal) (UINT8_MAX -sAlpha)*s[RgbU8Traits::blue_pos]+(qreal)
889
 
                      (UINT8_MAX -dAlpha)*d[RgbU8Traits::blue_pos])/UINT8_MAX ;
890
 
                d[RgbU8Traits::blue_pos]=RoundSignedToQuantum(Qt::blue);
891
 
            }
892
 
 
893
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::alpha_pos ) ) {
894
 
                alpha =((qreal) (UINT8_MAX -sAlpha)+
895
 
                       (qreal) (UINT8_MAX -dAlpha))/UINT8_MAX ;
896
 
                d[RgbU8Traits::alpha_pos]=UINT8_MAX -RoundSignedToQuantum(alpha );
897
 
            }
898
 
        }
899
 
        dst += dstRowSize;
900
 
        src += srcRowSize;
901
 
    }
902
 
 
903
 
}
904
 
 
905
 
 
906
 
 
907
 
void KoRgbU8CompositeOp::compositeMinus(qint32 pixelSize,
908
 
                                         quint8 *dst,
909
 
                                         qint32 dstRowSize,
910
 
                                         const quint8 *src,
911
 
                                         qint32 srcRowSize,
912
 
                                         qint32 rows,
913
 
                                         qint32 cols,
914
 
                                         quint8 opacity, const QBitArray & channelFlags) const
915
 
{
916
 
    if (opacity == OPACITY_TRANSPARENT)
917
 
        return;
918
 
 
919
 
    quint8 *d;
920
 
    const quint8 *s;
921
 
 
922
 
    qint32 i;
923
 
 
924
 
    qreal sAlpha, dAlpha;
925
 
    qreal alpha, red, green, blue;
926
 
 
927
 
    while (rows-- > 0) {
928
 
        d = dst;
929
 
        s = src;
930
 
        for (i = cols; i > 0; i--, d += pixelSize, s += pixelSize) {
931
 
            sAlpha = UINT8_MAX - s[RgbU8Traits::alpha_pos];
932
 
            dAlpha = UINT8_MAX - d[RgbU8Traits::alpha_pos];
933
 
 
934
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::red_pos ) ) {
935
 
                red=((qreal) (UINT8_MAX -dAlpha)*d[RgbU8Traits::red_pos]-
936
 
                     (qreal) (UINT8_MAX -sAlpha)*s[RgbU8Traits::red_pos])/UINT8_MAX ;
937
 
                d[RgbU8Traits::red_pos]=RoundSignedToQuantum(Qt::red);
938
 
            }
939
 
 
940
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::green_pos ) ) {
941
 
                green=((qreal) (UINT8_MAX -dAlpha)*d[RgbU8Traits::green_pos]-
942
 
                       (qreal) (UINT8_MAX -sAlpha)*s[RgbU8Traits::green_pos])/UINT8_MAX ;
943
 
                d[RgbU8Traits::green_pos]=RoundSignedToQuantum(Qt::green);
944
 
            }
945
 
 
946
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::blue_pos ) ) {
947
 
                blue=((qreal) (UINT8_MAX -dAlpha)*d[RgbU8Traits::blue_pos]-
948
 
                      (qreal) (UINT8_MAX -sAlpha)*s[RgbU8Traits::blue_pos])/UINT8_MAX ;
949
 
                d[RgbU8Traits::blue_pos]=RoundSignedToQuantum(Qt::blue);
950
 
            }
951
 
 
952
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::alpha_pos ) ) {
953
 
                alpha =((qreal) (UINT8_MAX -dAlpha)-
954
 
                        (qreal) (UINT8_MAX -sAlpha))/UINT8_MAX ;
955
 
                d[RgbU8Traits::alpha_pos]=UINT8_MAX -RoundSignedToQuantum(alpha );
956
 
            }
957
 
        }
958
 
        dst += dstRowSize;
959
 
        src += srcRowSize;
960
 
    }
961
 
 
962
 
}
963
 
 
964
 
void KoRgbU8CompositeOp::compositeAdd(qint32 pixelSize,
965
 
                                       quint8 *dst,
966
 
                                       qint32 dstRowSize,
967
 
                                       const quint8 *src,
968
 
                                       qint32 srcRowSize,
969
 
                                       qint32 rows,
970
 
                                       qint32 cols,
971
 
                                       quint8 opacity, const QBitArray & channelFlags) const
972
 
{
973
 
    if (opacity == OPACITY_TRANSPARENT)
974
 
        return;
975
 
 
976
 
    quint8 *d;
977
 
    const quint8 *s;
978
 
 
979
 
    qint32 i;
980
 
 
981
 
    qreal sAlpha, dAlpha;
982
 
    qreal red, green, blue;
983
 
 
984
 
    while (rows-- > 0) {
985
 
        d = dst;
986
 
        s = src;
987
 
        for (i = cols; i > 0; i--, d += pixelSize, s += pixelSize) {
988
 
            sAlpha = UINT8_MAX - s[RgbU8Traits::alpha_pos];
989
 
            dAlpha = UINT8_MAX - d[RgbU8Traits::alpha_pos];
990
 
 
991
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::red_pos ) ) {
992
 
                red=(qreal) s[RgbU8Traits::red_pos]+d[RgbU8Traits::red_pos];
993
 
                d[RgbU8Traits::red_pos]=(quint8)
994
 
                                        (red > UINT8_MAX  ? red-=UINT8_MAX  : red+0.5);
995
 
            }
996
 
 
997
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::green_pos ) ) {
998
 
                green=(qreal) s[RgbU8Traits::green_pos]+d[RgbU8Traits::green_pos];
999
 
                d[RgbU8Traits::green_pos]=(quint8)
1000
 
                                          (green > UINT8_MAX  ? green-=UINT8_MAX  : green+0.5);
1001
 
            }
1002
 
 
1003
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::blue_pos ) ) {
1004
 
                blue=(qreal) s[RgbU8Traits::blue_pos]+d[RgbU8Traits::blue_pos];
1005
 
                d[RgbU8Traits::blue_pos]=(quint8)
1006
 
                                         (blue > UINT8_MAX  ? blue-=UINT8_MAX  : blue+0.5);
1007
 
            }
1008
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::alpha_pos ) )
1009
 
                d[RgbU8Traits::alpha_pos]=OPACITY_OPAQUE;
1010
 
        }
1011
 
        dst += dstRowSize;
1012
 
        src += srcRowSize;
1013
 
    }
1014
 
 
1015
 
}
1016
 
 
1017
 
 
1018
 
void KoRgbU8CompositeOp::compositeDiff(qint32 pixelSize,
1019
 
                                        quint8 *dst,
1020
 
                                        qint32 dstRowSize,
1021
 
                                        const quint8 *src,
1022
 
                                        qint32 srcRowSize,
1023
 
                                        qint32 rows,
1024
 
                                        qint32 cols,
1025
 
                                        quint8 opacity, const QBitArray & channelFlags) const
1026
 
{
1027
 
    if (opacity == OPACITY_TRANSPARENT)
1028
 
        return;
1029
 
 
1030
 
    quint8 *d;
1031
 
    const quint8 *s;
1032
 
 
1033
 
    qint32 i;
1034
 
 
1035
 
    qreal sAlpha, dAlpha;
1036
 
 
1037
 
    while (rows-- > 0) {
1038
 
        d = dst;
1039
 
        s = src;
1040
 
        for (i = cols; i > 0; i--, d += pixelSize, s += pixelSize) {
1041
 
            sAlpha = UINT8_MAX - s[RgbU8Traits::alpha_pos];
1042
 
            dAlpha = UINT8_MAX - d[RgbU8Traits::alpha_pos];
1043
 
 
1044
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::red_pos ) )
1045
 
                d[RgbU8Traits::red_pos]=(quint8)
1046
 
                                        AbsoluteValue(s[RgbU8Traits::red_pos]-(qreal) d[RgbU8Traits::red_pos]);
1047
 
 
1048
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::green_pos ) )
1049
 
                d[RgbU8Traits::green_pos]=(quint8)
1050
 
                                          AbsoluteValue(s[RgbU8Traits::green_pos]-(qreal) d[RgbU8Traits::green_pos]);
1051
 
 
1052
 
 
1053
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::blue_pos ) )
1054
 
                d[RgbU8Traits::blue_pos]=(quint8)
1055
 
                                         AbsoluteValue(s[RgbU8Traits::blue_pos]-(qreal) d[RgbU8Traits::blue_pos]);
1056
 
 
1057
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::alpha_pos ) )
1058
 
                d[RgbU8Traits::alpha_pos]=UINT8_MAX - (quint8)
1059
 
                                          AbsoluteValue(sAlpha-(qreal) dAlpha);
1060
 
 
1061
 
        }
1062
 
        dst += dstRowSize;
1063
 
        src += srcRowSize;
1064
 
 
1065
 
    }
1066
 
}
1067
 
 
1068
 
void KoRgbU8CompositeOp::compositeBumpmap(qint32 pixelSize,
1069
 
                                           quint8 *dst,
1070
 
                                           qint32 dstRowSize,
1071
 
                                           const quint8 *src,
1072
 
                                           qint32 srcRowSize,
1073
 
                                           qint32 rows,
1074
 
                                           qint32 cols,
1075
 
                                           quint8 opacity, const QBitArray & channelFlags) const
1076
 
{
1077
 
    if (opacity == OPACITY_TRANSPARENT)
1078
 
        return;
1079
 
 
1080
 
    quint8 *d;
1081
 
    const quint8 *s;
1082
 
 
1083
 
    qint32 i;
1084
 
 
1085
 
    qreal intensity;
1086
 
 
1087
 
    while (rows-- > 0) {
1088
 
        d = dst;
1089
 
        s = src;
1090
 
        for (i = cols; i > 0; i--, d += pixelSize, s += pixelSize) {
1091
 
            // Is this correct? It's not this way in GM.
1092
 
            if (s[RgbU8Traits::alpha_pos] == OPACITY_TRANSPARENT)
1093
 
                continue;
1094
 
 
1095
 
            // And I'm not sure whether this is correct, either.
1096
 
            intensity = ((qreal)306.0 * s[RgbU8Traits::red_pos] +
1097
 
                         (qreal)601.0 * s[RgbU8Traits::green_pos] +
1098
 
                         (qreal)117.0 * s[RgbU8Traits::blue_pos]) / 1024.0;
1099
 
 
1100
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::red_pos ) )
1101
 
                d[RgbU8Traits::red_pos]=(quint8) (((qreal)
1102
 
                                                   intensity * d[RgbU8Traits::red_pos])/UINT8_MAX +0.5);
1103
 
 
1104
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::green_pos ) )
1105
 
                d[RgbU8Traits::green_pos]=(quint8) (((qreal)
1106
 
                                                     intensity * d[RgbU8Traits::green_pos])/UINT8_MAX +0.5);
1107
 
 
1108
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::blue_pos ) )
1109
 
                d[RgbU8Traits::blue_pos]=(quint8) (((qreal)
1110
 
                                                    intensity * d[RgbU8Traits::blue_pos])/UINT8_MAX +0.5);
1111
 
 
1112
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::alpha_pos ) )
1113
 
                d[RgbU8Traits::alpha_pos]= (quint8) (((qreal)
1114
 
                                                      intensity * d[RgbU8Traits::alpha_pos])/UINT8_MAX +0.5);
1115
 
 
1116
 
 
1117
 
        }
1118
 
        dst += dstRowSize;
1119
 
        src += srcRowSize;
1120
 
    }
1121
 
 
1122
 
}
1123
 
 
1124
 
 
1125
 
void KoRgbU8CompositeOp::compositeCopyChannel(quint8 pixel, quint32 pixelSize, quint8 *dst, qint32 dstRowSize, const quint8 *src, qint32 srcRowSize,qint32 rows, qint32 cols, quint8 opacity, const QBitArray & channelFlags) const
1126
 
{
1127
 
    Q_UNUSED( channelFlags );
1128
 
    Q_UNUSED( opacity );
1129
 
    quint8 *d;
1130
 
    const quint8 *s;
1131
 
    qint32 i;
1132
 
 
1133
 
    while (rows-- > 0) {
1134
 
        d = dst;
1135
 
        s = src;
1136
 
 
1137
 
        for (i = cols; i > 0; i--, d += pixelSize, s += pixelSize) {
1138
 
            d[pixel] = s[pixel];
1139
 
        }
1140
 
 
1141
 
        dst += dstRowSize;
1142
 
        src += srcRowSize;
1143
 
    }
1144
 
}
1145
 
 
1146
 
void KoRgbU8CompositeOp::compositeCopyRed(qint32 pixelSize,
1147
 
                                           quint8 *dst,
1148
 
                                           qint32 dstRowSize,
1149
 
                                           const quint8 *src,
1150
 
                                           qint32 srcRowSize,
1151
 
                                           qint32 rows,
1152
 
                                           qint32 cols,
1153
 
                                           quint8 opacity, const QBitArray & channelFlags) const
1154
 
{
1155
 
    compositeCopyChannel(RgbU8Traits::red_pos, pixelSize, dst, dstRowSize, src, srcRowSize, rows, cols, opacity, channelFlags);
1156
 
}
1157
 
 
1158
 
void KoRgbU8CompositeOp::compositeCopyGreen(qint32 pixelSize,
1159
 
                                             quint8 *dst,
1160
 
                                             qint32 dstRowSize,
1161
 
                                             const quint8 *src,
1162
 
                                             qint32 srcRowSize,
1163
 
                                             qint32 rows,
1164
 
                                             qint32 cols,
1165
 
                                             quint8 opacity, const QBitArray & channelFlags) const
1166
 
{
1167
 
    compositeCopyChannel(RgbU8Traits::green_pos, pixelSize, dst, dstRowSize, src, srcRowSize, rows, cols, opacity, channelFlags);
1168
 
}
1169
 
 
1170
 
void KoRgbU8CompositeOp::compositeCopyBlue(qint32 pixelSize,
1171
 
                                            quint8 *dst,
1172
 
                                            qint32 dstRowSize,
1173
 
                                            const quint8 *src,
1174
 
                                            qint32 srcRowSize,
1175
 
                                            qint32 rows,
1176
 
                                            qint32 cols,
1177
 
                                            quint8 opacity, const QBitArray & channelFlags) const
1178
 
{
1179
 
    compositeCopyChannel(RgbU8Traits::blue_pos, pixelSize, dst, dstRowSize, src, srcRowSize, rows, cols, opacity, channelFlags);
1180
 
}
1181
 
 
1182
 
 
1183
 
void KoRgbU8CompositeOp::compositeCopyOpacity(qint32 pixelSize,
1184
 
                                               quint8 *dst,
1185
 
                                               qint32 dstRowSize,
1186
 
                                               const quint8 *src,
1187
 
                                               qint32 srcRowSize,
1188
 
                                               qint32 rows,
1189
 
                                               qint32 cols,
1190
 
                                               quint8 opacity, const QBitArray & channelFlags) const
1191
 
{
1192
 
 
1193
 
    // XXX: mess with intensity if there isn't an alpha channel, according to GM.
1194
 
    compositeCopyChannel(RgbU8Traits::alpha_pos, pixelSize, dst, dstRowSize, src, srcRowSize, rows, cols, opacity, channelFlags);
1195
 
 
1196
 
}
1197
 
 
1198
 
 
1199
 
void KoRgbU8CompositeOp::compositeClear(qint32 pixelSize,
1200
 
                                         quint8 *dst,
1201
 
                                         qint32 dstRowSize,
1202
 
                                         const quint8 *src,
1203
 
                                         qint32 srcRowSize,
1204
 
                                         qint32 rows,
1205
 
                                         qint32 cols,
1206
 
                                         quint8 opacity, const QBitArray & channelFlags) const
1207
 
{
1208
 
    Q_UNUSED( opacity );
1209
 
    Q_UNUSED( srcRowSize );
1210
 
 
1211
 
    qint32 linesize = pixelSize * sizeof(quint8) * cols;
1212
 
    quint8 *d;
1213
 
    const quint8 *s;
1214
 
 
1215
 
    d = dst;
1216
 
    s = src;
1217
 
    if ( channelFlags.isEmpty() ) {
1218
 
        while (rows-- > 0) {
1219
 
            memset(d, 0, linesize);
1220
 
            d += dstRowSize;
1221
 
        }
1222
 
    }
1223
 
    else {
1224
 
        while ( rows-- > 0 ) {
1225
 
            for (int channel = 0; channel < MAX_CHANNEL_RGB; channel++) {
1226
 
                if ( channelFlags.testBit( channel ) )
1227
 
                    memset( d, 0, pixelSize );
1228
 
                ++d;
1229
 
            }
1230
 
        }
1231
 
    }
1232
 
}
1233
 
 
1234
 
 
1235
 
void KoRgbU8CompositeOp::compositeDissolve(qint32 pixelSize,
1236
 
                                            quint8 *dst,
1237
 
                                            qint32 dstRowSize,
1238
 
                                            const quint8 *src,
1239
 
                                            qint32 srcRowSize,
1240
 
                                            qint32 rows,
1241
 
                                            qint32 cols,
1242
 
                                            quint8 opacity, const QBitArray & channelFlags) const
1243
 
{
1244
 
    if (opacity == OPACITY_TRANSPARENT)
1245
 
        return;
1246
 
 
1247
 
    quint8 *d;
1248
 
    const quint8 *s;
1249
 
 
1250
 
    qint32 i;
1251
 
 
1252
 
    qreal sAlpha, dAlpha;
1253
 
 
1254
 
    while (rows-- > 0) {
1255
 
        d = dst;
1256
 
        s = src;
1257
 
        for (i = cols; i > 0; i--, d += pixelSize, s += pixelSize) {
1258
 
            // XXX: correct?
1259
 
            if (s[RgbU8Traits::alpha_pos] == OPACITY_TRANSPARENT) continue;
1260
 
 
1261
 
            sAlpha = UINT8_MAX - s[RgbU8Traits::alpha_pos];
1262
 
            dAlpha = UINT8_MAX - d[RgbU8Traits::alpha_pos];
1263
 
 
1264
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::red_pos ) )
1265
 
                d[RgbU8Traits::red_pos]=(quint8) (((qreal) sAlpha*s[RgbU8Traits::red_pos]+
1266
 
                                                   (UINT8_MAX -sAlpha)*d[RgbU8Traits::red_pos])/UINT8_MAX +0.5);
1267
 
 
1268
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::green_pos ) )
1269
 
                d[RgbU8Traits::green_pos]= (quint8) (((qreal) sAlpha*s[RgbU8Traits::green_pos]+
1270
 
                                                      (UINT8_MAX -sAlpha)*d[RgbU8Traits::green_pos])/UINT8_MAX +0.5);
1271
 
 
1272
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::blue_pos ) )
1273
 
                d[RgbU8Traits::blue_pos] = (quint8) (((qreal) sAlpha*s[RgbU8Traits::blue_pos]+
1274
 
                                                      (UINT8_MAX -sAlpha)*d[RgbU8Traits::blue_pos])/UINT8_MAX +0.5);
1275
 
 
1276
 
            if ( channelFlags.isEmpty() || channelFlags.testBit( RgbU8Traits::alpha_pos ) )
1277
 
                d[RgbU8Traits::alpha_pos] = OPACITY_OPAQUE;
1278
 
 
1279
 
        }
1280
 
        dst += dstRowSize;
1281
 
        src += srcRowSize;
1282
 
 
1283
 
    }
1284
 
}
1285
 
 
1286
 
void KoRgbU8CompositeOp::compositeCopy(qint32 pixelSize,
1287
 
                                        quint8 *dstRowStart,
1288
 
                                        qint32 dstRowStride,
1289
 
                                        const quint8 *srcRowStart,
1290
 
                                        qint32 srcRowStride,
1291
 
                                        const quint8 *maskRowStart,
1292
 
                                        qint32 maskRowStride,
1293
 
                                        qint32 rows,
1294
 
                                        qint32 numColumns,
1295
 
                                        quint8 opacity, const QBitArray & channelFlags) const
1296
 
{
1297
 
 
1298
 
    Q_UNUSED(maskRowStart);
1299
 
    Q_UNUSED(maskRowStride);
1300
 
 
1301
 
    quint8 *dst = dstRowStart;
1302
 
    const quint8 *src = srcRowStart;
1303
 
 
1304
 
    if ( channelFlags.isEmpty() ) {
1305
 
        while (rows > 0) {
1306
 
 
1307
 
            memcpy(dst, src, numColumns * pixelSize);
1308
 
 
1309
 
            if (opacity != OPACITY_OPAQUE) {
1310
 
                colorSpace()->multiplyAlpha(dst, opacity, numColumns);
1311
 
            }
1312
 
 
1313
 
            dst += dstRowStride;
1314
 
            src += srcRowStride;
1315
 
            --rows;
1316
 
        }
1317
 
    }
1318
 
    else {
1319
 
        while ( rows > 0 ) {
1320
 
            for (int channel = 0; channel < MAX_CHANNEL_RGB; channel++) {
1321
 
                if ( channelFlags.testBit( channel ) ) {
1322
 
                    memcpy( dst, src, pixelSize );
1323
 
                }
1324
 
                ++dst;
1325
 
                ++src;
1326
 
            }
1327
 
            // XXX: how about the opacity here?
1328
 
            --rows;
1329
 
        }
1330
 
    }
1331
 
}