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

« back to all changes in this revision

Viewing changes to filters/krita/tiff/kis_ycbcr_u8_colorspace.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2006-04-20 21:38:53 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20060420213853-j5lxluqvymxt2zny
Tags: 1:1.5.0-0ubuntu2
UbuntuĀ uploadĀ 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Copyright (c) 2006 Cyrille Berger <cberger@cberger.net>
 
3
 *
 
4
 *  This program is free software; you can redistribute it and/or modify
 
5
 *  it under the terms of the GNU 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 General Public License for more details.
 
13
 *
 
14
 *  You should have received a copy of the GNU General Public License
 
15
 *  along with this program; if not, write to the Free Software
 
16
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor,
 
17
 * Boston, MA 02110-1301, USA.
 
18
 */
 
19
 
 
20
#include "kis_ycbcr_u8_colorspace.h"
 
21
#include "kis_ycbcr_colorspace.h"
 
22
 
 
23
#include <qimage.h>
 
24
 
 
25
#include <klocale.h>
 
26
 
 
27
#include <kis_integer_maths.h>
 
28
 
 
29
KisYCbCrU8ColorSpace::KisYCbCrU8ColorSpace(KisColorSpaceFactoryRegistry* parent, KisProfile* p)
 
30
    : KisU8BaseColorSpace(KisID("YCbCrAU8", "YCbCr (8-bit integer/channel)"), TYPE_YCbCr_8, icSigYCbCrData, parent, p)
 
31
{
 
32
    m_channels.push_back(new KisChannelInfo("Y", PIXEL_Y * sizeof(Q_UINT8), KisChannelInfo::COLOR, KisChannelInfo::UINT8, sizeof(Q_UINT8)));
 
33
    m_channels.push_back(new KisChannelInfo("Cb", PIXEL_Cb * sizeof(Q_UINT8), KisChannelInfo::COLOR, KisChannelInfo::UINT8, sizeof(Q_UINT8)));
 
34
    m_channels.push_back(new KisChannelInfo("Cr", PIXEL_Cr * sizeof(Q_UINT8), KisChannelInfo::COLOR, KisChannelInfo::UINT8, sizeof(Q_UINT8)));
 
35
    m_channels.push_back(new KisChannelInfo(i18n("Alpha"), PIXEL_ALPHA * sizeof(Q_UINT8), KisChannelInfo::ALPHA, KisChannelInfo::UINT8, sizeof(Q_UINT8)));
 
36
 
 
37
    m_alphaPos = PIXEL_ALPHA * sizeof(Q_UINT8);
 
38
}
 
39
 
 
40
 
 
41
KisYCbCrU8ColorSpace::~KisYCbCrU8ColorSpace()
 
42
{
 
43
}
 
44
 
 
45
void KisYCbCrU8ColorSpace::setPixel(Q_UINT8 *dst, Q_UINT8 Y, Q_UINT8 Cb, Q_UINT8 Cr, Q_UINT8 alpha) const
 
46
{
 
47
    Pixel *dstPixel = reinterpret_cast<Pixel *>(dst);
 
48
 
 
49
    dstPixel->Y = Y;
 
50
    dstPixel->Cb = Cb;
 
51
    dstPixel->Cr = Cr;
 
52
    dstPixel->alpha = alpha;
 
53
}
 
54
 
 
55
void KisYCbCrU8ColorSpace::getPixel(const Q_UINT8 *src, Q_UINT8 *Y, Q_UINT8 *Cb, Q_UINT8 *Cr, Q_UINT8 *alpha) const
 
56
{
 
57
    const Pixel *srcPixel = reinterpret_cast<const Pixel *>(src);
 
58
 
 
59
    *Y = srcPixel->Y;
 
60
    *Cb = srcPixel->Cb;
 
61
    *Cr = srcPixel->Cr;
 
62
    *alpha = srcPixel->alpha;
 
63
 
 
64
}
 
