krita

kis_image.cc

00001 /*
00002  *  Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  */
00018 #include <stdlib.h>
00019 #include <math.h>
00020 
00021 #include <config.h>
00022 #include LCMS_HEADER
00023 
00024 #include <qimage.h>
00025 #include <qpainter.h>
00026 #include <qsize.h>
00027 #include <qtl.h>
00028 #include <qapplication.h>
00029 #include <qthread.h>
00030 #include <qdatetime.h>
00031 
00032 #include <kcommand.h>
00033 #include <kdebug.h>
00034 #include <klocale.h>
00035 
00036 #include "kis_image_iface.h"
00037 
00038 #include "kis_annotation.h"
00039 #include "kis_colorspace_factory_registry.h"
00040 #include "kis_color.h"
00041 #include "kis_command.h"
00042 #include "kis_types.h"
00043 //#include "kis_guide.h"
00044 #include "kis_image.h"
00045 #include "kis_paint_device.h"
00046 #include "kis_paint_device_action.h"
00047 #include "kis_selection.h"
00048 #include "kis_painter.h"
00049 #include "kis_fill_painter.h"
00050 #include "kis_layer.h"
00051 #include "kis_group_layer.h"
00052 #include "kis_adjustment_layer.h"
00053 #include "kis_paint_layer.h"
00054 #include "kis_colorspace_convert_visitor.h"
00055 #include "kis_background.h"
00056 #include "kis_nameserver.h"
00057 #include "kis_undo_adapter.h"
00058 #include "kis_merge_visitor.h"
00059 #include "kis_transaction.h"
00060 #include "kis_crop_visitor.h"
00061 #include "kis_transform_visitor.h"
00062 #include "kis_filter_strategy.h"
00063 #include "kis_profile.h"
00064 #include "kis_paint_layer.h"
00065 #include "kis_change_profile_visitor.h"
00066 #include "kis_group_layer.h"
00067 #include "kis_iterators_pixel.h"
00068 #include "kis_shear_visitor.h"
00069 
00070 class KisImage::KisImagePrivate {
00071 public:
00072     KisColor backgroundColor;
00073     Q_UINT32     lockCount;
00074     bool sizeChangedWhileLocked;
00075     bool selectionChangedWhileLocked;
00076 };
00077 
00078 
00079 namespace {
00080 
00081     class KisResizeImageCmd : public KNamedCommand {
00082         typedef KNamedCommand super;
00083 
00084     public:
00085         KisResizeImageCmd(KisUndoAdapter *adapter,
00086                           KisImageSP img,
00087                           Q_INT32 width,
00088                           Q_INT32 height,
00089                           Q_INT32 oldWidth,
00090                           Q_INT32 oldHeight) : super(i18n("Resize Image"))
00091             {
00092                 m_adapter = adapter;
00093                 m_img = img;
00094                 m_before = QSize(oldWidth, oldHeight);
00095                 m_after = QSize(width, height);
00096             }
00097 
00098         virtual ~KisResizeImageCmd()
00099             {
00100             }
00101 
00102     public:
00103         virtual void execute()
00104             {
00105                 m_adapter->setUndo(false);
00106                 m_img->resize(m_after.width(), m_after.height());
00107                 m_adapter->setUndo(true);
00108             }
00109 
00110         virtual void unexecute()
00111             {
00112                 m_adapter->setUndo(false);
00113                 m_img->resize(m_before.width(), m_before.height());
00114                 m_adapter->setUndo(true);
00115             }
00116 
00117     private:
00118         KisUndoAdapter *m_adapter;
00119         KisImageSP m_img;
00120         QSize m_before;
00121         QSize m_after;
00122     };
00123 
00124     // -------------------------------------------------------
00125 
00126     class KisChangeLayersCmd : public KNamedCommand {
00127         typedef KNamedCommand super;
00128 
00129     public:
00130         KisChangeLayersCmd(KisUndoAdapter *adapter, KisImageSP img,
00131                            KisGroupLayerSP oldRootLayer, KisGroupLayerSP newRootLayer, const QString& name)
00132             : super(name)
00133             {
00134                 m_adapter = adapter;
00135                 m_img = img;
00136                 m_oldRootLayer = oldRootLayer;
00137                 m_newRootLayer = newRootLayer;
00138             }
00139 
00140         virtual ~KisChangeLayersCmd()
00141             {
00142             }
00143 
00144     public:
00145         virtual void execute()
00146             {
00147                 m_adapter->setUndo(false);
00148                 m_img->setRootLayer(m_newRootLayer);
00149                 m_adapter->setUndo(true);
00150                 m_img->notifyLayersChanged();
00151             }
00152 
00153         virtual void unexecute()
00154             {
00155                 m_adapter->setUndo(false);
00156                 m_img->setRootLayer(m_oldRootLayer);
00157                 m_adapter->setUndo(true);
00158                 m_img->notifyLayersChanged();
00159             }
00160 
00161     private:
00162         KisUndoAdapter *m_adapter;
00163         KisImageSP m_img;
00164         KisGroupLayerSP m_oldRootLayer;
00165         KisGroupLayerSP m_newRootLayer;
00166     };
00167 
00168 
00169     // -------------------------------------------------------
00170 
00171     class KisConvertImageTypeCmd : public KNamedCommand {
00172         typedef KNamedCommand super;
00173 
00174     public:
00175         KisConvertImageTypeCmd(KisUndoAdapter *adapter, KisImageSP img,
00176                                KisColorSpace * beforeColorSpace, KisColorSpace * afterColorSpace
00177             ) : super(i18n("Convert Image Type"))
00178             {
00179                 m_adapter = adapter;
00180                 m_img = img;
00181                 m_beforeColorSpace = beforeColorSpace;
00182                 m_afterColorSpace = afterColorSpace;
00183             }
00184 
00185         virtual ~KisConvertImageTypeCmd()
00186             {
00187             }
00188 
00189     public:
00190         virtual void execute()
00191             {
00192                 m_adapter->setUndo(false);
00193 
00194                 m_img->setColorSpace(m_afterColorSpace);
00195                 m_img->setProfile(m_afterColorSpace->getProfile());
00196 
00197                 m_adapter->setUndo(true);
00198             }
00199 
00200         virtual void unexecute()
00201             {
00202                 m_adapter->setUndo(false);
00203 
00204                 m_img->setColorSpace(m_beforeColorSpace);
00205                 m_img->setProfile(m_beforeColorSpace->getProfile());
00206 
00207                 m_adapter->setUndo(true);
00208             }
00209 
00210     private:
00211         KisUndoAdapter *m_adapter;
00212         KisImageSP m_img;
00213         KisColorSpace * m_beforeColorSpace;
00214         KisColorSpace * m_afterColorSpace;
00215     };
00216 
00217 
00218     // -------------------------------------------------------
00219 
00220     class KisImageCommand : public KNamedCommand {
00221         typedef KNamedCommand super;
00222 
00223     public:
00224         KisImageCommand(const QString& name, KisImageSP image);
00225         virtual ~KisImageCommand() {}
00226 
00227         virtual void execute() = 0;
00228         virtual void unexecute() = 0;
00229 
00230     protected:
00231         void setUndo(bool undo);
00232 
00233         KisImageSP m_image;
00234     };
00235 
00236     KisImageCommand::KisImageCommand(const QString& name, KisImageSP image) :
00237         super(name), m_image(image)
00238     {
00239     }
00240 
00241     void KisImageCommand::setUndo(bool undo)
00242     {
00243         if (m_image->undoAdapter()) {
00244             m_image->undoAdapter()->setUndo(undo);
00245         }
00246     }
00247 
00248 
00249     // -------------------------------------------------------
00250 
00251     class KisLayerPositionCommand : public KisImageCommand {
00252         typedef KisImageCommand super;
00253 
00254     public:
00255         KisLayerPositionCommand(const QString& name, KisImageSP image, KisLayerSP layer, KisGroupLayerSP parent, KisLayerSP aboveThis) : super(name, image)
00256             {
00257                 m_layer = layer;
00258                 m_oldParent = layer->parent();
00259                 m_oldAboveThis = layer->nextSibling();
00260                 m_newParent = parent;
00261                 m_newAboveThis = aboveThis;
00262            }
00263 
00264         virtual void execute()
00265             {
00266                 setUndo(false);
00267                 m_image->moveLayer(m_layer, m_newParent, m_newAboveThis);
00268                 setUndo(true);
00269             }
00270 
00271         virtual void unexecute()
00272             {
00273                 setUndo(false);
00274                 m_image->moveLayer(m_layer, m_oldParent, m_oldAboveThis);
00275                 setUndo(true);
00276             }
00277 
00278     private:
00279         KisLayerSP m_layer;
00280         KisGroupLayerSP m_oldParent;
00281         KisLayerSP m_oldAboveThis;
00282         KisGroupLayerSP m_newParent;
00283         KisLayerSP m_newAboveThis;
00284     };
00285 
00286 
00287     // -------------------------------------------------------
00288 
00289     class LayerAddCmd : public KisCommand {
00290         typedef KisCommand super;
00291 
00292     public:
00293         LayerAddCmd(KisUndoAdapter *adapter, KisImageSP img, KisLayerSP layer) : super(i18n("Add Layer"), adapter)
00294             {
00295                 m_img = img;
00296                 m_layer = layer;
00297                 m_parent = layer->parent();
00298                 m_aboveThis = layer->nextSibling();
00299             }
00300 
00301         virtual ~LayerAddCmd()
00302             {
00303             }
00304 
00305         virtual void execute()
00306             {
00307                 adapter()->setUndo(false);
00308                 m_img->addLayer(m_layer, m_parent.data(), m_aboveThis);
00309                 adapter()->setUndo(true);
00310             }
00311 
00312         virtual void unexecute()
00313             {
00314                 adapter()->setUndo(false);
00315                 m_img->removeLayer(m_layer);
00316                 adapter()->setUndo(true);
00317             }
00318 
00319     private:
00320         KisImageSP m_img;
00321         KisLayerSP m_layer;
00322         KisGroupLayerSP m_parent;
00323         KisLayerSP m_aboveThis;
00324     };
00325 
00326     // -------------------------------------------------------
00327 
00328     class LayerRmCmd : public KNamedCommand {
00329         typedef KNamedCommand super;
00330 
00331     public:
00332         LayerRmCmd(KisUndoAdapter *adapter, KisImageSP img,
00333                    KisLayerSP layer, KisGroupLayerSP wasParent, KisLayerSP wasAbove)
00334             : super(i18n("Remove Layer"))
00335             {
00336                 m_adapter = adapter;
00337                 m_img = img;
00338                 m_layer = layer;
00339                 m_prevParent = wasParent;
00340                 m_prevAbove = wasAbove;
00341             }
00342 
00343         virtual ~LayerRmCmd()
00344             {
00345             }
00346 
00347         virtual void execute()
00348             {
00349                 m_adapter->setUndo(false);
00350                 m_img->removeLayer(m_layer);
00351                 m_adapter->setUndo(true);
00352             }
00353 
00354         virtual void unexecute()
00355             {
00356                 m_adapter->setUndo(false);
00357                 m_img->addLayer(m_layer, m_prevParent.data(), m_prevAbove);
00358                 m_adapter->setUndo(true);
00359             }
00360 
00361     private:
00362         KisUndoAdapter *m_adapter;
00363         KisImageSP m_img;
00364         KisLayerSP m_layer;
00365         KisGroupLayerSP m_prevParent;
00366         KisLayerSP m_prevAbove;
00367     };
00368 
00369     class LayerMoveCmd: public KNamedCommand {
00370         typedef KNamedCommand super;
00371 
00372     public:
00373         LayerMoveCmd(KisUndoAdapter *adapter, KisImageSP img,
00374                          KisLayerSP layer, KisGroupLayerSP wasParent, KisLayerSP wasAbove)
00375             : super(i18n("Move Layer"))
00376             {
00377                 m_adapter = adapter;
00378                 m_img = img;
00379                 m_layer = layer;
00380                 m_prevParent = wasParent;
00381                 m_prevAbove = wasAbove;
00382                 m_newParent = layer->parent();
00383                 m_newAbove = layer->nextSibling();
00384             }
00385 
00386         virtual ~LayerMoveCmd()
00387             {
00388             }
00389 
00390         virtual void execute()
00391             {
00392                 m_adapter->setUndo(false);
00393                 m_img->moveLayer(m_layer, m_newParent.data(), m_newAbove);
00394                 m_adapter->setUndo(true);
00395             }
00396 
00397         virtual void unexecute()
00398             {
00399                 m_adapter->setUndo(false);
00400                 m_img->moveLayer(m_layer, m_prevParent.data(), m_prevAbove);
00401                 m_adapter->setUndo(true);
00402             }
00403 
00404     private:
00405         KisUndoAdapter *m_adapter;
00406         KisImageSP m_img;
00407         KisLayerSP m_layer;
00408         KisGroupLayerSP m_prevParent;
00409         KisLayerSP m_prevAbove;
00410         KisGroupLayerSP m_newParent;
00411         KisLayerSP m_newAbove;
00412     };
00413 
00414 
00415     // -------------------------------------------------------
00416 
00417     class LayerPropsCmd : public KNamedCommand {
00418         typedef KNamedCommand super;
00419 
00420     public:
00421         LayerPropsCmd(KisLayerSP layer,
00422                       KisImageSP img,
00423                       KisUndoAdapter *adapter,
00424                       const QString& name,
00425                       Q_INT32 opacity,
00426                       const KisCompositeOp& compositeOp) : super(i18n("Layer Property Changes"))
00427             {
00428                 m_layer = layer;
00429                 m_img = img;
00430                 m_adapter = adapter;
00431                 m_name = name;
00432                 m_opacity = opacity;
00433                 m_compositeOp = compositeOp;
00434             }
00435 
00436         virtual ~LayerPropsCmd()
00437             {
00438             }
00439 
00440     public:
00441         virtual void execute()
00442             {
00443                 QString name = m_layer->name();
00444                 Q_INT32 opacity = m_layer->opacity();
00445                 KisCompositeOp compositeOp = m_layer->compositeOp();
00446 
00447                 m_adapter->setUndo(false);
00448                 m_img->setLayerProperties(m_layer,
00449                                             m_opacity,
00450                                             m_compositeOp,
00451                                             m_name);
00452                 m_adapter->setUndo(true);
00453                 m_name = name;
00454                 m_opacity = opacity;
00455                 m_compositeOp = compositeOp;
00456                 m_layer->setDirty();
00457             }
00458 
00459         virtual void unexecute()
00460             {
00461                 execute();
00462             }
00463 
00464     private:
00465         KisUndoAdapter *m_adapter;
00466         KisLayerSP m_layer;
00467         KisImageSP m_img;
00468         QString m_name;
00469         Q_INT32 m_opacity;
00470         KisCompositeOp m_compositeOp;
00471     };
00472 
00473     // -------------------------------------------------------
00474 
00475     class LockImageCommand : public KNamedCommand {
00476         typedef KNamedCommand super;
00477 
00478     public:
00479         LockImageCommand(KisImageSP img, bool lockImage) : super("lock image")  // Not for translation, this
00480             {                                                                   // is only ever used inside a macro command.
00481                 m_img = img;
00482                 m_lockImage = lockImage;
00483             }
00484 
00485         virtual ~LockImageCommand()
00486             {
00487             }
00488 
00489         virtual void execute()
00490             {
00491                 if (m_lockImage) {
00492                     m_img->lock();
00493                 } else {
00494                     m_img->unlock();
00495                 }
00496             }
00497 
00498         virtual void unexecute()
00499             {
00500                 if (m_lockImage) {
00501                     m_img->unlock();
00502                 } else {
00503                     m_img->lock();
00504                 }
00505             }
00506 
00507     private:
00508         KisImageSP m_img;
00509         bool m_lockImage;
00510     };
00511 }
00512 
00513 KisImage::KisImage(KisUndoAdapter *adapter, Q_INT32 width, Q_INT32 height,  KisColorSpace * colorSpace, const QString& name)
00514     : QObject(0, name.latin1()), KShared()
00515 {
00516     init(adapter, width, height, colorSpace, name);
00517     setName(name);
00518     m_dcop = 0L;
00519 }
00520 
00521 KisImage::KisImage(const KisImage& rhs) : QObject(), KShared(rhs)
00522 {
00523     m_dcop = 0L;
00524     if (this != &rhs) {
00525         m_private = new KisImagePrivate(*rhs.m_private);
00526         m_uri = rhs.m_uri;
00527         m_name = QString::null;
00528         m_width = rhs.m_width;
00529         m_height = rhs.m_height;
00530         m_xres = rhs.m_xres;
00531         m_yres = rhs.m_yres;
00532         m_unit = rhs.m_unit;
00533         m_colorSpace = rhs.m_colorSpace;
00534         m_dirty = rhs.m_dirty;
00535         m_adapter = rhs.m_adapter;
00536 
00537         m_bkg = new KisBackground();
00538         Q_CHECK_PTR(m_bkg);
00539 
00540         m_rootLayer = static_cast<KisGroupLayer*>(rhs.m_rootLayer->clone().data());
00541         connect(m_rootLayer, SIGNAL(sigDirty(QRect)), this, SIGNAL(sigImageUpdated(QRect)));
00542 
00543         m_annotations = rhs.m_annotations; // XXX the annotations would probably need to be deep-copied
00544 
00545         m_nserver = new KisNameServer(i18n("Layer %1"), rhs.m_nserver->currentSeed() + 1);
00546         Q_CHECK_PTR(m_nserver);
00547 
00548         //m_guides = rhs.m_guides;
00549     }
00550 }
00551 
00552 
00553 
00554 DCOPObject * KisImage::dcopObject()
00555 {
00556     if (!m_dcop) {
00557         m_dcop = new KisImageIface(this);
00558         Q_CHECK_PTR(m_dcop);
00559     }
00560     return m_dcop;
00561 }
00562 
00563 KisImage::~KisImage()
00564 {
00565     delete m_private;
00566     delete m_nserver;
00567     delete m_dcop;
00568 }
00569 
00570 QString KisImage::name() const
00571 {
00572     return m_name;
00573 }
00574 
00575 void KisImage::setName(const QString& name)
00576 {
00577     if (!name.isEmpty())
00578         m_name = name;
00579 }
00580 
00581 QString KisImage::description() const
00582 {
00583     return m_description;
00584 }
00585 
00586 void KisImage::setDescription(const QString& description)
00587 {
00588     if (!description.isEmpty())
00589         m_description = description;
00590 }
00591 
00592 
00593 KisColor KisImage::backgroundColor() const
00594 {
00595     return m_private->backgroundColor;
00596 }
00597 
00598 void KisImage::setBackgroundColor(const KisColor & color)
00599 {
00600     m_private->backgroundColor = color;
00601 }
00602 
00603 
00604 QString KisImage::nextLayerName() const
00605 {
00606     if (m_nserver->currentSeed() == 0) {
00607         m_nserver->number();
00608         return i18n("background");
00609     }
00610 
00611     return m_nserver->name();
00612 }
00613 
00614 void KisImage::rollBackLayerName()
00615 {
00616     m_nserver->rollback();
00617 }
00618 
00619 void KisImage::init(KisUndoAdapter *adapter, Q_INT32 width, Q_INT32 height,  KisColorSpace * colorSpace, const QString& name)
00620 {
00621     Q_ASSERT(colorSpace);
00622 
00623     if (colorSpace == 0) {
00624         colorSpace = KisMetaRegistry::instance()->csRegistry()->getRGB8();
00625         kdWarning(41010) << "No colorspace specified: using RGBA\n";
00626     }
00627 
00628     m_private = new KisImagePrivate();
00629     m_private->backgroundColor = KisColor(Qt::white, colorSpace);
00630     m_private->lockCount = 0;
00631     m_private->sizeChangedWhileLocked = false;
00632     m_private->selectionChangedWhileLocked = false;
00633 
00634     m_adapter = adapter;
00635 
00636     m_nserver = new KisNameServer(i18n("Layer %1"), 1);
00637     m_name = name;
00638 
00639     m_colorSpace = colorSpace;
00640     m_bkg = new KisBackground();
00641 
00642     m_rootLayer = new KisGroupLayer(this,"root", OPACITY_OPAQUE);
00643     connect(m_rootLayer, SIGNAL(sigDirty(QRect)), this, SIGNAL(sigImageUpdated(QRect)));
00644 
00645     m_xres = 1.0;
00646     m_yres = 1.0;
00647     m_unit = KoUnit::U_PT;
00648     m_dirty = false;
00649     m_width = width;
00650     m_height = height;
00651 }
00652 
00653 bool KisImage::locked() const
00654 {
00655     return m_private->lockCount != 0;
00656 }
00657 
00658 void KisImage::lock()
00659 {
00660     if (!locked()) {
00661         if (m_rootLayer) disconnect(m_rootLayer, SIGNAL(sigDirty(QRect)), this, SIGNAL(sigImageUpdated(QRect)));
00662         m_private->sizeChangedWhileLocked = false;
00663         m_private->selectionChangedWhileLocked = false;
00664     }
00665     m_private->lockCount++;
00666 }
00667 
00668 void KisImage::unlock()
00669 {
00670     Q_ASSERT(locked());
00671 
00672     if (locked()) {
00673         m_private->lockCount--;
00674 
00675         if (m_private->lockCount == 0) {
00676             if (m_private->sizeChangedWhileLocked) {
00677                 // A size change implies a full image update so only send this.
00678                 emit sigSizeChanged(m_width, m_height);
00679             } else {
00680                 if (m_rootLayer->dirty()) emit sigImageUpdated( m_rootLayer->dirtyRect() );
00681             }
00682 
00683             if (m_private->selectionChangedWhileLocked) {
00684                 emit sigActiveSelectionChanged(this);
00685             }
00686 
00687             if (m_rootLayer) connect(m_rootLayer, SIGNAL(sigDirty(QRect)), this, SIGNAL(sigImageUpdated(QRect)));
00688         }
00689     }
00690 }
00691 
00692 void KisImage::emitSizeChanged()
00693 {
00694     if (!locked()) {
00695         emit sigSizeChanged(m_width, m_height);
00696     } else {
00697         m_private->sizeChangedWhileLocked = true;
00698     }
00699 }
00700 
00701 void KisImage::notifyLayerUpdated(KisLayerSP layer, QRect rc)
00702 {
00703     emit sigLayerUpdated(layer, rc);
00704 }
00705 
00706 void KisImage::resize(Q_INT32 w, Q_INT32 h, Q_INT32 x, Q_INT32 y, bool cropLayers)
00707 {
00708     if (w != width() || h != height()) {
00709 
00710         lock();
00711 
00712         if (undo()) {
00713             if (cropLayers)
00714                 m_adapter->beginMacro(i18n("Crop Image"));
00715             else
00716                 m_adapter->beginMacro(i18n("Resize Image"));
00717 
00718             m_adapter->addCommand(new LockImageCommand(this, true));
00719             m_adapter->addCommand(new KisResizeImageCmd(m_adapter, this, w, h, width(), height()));
00720         }
00721 
00722         m_width = w;
00723         m_height = h;
00724 
00725         if (cropLayers) {
00726             KisCropVisitor v(QRect(x, y, w, h));
00727             m_rootLayer->accept(v);
00728         }
00729 
00730         emitSizeChanged();
00731 
00732         unlock();
00733 
00734         if (undo()) {
00735             m_adapter->addCommand(new LockImageCommand(this, false));
00736             m_adapter->endMacro();
00737         }
00738     }
00739 }
00740 
00741 void KisImage::resize(const QRect& rc, bool cropLayers)
00742 {
00743     resize(rc.width(), rc.height(), rc.x(), rc.y(), cropLayers);
00744 }
00745 
00746 
00747 void KisImage::scale(double sx, double sy, KisProgressDisplayInterface *progress, KisFilterStrategy *filterStrategy)
00748 {
00749     if (nlayers() == 0) return; // Nothing to scale
00750 
00751     // New image size. XXX: Pass along to discourage rounding errors?
00752     Q_INT32 w, h;
00753     w = (Q_INT32)(( width() * sx) + 0.5);
00754     h = (Q_INT32)(( height() * sy) + 0.5);
00755 
00756     if (w != width() || h != height()) {
00757 
00758         lock();
00759 
00760         if (undo()) {
00761             m_adapter->beginMacro(i18n("Scale Image"));
00762             m_adapter->addCommand(new LockImageCommand(this, true));
00763         }
00764 
00765         {
00766             KisTransformVisitor visitor (this, sx, sy, 0.0, 0.0, 0.0, 0, 0, progress, filterStrategy);
00767             m_rootLayer->accept(visitor);
00768         }
00769 
00770         if (undo()) {
00771             m_adapter->addCommand(new KisResizeImageCmd(m_adapter, this, w, h, width(), height()));
00772         }
00773 
00774         m_width = w;
00775         m_height = h;
00776 
00777         emitSizeChanged();
00778 
00779         unlock();
00780 
00781         if (undo()) {
00782             m_adapter->addCommand(new LockImageCommand(this, false));
00783             m_adapter->endMacro();
00784         }
00785     }
00786 }
00787 
00788 
00789 
00790 void KisImage::rotate(double angle, KisProgressDisplayInterface *progress)
00791 {
00792     lock();
00793 
00794     angle *= M_PI/180;
00795     Q_INT32 w = width();
00796     Q_INT32 h = height();
00797     Q_INT32 tx = Q_INT32((w*cos(angle) - h*sin(angle) - w) / 2 + 0.5);
00798     Q_INT32 ty = Q_INT32((h*cos(angle) + w*sin(angle) - h) / 2 + 0.5);
00799     w = (Q_INT32)(width()*QABS(cos(angle)) + height()*QABS(sin(angle)) + 0.5);
00800     h = (Q_INT32)(height()*QABS(cos(angle)) + width()*QABS(sin(angle)) + 0.5);
00801 
00802     tx -= (w - width()) / 2;
00803     ty -= (h - height()) / 2;
00804 
00805     if (undo()) {
00806         m_adapter->beginMacro(i18n("Rotate Image"));
00807         m_adapter->addCommand(new LockImageCommand(this, true));
00808     }
00809 
00810     KisFilterStrategy *filter = KisFilterStrategyRegistry::instance()->get(KisID("Triangle"));
00811     KisTransformVisitor visitor (this, 1.0, 1.0, 0, 0, angle, -tx, -ty, progress, filter);
00812     m_rootLayer->accept(visitor);
00813 
00814     if (undo()) m_adapter->addCommand(new KisResizeImageCmd(undoAdapter(), this, w, h, width(), height()));
00815 
00816     m_width = w;
00817     m_height = h;
00818 
00819     emitSizeChanged();
00820 
00821     unlock();
00822 
00823     if (undo()) {
00824         m_adapter->addCommand(new LockImageCommand(this, false));
00825         m_adapter->endMacro();
00826     }
00827 }
00828 
00829 void KisImage::shear(double angleX, double angleY, KisProgressDisplayInterface *m_progress)
00830 {
00831     const double pi=3.1415926535897932385;
00832 
00833     //new image size
00834     Q_INT32 w=width();
00835     Q_INT32 h=height();
00836 
00837 
00838     if(angleX != 0 || angleY != 0){
00839         double deltaY=height()*QABS(tan(angleX*pi/180)*tan(angleY*pi/180));
00840         w = (Q_INT32) ( width() + QABS(height()*tan(angleX*pi/180)) );
00841         //ugly fix for the problem of having two extra pixels if only a shear along one
00842         //axis is done. This has to be fixed in the cropping code in KisRotateVisitor!
00843         if (angleX == 0 || angleY == 0)
00844             h = (Q_INT32) ( height() + QABS(w*tan(angleY*pi/180)) );
00845         else if (angleX > 0 && angleY > 0)
00846             h = (Q_INT32) ( height() + QABS(w*tan(angleY*pi/180))- 2 * deltaY + 2 );
00847         else if (angleX < 0 && angleY < 0)
00848             h = (Q_INT32) ( height() + QABS(w*tan(angleY*pi/180))- 2 * deltaY + 2 );
00849         else
00850             h = (Q_INT32) ( height() + QABS(w*tan(angleY*pi/180)) );
00851     }
00852 
00853     if (w != width() || h != height()) {
00854 
00855         lock();
00856 
00857         if (undo()) {
00858             m_adapter->beginMacro(i18n("Shear Image"));
00859             m_adapter->addCommand(new LockImageCommand(this, true));
00860         }
00861 
00862         KisShearVisitor v(angleX, angleY, m_progress);
00863         v.setUndoAdapter(undoAdapter());
00864         rootLayer()->accept(v);
00865 
00866         if (undo()) m_adapter->addCommand(new KisResizeImageCmd(m_adapter, this, w, h, width(), height()));
00867 
00868         m_width = w;
00869         m_height = h;
00870 
00871         emitSizeChanged();
00872 
00873         unlock();
00874 
00875         if (undo()) {
00876             m_adapter->addCommand(new LockImageCommand(this, false));
00877             m_adapter->endMacro();
00878         }
00879     }
00880 }
00881 
00882 void KisImage::convertTo(KisColorSpace * dstColorSpace, Q_INT32 renderingIntent)
00883 {
00884     if ( m_colorSpace == dstColorSpace )
00885     {
00886         return;
00887     }
00888 
00889     lock();
00890 
00891     KisColorSpace * oldCs = m_colorSpace;
00892 
00893     if (undo()) {
00894         m_adapter->beginMacro(i18n("Convert Image Type"));
00895         m_adapter->addCommand(new LockImageCommand(this, true));
00896     }
00897 
00898     setColorSpace(dstColorSpace);
00899 
00900     KisColorSpaceConvertVisitor visitor(dstColorSpace, renderingIntent);
00901     m_rootLayer->accept(visitor);
00902 
00903     unlock();
00904 
00905     emit sigLayerPropertiesChanged( m_activeLayer );
00906 
00907     if (undo()) {
00908 
00909         m_adapter->addCommand(new KisConvertImageTypeCmd(undoAdapter(), this,
00910                                                          oldCs, dstColorSpace));
00911         m_adapter->addCommand(new LockImageCommand(this, false));
00912         m_adapter->endMacro();
00913     }
00914 }
00915 
00916 KisProfile *  KisImage::getProfile() const
00917 {
00918     return colorSpace()->getProfile();
00919 }
00920 
00921 void KisImage::setProfile(const KisProfile * profile)
00922 {
00923     if (profile == 0) return;
00924 
00925     KisColorSpace * dstCs= KisMetaRegistry::instance()->csRegistry()->getColorSpace( colorSpace()->id(),
00926                                                                                          profile);
00927     if (dstCs) {
00928 
00929         lock();
00930 
00931         KisColorSpace * oldCs = colorSpace();
00932         setColorSpace(dstCs);
00933         emit(sigProfileChanged(const_cast<KisProfile *>(profile)));
00934 
00935         KisChangeProfileVisitor visitor(oldCs, dstCs);
00936         m_rootLayer->accept(visitor);
00937 
00938         unlock();
00939     }
00940 }
00941 
00942 double KisImage::xRes()
00943 {
00944     return m_xres;
00945 }
00946 
00947 double KisImage::yRes()
00948 {
00949     return m_yres;
00950 }
00951 
00952 void KisImage::setResolution(double xres, double yres)
00953 {
00954     m_xres = xres;
00955     m_yres = yres;
00956 }
00957 
00958 Q_INT32 KisImage::width() const
00959 {
00960     return m_width;
00961 }
00962 
00963 Q_INT32 KisImage::height() const
00964 {
00965     return m_height;
00966 }
00967 
00968 KisPaintDeviceSP KisImage::activeDevice()
00969 {
00970     if (KisPaintLayer* layer = dynamic_cast<KisPaintLayer*>(m_activeLayer.data())) {
00971         return layer->paintDevice();
00972     }
00973     else if (KisAdjustmentLayer* layer = dynamic_cast<KisAdjustmentLayer*>(m_activeLayer.data())) {
00974         if (layer->selection()) {
00975             return layer->selection().data();
00976         }
00977     }
00978     else if (KisGroupLayer * layer = dynamic_cast<KisGroupLayer*>(m_activeLayer.data())) {
00979         // Find first child
00980         KisLayer * child = layer->lastChild();
00981         while(child)
00982         {
00983             if (KisPaintLayer* layer = dynamic_cast<KisPaintLayer*>(m_activeLayer.data())) {
00984                 return layer->paintDevice();
00985             }
00986             child = child->prevSibling();
00987         }
00988     }
00989     // XXX: We're buggered!
00990     return 0;
00991 }
00992 
00993 KisLayerSP KisImage::newLayer(const QString& name, Q_UINT8 opacity, const KisCompositeOp& compositeOp, KisColorSpace * colorstrategy)
00994 {
00995     KisPaintLayer * layer;
00996     if (colorstrategy)
00997         layer = new KisPaintLayer(this, name, opacity, colorstrategy);
00998     else
00999         layer = new KisPaintLayer(this, name, opacity);
01000     Q_CHECK_PTR(layer);
01001 
01002     if (compositeOp.isValid())
01003         layer->setCompositeOp(compositeOp);
01004     layer->setVisible(true);
01005 
01006     if (m_activeLayer != 0) {
01007         addLayer(layer, m_activeLayer->parent().data(), m_activeLayer->nextSibling());
01008     }
01009     else {
01010         addLayer(layer, m_rootLayer, 0);
01011     }
01012     activate(layer);
01013 
01014     return layer;
01015 }
01016 
01017 void KisImage::setLayerProperties(KisLayerSP layer, Q_UINT8 opacity, const KisCompositeOp& compositeOp, const QString& name)
01018 {
01019     if (layer && (layer->opacity() != opacity || layer->compositeOp() != compositeOp || layer->name() != name)) {
01020         if (undo()) {
01021             QString oldname = layer->name();
01022             Q_INT32 oldopacity = layer->opacity();
01023             KisCompositeOp oldCompositeOp = layer->compositeOp();
01024             layer->setName(name);
01025             layer->setOpacity(opacity);
01026             layer->setCompositeOp(compositeOp);
01027             m_adapter->addCommand(new LayerPropsCmd(layer, this, m_adapter, oldname, oldopacity, oldCompositeOp));
01028         } else {
01029             layer->setName(name);
01030             layer->setOpacity(opacity);
01031             layer->setCompositeOp(compositeOp);
01032         }
01033     }
01034 }
01035 
01036 KisGroupLayerSP KisImage::rootLayer() const
01037 {
01038     return m_rootLayer;
01039 }
01040 
01041 KisLayerSP KisImage::activeLayer() const
01042 {
01043     return m_activeLayer;
01044 }
01045 
01046 KisPaintDeviceSP KisImage::projection()
01047 {
01048     return m_rootLayer->projection(QRect(0, 0, m_width, m_height));
01049 }
01050 
01051 KisLayerSP KisImage::activate(KisLayerSP layer)
01052 {
01053     if (layer != m_activeLayer) {
01054         if (m_activeLayer) m_activeLayer->deactivate();
01055         m_activeLayer = layer;
01056         if (m_activeLayer) m_activeLayer->activate();
01057         emit sigLayerActivated(m_activeLayer);
01058     }
01059 
01060     return layer;
01061 }
01062 
01063 KisLayerSP KisImage::findLayer(const QString& name) const
01064 {
01065     return rootLayer()->findLayer(name);
01066 }
01067 
01068 KisLayerSP KisImage::findLayer(int id) const
01069 {
01070     return rootLayer()->findLayer(id);
01071 }
01072 
01073 
01074 bool KisImage::addLayer(KisLayerSP layer, KisGroupLayerSP parent)
01075 {
01076     return addLayer(layer, parent, parent->firstChild());
01077 }
01078 
01079 bool KisImage::addLayer(KisLayerSP layer, KisGroupLayerSP parent, KisLayerSP aboveThis)
01080 {
01081     if (!parent)
01082         return false;
01083 
01084     const bool success = parent->addLayer(layer, aboveThis);
01085     if (success)
01086     {
01087         KisPaintLayerSP player = dynamic_cast<KisPaintLayer*>(layer.data());
01088         if (player != 0) {
01089 
01090             // XXX: This should also be done whenever a layer grows!
01091             QValueVector<KisPaintDeviceAction *> actions = KisMetaRegistry::instance() ->
01092                 csRegistry()->paintDeviceActionsFor(player->paintDevice()->colorSpace());
01093             for (uint i = 0; i < actions.count(); i++) {
01094                 actions.at(i)->act(player.data()->paintDevice(), width(), height());
01095             }
01096         }
01097 
01098         if (layer->extent().isValid()) layer->setDirty();
01099 
01100         if (!layer->temporary()) {
01101             emit sigLayerAdded(layer);
01102             activate(layer);
01103         }
01104 
01105 
01106         if (!layer->temporary() && undo()) {
01107             m_adapter->addCommand(new LayerAddCmd(m_adapter, this, layer));
01108         }
01109     }
01110 
01111     return success;
01112 }
01113 
01114 bool KisImage::removeLayer(KisLayerSP layer)
01115 {
01116     if (!layer || layer->image() != this)
01117         return false;
01118 
01119     if (KisGroupLayerSP parent = layer->parent()) {
01120         // Adjustment layers should mark the layers underneath them, whose rendering
01121         // they have cached, diryt on removal. Otherwise, the group won't be re-rendered.
01122         KisAdjustmentLayer * al = dynamic_cast<KisAdjustmentLayer*>(layer.data());
01123         if (al) {
01124             QRect r = al->extent();
01125             lock(); // Lock the image, because we are going to dirty a lot of layers
01126             KisLayerSP l = layer->nextSibling();
01127             while (l) {
01128                 KisAdjustmentLayer * al2 = dynamic_cast<KisAdjustmentLayer*>(l.data());
01129                 l->setDirty(r, false);
01130                 if (al2 != 0) break;
01131                 l = l->nextSibling();
01132             }
01133             unlock();
01134         }
01135         KisLayerSP l = layer->prevSibling();
01136         QRect r = layer->extent();
01137         while (l) {
01138             l->setDirty(r, false);
01139             l = l->prevSibling();
01140         }
01141 
01142         KisLayerSP wasAbove = layer->nextSibling();
01143         KisLayerSP wasBelow = layer->prevSibling();
01144         const bool wasActive = layer == activeLayer();
01145         // sigLayerRemoved can set it to 0, we don't want that in the else of wasActive!
01146         KisLayerSP actLayer = activeLayer();
01147         const bool success = parent->removeLayer(layer);
01148         if (success) {
01149             layer->setImage(0);
01150             if (!layer->temporary() && undo()) {
01151                 m_adapter->addCommand(new LayerRmCmd(m_adapter, this, layer, parent, wasAbove));
01152             }
01153             if (!layer->temporary()) {
01154                 emit sigLayerRemoved(layer, parent, wasAbove);
01155                 if (wasActive) {
01156                     if (wasBelow)
01157                         activate(wasBelow);
01158                     else if (wasAbove)
01159                         activate(wasAbove);
01160                     else if (parent != rootLayer())
01161                         activate(parent.data());
01162                     else
01163                         activate(rootLayer()->firstChild());
01164                 } else {
01165                     activate(actLayer);
01166                 }
01167             }
01168         }
01169         return success;
01170     }
01171 
01172     return false;
01173 }
01174 
01175 bool KisImage::raiseLayer(KisLayerSP layer)
01176 {
01177     if (!layer)
01178         return false;
01179     return moveLayer(layer, layer->parent().data(), layer->prevSibling());
01180 }
01181 
01182 bool KisImage::lowerLayer(KisLayerSP layer)
01183 {
01184     if (!layer)
01185         return false;
01186     if (KisLayerSP next = layer->nextSibling())
01187         return moveLayer(layer, layer->parent().data(), next->nextSibling());
01188     return false;
01189 }
01190 
01191 bool KisImage::toTop(KisLayerSP layer)
01192 {
01193     if (!layer)
01194         return false;
01195     return moveLayer(layer, rootLayer(), rootLayer()->firstChild());
01196 }
01197 
01198 bool KisImage::toBottom(KisLayerSP layer)
01199 {
01200     if (!layer)
01201         return false;
01202     return moveLayer(layer, rootLayer(), 0);
01203 }
01204 
01205 bool KisImage::moveLayer(KisLayerSP layer, KisGroupLayerSP parent, KisLayerSP aboveThis)
01206 {
01207     if (!parent)
01208         return false;
01209 
01210     KisGroupLayerSP wasParent = layer->parent();
01211     KisLayerSP wasAbove = layer->nextSibling();
01212 
01213     if (wasParent.data() == parent.data() && wasAbove.data() == aboveThis.data())
01214         return false;
01215 
01216     lock();
01217 
01218     if (!wasParent->removeLayer(layer)) {
01219         unlock();
01220         return false;
01221     }
01222 
01223     const bool success = parent->addLayer(layer, aboveThis);
01224 
01225     layer->setDirty();
01226 
01227     unlock();
01228 
01229     if (success)
01230     {
01231         emit sigLayerMoved(layer, wasParent, wasAbove);
01232         if (undo())
01233             m_adapter->addCommand(new LayerMoveCmd(m_adapter, this, layer, wasParent, wasAbove));
01234     }
01235     else //we already removed the layer above, but re-adding it failed, so...
01236     {
01237         emit sigLayerRemoved(layer, wasParent, wasAbove);
01238         if (undo())
01239             m_adapter->addCommand(new LayerRmCmd(m_adapter, this, layer, wasParent, wasAbove));
01240     }
01241 
01242     return success;
01243 }
01244 
01245 Q_INT32 KisImage::nlayers() const
01246 {
01247     return rootLayer()->numLayers() - 1;
01248 }
01249 
01250 Q_INT32 KisImage::nHiddenLayers() const
01251 {
01252     return rootLayer()->numLayers(KisLayer::Hidden);
01253 }
01254 
01255 void KisImage::flatten()
01256 {
01257     KisGroupLayerSP oldRootLayer = m_rootLayer;
01258     disconnect(oldRootLayer, SIGNAL(sigDirty(QRect)), this, SIGNAL(sigImageUpdated(QRect)));
01259 
01260     KisPaintLayer *dst = new KisPaintLayer(this, nextLayerName(), OPACITY_OPAQUE, colorSpace());
01261     Q_CHECK_PTR(dst);
01262 
01263     QRect rc = mergedImage()->extent();
01264 
01265     KisPainter gc(dst->paintDevice());
01266     gc.bitBlt(rc.x(), rc.y(), COMPOSITE_COPY, mergedImage(), OPACITY_OPAQUE, rc.left(), rc.top(), rc.width(), rc.height());
01267 
01268     m_rootLayer = new KisGroupLayer(this, "", OPACITY_OPAQUE);
01269     connect(m_rootLayer, SIGNAL(sigDirty(QRect)), this, SIGNAL(sigImageUpdated(QRect)));
01270 
01271     if (undo()) {
01272         m_adapter->beginMacro(i18n("Flatten Image"));
01273         m_adapter->addCommand(new LockImageCommand(this, true));
01274         m_adapter->addCommand(new KisChangeLayersCmd(m_adapter, this, oldRootLayer, m_rootLayer, ""));
01275     }
01276 
01277     lock();
01278 
01279     addLayer(dst, m_rootLayer, 0);
01280     activate(dst);
01281 
01282     unlock();
01283 
01284     notifyLayersChanged();
01285 
01286     if (undo()) {
01287         m_adapter->addCommand(new LockImageCommand(this, false));
01288         m_adapter->endMacro();
01289     }
01290 }
01291 
01292 
01293 void KisImage::mergeLayer(KisLayerSP layer)
01294 {
01295     KisPaintLayer *player = new KisPaintLayer(this, layer->name(), OPACITY_OPAQUE, colorSpace());
01296     Q_CHECK_PTR(player);
01297 
01298     QRect rc = layer->extent() | layer->nextSibling()->extent();
01299 
01300     undoAdapter()->beginMacro(i18n("Merge with Layer Below"));
01301 
01302     //Abuse the merge visitor to only merge two layers (if either are groups they'll recursively merge)
01303     KisMergeVisitor visitor(player->paintDevice(), rc);
01304     layer->nextSibling()->accept(visitor);
01305     layer->accept(visitor);
01306 
01307     removeLayer(layer->nextSibling());
01308     addLayer(player, layer->parent(), layer);
01309     removeLayer(layer);
01310 
01311     undoAdapter()->endMacro();
01312 }
01313 
01314 
01315 void KisImage::setModified()
01316 {
01317     emit sigImageModified();
01318 }
01319 
01320 void KisImage::renderToPainter(Q_INT32 x1,
01321                                Q_INT32 y1,
01322                                Q_INT32 x2,
01323                                Q_INT32 y2,
01324                                QPainter &painter,
01325                                KisProfile *  monitorProfile,
01326                                PaintFlags paintFlags,
01327                                float exposure)
01328 {
01329 
01330     QImage img = convertToQImage(x1, y1, x2, y2, monitorProfile, exposure);
01331 
01332     Q_INT32 w = x2 - x1 + 1;
01333     Q_INT32 h = y2 - y1 + 1;
01334 
01335 
01336     if (paintFlags & PAINT_BACKGROUND) {
01337         m_bkg->paintBackground(img, x1, y1);
01338         img.setAlphaBuffer(false);
01339     }
01340 
01341     if (paintFlags & PAINT_SELECTION) {
01342         if (m_activeLayer != 0) {
01343             m_activeLayer->paintSelection(img, x1, y1, w, h);
01344         }
01345     }
01346 
01347     if (paintFlags & PAINT_MASKINACTIVELAYERS) {
01348         if (m_activeLayer != 0) {
01349             m_activeLayer->paintMaskInactiveLayers(img, x1, y1, w, h);
01350         }
01351     }
01352 
01353     painter.drawImage(x1, y1, img, 0, 0, w, h);
01354 }
01355 
01356 QImage KisImage::convertToQImage(Q_INT32 x1,
01357                                  Q_INT32 y1,
01358                                  Q_INT32 x2,
01359                                  Q_INT32 y2,
01360                                  KisProfile * profile,
01361                                  float exposure)
01362 {
01363     Q_INT32 w = x2 - x1 + 1;
01364     Q_INT32 h = y2 - y1 + 1;
01365 
01366     KisPaintDeviceSP dev = m_rootLayer->projection(QRect(x1, y1, w, h));
01367     QImage img = dev->convertToQImage(profile, x1, y1, w, h, exposure);
01368 
01369     if (!img.isNull()) {
01370 
01371 #ifdef __BIG_ENDIAN__
01372         uchar * data = img.bits();
01373         for (int i = 0; i < w * h; ++i) {
01374             uchar r, g, b, a;
01375             a = data[0];
01376             b = data[1];
01377             g = data[2];
01378             r = data[3];
01379             data[0] = r;
01380             data[1] = g;
01381             data[2] = b;
01382             data[3] = a;
01383             data += 4;
01384         }
01385 #endif
01386 
01387         return img;
01388     }
01389 
01390     return QImage();
01391 }
01392 
01393 QImage KisImage::convertToQImage(const QRect& r, const QSize& scaledImageSize, KisProfile *profile, PaintFlags paintFlags, float exposure)
01394 {
01395     if (r.isEmpty() || scaledImageSize.isEmpty()) {
01396         return QImage();
01397     }
01398 
01399     Q_INT32 imageWidth = width();
01400     Q_INT32 imageHeight = height();
01401     Q_UINT32 pixelSize = colorSpace()->pixelSize();
01402 
01403     double xScale = static_cast<double>(imageWidth) / scaledImageSize.width();
01404     double yScale = static_cast<double>(imageHeight) / scaledImageSize.height();
01405 
01406     QRect srcRect;
01407 
01408     srcRect.setLeft(static_cast<int>(r.left() * xScale));
01409     srcRect.setRight(static_cast<int>(ceil((r.right() + 1) * xScale)) - 1);
01410     srcRect.setTop(static_cast<int>(r.top() * yScale));
01411     srcRect.setBottom(static_cast<int>(ceil((r.bottom() + 1) * yScale)) - 1);
01412 
01413     KisPaintDeviceSP mergedImage = m_rootLayer->projection(srcRect);
01414     //QTime t;
01415     //t.start();
01416 
01417     Q_UINT8 *scaledImageData = new Q_UINT8[r.width() * r.height() * pixelSize];
01418 
01419     Q_UINT8 *imageRow = new Q_UINT8[srcRect.width() * pixelSize];
01420     const Q_INT32 imageRowX = srcRect.x();
01421 
01422     for (Q_INT32 y = 0; y < r.height(); ++y) {
01423 
01424         Q_INT32 dstY = r.y() + y;
01425         Q_INT32 dstX = r.x();
01426         Q_INT32 srcY = (dstY * imageHeight) / scaledImageSize.height();
01427 
01428         mergedImage->readBytes(imageRow, imageRowX, srcY, srcRect.width(), 1);
01429 
01430         Q_UINT8 *dstPixel = scaledImageData + (y * r.width() * pixelSize);
01431         Q_UINT32 columnsRemaining = r.width();
01432 
01433         while (columnsRemaining > 0) {
01434 
01435             Q_INT32 srcX = (dstX * imageWidth) / scaledImageSize.width();
01436 
01437             memcpy(dstPixel, imageRow + ((srcX - imageRowX) * pixelSize), pixelSize);
01438 
01439             ++dstX;
01440             dstPixel += pixelSize;
01441             --columnsRemaining;
01442         }
01443     }
01444 
01445     delete [] imageRow;
01446 
01447     QImage image = colorSpace()->convertToQImage(scaledImageData, r.width(), r.height(), profile, INTENT_PERCEPTUAL, exposure);
01448     delete [] scaledImageData;
01449 
01450     if (paintFlags & PAINT_BACKGROUND) {
01451         m_bkg->paintBackground(image, r, scaledImageSize, QSize(imageWidth, imageHeight));
01452         image.setAlphaBuffer(false);
01453     }
01454 
01455     if (paintFlags & PAINT_SELECTION) {
01456         if (m_activeLayer != 0) {
01457             m_activeLayer->paintSelection(image, r, scaledImageSize, QSize(imageWidth, imageHeight));
01458         }
01459     }
01460 
01461     /*if (paintFlags & PAINT_MASKINACTIVELAYERS) {
01462         if (m_activeLayer != 0) {
01463             m_activeLayer->paintMaskInactiveLayers(img, x1, y1, w, h);
01464         }
01465     }*/
01466 
01467     return image;
01468 }
01469 
01470 KisPaintDeviceSP KisImage::mergedImage()
01471 {
01472     return m_rootLayer->projection(QRect(0, 0, m_width, m_height));
01473 }
01474 
01475 KisColor KisImage::mergedPixel(Q_INT32 x, Q_INT32 y)
01476 {
01477     return m_rootLayer->projection(QRect(x, y, 1, 1))->colorAt(x, y);
01478 }
01479 
01480 void KisImage::notifyLayersChanged()
01481 {
01482     emit sigLayersChanged(rootLayer());
01483 }
01484 
01485 void KisImage::notifyPropertyChanged(KisLayerSP layer)
01486 {
01487     emit sigLayerPropertiesChanged(layer);
01488 }
01489 
01490 void KisImage::notifyImageLoaded()
01491 {
01492 }
01493 
01494 QRect KisImage::bounds() const
01495 {
01496     return QRect(0, 0, width(), height());
01497 }
01498 
01499 
01500 void KisImage::setUndoAdapter(KisUndoAdapter * adapter)
01501 {
01502     m_adapter = adapter;
01503 }
01504 
01505 
01506 KisUndoAdapter* KisImage::undoAdapter() const
01507 {
01508     return m_adapter;
01509 }
01510 
01511 bool KisImage::undo() const
01512 {
01513     return (m_adapter && m_adapter->undo());
01514 }
01515 
01516 //KisGuideMgr *KisImage::guides() const
01517 //{
01518 //    return const_cast<KisGuideMgr*>(&m_guides);
01519 //}
01520 
01521 void KisImage::slotSelectionChanged()
01522 {
01523     slotSelectionChanged(bounds());
01524 }
01525 
01526 void KisImage::slotSelectionChanged(const QRect& r)
01527 {
01528     QRect r2(r.x() - 1, r.y() - 1, r.width() + 2, r.height() + 2);
01529 
01530     if (!locked()) {
01531         emit sigActiveSelectionChanged(this);
01532     } else {
01533         m_private->selectionChangedWhileLocked = true;
01534     }
01535 }
01536 
01537 KisColorSpace * KisImage::colorSpace() const
01538 {
01539     return m_colorSpace;
01540 }
01541 
01542 void KisImage::setColorSpace(KisColorSpace * colorSpace)
01543 {
01544     m_colorSpace = colorSpace;
01545     m_rootLayer->resetProjection();
01546     emit sigColorSpaceChanged(colorSpace);
01547 }
01548 
01549 void KisImage::setRootLayer(KisGroupLayerSP rootLayer)
01550 {
01551     disconnect(m_rootLayer, SIGNAL(sigDirty(QRect)), this, SIGNAL(sigImageUpdated(QRect)));
01552 
01553     m_rootLayer = rootLayer;
01554 
01555     if (!locked()) {
01556         connect(m_rootLayer, SIGNAL(sigDirty(QRect)), this, SIGNAL(sigImageUpdated(QRect)));
01557     }
01558     activate(m_rootLayer->firstChild());
01559 }
01560 
01561 void KisImage::addAnnotation(KisAnnotationSP annotation)
01562 {
01563     // Find the icc annotation, if there is one
01564     vKisAnnotationSP_it it = m_annotations.begin();
01565     while (it != m_annotations.end()) {
01566         if ((*it)->type() == annotation->type()) {
01567             *it = annotation;
01568             return;
01569         }
01570         ++it;
01571     }
01572     m_annotations.push_back(annotation);
01573 }
01574 
01575 KisAnnotationSP KisImage::annotation(QString type)
01576 {
01577     vKisAnnotationSP_it it = m_annotations.begin();
01578     while (it != m_annotations.end()) {
01579         if ((*it)->type() == type) {
01580             return *it;
01581         }
01582         ++it;
01583     }
01584     return 0;
01585 }
01586 
01587 void KisImage::removeAnnotation(QString type)
01588 {
01589     vKisAnnotationSP_it it = m_annotations.begin();
01590     while (it != m_annotations.end()) {
01591         if ((*it)->type() == type) {
01592             m_annotations.erase(it);
01593             return;
01594         }
01595         ++it;
01596     }
01597 }
01598 
01599 vKisAnnotationSP_it KisImage::beginAnnotations()
01600 {
01601     KisProfile * profile = colorSpace()->getProfile();
01602     KisAnnotationSP annotation;
01603 
01604     if (profile)
01605         annotation =  profile->annotation();
01606 
01607     if (annotation)
01608          addAnnotation(annotation);
01609     else
01610         removeAnnotation("icc");
01611 
01612     return m_annotations.begin();
01613 }
01614 
01615 vKisAnnotationSP_it KisImage::endAnnotations()
01616 {
01617     return m_annotations.end();
01618 }
01619 
01620 KisBackgroundSP KisImage::background() const
01621 {
01622     return m_bkg;
01623 }
01624 #include "kis_image.moc"
01625 
KDE Home | KDE Accessibility Home | Description of Access Keys