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

« back to all changes in this revision

Viewing changes to libs/pigment/colorspaces/KoAlphaColorSpace.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:
16
16
 *  along with this program; if not, write to the Free Software
17
17
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18
18
 */
 
19
#include "KoAlphaColorSpace.h"
19
20
 
20
21
#include <limits.h>
21
22
#include <stdlib.h>
25
26
 
26
27
#include <klocale.h>
27
28
 
28
 
#include <lcms.h>
29
 
 
30
 
#include "KoAlphaColorSpace.h"
31
29
#include "KoChannelInfo.h"
32
30
#include "KoID.h"
33
31
#include "KoIntegerMaths.h"
34
32
#include "KoCompositeOpOver.h"
35
33
#include "KoCompositeOpErase.h"
36
34
#include "KoCompositeOpAlphaDarken.h"
37
 
 
38
 
namespace {
39
 
    const quint8 PIXEL_MASK = 0;
40
 
 
41
 
    class CompositeClear : public KoCompositeOp {
42
 
 
43
 
    public:
44
 
 
45
 
        CompositeClear(KoColorSpace * cs)
46
 
            : KoCompositeOp(cs, COMPOSITE_CLEAR, i18n("Clear" ), KoCompositeOp::categoryMix() )
47
 
            {
48
 
            }
49
 
 
50
 
    public:
51
 
 
52
 
        using KoCompositeOp::composite;
53
 
 
54
 
        void composite(quint8 *dst,
55
 
                       qint32 dststride,
56
 
                       const quint8 *src,
57
 
                       qint32 srcstride,
58
 
                       const quint8 *maskRowStart,
59
 
                       qint32 maskstride,
60
 
                       qint32 rows,
61
 
                       qint32 cols,
62
 
                       quint8 opacity,
63
 
                       const QBitArray & channelFlags) const
64
 
            {
65
 
                Q_UNUSED( src );
66
 
                Q_UNUSED( srcstride );
67
 
                Q_UNUSED( opacity );
68
 
                Q_UNUSED( channelFlags );
69
 
 
70
 
                quint8 *d;
71
 
                qint32 linesize;
72
 
 
73
 
                if (rows <= 0 || cols <= 0)
74
 
                    return;
75
 
 
76
 
                if ( maskRowStart == 0 ) {
77
 
 
78
 
                    linesize = sizeof(quint8) * cols;
79
 
                    d = dst;
80
 
                    while (rows-- > 0) {
81
 
 
82
 
                        memset(d, OPACITY_TRANSPARENT, linesize);
83
 
                        d += dststride;
84
 
                    }
85
 
                }
86
 
                else {
87
 
                    while (rows-- > 0) {
88
 
 
89
 
                        const quint8 *mask = maskRowStart;
90
 
 
91
 
                        d = dst;
92
 
 
93
 
                        for (qint32 i = cols; i > 0; i--, d++) {
94
 
                            // If the mask tells us to completely not
95
 
                            // blend this pixel, continue.
96
 
                            if ( mask != 0 ) {
97
 
                                if ( mask[0] == OPACITY_TRANSPARENT ) {
98
 
                                    mask++;
99
 
                                    continue;
100
 
                                }
101
 
                                mask++;
102
 
                            }
103
 
                            // linesize is uninitialized here, so it just crashes
104
 
                            //memset(d, OPACITY_TRANSPARENT, linesize);
105
 
                        }
106
 
                        dst += dststride;
107
 
                        src += srcstride;
108
 
                        maskRowStart += maskstride;
109
 
                    }
110
 
                }
111
 
 
112
 
            }
113
 
 
114
 
    };
115
 
 
116
 
    class CompositeSubtract : public KoCompositeOp {
117
 
 
118
 
    public:
119
 
 
120
 
        CompositeSubtract(KoColorSpace * cs)
121
 
            : KoCompositeOp(cs, COMPOSITE_SUBTRACT, i18n("Subtract" ), KoCompositeOp::categoryArithmetic() )
122
 
            {
123
 
            }
124
 
 
125
 
    public:
126
 
 
127
 
        using KoCompositeOp::composite;
128
 
 
129
 
        void composite(quint8 *dst,
130
 
                       qint32 dststride,
131
 
                       const quint8 *src,
132
 
                       qint32 srcstride,
133
 
                       const quint8 *maskRowStart,
134
 
                       qint32 maskstride,
135
 
                       qint32 rows,
136
 
                       qint32 cols,
137
 
                       quint8 opacity,
138
 
                       const QBitArray & channelFlags) const
139
 