65
 
 
66
void KisYCbCrU8ColorSpace::fromQColor(const QColor& c, Q_UINT8 *dstU8, KisProfile * profile )
 
67
{
 
68
    if(getProfile())
 
69
    {
 
70
        KisU8BaseColorSpace::fromQColor(c, dstU8, profile);
 
71
    } else {
 
72
        Pixel *dst = reinterpret_cast<Pixel *>(dstU8);
 
73
        dst->Y = computeY( c.red(), c.green(), c.blue());
 
74
        dst->Cb = computeCb( c.red(), c.green(), c.blue());
 
75
        dst->Cr = computeCr( c.red(), c.green(), c.blue());
 
76
    }
 
77
}
 
78
 
 
79
void KisYCbCrU8ColorSpace::fromQColor(const QColor& c, Q_UINT8 opacity, Q_UINT8 *dstU8, KisProfile * profile )
 
80
{
 
81
    if(getProfile())
 
82
    {
 
83
        KisU8BaseColorSpace::fromQColor(c, opacity, dstU8, profile);
 
84
    } else {
 
85
        Pixel *dst = reinterpret_cast<Pixel *>(dstU8);
 
86
        dst->Y = computeY( c.red(), c.green(), c.blue());
 
87
        dst->Cb = computeCb( c.red(), c.green(), c.blue());
 
88
        dst->Cr = computeCr( c.red(), c.green(), c.blue());
 
89
        dst->alpha = opacity;
 
90
    }
 
91
}
 
92
 
 
93
void KisYCbCrU8ColorSpace::toQColor(const Q_UINT8 *srcU8, QColor *c, KisProfile * profile)
 
94
{
 
95
    if(getProfile())
 
96
    {
 
97
        KisU8BaseColorSpace::toQColor(srcU8, c, profile);
 
98
 
 
99
    } else {
 
100
        const Pixel *src = reinterpret_cast<const Pixel *>(srcU8);
 
101
        c->setRgb(computeRed(src->Y,src->Cb,src->Cr), computeGreen(src->Y,src->Cb,src->Cr),     computeBlue(src->Y,src->Cb,src->Cr));
 
102
    }
 
103
}
 
104
 
 
105
void KisYCbCrU8ColorSpace::toQColor(const Q_UINT8 *srcU8, QColor *c, Q_UINT8 *opacity, KisProfile * profile)
 
106
{
 
107
    if(getProfile())
 
108
    {
 
109
        KisU8BaseColorSpace::toQColor(srcU8, c, opacity, profile);
 
110
    } else {
 
111
        const Pixel *src = reinterpret_cast<const Pixel *>(srcU8);
 
112
        c->setRgb(computeRed(src->Y,src->Cb,src->Cr), computeGreen(src->Y,src->Cb,src->Cr), computeBlue(src->Y,src->Cb,src->Cr));
 
113
        *opacity = src->alpha;
 
114
    }
 
115
}
 
116
 
 
117
Q_UINT8 KisYCbCrU8ColorSpace::difference(const Q_UINT8 *src1U8, const Q_UINT8 *src2U8)
 
118
{
 
119
    if(getProfile())
 
120
        return KisU8BaseColorSpace::difference(src1U8, src2U8);
 
121
    const Pixel *src1 = reinterpret_cast<const Pixel *>(src1U8);
 
122
    const Pixel *src2 = reinterpret_cast<const Pixel *>(src2U8);
 
123
 
 
124
    return QMAX(QABS(src2->Y - src1->Y), QMAX(QABS(src2->Cb - src1->Cb), QABS(src2->Cr - src1->Cr)));
 
125
 
 
126
}
 
127
 
 
128
void KisYCbCrU8ColorSpace::mixColors(const Q_UINT8 **colors, const Q_UINT8 *weights, Q_UINT32 nColors, Q_UINT8 *dst) const
 
