krita

kis_image.cc

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