            {
140
 
 
141
 
                Q_UNUSED( opacity );
142
 
                Q_UNUSED( channelFlags );
143
 
 
144
 
 
145
 
                quint8 *d;
146
 
                const quint8 *s;
147
 
                qint32 i;
148
 
 
149
 
                if (rows <= 0 || cols <= 0)
150
 
                    return;
151
 
 
152
 
                while (rows-- > 0) {
153
 
                    const quint8 *mask = maskRowStart;
154
 
                    d = dst;
155
 
                    s = src;
156
 
 
157
 
                    for (i = cols; i > 0; i--, d++, s++) {
158
 
 
159
 
                        // If the mask tells us to completely not
160
 
                        // blend this pixel, continue.
161
 
                        if ( mask != 0 ) {
162
 
                            if ( mask[0] == OPACITY_TRANSPARENT ) {
163
 
                                mask++;
164
 
                                continue;
165
 
                            }
 
35
#include <colorprofiles/KoDummyColorProfile.h>
 
36
 
 
37
namespace
 
38
{
 
39
const quint8 PIXEL_MASK = 0;
 
40
 
 
41
class CompositeClear : public KoCompositeOp
 
42
{
 
43
 
 
44
public:
 
45
 
 
46
    CompositeClear(KoColorSpace * cs)
 
47
            : KoCompositeOp(cs, COMPOSITE_CLEAR, i18n("Clear"), KoCompositeOp::categoryMix()) {
 
48
    }
 
49
 
 
50
public:
 
51
 
 
52
    using KoCompositeOp::composite;
 
53
 
 
54
    void composite(quint8 *dst,
 
55
                   qint32 dststride,
 
56
                   const quint8 *src,
 
57
                   qint32 srcstride,
 
58
                   const quint8 *maskRowStart,
 
59
                   qint32 maskstride,
 
60
                   qint32 rows,
 
61
                   qint32 cols,
 
62
                   quint8 opacity,
 
63
                   const QBitArray & channelFlags) const {
 
64
        Q_UNUSED(src);
 
65
        Q_UNUSED(srcstride);
 
66
        Q_UNUSED(opacity);
 
67
        Q_UNUSED(channelFlags);
 
68
 
 
69
        quint8 *d;
 
70
        qint32 linesize;
 
71
 
 
72
        if (rows <= 0 || cols <= 0)
 
73
            return;
 
74
 
 
75
        if (maskRowStart == 0) {
 
76
 
 
77
            linesize = sizeof(quint8) * cols;
 
78
            d = dst;
 
79
            while (rows-- > 0) {
 
80
 
 
81
                memset(d, OPACITY_TRANSPARENT_U8, linesize);
 
82
                d += dststride;
 
83
            }
 
84
        } else {
 
85
            while (rows-- > 0) {
 
86
 
 
87
                const quint8 *mask = maskRowStart;
 
88
 
 
89
                d = dst;
 
90
 
 
91
                for (qint32 i = cols; i > 0; i--, d++) {
 
92
                    // If the mask tells us to completely not
 
93
                    // blend this pixel, continue.
 
94
                    if (mask != 0) {
 
95
                        if (mask[0] == OPACITY_TRANSPARENT_U8) {
166
96
                            mask++;
167
 
                        }
168
 
 
169
 
                        if (d[PIXEL_MASK] <= s[PIXEL_MASK]) {
170
 
                            d[PIXEL_MASK] = OPACITY_TRANSPARENT;
171
 
                        } else {
172
 
                            d[PIXEL_MASK] -= s[PIXEL_MASK];
173
 
                        }
174
 
                    }
175
 
 
176
 
                    dst += dststride;
177
 
                    src += srcstride;
178
 
 
179
 
                    if(maskRowStart) {
180
 
                        maskRowStart += maskstride;
181
 
                    }
182
 
                }
183
 
            }
184
 
    };
 
97
                            continue;
 
98
                        }
 
99
                        mask++;
 
100
                    }
 
101
                    // linesize is uninitialized here, so it just crashes
 
102
                    //memset(d, OPACITY_TRANSPARENT, linesize);
 
103
                }
 
104
                dst += dststride;
 
105
                src += srcstride;
 
106
                maskRowStart += maskstride;
 
107
            }
 
108
        }
 
109
 
 
110
    }
 
111
 
 
112
};
 
113
 
 
114
class CompositeSubtract : public KoCompositeOp
 
115
{
 
116
 
 
117
public:
 
118
 
 
119
    CompositeSubtract(KoColorSpace * cs)
 
120
            : KoCompositeOp(cs, COMPOSITE_SUBTRACT, i18n("Subtract"), KoCompositeOp::categoryArithmetic()) {
 
121
    }
 
122
 
 
123
public:
 
124
 
 
125
    using KoCompositeOp::composite;
 
126
 
 
127
    void composite(quint8 *dst,
 
128
                   qint32 dststride,
 
129
                   const quint8 *src,
 
130
                   qint32 srcstride,
 
131
                   const quint8 *maskRowStart,
 
132
                   qint32 maskstride,
 
133
                   qint32 rows,
 
134
                   qint32 cols,
 
135
                   quint8 opacity,
 
136
                   const QBitArray & channelFlags) const {
 
137
 
 
138
        Q_UNUSED(opacity);
 
139
        Q_UNUSED(channelFlags);
 
140
 
 
141
 
 
142
        quint8 *d;
 
143
        const quint8 *s;
 
144
        qint32 i;
 
145
 
 
146
        if (rows <= 0 || cols <= 0)
 
147
            return;
 
148
 
 
149
        while (rows-- > 0) {
 
150
            const quint8 *mask = maskRowStart;
 
151
            d = dst;
 
152
            s = src;
 
153
 
 
154
            for (i = cols; i > 0; i--, d++, s++) {
 
155
 
 
156
                // If the mask tells us to completely not
 
157
                // blend this pixel, continue.
 
158
                if (mask != 0) {
 
159
                    if (mask[0] == OPACITY_TRANSPARENT_U8) {
 
160
                        mask++;
 
161
                        continue;
 
162
                    }
 
163
                    mask++;
 
164
                }
 
165
 
 
166
                if (d[PIXEL_MASK] <= s[PIXEL_MASK]) {
 
167
                    d[PIXEL_MASK] = OPACITY_TRANSPARENT_U8;
 
168
                } else {
 
169
                    d[PIXEL_MASK] -= s[PIXEL_MASK];
 
170
                }
 
171
            }
 
172
 
 
173
            dst += dststride;
 
174
            src += srcstride;
 
175
 
 
176
            if (maskRowStart) {
 
177
                maskRowStart += maskstride;
 
178
            }
 
179
        }
 
180
    }
 
181
};
185
182
 
186
183
}
187
184
 
188
185
KoAlphaColorSpace::KoAlphaColorSpace() :
189
 