129
{
 
130
    Q_UINT8 totalY = 0, totalCb = 0, totalCr = 0, newAlpha = 0;
 
131
 
 
132
    while (nColors--)
 
133
    {
 
134
        const Pixel *pixel = reinterpret_cast<const Pixel *>(*colors);
 
135
 
 
136
        Q_UINT8 alpha = pixel->alpha;
 
137
        float alphaTimesWeight = alpha * *weights;
 
138
 
 
139
        totalY += (Q_UINT8)(pixel->Y * alphaTimesWeight);
 
140
        totalCb += (Q_UINT8)(pixel->Cb * alphaTimesWeight);
 
141
        totalCr += (Q_UINT8)(pixel->Cr * alphaTimesWeight);
 
142
        newAlpha += (Q_UINT8)(alphaTimesWeight);
 
143
 
 
144
        weights++;
 
145
        colors++;
 
146
    }
 
147
 
 
148
    Pixel *dstPixel = reinterpret_cast<Pixel *>(dst);
 
149
 
 
150
    dstPixel->alpha = newAlpha;
 
151
 
 
152
    if (newAlpha > 0) {
 
153
        totalY = totalY / newAlpha;
 
154
        totalCb = totalCb / newAlpha;
 
155
        totalCr = totalCr / newAlpha;
 
156
    }
 
157
 
 
158
    dstPixel->Y = totalY;
 
159
    dstPixel->Cb = totalCb;
 
160
    dstPixel->Cr = totalCr;
 
161
}
 
162
 
 
163
QValueVector<KisChannelInfo *> KisYCbCrU8ColorSpace::channels() const {
 
164
    return m_channels;
 
165
}
 
166
 
 
167
Q_UINT32 KisYCbCrU8ColorSpace::nChannels() const {
 
168
    return MAX_CHANNEL_YCbCrA;
 
169
}
 
170
 
 
171
Q_UINT32 KisYCbCrU8ColorSpace::nColorChannels() const {
 
172
    return MAX_CHANNEL_YCbCr;
 
173
}
 
174
 
 
175
Q_UINT32 KisYCbCrU8ColorSpace::pixelSize() const {
 
176
    return MAX_CHANNEL_YCbCrA*sizeof(Q_UINT8);
 
177
}
 
178
 
 
179
 
 
180
QImage KisYCbCrU8ColorSpace::convertToQImage(const Q_UINT8 *data, Q_INT32 width, Q_INT32 height, KisProfile *  dstProfile, Q_INT32 renderingIntent, float exposure )
 
181
{
 
182
    if(getProfile())
 
183
        return KisU8BaseColorSpace::convertToQImage( data, width, height, dstProfile, renderingIntent, exposure);
 
184
 
 
185
    QImage img = QImage(width, height, 32, 0, QImage::LittleEndian);
 
186
    img.setAlphaBuffer(true);
 
187
 
 
188
    Q_INT32 i = 0;
 
189
    uchar *j = img.bits();
 
190
 
 
191
    while ( i < width * height * MAX_CHANNEL_YCbCrA) {
 
192
        Q_UINT8 Y = *( data + i + PIXEL_Y );
 
193
        Q_UINT8 Cb = *( data + i + PIXEL_Cb );
 
194
        Q_UINT8 Cr = *( data + i + PIXEL_Cr );
 
195
#ifdef __BIG_ENDIAN__
 
196
        *( j + 0)  = *( data + i + PIXEL_ALPHA );
 
197
        *( j + 1 ) = computeRed(Y,Cb,Cr);
 
198
        *( j + 2 ) = computeGreen(Y,Cb,Cr);
 
199
        *( j + 3 ) = computeBlue(Y,Cr,Cr);
 
200
#else
 
201
        *( j + 3)  = *( data + i + PIXEL_ALPHA );
 
202
        *( j + 2 ) = computeRed(Y,Cb,Cr);
 
203
        *( j + 1 ) = computeGreen(Y,Cb,Cr);
 
204
        *( j + 0 ) = computeBlue(Y,Cb,Cr);
 
205
/*        *( j + 2 ) = Y;
 
206
        *( j + 1 ) = Cb;
 
207
        *( j + 0 ) = Cr;*/
 
208
#endif
 
209
        i += MAX_CHANNEL_YCbCrA;
 
210
        j += MAX_CHANNEL_YCbCrA;
 
211
    }
 
212
    return img;
 
213
}
 
