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