    KoColorSpaceAbstract<AlphaU8Traits>("ALPHA", i18n("Alpha mask") )
 
186
        KoColorSpaceAbstract<AlphaU8Traits>("ALPHA", i18n("Alpha mask"))
190
187
{
191
 
    addChannel(new KoChannelInfo(i18n("Alpha"), 0, KoChannelInfo::ALPHA, KoChannelInfo::UINT8));
192
 
    addCompositeOp( new KoCompositeOpOver<AlphaU8Traits>( this ) );
193
 
    addCompositeOp( new CompositeClear( this ) );
194
 
    addCompositeOp( new KoCompositeOpErase<AlphaU8Traits>( this ) );
195
 
    addCompositeOp( new CompositeSubtract( this ) );
196
 
    addCompositeOp( new KoCompositeOpAlphaDarken<AlphaU8Traits>( this ) );
 
188
    addChannel(new KoChannelInfo(i18n("Alpha"), 0, 0, KoChannelInfo::ALPHA, KoChannelInfo::UINT8));
 
189
    addCompositeOp(new KoCompositeOpOver<AlphaU8Traits>(this));
 
190
    addCompositeOp(new CompositeClear(this));
 
191
    addCompositeOp(new KoCompositeOpErase<AlphaU8Traits>(this));
 
192
    addCompositeOp(new CompositeSubtract(this));
 
193
    addCompositeOp(new KoCompositeOpAlphaDarken<AlphaU8Traits>(this));
 
194
    m_profile = new KoDummyColorProfile;
197
195
}
198
196
 
199
197
KoAlphaColorSpace::~KoAlphaColorSpace()
200
198
{
 
199
    delete m_profile;
 
200
    m_profile = 0;
201
201
}
202
202
 
203
203
void KoAlphaColorSpace::fromQColor(const QColor& c, quint8 *dst, const KoColorProfile * /*profile*/) const
216
216
    return qAbs(src2[PIXEL_MASK] - src1[PIXEL_MASK]);
217
217
}
218
218
 