214
 
 
215
 
 
216
void KisYCbCrU8ColorSpace::bitBlt(Q_UINT8 *dst, Q_INT32 dstRowStride, const Q_UINT8 *src, Q_INT32 srcRowStride, const Q_UINT8 *srcAlphaMask, Q_INT32 maskRowStride, Q_UINT8 opacity, Q_INT32 rows, Q_INT32 cols, const KisCompositeOp& op)
 
217
{
 
218
    switch (op.op()) {
 
219
        case COMPOSITE_UNDEF:
 
220
        // Undefined == no composition
 
221
            break;
 
222
        case COMPOSITE_OVER:
 
223
            compositeOver(dst, dstRowStride, src, srcRowStride, srcAlphaMask, maskRowStride, rows, cols, opacity);
 
224
            break;
 
225
        case COMPOSITE_COPY:
 
226
            compositeCopy(dst, dstRowStride, src, srcRowStride, srcAlphaMask, maskRowStride, rows, cols, opacity);
 
227
            break;
 
228
        case COMPOSITE_ERASE:
 
229
            compositeErase(dst, dstRowStride, src, srcRowStride, srcAlphaMask, maskRowStride, rows, cols, opacity);
 
230
            break;
 
231
        default:
 
232
            break;
 
233
    }
 
234
}
 
235
 
 
236
void KisYCbCrU8ColorSpace::compositeOver(Q_UINT8 *dstRowStart, Q_INT32 dstRowStride, const Q_UINT8 *srcRowStart, Q_INT32 srcRowStride, const Q_UINT8 *maskRowStart, Q_INT32 maskRowStride, Q_INT32 rows, Q_INT32 numColumns, Q_UINT8 opacity)
 
237
{
 
238
    while (rows > 0) {
 
239
 
 
240
        const Q_UINT8 *src = srcRowStart;
 
241
        Q_UINT8 *dst = dstRowStart;
 
242
        const Q_UINT8 *mask = maskRowStart;
 
243
        Q_INT32 columns = numColumns;
 
244
 
 
245
        while (columns > 0) {
 
246
 
 
247
            Q_UINT8 srcAlpha = src[PIXEL_ALPHA];
 
248
 
 
249
            // apply the alphamask
 
250
            if (mask != 0) {
 
251
                if (*mask != OPACITY_OPAQUE) {
 
252
                    srcAlpha *= *mask;
 
253
                }
 
254
                mask++;
 
255
            }
 
256
 
 
257
            if (srcAlpha > OPACITY_TRANSPARENT) {
 
258
 
 
259
                if (opacity < OPACITY_OPAQUE) {
 
260
                    srcAlpha *= opacity;
 
261
                }
 
262
 
 
263
                if (srcAlpha == OPACITY_OPAQUE) {
 
264
                    memcpy(dst, src, MAX_CHANNEL_YCbCrA * sizeof(Q_UINT8));
 
265
                } else {
 
266
                    Q_UINT8 dstAlpha = dst[PIXEL_ALPHA];
 
267
 
 
268
                    Q_UINT8 srcBlend;
 
269
 
 
270
                    if (dstAlpha == OPACITY_OPAQUE ) {
 
271
                        srcBlend = srcAlpha;
 
272
                    } else {
 
273
                        Q_UINT8 newAlpha = dstAlpha + (OPACITY_OPAQUE - dstAlpha) * srcAlpha;
 
274
                        dst[PIXEL_ALPHA] = newAlpha;
 
275
 
 
276
                        if (newAlpha > 0) {
 
277
                            srcBlend = srcAlpha / newAlpha;
 
278
                        } else {
 
279
                            srcBlend = srcAlpha;
 
280
                        }
 
281
                    }
 
282
 
 
283
                    if (srcBlend == OPACITY_OPAQUE) {
 
284
                        memcpy(dst, src, MAX_CHANNEL_YCbCr * sizeof(Q_UINT8));
 
285
                    } else {
 
286
                        dst[PIXEL_Y] = UINT8_BLEND(src[PIXEL_Y], dst[PIXEL_Y], srcBlend);
 
287
                        dst[PIXEL_Cb] = UINT8_BLEND(src[PIXEL_Cb], dst[PIXEL_Cb], srcBlend);
 
288
                        dst[PIXEL_Cr] = UINT8_BLEND(src[PIXEL_Cr], dst[PIXEL_Cr], srcBlend);
 
289
                    }
 
290
                }
 
291
            }
 
292
 
 
293
            columns--;
 
294
            src += MAX_CHANNEL_YCbCrA;
 
295
            dst += MAX_CHANNEL_YCbCrA;
 
296
        }
 
297
 
 
298
        rows--;
 
299
        srcRowStart += srcRowStride;
 
300
        dstRowStart += dstRowStride;
 
301
        if(maskRowStart) {
 
302
            maskRowStart += maskRowStride;
 
303
        }
 
304
    }
 
305
}
 
