24
24
#include <qimage.h>
25
25
#include <qpainter.h>
28
#include <qapplication.h>
30
#include <qdatetime.h>
30
32
#include <kcommand.h>
31
#include <kocommandhistory.h>
32
33
#include <kdebug.h>
33
34
#include <klocale.h>
35
#include "KIsImageIface.h"
36
#include "kis_image_iface.h"
38
#include "kis_annotation.h"
39
#include "kis_colorspace_factory_registry.h"
40
#include "kis_color.h"
41
#include "kis_command.h"
42
#include "kis_types.h"
43
//#include "kis_guide.h"
37
44
#include "kis_image.h"
38
45
#include "kis_paint_device.h"
39
#include "kis_paint_device_visitor.h"
46
#include "kis_paint_device_action.h"
47
#include "kis_selection.h"
40
48
#include "kis_painter.h"
41
49
#include "kis_fill_painter.h"
42
50
#include "kis_layer.h"
51
#include "kis_group_layer.h"
52
#include "kis_adjustment_layer.h"
53
#include "kis_paint_layer.h"
54
#include "kis_colorspace_convert_visitor.h"
43
55
#include "kis_background.h"
45
56
#include "kis_nameserver.h"
46
#include "visitors/kis_flatten.h"
47
#include "visitors/kis_merge.h"
57
#include "kis_undo_adapter.h"
58
#include "kis_merge_visitor.h"
48
59
#include "kis_transaction.h"
49
#include "kis_scale_visitor.h"
60
#include "kis_crop_visitor.h"
61
#include "kis_transform_visitor.h"
62
#include "kis_filter_strategy.h"
50
63
#include "kis_profile.h"
51
#include "kis_config.h"
52
#include "kis_colorspace_registry.h"
54
#define DEBUG_IMAGES 0
57
static int numImages = 0;
64
#include "kis_paint_layer.h"
65
#include "kis_change_profile_visitor.h"
66
#include "kis_group_layer.h"
67
#include "kis_iterators_pixel.h"
68
#include "kis_shear_visitor.h"
70
class KisImage::KisImagePrivate {
72
KisColor backgroundColor;
74
bool sizeChangedWhileLocked;
75
bool selectionChangedWhileLocked;
62
class KisResizeImageCmd : public KNamedCommand {
63
typedef KNamedCommand super;
66
KisResizeImageCmd(KisUndoAdapter *adapter,
71
Q_INT32 oldHeight) : super(i18n("Resize Image"))
75
m_before = QSize(oldWidth, oldHeight);
76
m_after = QSize(width, height);
79
virtual ~KisResizeImageCmd()
84
virtual void execute()
86
m_adapter -> setUndo(false);
87
m_img -> resize(m_after.width(), m_after.height());
88
m_adapter -> setUndo(true);
89
m_img -> notify(0, 0, QMAX(m_before.width(), m_after.width()), QMAX(m_before.height(), m_after.height()));
92
virtual void unexecute()
94
m_adapter -> setUndo(false);
95
m_img -> resize(m_before.width(), m_before.height());
96
m_adapter -> setUndo(true);
97
m_img -> notify(0, 0, QMAX(m_before.width(), m_after.width()), QMAX(m_before.height(), m_after.height()));
101
KisUndoAdapter *m_adapter;
108
class KisChangeLayersCmd : public KNamedCommand {
109
typedef KNamedCommand super;
112
KisChangeLayersCmd(KisUndoAdapter *adapter, KisImageSP img, vKisLayerSP& beforeLayers, vKisLayerSP& afterLayers, const QString& name) : super(name)
116
m_beforeLayers = beforeLayers;
117
m_afterLayers = afterLayers;
120
virtual ~KisChangeLayersCmd()
125
virtual void execute()
127
m_adapter -> setUndo(false);
129
for (vKisLayerSP::const_iterator it = m_beforeLayers.begin(); it != m_beforeLayers.end(); it++) {
133
for (vKisLayerSP::const_iterator it = m_afterLayers.begin(); it != m_afterLayers.end(); it++) {
134
m_img -> add(*it, -1);
137
m_adapter -> setUndo(true);
139
m_img -> notifyLayersChanged();
142
virtual void unexecute()
144
m_adapter -> setUndo(false);
146
for (vKisLayerSP::const_iterator it = m_afterLayers.begin(); it != m_afterLayers.end(); it++) {
150
for (vKisLayerSP::const_iterator it = m_beforeLayers.begin(); it != m_beforeLayers.end(); it++) {
151
m_img -> add(*it, -1);
154
m_adapter -> setUndo(true);
156
m_img -> notifyLayersChanged();
160
KisUndoAdapter *m_adapter;
162
vKisLayerSP m_beforeLayers;
163
vKisLayerSP m_afterLayers;
166
class KisConvertImageTypeCmd : public KNamedCommand {
167
typedef KNamedCommand super;
170
KisConvertImageTypeCmd(KisUndoAdapter *adapter, KisImageSP img,
171
KisStrategyColorSpaceSP beforeColorSpace, KisProfileSP beforeProfile,
172
KisStrategyColorSpaceSP afterColorSpace, KisProfileSP afterProfile
173
) : super(i18n("&Convert Image Type...")) //XXX: fix when string freeze over
177
m_beforeColorSpace = beforeColorSpace;
178
m_beforeProfile = beforeProfile;
179
m_afterColorSpace = afterColorSpace;
180
m_afterProfile = afterProfile;
183
virtual ~KisConvertImageTypeCmd()
188
virtual void execute()
190
m_adapter -> setUndo(false);
192
m_img -> setColorStrategy(m_afterColorSpace);
193
m_img -> setProfile(m_afterProfile);
195
m_adapter -> setUndo(true);
197
m_img -> notifyLayersChanged();
200
virtual void unexecute()
202
m_adapter -> setUndo(false);
204
m_img -> setColorStrategy(m_beforeColorSpace);
205
m_img -> setProfile(m_beforeProfile);
207
m_adapter -> setUndo(true);
209
m_img -> notifyLayersChanged();
213
KisUndoAdapter *m_adapter;
215
KisStrategyColorSpaceSP m_beforeColorSpace;
216
KisStrategyColorSpaceSP m_afterColorSpace;
217
KisProfileSP m_beforeProfile;
218
KisProfileSP m_afterProfile;
81
class KisResizeImageCmd : public KNamedCommand {
82
typedef KNamedCommand super;
85
KisResizeImageCmd(KisUndoAdapter *adapter,
90
Q_INT32 oldHeight) : super(i18n("Resize Image"))
94
m_before = QSize(oldWidth, oldHeight);
95
m_after = QSize(width, height);
98
virtual ~KisResizeImageCmd()
103
virtual void execute()
105
m_adapter->setUndo(false);
106
m_img->resize(m_after.width(), m_after.height());
107
m_adapter->setUndo(true);
110
virtual void unexecute()
112
m_adapter->setUndo(false);
113
m_img->resize(m_before.width(), m_before.height());
114
m_adapter->setUndo(true);
118
KisUndoAdapter *m_adapter;
124
// -------------------------------------------------------
126
class KisChangeLayersCmd : public KNamedCommand {
127
typedef KNamedCommand super;
130
KisChangeLayersCmd(KisUndoAdapter *adapter, KisImageSP img,
131
KisGroupLayerSP oldRootLayer, KisGroupLayerSP newRootLayer, const QString& name)
136
m_oldRootLayer = oldRootLayer;
137
m_newRootLayer = newRootLayer;
140
virtual ~KisChangeLayersCmd()
145
virtual void execute()
147
m_adapter->setUndo(false);
148
m_img->setRootLayer(m_newRootLayer);
149
m_adapter->setUndo(true);
150
m_img->notifyLayersChanged();
153
virtual void unexecute()
155
m_adapter->setUndo(false);
156
m_img->setRootLayer(m_oldRootLayer);
157
m_adapter->setUndo(true);
158
m_img->notifyLayersChanged();
162
KisUndoAdapter *m_adapter;
164
KisGroupLayerSP m_oldRootLayer;
165
KisGroupLayerSP m_newRootLayer;
169
// -------------------------------------------------------
171
class KisConvertImageTypeCmd : public KNamedCommand {
172
typedef KNamedCommand super;
175
KisConvertImageTypeCmd(KisUndoAdapter *adapter, KisImageSP img,
176
KisColorSpace * beforeColorSpace, KisColorSpace * afterColorSpace
177
) : super(i18n("Convert Image Type"))
181
m_beforeColorSpace = beforeColorSpace;
182
m_afterColorSpace = afterColorSpace;
185
virtual ~KisConvertImageTypeCmd()
190
virtual void execute()
192
m_adapter->setUndo(false);
194
m_img->setColorSpace(m_afterColorSpace);
195
m_img->setProfile(m_afterColorSpace->getProfile());
197
m_adapter->setUndo(true);
200
virtual void unexecute()
202
m_adapter->setUndo(false);
204
m_img->setColorSpace(m_beforeColorSpace);
205
m_img->setProfile(m_beforeColorSpace->getProfile());
207
m_adapter->setUndo(true);
211
KisUndoAdapter *m_adapter;
213
KisColorSpace * m_beforeColorSpace;
214
KisColorSpace * m_afterColorSpace;
218
// -------------------------------------------------------
220
class KisImageCommand : public KNamedCommand {
221
typedef KNamedCommand super;
224
KisImageCommand(const QString& name, KisImageSP image);
225
virtual ~KisImageCommand() {}
227
virtual void execute() = 0;
228
virtual void unexecute() = 0;
231
void setUndo(bool undo);
236
KisImageCommand::KisImageCommand(const QString& name, KisImageSP image) :
237
super(name), m_image(image)
241
void KisImageCommand::setUndo(bool undo)
243
if (m_image->undoAdapter()) {
244
m_image->undoAdapter()->setUndo(undo);
249
// -------------------------------------------------------
251
class KisLayerPositionCommand : public KisImageCommand {
252
typedef KisImageCommand super;
255
KisLayerPositionCommand(const QString& name, KisImageSP image, KisLayerSP layer, KisGroupLayerSP parent, KisLayerSP aboveThis) : super(name, image)
258
m_oldParent = layer->parent();
259
m_oldAboveThis = layer->nextSibling();
260
m_newParent = parent;
261
m_newAboveThis = aboveThis;
264
virtual void execute()
267
m_image->moveLayer(m_layer, m_newParent, m_newAboveThis);
271
virtual void unexecute()
274
m_image->moveLayer(m_layer, m_oldParent, m_oldAboveThis);
280
KisGroupLayerSP m_oldParent;
281
KisLayerSP m_oldAboveThis;
282
KisGroupLayerSP m_newParent;
283
KisLayerSP m_newAboveThis;
287
// -------------------------------------------------------
289
class LayerAddCmd : public KisCommand {
290
typedef KisCommand super;
293
LayerAddCmd(KisUndoAdapter *adapter, KisImageSP img, KisLayerSP layer) : super(i18n("Add Layer"), adapter)
297
m_parent = layer->parent();
298
m_aboveThis = layer->nextSibling();
301
virtual ~LayerAddCmd()
305
virtual void execute()
307
adapter()->setUndo(false);
308
m_img->addLayer(m_layer, m_parent.data(), m_aboveThis);
309
adapter()->setUndo(true);
312
virtual void unexecute()
314
adapter()->setUndo(false);
315
m_img->removeLayer(m_layer);
316
adapter()->setUndo(true);
322
KisGroupLayerSP m_parent;
323
KisLayerSP m_aboveThis;
326
// -------------------------------------------------------
328
class LayerRmCmd : public KNamedCommand {
329
typedef KNamedCommand super;
332
LayerRmCmd(KisUndoAdapter *adapter, KisImageSP img,
333
KisLayerSP layer, KisGroupLayerSP wasParent, KisLayerSP wasAbove)
334
: super(i18n("Remove Layer"))
339
m_prevParent = wasParent;
340
m_prevAbove = wasAbove;
343
virtual ~LayerRmCmd()
347
virtual void execute()
349
m_adapter->setUndo(false);
350
m_img->removeLayer(m_layer);
351
m_adapter->setUndo(true);
354
virtual void unexecute()
356
m_adapter->setUndo(false);
357
m_img->addLayer(m_layer, m_prevParent.data(), m_prevAbove);
358
m_adapter->setUndo(true);
362
KisUndoAdapter *m_adapter;
365
KisGroupLayerSP m_prevParent;
366
KisLayerSP m_prevAbove;
369
class LayerMoveCmd: public KNamedCommand {
370
typedef KNamedCommand super;
373
LayerMoveCmd(KisUndoAdapter *adapter, KisImageSP img,
374
KisLayerSP layer, KisGroupLayerSP wasParent, KisLayerSP wasAbove)
375
: super(i18n("Move Layer"))
380
m_prevParent = wasParent;
381
m_prevAbove = wasAbove;
382
m_newParent = layer->parent();
383
m_newAbove = layer->nextSibling();
386
virtual ~LayerMoveCmd()
390
virtual void execute()
392
m_adapter->setUndo(false);
393
m_img->moveLayer(m_layer, m_newParent.data(), m_newAbove);
394
m_adapter->setUndo(true);
397
virtual void unexecute()
399
m_adapter->setUndo(false);
400
m_img->moveLayer(m_layer, m_prevParent.data(), m_prevAbove);
401
m_adapter->setUndo(true);
405
KisUndoAdapter *m_adapter;
408
KisGroupLayerSP m_prevParent;
409
KisLayerSP m_prevAbove;
410
KisGroupLayerSP m_newParent;
411
KisLayerSP m_newAbove;
415
// -------------------------------------------------------
417
class LayerPropsCmd : public KNamedCommand {
418
typedef KNamedCommand super;
421
LayerPropsCmd(KisLayerSP layer,
423
KisUndoAdapter *adapter,
426
const KisCompositeOp& compositeOp) : super(i18n("Layer Property Changes"))
433
m_compositeOp = compositeOp;
436
virtual ~LayerPropsCmd()
441
virtual void execute()
443
QString name = m_layer->name();
444
Q_INT32 opacity = m_layer->opacity();
445
KisCompositeOp compositeOp = m_layer->compositeOp();
447
m_adapter->setUndo(false);
448
m_img->setLayerProperties(m_layer,
452
m_adapter->setUndo(true);
455
m_compositeOp = compositeOp;
459
virtual void unexecute()
465
KisUndoAdapter *m_adapter;
470
KisCompositeOp m_compositeOp;
473
// -------------------------------------------------------
475
class LockImageCommand : public KNamedCommand {
476
typedef KNamedCommand super;
479
LockImageCommand(KisImageSP img, bool lockImage) : super("lock image") // Not for translation, this
480
{ // is only ever used inside a macro command.
482
m_lockImage = lockImage;
485
virtual ~LockImageCommand()
489
virtual void execute()
498
virtual void unexecute()
223
KisImage::KisImage(KisUndoAdapter *undoAdapter, Q_INT32 width, Q_INT32 height, KisStrategyColorSpaceSP colorStrategy, const QString& name)
513
KisImage::KisImage(KisUndoAdapter *adapter, Q_INT32 width, Q_INT32 height, KisColorSpace * colorSpace, const QString& name)
514
: QObject(0, name.latin1()), KShared()
227
kdDebug() << "IMAGE " << name << " CREATED total now = " << numImages << endl;
229
init(undoAdapter, width, height, colorStrategy, name);
516
init(adapter, width, height, colorSpace, name);
235
521
KisImage::KisImage(const KisImage& rhs) : QObject(), KShared(rhs)
239
kdDebug() << "IMAGE " << rhs.m_name << " copy CREATED total now = " << numImages << endl;
243
m_undoHistory = rhs.m_undoHistory;
245
m_name = QString::null;
246
m_width = rhs.m_width;
247
m_height = rhs.m_height;
251
m_colorStrategy = rhs.m_colorStrategy;
252
m_dirty = rhs.m_dirty;
253
m_adapter = rhs.m_adapter;
254
m_profile = rhs.m_profile;
256
m_bkg = new KisBackground(this, rhs.width(), rhs.height());
259
m_projection = new KisLayer(this, "projection", OPACITY_OPAQUE);
260
Q_CHECK_PTR(m_projection);
262
m_layers.reserve(rhs.m_layers.size());
264
for (vKisLayerSP_cit it = rhs.m_layers.begin(); it != rhs.m_layers.end(); it++) {
265
KisLayerSP layer = new KisLayer(**it);
268
layer -> setImage(this);
269
m_layers.push_back(layer);
270
m_layerStack.push_back(layer);
271
m_activeLayer = layer;
274
m_annotations = rhs.m_annotations; // XXX the annotations would probably need to be deep-copied
277
m_nserver = new KisNameServer(i18n("Layer %1"), rhs.m_nserver -> currentSeed() + 1);
278
Q_CHECK_PTR(m_nserver);
280
m_pixmap = rhs.m_pixmap;
525
m_private = new KisImagePrivate(*rhs.m_private);
527
m_name = QString::null;
528
m_width = rhs.m_width;
529
m_height = rhs.m_height;
533
m_colorSpace = rhs.m_colorSpace;
534
m_dirty = rhs.m_dirty;
535
m_adapter = rhs.m_adapter;
537
m_bkg = new KisBackground();
540
m_rootLayer = static_cast<KisGroupLayer*>(rhs.m_rootLayer->clone().data());
541
connect(m_rootLayer, SIGNAL(sigDirty(QRect)), this, SIGNAL(sigImageUpdated(QRect)));
543
m_annotations = rhs.m_annotations; // XXX the annotations would probably need to be deep-copied
545
m_nserver = new KisNameServer(i18n("Layer %1"), rhs.m_nserver->currentSeed() + 1);
546
Q_CHECK_PTR(m_nserver);
548
//m_guides = rhs.m_guides;
286
DCOPObject *KisImage::dcopObject()
554
DCOPObject * KisImage::dcopObject()
289
m_dcop = new KIsImageIface(this);
557
m_dcop = new KisImageIface(this);
295
563
KisImage::~KisImage()
299
kdDebug() << "IMAGE " << name() << " DESTROYED total now = " << numImages << endl;
305
570
QString KisImage::name() const
310
575
void KisImage::setName(const QString& name)
316
581
QString KisImage::description() const
318
return m_description;
583
return m_description;
321
586
void KisImage::setDescription(const QString& description)
323
if (!description.isEmpty())
324
m_description = description;
588
if (!description.isEmpty())
589
m_description = description;
593
KisColor KisImage::backgroundColor() const
595
return m_private->backgroundColor;
598
void KisImage::setBackgroundColor(const KisColor & color)
600
m_private->backgroundColor = color;
328
604
QString KisImage::nextLayerName() const
330
if (m_nserver -> currentSeed() == 0) {
331
m_nserver -> number();
332
return i18n("background");
335
return m_nserver -> name();
338
void KisImage::init(KisUndoAdapter *adapter, Q_INT32 width, Q_INT32 height, KisStrategyColorSpaceSP colorStrategy, const QString& name)
340
Q_ASSERT(colorStrategy != 0);
341
Q_ASSERT(adapter != 0);
344
m_nserver = new KisNameServer(i18n("Layer %1"), 1);
345
Q_CHECK_PTR(m_nserver);
348
m_colorStrategy = colorStrategy;
349
m_bkg = new KisBackground(this, width, height);
352
m_projection = new KisLayer(this, "projection", OPACITY_OPAQUE);
353
Q_CHECK_PTR(m_projection);
357
m_unit = KoUnit::U_PT;
364
void KisImage::resize(Q_INT32 w, Q_INT32 h, bool cropLayers)
366
// kdDebug() << "KisImage::resize. From: ("
376
if (w != width() || h != height()) {
377
if (m_adapter && m_adapter -> undo()) {
378
m_adapter -> beginMacro("Resize image");
379
m_adapter -> addCommand(new KisResizeImageCmd(m_adapter, this, w, h, width(), height()));
385
m_projection = new KisLayer(this, "projection", OPACITY_OPAQUE);
386
Q_CHECK_PTR(m_projection);
388
m_bkg = new KisBackground(this, w, h);
393
for ( it = m_layers.begin(); it != m_layers.end(); ++it ) {
394
KisLayerSP layer = (*it);
395
KisTransaction * t = new KisTransaction("crop", layer.data());
397
layer -> crop(0, 0, w, h);
398
if (m_adapter && m_adapter -> undo())
399
m_adapter -> addCommand(t);
403
if (m_adapter && m_adapter -> undo()) {
404
m_adapter -> endMacro();
407
emit sizeChanged(KisImageSP(this), w, h);
606
if (m_nserver->currentSeed() == 0) {
608
return i18n("background");
611
return m_nserver->name();
614
void KisImage::rollBackLayerName()
616
m_nserver->rollback();
619
void KisImage::init(KisUndoAdapter *adapter, Q_INT32 width, Q_INT32 height, KisColorSpace * colorSpace, const QString& name)
621
Q_ASSERT(colorSpace);
623
if (colorSpace == 0) {
624
colorSpace = KisMetaRegistry::instance()->csRegistry()->getRGB8();
625
kdWarning(41010) << "No colorspace specified: using RGBA\n";
628
m_private = new KisImagePrivate();
629
m_private->backgroundColor = KisColor(Qt::white, colorSpace);
630
m_private->lockCount = 0;
631
m_private->sizeChangedWhileLocked = false;
632
m_private->selectionChangedWhileLocked = false;
636
m_nserver = new KisNameServer(i18n("Layer %1"), 1);
639
m_colorSpace = colorSpace;
640
m_bkg = new KisBackground();
642
m_rootLayer = new KisGroupLayer(this,"root", OPACITY_OPAQUE);
643
connect(m_rootLayer, SIGNAL(sigDirty(QRect)), this, SIGNAL(sigImageUpdated(QRect)));
647
m_unit = KoUnit::U_PT;
653
bool KisImage::locked() const
655
return m_private->lockCount != 0;
658
void KisImage::lock()
661
if (m_rootLayer) disconnect(m_rootLayer, SIGNAL(sigDirty(QRect)), this, SIGNAL(sigImageUpdated(QRect)));
662
m_private->sizeChangedWhileLocked = false;
663
m_private->selectionChangedWhileLocked = false;
665
m_private->lockCount++;
668
void KisImage::unlock()
673
m_private->lockCount--;
675
if (m_private->lockCount == 0) {
676
if (m_private->sizeChangedWhileLocked) {
677
// A size change implies a full image update so only send this.
678
emit sigSizeChanged(m_width, m_height);
680
if (m_rootLayer->dirty()) emit sigImageUpdated( m_rootLayer->dirtyRect() );
683
if (m_private->selectionChangedWhileLocked) {
684
emit sigActiveSelectionChanged(this);
687
if (m_rootLayer) connect(m_rootLayer, SIGNAL(sigDirty(QRect)), this, SIGNAL(sigImageUpdated(QRect)));
692
void KisImage::emitSizeChanged()
695
emit sigSizeChanged(m_width, m_height);
697
m_private->sizeChangedWhileLocked = true;
701
void KisImage::notifyLayerUpdated(KisLayerSP layer, QRect rc)
703
emit sigLayerUpdated(layer, rc);
706
void KisImage::resize(Q_INT32 w, Q_INT32 h, Q_INT32 x, Q_INT32 y, bool cropLayers)
708
if (w != width() || h != height()) {
714
m_adapter->beginMacro(i18n("Crop Image"));
716
m_adapter->beginMacro(i18n("Resize Image"));
718
m_adapter->addCommand(new LockImageCommand(this, true));
719
m_adapter->addCommand(new KisResizeImageCmd(m_adapter, this, w, h, width(), height()));
726
KisCropVisitor v(QRect(x, y, w, h));
727
m_rootLayer->accept(v);
735
m_adapter->addCommand(new LockImageCommand(this, false));
736
m_adapter->endMacro();
411
741
void KisImage::resize(const QRect& rc, bool cropLayers)
413
resize(rc.width(), rc.height(), cropLayers);
416
void KisImage::scale(double sx, double sy, KisProgressDisplayInterface *m_progress, enumFilterType ftype)
418
// kdDebug() << "KisImage::scale. SX: "
424
if (m_layers.empty()) return; // Nothing to scale
426
// New image size. XXX: Pass along to discourage rounding errors?
428
w = (Q_INT32)(( width() * sx) + 0.5);
429
h = (Q_INT32)(( height() * sy) + 0.5);
431
// kdDebug() << "Scaling from (" << m_projection -> width()
432
// << ", " << m_projection -> height()
433
// << "to: (" << w << ", " << h << ")\n";
435
if (w != width() || h != height()) {
437
undoAdapter() -> beginMacro("Scale image");
440
for ( it = m_layers.begin(); it != m_layers.end(); ++it ) {
441
KisLayerSP layer = (*it);
442
KisTransaction *cmd = 0;
444
if (undoAdapter() -> undo()) {
445
cmd = new KisTransaction("", layer.data());
449
layer -> scale(sx, sy, m_progress, ftype);
451
if (undoAdapter() -> undo()) {
452
undoAdapter() -> addCommand(cmd);
456
undoAdapter() -> addCommand(new KisResizeImageCmd(m_adapter, this, w, h, width(), height()));
461
m_projection = new KisLayer(this, "projection", OPACITY_OPAQUE);
462
Q_CHECK_PTR(m_projection);
464
m_bkg = new KisBackground(this, w, h);
467
undoAdapter() -> endMacro();
469
emit sizeChanged(KisImageSP(this), w, h);
473
void KisImage::rotate(double angle, KisProgressDisplayInterface *m_progress)
475
const double pi=3.1415926535897932385;
477
if (m_layers.empty()) return; // Nothing to scale
479
w = (Q_INT32)(width()*QABS(cos(angle*pi/180)) + height()*QABS(sin(angle*pi/180)) + 0.5);
480
h = (Q_INT32)(height()*QABS(cos(angle*pi/180)) + width()*QABS(sin(angle*pi/180)) + 0.5);
482
Q_INT32 oldCentreToNewCentreXOffset = (w - width()) / 2;
483
Q_INT32 oldCentreToNewCentreYOffset = (h - height()) / 2;
485
undoAdapter() -> beginMacro("Rotate image");
488
for ( it = m_layers.begin(); it != m_layers.end(); ++it ) {
489
KisLayerSP layer = (*it);
491
KisTransaction * t = 0;
492
if (undoAdapter() && undoAdapter() -> undo()) {
493
t = new KisTransaction("", layer.data());
497
layer -> rotate(angle, true, m_progress);
500
undoAdapter() -> addCommand(t);
503
//XXX: This is very ugly.
504
KNamedCommand *moveCommand = layer -> moveCommand(layer -> getX() + oldCentreToNewCentreXOffset,
505
layer -> getY() + oldCentreToNewCentreYOffset);
506
if (undoAdapter() && undoAdapter() -> undo()) {
507
undoAdapter() -> addCommand(moveCommand);
513
m_adapter -> addCommand(new KisResizeImageCmd(m_adapter, this, w, h, width(), height()));
518
m_projection = new KisLayer(this, "projection", OPACITY_OPAQUE);
519
Q_CHECK_PTR(m_projection);
521
m_bkg = new KisBackground(this, w, h);
524
undoAdapter()->endMacro();
526
emit sizeChanged(KisImageSP(this), w, h);
743
resize(rc.width(), rc.height(), rc.x(), rc.y(), cropLayers);
747
void KisImage::scale(double sx, double sy, KisProgressDisplayInterface *progress, KisFilterStrategy *filterStrategy)
749
if (nlayers() == 0) return; // Nothing to scale
751
// New image size. XXX: Pass along to discourage rounding errors?
753
w = (Q_INT32)(( width() * sx) + 0.5);
754
h = (Q_INT32)(( height() * sy) + 0.5);
756
if (w != width() || h != height()) {
761
m_adapter->beginMacro(i18n("Scale Image"));
762
m_adapter->addCommand(new LockImageCommand(this, true));
766
KisTransformVisitor visitor (this, sx, sy, 0.0, 0.0, 0.0, 0, 0, progress, filterStrategy);
767
m_rootLayer->accept(visitor);
771
m_adapter->addCommand(new KisResizeImageCmd(m_adapter, this, w, h, width(), height()));
782
m_adapter->addCommand(new LockImageCommand(this, false));
783
m_adapter->endMacro();
790
void KisImage::rotate(double angle, KisProgressDisplayInterface *progress)
796
Q_INT32 h = height();
797
Q_INT32 tx = Q_INT32((w*cos(angle) - h*sin(angle) - w) / 2 + 0.5);
798
Q_INT32 ty = Q_INT32((h*cos(angle) + w*sin(angle) - h) / 2 + 0.5);
799
w = (Q_INT32)(width()*QABS(cos(angle)) + height()*QABS(sin(angle)) + 0.5);
800
h = (Q_INT32)(height()*QABS(cos(angle)) + width()*QABS(sin(angle)) + 0.5);
802
tx -= (w - width()) / 2;
803
ty -= (h - height()) / 2;
806
m_adapter->beginMacro(i18n("Rotate Image"));
807
m_adapter->addCommand(new LockImageCommand(this, true));
810
KisFilterStrategy *filter = KisFilterStrategyRegistry::instance()->get(KisID("Triangle"));
811
KisTransformVisitor visitor (this, 1.0, 1.0, 0, 0, angle, -tx, -ty, progress, filter);
812
m_rootLayer->accept(visitor);
814
if (undo()) m_adapter->addCommand(new KisResizeImageCmd(undoAdapter(), this, w, h, width(), height()));
824
m_adapter->addCommand(new LockImageCommand(this, false));
825
m_adapter->endMacro();
529
829
void KisImage::shear(double angleX, double angleY, KisProgressDisplayInterface *m_progress)
531
const double pi=3.1415926535897932385;
533
if (m_layers.empty()) return; // Nothing to scale
540
if(angleX != 0 || angleY != 0){
541
double deltaY=height()*QABS(tan(angleX*pi/180)*tan(angleY*pi/180));
542
w = (Q_INT32) ( width() + QABS(height()*tan(angleX*pi/180)) );
543
//ugly fix for the problem of having two extra pixels if only a shear along one
544
//axis is done. This has to be fixed in the cropping code in KisRotateVisitor!
545
if (angleX == 0 || angleY == 0)
546
h = (Q_INT32) ( height() + QABS(w*tan(angleY*pi/180)) );
547
else if (angleX > 0 && angleY > 0)
548
h = (Q_INT32) ( height() + QABS(w*tan(angleY*pi/180))- 2 * deltaY + 2 );
549
else if (angleX < 0 && angleY < 0)
550
h = (Q_INT32) ( height() + QABS(w*tan(angleY*pi/180))- 2 * deltaY + 2 );
552
h = (Q_INT32) ( height() + QABS(w*tan(angleY*pi/180)) );
555
if (w != width() || h != height()) {
557
undoAdapter() -> beginMacro("Shear image");
560
for ( it = m_layers.begin(); it != m_layers.end(); ++it ) {
561
KisLayerSP layer = (*it);
563
KisTransaction * t = 0;
564
if (undoAdapter() && undoAdapter() -> undo()) {
565
t = new KisTransaction("", layer.data());
569
layer -> shear(angleX, angleY, m_progress);
572
undoAdapter() -> addCommand(t);
577
m_adapter -> addCommand(new KisResizeImageCmd(m_adapter, this, w, h, width(), height()));
582
m_projection = new KisLayer(this, "projection", OPACITY_OPAQUE);
583
Q_CHECK_PTR(m_projection);
585
m_bkg = new KisBackground(this, w, h);
588
undoAdapter()->endMacro();
590
emit sizeChanged(KisImageSP(this), w, h);
594
void KisImage::convertTo(KisStrategyColorSpaceSP dstColorStrategy, KisProfileSP dstProfile, Q_INT32 renderingIntent)
596
// XXX profile() == profile() will mostly result in extra work being done here, but there doesn't seem to be a better way?
597
if ( (m_colorStrategy -> id() == dstColorStrategy -> id())
600
&& (profile() -> profile() == dstProfile -> profile()) )
602
kdDebug() << "KisImage: NOT GOING TO CONVERT\n";
606
if (undoAdapter() && undoAdapter() -> undo()) {
607
undoAdapter() -> beginMacro(i18n("&Convert Image Type...")); //XXX: fix when string freeze over
611
for ( it = m_layers.begin(); it != m_layers.end(); ++it ) {
612
(*it) -> convertTo(dstColorStrategy, dstProfile, renderingIntent);
615
if (undoAdapter() && undoAdapter() -> undo()) {
617
undoAdapter() -> addCommand(new KisConvertImageTypeCmd(undoAdapter(), this, m_colorStrategy, m_profile,
618
dstColorStrategy, dstProfile));
619
undoAdapter() -> endMacro();
622
setColorStrategy(dstColorStrategy);
623
setProfile(dstProfile);
625
notifyLayersChanged();
629
KisProfileSP KisImage::profile() const
634
void KisImage::setProfile(const KisProfileSP& profile)
636
if (profile && profile -> valid()) {
638
m_projection -> setProfile(profile);
642
m_projection -> setProfile(m_profile);
645
emit(profileChanged(m_profile));
648
KURL KisImage::uri() const
653
void KisImage::uri(const KURL& uri)
659
KoUnit::Unit KisImage::unit() const
664
void KisImage::unit(const KoUnit::Unit& u)
831
const double pi=3.1415926535897932385;
838
if(angleX != 0 || angleY != 0){
839
double deltaY=height()*QABS(tan(angleX*pi/180)*tan(angleY*pi/180));
840
w = (Q_INT32) ( width() + QABS(height()*tan(angleX*pi/180)) );
841
//ugly fix for the problem of having two extra pixels if only a shear along one
842
//axis is done. This has to be fixed in the cropping code in KisRotateVisitor!
843
if (angleX == 0 || angleY == 0)
844
h = (Q_INT32) ( height() + QABS(w*tan(angleY*pi/180)) );
845
else if (angleX > 0 && angleY > 0)
846
h = (Q_INT32) ( height() + QABS(w*tan(angleY*pi/180))- 2 * deltaY + 2 );
847
else if (angleX < 0 && angleY < 0)
848
h = (Q_INT32) ( height() + QABS(w*tan(angleY*pi/180))- 2 * deltaY + 2 );
850
h = (Q_INT32) ( height() + QABS(w*tan(angleY*pi/180)) );
853
if (w != width() || h != height()) {
858
m_adapter->beginMacro(i18n("Shear Image"));
859
m_adapter->addCommand(new LockImageCommand(this, true));
862
KisShearVisitor v(angleX, angleY, m_progress);
863
v.setUndoAdapter(undoAdapter());
864
rootLayer()->accept(v);
866
if (undo()) m_adapter->addCommand(new KisResizeImageCmd(m_adapter, this, w, h, width(), height()));
876
m_adapter->addCommand(new LockImageCommand(this, false));
877
m_adapter->endMacro();
882
void KisImage::convertTo(KisColorSpace * dstColorSpace, Q_INT32 renderingIntent)
884
if ( m_colorSpace == dstColorSpace )
891
KisColorSpace * oldCs = m_colorSpace;
894
m_adapter->beginMacro(i18n("Convert Image Type"));
895
m_adapter->addCommand(new LockImageCommand(this, true));
898
setColorSpace(dstColorSpace);
900
KisColorSpaceConvertVisitor visitor(dstColorSpace, renderingIntent);
901
m_rootLayer->accept(visitor);
905
emit sigLayerPropertiesChanged( m_activeLayer );
909
m_adapter->addCommand(new KisConvertImageTypeCmd(undoAdapter(), this,
910
oldCs, dstColorSpace));
911
m_adapter->addCommand(new LockImageCommand(this, false));
912
m_adapter->endMacro();
916
KisProfile * KisImage::getProfile() const
918
return colorSpace()->getProfile();
921
void KisImage::setProfile(const KisProfile * profile)
923
if (profile == 0) return;
925
KisColorSpace * dstCs= KisMetaRegistry::instance()->csRegistry()->getColorSpace( colorSpace()->id(),
931
KisColorSpace * oldCs = colorSpace();
932
setColorSpace(dstCs);
933
emit(sigProfileChanged(const_cast<KisProfile *>(profile)));
935
KisChangeProfileVisitor visitor(oldCs, dstCs);
936
m_rootLayer->accept(visitor);
669
942
double KisImage::xRes()
674
947
double KisImage::yRes()
679
952
void KisImage::setResolution(double xres, double yres)
685
958
Q_INT32 KisImage::width() const
690
963
Q_INT32 KisImage::height() const
696
bool KisImage::empty() const
698
return m_layers.size() > 0;
701
vKisLayerSP KisImage::layers()
706
const vKisLayerSP& KisImage::layers() const
711
968
KisPaintDeviceSP KisImage::activeDevice()
714
return m_activeLayer.data();
720
const KisLayerSP KisImage::activeLayer() const
722
return m_activeLayer;
725
KisLayerSP KisImage::activeLayer()
727
return m_activeLayer;
970
if (KisPaintLayer* layer = dynamic_cast<KisPaintLayer*>(m_activeLayer.data())) {
971
return layer->paintDevice();
973
else if (KisAdjustmentLayer* layer = dynamic_cast<KisAdjustmentLayer*>(m_activeLayer.data())) {
974
if (layer->selection()) {
975
return layer->selection().data();
978
else if (KisGroupLayer * layer = dynamic_cast<KisGroupLayer*>(m_activeLayer.data())) {
980
KisLayer * child = layer->lastChild();
983
if (KisPaintLayer* layer = dynamic_cast<KisPaintLayer*>(m_activeLayer.data())) {
984
return layer->paintDevice();
986
child = child->prevSibling();
989
// XXX: We're buggered!
993
KisLayerSP KisImage::newLayer(const QString& name, Q_UINT8 opacity, const KisCompositeOp& compositeOp, KisColorSpace * colorstrategy)
995
KisPaintLayer * layer;
997
layer = new KisPaintLayer(this, name, opacity, colorstrategy);
999
layer = new KisPaintLayer(this, name, opacity);
1002
if (compositeOp.isValid())
1003
layer->setCompositeOp(compositeOp);
1004
layer->setVisible(true);
1006
if (m_activeLayer != 0) {
1007
addLayer(layer, m_activeLayer->parent().data(), m_activeLayer->nextSibling());
1010
addLayer(layer, m_rootLayer, 0);
1017
void KisImage::setLayerProperties(KisLayerSP layer, Q_UINT8 opacity, const KisCompositeOp& compositeOp, const QString& name)
1019
if (layer && (layer->opacity() != opacity || layer->compositeOp() != compositeOp || layer->name() != name)) {
1021
QString oldname = layer->name();
1022
Q_INT32 oldopacity = layer->opacity();
1023
KisCompositeOp oldCompositeOp = layer->compositeOp();
1024
layer->setName(name);
1025
layer->setOpacity(opacity);
1026
layer->setCompositeOp(compositeOp);
1027
m_adapter->addCommand(new LayerPropsCmd(layer, this, m_adapter, oldname, oldopacity, oldCompositeOp));
1029
layer->setName(name);
1030
layer->setOpacity(opacity);
1031
layer->setCompositeOp(compositeOp);
1036
KisGroupLayerSP KisImage::rootLayer() const
1041
KisLayerSP KisImage::activeLayer() const
1043
return m_activeLayer;
1046
KisPaintDeviceSP KisImage::projection()
1048
return m_rootLayer->projection(QRect(0, 0, m_width, m_height));
730
1051
KisLayerSP KisImage::activate(KisLayerSP layer)
734
if (m_layers.empty() || !layer)
737
it = qFind(m_layers.begin(), m_layers.end(), layer);
739
if (it == m_layers.end()) {
741
it = m_layers.begin();
745
it = qFind(m_layerStack.begin(), m_layerStack.end(), layer);
747
if (it != m_layerStack.end())
748
m_layerStack.erase(it);
750
m_layerStack.insert(m_layerStack.begin() + 0, layer);
753
if (layer != m_activeLayer) {
754
m_activeLayer = layer;
755
emit activeLayerChanged(KisImageSP(this));
762
KisLayerSP KisImage::activateLayer(Q_INT32 n)
764
if (n < 0 || static_cast<Q_UINT32>(n) > m_layers.size())
767
return activate(m_layers[n]);
770
Q_INT32 KisImage::index(const KisLayerSP &layer)
772
for (Q_UINT32 i = 0; i < m_layers.size(); i++) {
773
if (m_layers[i] == layer)
780
KisLayerSP KisImage::layer(const QString& name)
782
for (vKisLayerSP_it it = m_layers.begin(); it != m_layers.end(); it++) {
783
if ((*it) -> name() == name)
790
KisLayerSP KisImage::layer(Q_UINT32 npos)
792
if (npos >= m_layers.size())
795
return m_layers[npos];
798
bool KisImage::add(KisLayerSP layer, Q_INT32 position)
803
if (layer -> image() && layer -> image() != KisImageSP(this))
806
if (qFind(m_layers.begin(), m_layers.end(), layer) != m_layers.end())
809
layer -> setImage(KisImageSP(this));
811
if (position == -1) {
812
// Add to bottom of layer stack
813
position = m_layers.size();
816
m_layers.insert(m_layers.begin() + position, layer);
819
m_layerStack.push_back(layer);
823
void KisImage::rm(KisLayerSP layer)
828
vKisLayerSP_it it = qFind(m_layers.begin(), m_layers.end(), layer);
830
if (it == m_layers.end())
834
it = qFind(m_layerStack.begin(), m_layerStack.end(), layer);
836
if (it != m_layerStack.end())
837
m_layerStack.erase(it);
839
layer -> setImage(0);
841
if (layer == m_activeLayer) {
842
if (m_layers.empty()) {
844
emit activeLayerChanged(KisImageSP(this));
846
activate(m_layerStack[0]);
851
bool KisImage::raise(KisLayerSP layer)
858
position = index(layer);
863
return pos(layer, position - 1);
866
bool KisImage::lower(KisLayerSP layer)
874
position = index(layer);
875
size = m_layers.size();
877
if (position >= size)
880
return pos(layer, position + 1);
883
bool KisImage::top(KisLayerSP layer)
890
position = index(layer);
895
return pos(layer, 0);
898
bool KisImage::bottom(KisLayerSP layer)
906
position = index(layer);
907
size = m_layers.size();
909
if (position >= size - 1)
912
return pos(layer, size - 1);
915
bool KisImage::pos(KisLayerSP layer, Q_INT32 position)
928
nlayers = m_layers.size();
933
if (position >= nlayers)
934
position = nlayers - 1;
939
if (position < old) {
940
m_layers.erase(m_layers.begin() + old);
941
m_layers.insert(m_layers.begin() + position, layer);
944
m_layers.insert(m_layers.begin() + position + 1, layer);
945
m_layers.erase(m_layers.begin() + old);
1053
if (layer != m_activeLayer) {
1054
if (m_activeLayer) m_activeLayer->deactivate();
1055
m_activeLayer = layer;
1056
if (m_activeLayer) m_activeLayer->activate();
1057
emit sigLayerActivated(m_activeLayer);
1063
KisLayerSP KisImage::findLayer(const QString& name) const
1065
return rootLayer()->findLayer(name);
1068
KisLayerSP KisImage::findLayer(int id) const
1070
return rootLayer()->findLayer(id);
1074
bool KisImage::addLayer(KisLayerSP layer, KisGroupLayerSP parent)
1076
return addLayer(layer, parent, parent->firstChild());
1079
bool KisImage::addLayer(KisLayerSP layer, KisGroupLayerSP parent, KisLayerSP aboveThis)
1084
const bool success = parent->addLayer(layer, aboveThis);
1087
KisPaintLayerSP player = dynamic_cast<KisPaintLayer*>(layer.data());
1090
// XXX: This should also be done whenever a layer grows!
1091
QValueVector<KisPaintDeviceAction *> actions = KisMetaRegistry::instance() ->
1092
csRegistry()->paintDeviceActionsFor(player->paintDevice()->colorSpace());
1093
for (uint i = 0; i < actions.count(); i++) {
1094
actions.at(i)->act(player.data()->paintDevice(), width(), height());
1098
if (layer->extent().isValid()) layer->setDirty();
1100
if (!layer->temporary()) {
1101
emit sigLayerAdded(layer);
1106
if (!layer->temporary() && undo()) {
1107
m_adapter->addCommand(new LayerAddCmd(m_adapter, this, layer));
1114
bool KisImage::removeLayer(KisLayerSP layer)
1116
if (!layer || layer->image() != this)
1119
if (KisGroupLayerSP parent = layer->parent()) {
1120
// Adjustment layers should mark the layers underneath them, whose rendering
1121
// they have cached, diryt on removal. Otherwise, the group won't be re-rendered.
1122
KisAdjustmentLayer * al = dynamic_cast<KisAdjustmentLayer*>(layer.data());
1124
QRect r = al->extent();
1125
lock(); // Lock the image, because we are going to dirty a lot of layers
1126
KisLayerSP l = layer->nextSibling();
1128
KisAdjustmentLayer * al2 = dynamic_cast<KisAdjustmentLayer*>(l.data());
1129
l->setDirty(r, false);
1130
if (al2 != 0) break;
1131
l = l->nextSibling();
1135
KisLayerSP l = layer->prevSibling();
1136
QRect r = layer->extent();
1138
l->setDirty(r, false);
1139
l = l->prevSibling();
1142
KisLayerSP wasAbove = layer->nextSibling();
1143
KisLayerSP wasBelow = layer->prevSibling();
1144
const bool wasActive = layer == activeLayer();
1145
// sigLayerRemoved can set it to 0, we don't want that in the else of wasActive!
1146
KisLayerSP actLayer = activeLayer();
1147
const bool success = parent->removeLayer(layer);
1150
if (!layer->temporary() && undo()) {
1151
m_adapter->addCommand(new LayerRmCmd(m_adapter, this, layer, parent, wasAbove));
1153
if (!layer->temporary()) {
1154
emit sigLayerRemoved(layer, parent, wasAbove);
1160
else if (parent != rootLayer())
1161
activate(parent.data());
1163
activate(rootLayer()->firstChild());
1175
bool KisImage::raiseLayer(KisLayerSP layer)
1179
return moveLayer(layer, layer->parent().data(), layer->prevSibling());
1182
bool KisImage::lowerLayer(KisLayerSP layer)
1186
if (KisLayerSP next = layer->nextSibling())
1187
return moveLayer(layer, layer->parent().data(), next->nextSibling());
1191
bool KisImage::toTop(KisLayerSP layer)
1195
return moveLayer(layer, rootLayer(), rootLayer()->firstChild());
1198
bool KisImage::toBottom(KisLayerSP layer)
1202
return moveLayer(layer, rootLayer(), 0);
1205
bool KisImage::moveLayer(KisLayerSP layer, KisGroupLayerSP parent, KisLayerSP aboveThis)
1210
KisGroupLayerSP wasParent = layer->parent();
1211
KisLayerSP wasAbove = layer->nextSibling();
1213
if (wasParent.data() == parent.data() && wasAbove.data() == aboveThis.data())
1218
if (!wasParent->removeLayer(layer)) {
1223
const bool success = parent->addLayer(layer, aboveThis);
1231
emit sigLayerMoved(layer, wasParent, wasAbove);
1233
m_adapter->addCommand(new LayerMoveCmd(m_adapter, this, layer, wasParent, wasAbove));
1235
else //we already removed the layer above, but re-adding it failed, so...
1237
emit sigLayerRemoved(layer, wasParent, wasAbove);
1239
m_adapter->addCommand(new LayerRmCmd(m_adapter, this, layer, wasParent, wasAbove));
951
1245
Q_INT32 KisImage::nlayers() const
953
return m_layers.size();
1247
return rootLayer()->numLayers() - 1;
956
1250
Q_INT32 KisImage::nHiddenLayers() const
960
for (vKisLayerSP_cit it = m_layers.begin(); it != m_layers.end(); it++) {
961
const KisLayerSP& layer = *it;
963
if (!layer -> visible()) {
971
Q_INT32 KisImage::nLinkedLayers() const
975
for (vKisLayerSP_cit it = m_layers.begin(); it != m_layers.end(); it++) {
976
const KisLayerSP& layer = *it;
978
if (layer -> linked()) {
1252
return rootLayer()->numLayers(KisLayer::Hidden);
986
1255
void KisImage::flatten()
988
vKisLayerSP beforeLayers = m_layers;
990
if (m_layers.empty()) return;
992
KisLayerSP dst = new KisLayer(this, nextLayerName(), OPACITY_OPAQUE);
995
KisFillPainter painter(dst.data());
997
vKisLayerSP mergeLayers = layers();
999
KisLayerSP bottomLayer = mergeLayers.back();
1000
QString bottomName = bottomLayer -> name();
1002
KisMerge<isVisible, All> visitor(this);
1003
visitor(painter, mergeLayers);
1004
dst -> setName(bottomName);
1009
notifyLayersChanged();
1011
if (m_adapter && m_adapter -> undo()) {
1012
m_adapter -> addCommand(new KisChangeLayersCmd(m_adapter, this, beforeLayers, m_layers, i18n("Flatten Image")));
1016
void KisImage::mergeVisibleLayers()
1018
vKisLayerSP beforeLayers = m_layers;
1020
KisLayerSP dst = new KisLayer(this, nextLayerName(), OPACITY_OPAQUE);
1023
KisFillPainter painter(dst.data());
1025
vKisLayerSP mergeLayers = layers();
1026
KisMerge<isVisible, isVisible> visitor(this);
1027
visitor(painter, mergeLayers);
1029
int insertIndex = -1;
1031
if (visitor.insertMergedAboveLayer() != 0) {
1032
insertIndex = index(visitor.insertMergedAboveLayer());
1035
add(dst, insertIndex);
1038
notifyLayersChanged();
1040
if (m_adapter && m_adapter -> undo()) {
1041
m_adapter -> addCommand(new KisChangeLayersCmd(m_adapter, this, beforeLayers, m_layers, i18n("Merge Visible Layers")));
1045
void KisImage::mergeLinkedLayers()
1047
vKisLayerSP beforeLayers = m_layers;
1049
KisLayerSP dst = new KisLayer(this, nextLayerName(), OPACITY_OPAQUE);
1052
KisFillPainter painter(dst.data());
1054
vKisLayerSP mergeLayers = layers();
1055
KisMerge<isLinked, isLinked> visitor(this);
1056
visitor(painter, mergeLayers);
1058
int insertIndex = -1;
1060
if (visitor.insertMergedAboveLayer() != 0) {
1061
insertIndex = index(visitor.insertMergedAboveLayer());
1064
add(dst, insertIndex);
1067
notifyLayersChanged();
1069
if (m_adapter && m_adapter -> undo()) {
1070
m_adapter -> addCommand(new KisChangeLayersCmd(m_adapter, this, beforeLayers, m_layers, i18n("Merge Linked Layers")));
1074
void KisImage::mergeLayer(KisLayerSP l)
1076
vKisLayerSP beforeLayers = m_layers;
1078
KisLayerSP dst = new KisLayer(this, l -> name(), OPACITY_OPAQUE);
1081
KisFillPainter painter(dst.data());
1083
KisMerge<All, All> visitor(this);
1084
visitor(painter, layer(index(l) + 1));
1085
visitor(painter, l);
1087
int insertIndex = -1;
1089
if (visitor.insertMergedAboveLayer() != 0) {
1090
insertIndex = index(visitor.insertMergedAboveLayer());
1093
add(dst, insertIndex);
1096
notifyLayersChanged();
1098
if (m_adapter && m_adapter -> undo())
1100
m_adapter -> addCommand(new KisChangeLayersCmd(m_adapter, this, beforeLayers, m_layers, i18n("&Merge Layers")));
1101
//XXX fix name after string freeze
1106
void KisImage::enableUndo(KoCommandHistory *history)
1108
m_undoHistory = history;
1111
void KisImage::renderToProjection(Q_INT32 x, Q_INT32 y, Q_INT32 w, Q_INT32 h)
1115
gc.begin(m_projection.data());
1117
gc.bitBlt(x, y, COMPOSITE_COPY, m_bkg.data(), x, y, w, h);
1119
if (!m_layers.empty()) {
1120
KisFlatten<flattenAllVisible> visitor(x, y, w, h);
1122
visitor(gc, m_layers);
1124
if (m_activeLayer -> hasSelection()) {
1125
KisSelectionSP s = m_activeLayer -> selection();
1257
KisGroupLayerSP oldRootLayer = m_rootLayer;
1258
disconnect(oldRootLayer, SIGNAL(sigDirty(QRect)), this, SIGNAL(sigImageUpdated(QRect)));
1260
KisPaintLayer *dst = new KisPaintLayer(this, nextLayerName(), OPACITY_OPAQUE, colorSpace());
1263
QRect rc = mergedImage()->extent();
1265
KisPainter gc(dst->paintDevice());
1266
gc.bitBlt(rc.x(), rc.y(), COMPOSITE_COPY, mergedImage(), OPACITY_OPAQUE, rc.left(), rc.top(), rc.width(), rc.height());
1268
m_rootLayer = new KisGroupLayer(this, "", OPACITY_OPAQUE);
1269
connect(m_rootLayer, SIGNAL(sigDirty(QRect)), this, SIGNAL(sigImageUpdated(QRect)));
1272
m_adapter->beginMacro(i18n("Flatten Image"));
1273
m_adapter->addCommand(new LockImageCommand(this, true));
1274
m_adapter->addCommand(new KisChangeLayersCmd(m_adapter, this, oldRootLayer, m_rootLayer, ""));
1279
addLayer(dst, m_rootLayer, 0);
1284
notifyLayersChanged();
1287
m_adapter->addCommand(new LockImageCommand(this, false));
1288
m_adapter->endMacro();
1293
void KisImage::mergeLayer(KisLayerSP layer)
1295
KisPaintLayer *player = new KisPaintLayer(this, layer->name(), OPACITY_OPAQUE, colorSpace());
1296
Q_CHECK_PTR(player);
1298
QRect rc = layer->extent() | layer->nextSibling()->extent();
1300
undoAdapter()->beginMacro(i18n("Merge with Layer Below"));
1302
//Abuse the merge visitor to only merge two layers (if either are groups they'll recursively merge)
1303
KisMergeVisitor visitor(player->paintDevice(), rc);
1304
layer->nextSibling()->accept(visitor);
1305
layer->accept(visitor);
1307
removeLayer(layer->nextSibling());
1308
addLayer(player, layer->parent(), layer);
1311
undoAdapter()->endMacro();
1315
void KisImage::setModified()
1317
emit sigImageModified();
1133
1320
void KisImage::renderToPainter(Q_INT32 x1,
1138
KisProfileSP profile)
1143
// Flatten the layers onto the projection layer of the current image
1144
for (y = y1; y <= y2; y += RENDER_HEIGHT - (y % RENDER_HEIGHT)) {
1145
for (x = x1; x <= x2; x += RENDER_WIDTH - (x % RENDER_WIDTH)) {
1146
Q_INT32 w = QMIN(x2 - x, RENDER_WIDTH);
1147
Q_INT32 h = QMIN(y2 - y, RENDER_HEIGHT);
1148
renderToProjection(x, y, w, h);
1149
QImage img = m_projection -> convertToQImage(profile, x, y, w, h);
1150
if (!img.isNull()) {
1151
m_pixmap.convertFromImage(img);
1152
painter.drawPixmap(x, y, m_pixmap, 0, 0, w, h);
1158
void KisImage::notify()
1160
notify(0, 0, width(), height());
1163
void KisImage::notify(Q_INT32 x, Q_INT32 y, Q_INT32 width, Q_INT32 height)
1165
notify(QRect(x, y, width, height));
1168
void KisImage::notify(const QRect& rc)
1171
emit update(KisImageSP(this), rc);
1325
KisProfile * monitorProfile,
1326
PaintFlags paintFlags,
1330
QImage img = convertToQImage(x1, y1, x2, y2, monitorProfile, exposure);
1332
Q_INT32 w = x2 - x1 + 1;
1333
Q_INT32 h = y2 - y1 + 1;
1336
if (paintFlags & PAINT_BACKGROUND) {
1337
m_bkg->paintBackground(img, x1, y1);
1338
img.setAlphaBuffer(false);
1341
if (paintFlags & PAINT_SELECTION) {
1342
if (m_activeLayer != 0) {
1343
m_activeLayer->paintSelection(img, x1, y1, w, h);
1347
if (paintFlags & PAINT_MASKINACTIVELAYERS) {
1348
if (m_activeLayer != 0) {
1349
m_activeLayer->paintMaskInactiveLayers(img, x1, y1, w, h);
1353
painter.drawImage(x1, y1, img, 0, 0, w, h);
1356
QImage KisImage::convertToQImage(Q_INT32 x1,
1360
KisProfile * profile,
1363
Q_INT32 w = x2 - x1 + 1;
1364
Q_INT32 h = y2 - y1 + 1;
1366
KisPaintDeviceSP dev = m_rootLayer->projection(QRect(x1, y1, w, h));
1367
QImage img = dev->convertToQImage(profile, x1, y1, w, h, exposure);
1369
if (!img.isNull()) {
1371
#ifdef __BIG_ENDIAN__
1372
uchar * data = img.bits();
1373
for (int i = 0; i < w * h; ++i) {
1393
QImage KisImage::convertToQImage(const QRect& r, const QSize& scaledImageSize, KisProfile *profile, PaintFlags paintFlags, float exposure)
1395
if (r.isEmpty() || scaledImageSize.isEmpty()) {
1399
Q_INT32 imageWidth = width();
1400
Q_INT32 imageHeight = height();
1401
Q_UINT32 pixelSize = colorSpace()->pixelSize();
1403
double xScale = static_cast<double>(imageWidth) / scaledImageSize.width();
1404
double yScale = static_cast<double>(imageHeight) / scaledImageSize.height();
1408
srcRect.setLeft(static_cast<int>(r.left() * xScale));
1409
srcRect.setRight(static_cast<int>(ceil((r.right() + 1) * xScale)) - 1);
1410
srcRect.setTop(static_cast<int>(r.top() * yScale));
1411
srcRect.setBottom(static_cast<int>(ceil((r.bottom() + 1) * yScale)) - 1);
1413
KisPaintDeviceSP mergedImage = m_rootLayer->projection(srcRect);
1417
Q_UINT8 *scaledImageData = new Q_UINT8[r.width() * r.height() * pixelSize];
1419
Q_UINT8 *imageRow = new Q_UINT8[srcRect.width() * pixelSize];
1420
const Q_INT32 imageRowX = srcRect.x();
1422
for (Q_INT32 y = 0; y < r.height(); ++y) {
1424
Q_INT32 dstY = r.y() + y;
1425
Q_INT32 dstX = r.x();
1426
Q_INT32 srcY = (dstY * imageHeight) / scaledImageSize.height();
1428
mergedImage->readBytes(imageRow, imageRowX, srcY, srcRect.width(), 1);
1430
Q_UINT8 *dstPixel = scaledImageData + (y * r.width() * pixelSize);
1431
Q_UINT32 columnsRemaining = r.width();
1433
while (columnsRemaining > 0) {
1435
Q_INT32 srcX = (dstX * imageWidth) / scaledImageSize.width();
1437
memcpy(dstPixel, imageRow + ((srcX - imageRowX) * pixelSize), pixelSize);
1440
dstPixel += pixelSize;
1447
QImage image = colorSpace()->convertToQImage(scaledImageData, r.width(), r.height(), profile, INTENT_PERCEPTUAL, exposure);
1448
delete [] scaledImageData;
1450
if (paintFlags & PAINT_BACKGROUND) {
1451
m_bkg->paintBackground(image, r, scaledImageSize, QSize(imageWidth, imageHeight));
1452
image.setAlphaBuffer(false);
1455
if (paintFlags & PAINT_SELECTION) {
1456
if (m_activeLayer != 0) {
1457
m_activeLayer->paintSelection(image, r, scaledImageSize, QSize(imageWidth, imageHeight));
1461
/*if (paintFlags & PAINT_MASKINACTIVELAYERS) {
1462
if (m_activeLayer != 0) {
1463
m_activeLayer->paintMaskInactiveLayers(img, x1, y1, w, h);
1470
KisPaintDeviceSP KisImage::mergedImage()
1472
return m_rootLayer->projection(QRect(0, 0, m_width, m_height));
1475
KisColor KisImage::mergedPixel(Q_INT32 x, Q_INT32 y)
1477
return m_rootLayer->projection(QRect(x, y, 1, 1))->colorAt(x, y);
1176
1480
void KisImage::notifyLayersChanged()
1178
emit layersChanged(KisImageSP(this));
1482
emit sigLayersChanged(rootLayer());
1485
void KisImage::notifyPropertyChanged(KisLayerSP layer)
1487
emit sigLayerPropertiesChanged(layer);
1490
void KisImage::notifyImageLoaded()
1181
1494
QRect KisImage::bounds() const
1183
return QRect(0, 0, width(), height());
1496
return QRect(0, 0, width(), height());
1500
void KisImage::setUndoAdapter(KisUndoAdapter * adapter)
1502
m_adapter = adapter;
1186
1506
KisUndoAdapter* KisImage::undoAdapter() const
1511
bool KisImage::undo() const
1513
return (m_adapter && m_adapter->undo());
1516
//KisGuideMgr *KisImage::guides() const
1518
// return const_cast<KisGuideMgr*>(&m_guides);
1191
1521
void KisImage::slotSelectionChanged()
1193
kdDebug() << "KisImage::slotSelectionChanged\n";
1194
emit activeSelectionChanged(KisImageSP(this));
1197
void KisImage::slotSelectionCreated()
1199
kdDebug() << "KisImage::slotSelectionCreated\n";
1201
emit selectionCreated(KisImageSP(this));
1205
KisStrategyColorSpaceSP KisImage::colorStrategy() const
1207
return m_colorStrategy;
1210
void KisImage::setColorStrategy(KisStrategyColorSpaceSP colorStrategy)
1212
m_colorStrategy = colorStrategy;
1214
m_bkg = new KisBackground(this, m_width, m_height);
1217
m_projection = new KisLayer(this, "projection", OPACITY_OPAQUE);
1218
Q_CHECK_PTR(m_projection);
1523
slotSelectionChanged(bounds());
1526
void KisImage::slotSelectionChanged(const QRect& r)
1528
QRect r2(r.x() - 1, r.y() - 1, r.width() + 2, r.height() + 2);
1531
emit sigActiveSelectionChanged(this);
1533
m_private->selectionChangedWhileLocked = true;
1537
KisColorSpace * KisImage::colorSpace() const
1539
return m_colorSpace;
1542
void KisImage::setColorSpace(KisColorSpace * colorSpace)
1544
m_colorSpace = colorSpace;
1545
m_rootLayer->resetProjection();
1546
emit sigColorSpaceChanged(colorSpace);
1549
void KisImage::setRootLayer(KisGroupLayerSP rootLayer)
1551
disconnect(m_rootLayer, SIGNAL(sigDirty(QRect)), this, SIGNAL(sigImageUpdated(QRect)));
1553
m_rootLayer = rootLayer;
1556
connect(m_rootLayer, SIGNAL(sigDirty(QRect)), this, SIGNAL(sigImageUpdated(QRect)));
1558
activate(m_rootLayer->firstChild());
1222
1561
void KisImage::addAnnotation(KisAnnotationSP annotation)
1224
// Find the icc annotation, if there is one
1225
vKisAnnotationSP_it it = m_annotations.begin();
1226
while (it != m_annotations.end()) {
1227
if ((*it) -> type() == annotation -> type()) {
1233
m_annotations.push_back(annotation);
1563
// Find the icc annotation, if there is one
1564
vKisAnnotationSP_it it = m_annotations.begin();
1565
while (it != m_annotations.end()) {
1566
if ((*it)->type() == annotation->type()) {
1572
m_annotations.push_back(annotation);
1236
1575
KisAnnotationSP KisImage::annotation(QString type)
1238
vKisAnnotationSP_it it = m_annotations.begin();
1239
while (it != m_annotations.end()) {
1240
if ((*it) -> type() == type) {
1577
vKisAnnotationSP_it it = m_annotations.begin();
1578
while (it != m_annotations.end()) {
1579
if ((*it)->type() == type) {
1248
1587
void KisImage::removeAnnotation(QString type)
1250
vKisAnnotationSP_it it = m_annotations.begin();
1251
while (it != m_annotations.end()) {
1252
if ((*it) -> type() == type) {
1253
m_annotations.erase(it);
1589
vKisAnnotationSP_it it = m_annotations.begin();
1590
while (it != m_annotations.end()) {
1591
if ((*it)->type() == type) {
1592
m_annotations.erase(it);
1260
1599
vKisAnnotationSP_it KisImage::beginAnnotations()
1263
addAnnotation(m_profile -> annotation());
1265
removeAnnotation("icc");
1268
return m_annotations.begin();
1601
KisProfile * profile = colorSpace()->getProfile();
1602
KisAnnotationSP annotation;
1605
annotation = profile->annotation();
1608
addAnnotation(annotation);
1610
removeAnnotation("icc");
1612
return m_annotations.begin();
1271
1615
vKisAnnotationSP_it KisImage::endAnnotations()
1273
return m_annotations.end();
1617
return m_annotations.end();
1620
KisBackgroundSP KisImage::background() const
1276
1624
#include "kis_image.moc"