Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_fixed_paint_device.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2009 Boudewijn Rempt <boud@valdyas.org>
3 * SPDX-FileCopyrightText: 2010 Lukáš Tvrdý <lukast.dev@gmail.com>
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 */
8
10#include <KoColor.h>
12#include "kis_debug.h"
13
15 : m_colorSpace(colorSpace),
16 m_data(allocator)
17{
18}
19
23
31
33{
34 m_bounds = rhs.m_bounds;
36
37
38 const int referenceSize = m_bounds.height() * m_bounds.width() * pixelSize();
39
40 if (m_data.size() >= referenceSize) {
41 memcpy(m_data.data(), rhs.m_data.constData(), referenceSize);
42 } else {
43 m_data = rhs.m_data;
44 }
45
46 return *this;
47}
48
49void KisFixedPaintDevice::setRect(const QRect& rc)
50{
51 m_bounds = rc;
52}
53
58
60{
61 return m_bounds;
62}
63
64
69
70
72{
73 return m_colorSpace->pixelSize();
74}
75
76bool KisFixedPaintDevice::initialize(quint8 defaultValue)
77{
78 m_data.fill(defaultValue, m_bounds.height() * m_bounds.width() * pixelSize());
79
80 return true;
81}
82
84{
85 const int referenceSize = m_bounds.height() * m_bounds.width() * pixelSize();
86
87 if (referenceSize != m_data.size()) {
88 m_data.resize(m_bounds.height() * m_bounds.width() * pixelSize());
89 }
90}
91
93{
94 const int referenceSize = m_bounds.height() * m_bounds.width() * pixelSize();
95
96 if (m_data.size() < referenceSize) {
97 m_data.resize(referenceSize);
98 }
99}
100
102{
103 return (quint8*) m_data.data();
104}
105
107{
108 return (const quint8*) m_data.constData();
109}
110
112{
113 return const_cast<quint8*>(m_data.constData());
114}
115
118 KoColorConversionTransformation::ConversionFlags conversionFlags)
119{
120 if (*m_colorSpace == *dstColorSpace) {
121 return;
122 }
123 quint32 size = m_bounds.width() * m_bounds.height();
125
126 // make sure that we are not initializing the destination pixels!
127 dstData.resize(size * dstColorSpace->pixelSize());
128
129 m_colorSpace->convertPixelsTo(constData(), (quint8*)dstData.data(),
130 dstColorSpace,
131 size,
132 renderingIntent,
133 conversionFlags);
134
135 m_colorSpace = dstColorSpace;
136 m_data = dstData;
137}
138
140{
142
143 const KoColorSpace *dstColorSpace =
145 colorSpace()->colorModelId().id(),
146 colorSpace()->colorDepthId().id(),
147 profile);
148
149 KIS_SAFE_ASSERT_RECOVER_RETURN(dstColorSpace);
150
151 m_colorSpace = dstColorSpace;
152}
153
154void KisFixedPaintDevice::convertFromQImage(const QImage& _image, const QString &srcProfileName)
155{
156 QImage image = _image;
157
158 if (image.format() != QImage::Format_ARGB32) {
159 image.convertTo(QImage::Format_ARGB32);
160 }
161 setRect(image.rect());
163
164 // Don't convert if not no profile is given and both paint dev and qimage are rgba.
165 if (srcProfileName.isEmpty() && colorSpace()->id() == "RGBA") {
166 memcpy(data(), image.constBits(), image.sizeInBytes());
167 } else {
170 ->convertPixelsTo(image.constBits(), data(), colorSpace(), image.width() * image.height(),
173 }
174}
175
176QImage KisFixedPaintDevice::convertToQImage(const KoColorProfile * dstProfile, KoColorConversionTransformation::Intent intent, KoColorConversionTransformation::ConversionFlags conversionFlags) const
177{
178 qint32 x1;
179 qint32 y1;
180 qint32 w;
181 qint32 h;
182
183 x1 = m_bounds.x();
184 y1 = m_bounds.y();
185 w = m_bounds.width();
186 h = m_bounds.height();
187
188 return convertToQImage(dstProfile, x1, y1, w, h, intent, conversionFlags);
189}
190
191QImage KisFixedPaintDevice::convertToQImage(const KoColorProfile * dstProfile, qint32 x1, qint32 y1, qint32 w, qint32 h, KoColorConversionTransformation::Intent intent, KoColorConversionTransformation::ConversionFlags conversionFlags) const
192{
193 Q_ASSERT( m_bounds.contains(QRect(x1,y1,w,h)) );
194
195 if (w < 0)
196 return QImage();
197
198 if (h < 0)
199 return QImage();
200
201 if (QRect(x1, y1, w, h) == m_bounds) {
202 return colorSpace()->convertToQImage(constData(), w, h, dstProfile,
203 intent, conversionFlags);
204 } else {
205 try {
206 // XXX: fill the image row by row!
207 const int pSize = pixelSize();
208 const int deviceWidth = m_bounds.width();
209 quint8* newData = new quint8[w * h * pSize];
210 const quint8* srcPtr = constData() + x1 * pSize + y1 * deviceWidth * pSize;
211 quint8* dstPtr = newData;
212 // copy the right area out of the paint device into data
213 for (int row = 0; row < h; row++) {
214 memcpy(dstPtr, srcPtr, w * pSize);
215 srcPtr += deviceWidth * pSize;
216 dstPtr += w * pSize;
217 }
218 QImage image = colorSpace()->convertToQImage(newData, w, h, dstProfile, intent, conversionFlags);
219 return image;
220 }
221 catch(const std::bad_alloc&) {
222 return QImage();
223 }
224 }
225}
226
227void KisFixedPaintDevice::clear(const QRect & rc)
228{
229 KoColor c(Qt::black, m_colorSpace);
230 quint8* black = new quint8[pixelSize()];
231 memcpy(black, c.data(), m_colorSpace->pixelSize());
233 fill(rc.x(), rc.y(), rc.width(), rc.height(), black);
234 delete[] black;
235}
236
237void KisFixedPaintDevice::fill(const QRect &rc, const KoColor &color)
238{
239 KoColor realColor(color);
240 realColor.convertTo(colorSpace());
241 fill(rc.x(), rc.y(), rc.width(), rc.height(), realColor.data());
242}
243
244void KisFixedPaintDevice::fill(qint32 x, qint32 y, qint32 w, qint32 h, const quint8 *fillPixel)
245{
246 if (m_data.isEmpty() || m_bounds.isEmpty()) {
247 setRect(QRect(x, y, w, h));
249 }
250
251 QRect rc(x, y, w, h);
252 if (!m_bounds.contains(rc)) {
253 rc = m_bounds;
254 }
255
256 quint8 pixelSize = m_colorSpace->pixelSize();
257 quint8* dabPointer = data();
258
259 if (rc.contains(m_bounds)) {
260 for (int i = 0; i < w * h ; ++i) {
261 memcpy(dabPointer, fillPixel, pixelSize);
262 dabPointer += pixelSize;
263 }
264
265 } else {
266 int deviceWidth = bounds().width();
267 quint8* rowPointer = dabPointer + ((y - bounds().y()) * deviceWidth + (x - bounds().x())) * pixelSize;
268 for (int row = 0; row < h; row++) {
269 for (int col = 0; col < w; col++) {
270 memcpy(rowPointer + col * pixelSize , fillPixel, pixelSize);
271 }
272 rowPointer += deviceWidth * pixelSize;
273 }
274 }
275}
276
277
278void KisFixedPaintDevice::readBytes(quint8* dstData, qint32 x, qint32 y, qint32 w, qint32 h) const
279{
280 if (m_data.isEmpty() || m_bounds.isEmpty()) {
281 return;
282 }
283
284 QRect rc(x, y, w, h);
285 if (!m_bounds.contains(rc)){
286 return;
287 }
288
289 const int pixelSize = m_colorSpace->pixelSize();
290 const quint8* dabPointer = constData();
291
292 if (rc == m_bounds) {
293 memcpy(dstData, dabPointer, pixelSize * w * h);
294 } else {
295 int deviceWidth = m_bounds.width();
296 const quint8* rowPointer = dabPointer + ((y - bounds().y()) * deviceWidth + (x - bounds().x())) * pixelSize;
297 for (int row = 0; row < h; row++) {
298 memcpy(dstData, rowPointer, w * pixelSize);
299 rowPointer += deviceWidth * pixelSize;
300 dstData += w * pixelSize;
301 }
302 }
303}
304
305void KisFixedPaintDevice::mirror(bool horizontal, bool vertical)
306{
307 if (!horizontal && !vertical){
308 return;
309 }
310
312 int w = m_bounds.width();
313 int h = m_bounds.height();
314
315 if (horizontal){
316 int rowSize = pixelSize * w;
317
318 quint8 * dabPointer = data();
319 quint8 * row = new quint8[ rowSize ];
320 quint8 * mirror = 0;
321
322 for (int y = 0; y < h ; y++){
323 // TODO: implement better flipping of the data
324
325 memcpy(row, dabPointer, rowSize);
326 mirror = row;
327 mirror += (w-1) * pixelSize;
328 for (int x = 0; x < w; x++){
329 memcpy(dabPointer,mirror,pixelSize);
330 dabPointer += pixelSize;
331 mirror -= pixelSize;
332 }
333 }
334
335 delete [] row;
336 }
337
338 if (vertical){
339 int rowsToMove = h / 2;
340 int rowSize = pixelSize * w;
341
342 quint8 * startRow = data();
343 quint8 * endRow = data() + (h-1) * w * pixelSize;
344 quint8 * row = new quint8[ rowSize ];
345
346 for (int y = 0; y < rowsToMove; y++){
347 memcpy(row, startRow, rowSize);
348 memcpy(startRow, endRow, rowSize);
349 memcpy(endRow, row, rowSize);
350
351 startRow += rowSize;
352 endRow -= rowSize;
353 }
354
355 delete [] row;
356 }
357
358}
const KoID Integer8BitsColorDepthID("U8", ki18n("8-bit integer/channel"))
const KoID RGBAColorModelID("RGBA", ki18n("RGB/Alpha"))
const quint8 OPACITY_TRANSPARENT_U8
void readBytes(quint8 *dstData, qint32 x, qint32 y, qint32 w, qint32 h) const
const quint8 * constData() const
const KoColorSpace * m_colorSpace
void setColorSpace(const KoColorSpace *cs)
KisFixedPaintDevice(const KoColorSpace *colorSpace, KisOptimizedByteArray::MemoryAllocatorSP allocator=KisOptimizedByteArray::MemoryAllocatorSP())
void setRect(const QRect &rc)
bool initialize(quint8 defaultValue=0)
KisOptimizedByteArray m_data
void clear(const QRect &rc)
virtual QImage convertToQImage(const KoColorProfile *dstProfile, qint32 x, qint32 y, qint32 w, qint32 h, KoColorConversionTransformation::Intent renderingIntent=KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::ConversionFlags conversionFlags=KoColorConversionTransformation::internalConversionFlags()) const
void setProfile(const KoColorProfile *profile)
virtual void convertFromQImage(const QImage &image, const QString &srcProfileName)
KisFixedPaintDevice & operator=(const KisFixedPaintDevice &rhs)
void mirror(bool horizontal, bool vertical)
void convertTo(const KoColorSpace *dstColorSpace=0, KoColorConversionTransformation::Intent renderingIntent=KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::ConversionFlags conversionFlags=KoColorConversionTransformation::internalConversionFlags())
void fill(qint32 x, qint32 y, qint32 w, qint32 h, const quint8 *fillPixel)
const KoColorSpace * colorSpace() const
const quint8 * constData() const
void fill(quint8 value, int size=-1)
MemoryAllocatorSP customMemoryAllocator() const
virtual quint32 pixelSize() const =0
virtual QImage convertToQImage(const quint8 *data, qint32 width, qint32 height, const KoColorProfile *dstProfile, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags) const
virtual void setOpacity(quint8 *pixels, quint8 alpha, qint32 nPixels) const =0
virtual bool convertPixelsTo(const quint8 *src, quint8 *dst, const KoColorSpace *dstColorSpace, quint32 numPixels, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags) const
void convertTo(const KoColorSpace *cs, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags)
Definition KoColor.cpp:136
quint8 * data()
Definition KoColor.h:144
QString id() const
Definition KoID.cpp:63
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128
const KoColorSpace * colorSpace(const QString &colorModelId, const QString &colorDepthId, const KoColorProfile *profile)
static KoColorSpaceRegistry * instance()