219
 
void KoAlphaColorSpace::mixColors(const quint8 **colors, const quint8 *weights, quint32 nColors, quint8 *dst) const
220
 
{
221
 
    if (nColors > 0) {
222
 
        quint32 total = 0;
223
 
 
224
 
        while(nColors)
225
 
        {
226
 
            nColors--;
227
 
            total += *colors[nColors] * weights[nColors];
228
 
        }
229
 
        *dst = total / 255;
230
 
    }
231
 
}
232
 
 
233
219
bool KoAlphaColorSpace::convertPixelsTo(const quint8 *src,
234
 
                     quint8 *dst, const KoColorSpace * dstColorSpace,
235
 
                     quint32 numPixels,
236
 
                     KoColorConversionTransformation::Intent /*renderingIntent*/) const
 
220
                                        quint8 *dst, const KoColorSpace * dstColorSpace,
 
221
                                        quint32 numPixels,
 
222
                                        KoColorConversionTransformation::Intent /*renderingIntent*/) const
237
223
{
238
224
    // No lcms trickery here, we are only a opacity channel
239
225
    qint32 size = dstColorSpace->pixelSize();
245
231
 
246
232
}
247
233
 
248
 
 
249
 
 
250
234
QString KoAlphaColorSpace::channelValueText(const quint8 *pixel, quint32 channelIndex) const
251
235
{
252
236
    Q_ASSERT(channelIndex < channelCount());
263
247
    return QString().setNum(static_cast<float>(pixel[channelPosition]) / UINT8_MAX);
264
248
}
265
249
 
266
 
 
267
 
void KoAlphaColorSpace::convolveColors(quint8** colors, qint32 * kernelValues, quint8 *dst, qint32 factor, qint32 offset, qint32 nColors, const QBitArray & channelFlags) const
 
250
void KoAlphaColorSpace::convolveColors(quint8** colors, qreal * kernelValues, quint8 *dst, qreal factor, qreal offset, qint32 nColors, const QBitArray & channelFlags) const
268
251
{
269
 
    qint32 totalAlpha = 0;
 
252
    qreal totalAlpha = 0;
270
253
 
271
 
    while (nColors--)
272
 
    {
273
 
        qint32 weight = *kernelValues;
 
254
    while (nColors--) {
 
255
        qreal weight = *kernelValues;
274
256
 
275
257
        if (weight != 0) {
276
258
            totalAlpha += (*colors)[PIXEL_MASK] * weight;
279
261
        kernelValues++;
280
262
    }
281
263
 
282
 
    if ( channelFlags.isEmpty() || channelFlags.testBit(PIXEL_MASK) )
283
 
        dst[PIXEL_MASK] = CLAMP((totalAlpha/ factor) + offset, 0, SCHAR_MAX);
 
264
    if (channelFlags.isEmpty() || channelFlags.testBit(PIXEL_MASK))
 
265
        dst[PIXEL_MASK] = CLAMP((totalAlpha / factor) + offset, 0, SCHAR_MAX);
284
266
}
285
267
 
 
268
 
286
269
QImage KoAlphaColorSpace::convertToQImage(const quint8 *data, qint32 width, qint32 height,
287
 
                                   const KoColorProfile *  /*dstProfile*/, KoColorConversionTransformation::Intent /*renderingIntent*/) const
 
270
        const KoColorProfile *  /*dstProfile*/, KoColorConversionTransformation::Intent /*renderingIntent*/) const
288
271
{
289
 
    QImage img(width, height, QImage::Format_RGB32);
 
272
    QImage img(width, height, QImage::Format_Indexed8);
 
273
    QVector<QRgb> table;
 
274
    for (int i = 0; i < 256; ++i) table.append(qRgb(i, i, i));
 
275
    img.setColorTable(table);
290
276
 
291
 
    for (int x = 0; x < width; x++) {
292
 
        for (int y = 0; y < height; y++) {
293
 
            quint8 c = data[x + y * width];
294
 
            img.setPixel(x, y, qRgb(c, c, c));
295
 
        }
 
277
    quint8* data_img;
 
278
    for (int i = 0; i < height; ++i) {
 
279
        data_img=img.scanLine(i);
 
280
        for (int j = 0; j < width; j++)
 
281
            data_img[j]=*(data++);
296
282
    }
 
283
 
297
284
    return img;
298
285
}
299
286