306
 
 
307
void KisYCbCrU8ColorSpace::compositeErase(Q_UINT8 *dst, Q_INT32 dstRowSize, const Q_UINT8 *src, Q_INT32 srcRowSize, const Q_UINT8 *srcAlphaMask, Q_INT32 maskRowStride, Q_INT32 rows, Q_INT32 cols, Q_UINT8 /*opacity*/)
 
308
{
 
309
    while (rows-- > 0)
 
310
    {
 
311
        const Pixel *s = reinterpret_cast<const Pixel *>(src);
 
312
        Pixel *d = reinterpret_cast<Pixel *>(dst);
 
313
        const Q_UINT8 *mask = srcAlphaMask;
 
314
 
 
315
        for (Q_INT32 i = cols; i > 0; i--, s++, d++)
 
316
        {
 
317
            Q_UINT8 srcAlpha = s -> alpha;
 
318
 
 
319
            // apply the alphamask
 
320
            if (mask != 0) {
 
321
                if (*mask != OPACITY_OPAQUE) {
 
322
                    srcAlpha = *mask;
 
323
                }
 
324
                mask++;
 
325
            }
 
326
            d -> alpha = srcAlpha * d -> alpha;
 
327
        }
 
328
 
 
329
        dst += dstRowSize;
 
330
        src += srcRowSize;
 
331
        if(srcAlphaMask) {
 
332
            srcAlphaMask += maskRowStride;
 
333
        }
 
334
    }
 
335
}
 
336
 
 
337
void KisYCbCrU8ColorSpace::compositeCopy(Q_UINT8 *dstRowStart, Q_INT32 dstRowStride, const Q_UINT8 *srcRowStart, Q_INT32 srcRowStride, const Q_UINT8 */*mask*/, Q_INT32 /*maskRowStride*/, Q_INT32 rows, Q_INT32 numColumns, Q_UINT8 /*opacity*/)
 
338
{
 
339
    while (rows > 0) {
 
340
        memcpy(dstRowStart, srcRowStart, numColumns * sizeof(Pixel));
 
341
        --rows;
 
342
        srcRowStart += srcRowStride;
 
343
        dstRowStart += dstRowStride;
 
344
    }
 
345
}
 
346
 
 
347
KisCompositeOpList KisYCbCrU8ColorSpace::userVisiblecompositeOps() const
 
348
{
 
349
    KisCompositeOpList list;
 
350
 
 
351
    list.append(KisCompositeOp(COMPOSITE_OVER));
 
352
    return list;
 
353
}