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 #if 0
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 #endif
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 radians, KisProgressDisplayInterface *progress)
00805 {
00806     lock();
00807 
00808     Q_INT32 w = width();
00809     Q_INT32 h = height();
00810     Q_INT32 tx = Q_INT32((w*cos(radians) - h*sin(radians) - w) / 2 + 0.5);
00811     Q_INT32 ty = Q_INT32((h*cos(radians) + w*sin(radians) - h) / 2 + 0.5);
00812     w = (Q_INT32)(width()*QABS(cos(radians)) + height()*QABS(sin(radians)) + 0.5);
00813     h = (Q_INT32)(height()*QABS(cos(radians)) + width()*QABS(sin(radians)) + 0.5);
00814 
00815     tx -= (w - width()) / 2;
00816     ty -= (h - height()) / 2;
00817 
00818     if (undo()) {
00819         m_adapter->beginMacro(i18n("Rotate Image"));
00820         m_adapter->addCommand(new LockImageCommand(this, true));
00821     }
00822 
00823     KisFilterStrategy *filter = KisFilterStrategyRegistry::instance()->get(KisID("Triangle"));
00824     KisTransformVisitor visitor (this, 1.0, 1.0, 0, 0, radians, -tx, -ty, progress, filter);
00825     m_rootLayer->accept(visitor);
00826 
00827     if (undo()) m_adapter->addCommand(new KisResizeImageCmd(undoAdapter(), this, w, h, width(), height()));
00828 
00829     m_width = w;
00830     m_height = h;
00831 
00832     emitSizeChanged();
00833 
00834     unlock();
00835 
00836     if (undo()) {
00837         m_adapter->addCommand(new LockImageCommand(this, false));
00838         m_adapter->endMacro();
00839     }
00840 }
00841 
00842 void KisImage::shear(double angleX, double angleY, KisProgressDisplayInterface *m_progress)
00843 {
00844     const double pi=3.1415926535897932385;
00845 
00846     //new image size
00847     Q_INT32 w=width();
00848     Q_INT32 h=height();
00849 
00850 
00851     if(angleX != 0 || angleY != 0){
00852         double deltaY=height()*QABS(tan(angleX*pi/180)*tan(angleY*pi/180));
00853         w = (Q_INT32) ( width() + QABS(height()*tan(angleX*pi/180)) );
00854         //ugly fix for the problem of having two extra pixels if only a shear along one
00855         //axis is done. This has to be fixed in the cropping code in KisRotateVisitor!
00856         if (angleX == 0 || angleY == 0)
00857             h = (Q_INT32) ( height() + QABS(w*tan(angleY*pi/180)) );
00858         else if (angleX > 0 && angleY > 0)
00859             h = (Q_INT32) ( height() + QABS(w*tan(angleY*pi/180))- 2 * deltaY + 2 );
00860         else if (angleX < 0 && angleY < 0)
00861             h = (Q_INT32) ( height() + QABS(w*tan(angleY*pi/180))- 2 * deltaY + 2 );
00862         else
00863             h = (Q_INT32) ( height() + QABS(w*tan(angleY*pi/180)) );
00864     }
00865 
00866     if (w != width() || h != height()) {
00867 
00868         lock();
00869 
00870         if (undo()) {
00871             m_adapter->beginMacro(i18n("Shear Image"));
00872             m_adapter->addCommand(new LockImageCommand(this, true));
00873         }
00874 
00875         KisShearVisitor v(angleX, angleY, m_progress);
00876         v.setUndoAdapter(undoAdapter());
00877         rootLayer()->accept(v);
00878 
00879         if (undo()) m_adapter->addCommand(new KisResizeImageCmd(m_adapter, this, w, h, width(), height()));
00880 
00881         m_width = w;
00882         m_height = h;
00883 
00884         emitSizeChanged();
00885 
00886         unlock();
00887 
00888         if (undo()) {
00889             m_adapter->addCommand(new LockImageCommand(this, false));
00890             m_adapter->endMacro();
00891         }
00892     }
00893 }
00894 
00895 void KisImage::convertTo(KisColorSpace * dstColorSpace, Q_INT32 renderingIntent)
00896 {
00897     if ( m_colorSpace == dstColorSpace )
00898     {
00899         return;
00900     }
00901 
00902     lock();
00903 
00904     KisColorSpace * oldCs = m_colorSpace;
00905 
00906     if (undo()) {
00907         m_adapter->beginMacro(i18n("Convert Image Type"));
00908         m_adapter->addCommand(new LockImageCommand(this, true));
00909     }
00910 
00911     setColorSpace(dstColorSpace);
00912 
00913     KisColorSpaceConvertVisitor visitor(dstColorSpace, renderingIntent);
00914     m_rootLayer->accept(visitor);
00915 
00916     unlock();
00917 
00918     emit sigLayerPropertiesChanged( m_activeLayer );
00919 
00920     if (undo()) {
00921 
00922         m_adapter->addCommand(new KisConvertImageTypeCmd(undoAdapter(), this,
00923                                                          oldCs, dstColorSpace));
00924         m_adapter->addCommand(new LockImageCommand(this, false));
00925         m_adapter->endMacro();
00926     }
00927 }
00928 
00929 KisProfile *  KisImage::getProfile() const
00930 {
00931     return colorSpace()->getProfile();
00932 }
00933 
00934 void KisImage::setProfile(const KisProfile * profile)
00935 {
00936     if (profile == 0) return;
00937 
00938     KisColorSpace * dstCs= KisMetaRegistry::instance()->csRegistry()->getColorSpace( colorSpace()->id(),
00939                                                                                          profile);
00940     if (dstCs) {
00941 
00942         lock();
00943 
00944         KisColorSpace * oldCs = colorSpace();
00945         setColorSpace(dstCs);
00946         emit(sigProfileChanged(const_cast<KisProfile *>(profile)));
00947 
00948         KisChangeProfileVisitor visitor(oldCs, dstCs);
00949         m_rootLayer->accept(visitor);
00950 
00951         unlock();
00952     }
00953 }
00954 
00955 double KisImage::xRes()
00956 {
00957     return m_xres;
00958 }
00959 
00960 double KisImage::yRes()
00961 {
00962     return m_yres;
00963 }
00964 
00965 void KisImage::setResolution(double xres, double yres)
00966 {
00967     m_xres = xres;
00968     m_yres = yres;
00969 }
00970 
00971 Q_INT32 KisImage::width() const
00972 {
00973     return m_width;
00974 }
00975 
00976 Q_INT32 KisImage::height() const
00977 {
00978     return m_height;
00979 }
00980 
00981 KisPaintDeviceSP KisImage::activeDevice()
00982 {
00983     if (KisPaintLayer* layer = dynamic_cast<KisPaintLayer*>(m_activeLayer.data())) {
00984         return layer->paintDeviceOrMask();
00985     }
00986     else if (KisAdjustmentLayer* layer = dynamic_cast<KisAdjustmentLayer*>(m_activeLayer.data())) {
00987         if (layer->selection()) {
00988             return layer->selection().data();
00989         }
00990     }
00991     else if (KisGroupLayer * layer = dynamic_cast<KisGroupLayer*>(m_activeLayer.data())) {
00992         // Find first child
00993         KisLayerSP child = layer->lastChild();
00994         while(child)
00995         {
00996             if (KisPaintLayer* layer = dynamic_cast<KisPaintLayer*>(child.data())) {
00997                 return layer->paintDevice();
00998             }
00999             child = child->prevSibling();
01000         }
01001         KisLayerSP sibling = layer->nextSibling();
01002         while (sibling) {
01003             if (KisPaintLayer* layer = dynamic_cast<KisPaintLayer*>(sibling.data())) {
01004                 return layer->paintDevice();
01005             }
01006             sibling = sibling->nextSibling();
01007         }
01008     }
01009     else if (KisLayerSP layer = m_activeLayer) {
01010         // A weird layer -- let's not return it, but a sibling
01011         KisLayerSP sibling = layer->nextSibling();
01012         while (sibling) {
01013             if (KisPaintLayer* layer = dynamic_cast<KisPaintLayer*>(sibling.data())) {
01014                 return layer->paintDevice();
01015             }
01016             sibling = sibling->nextSibling();
01017         }
01018     }
01019     // XXX: We're buggered!
01020     return 0;
01021 }
01022 
01023 KisLayerSP KisImage::newLayer(const QString& name, Q_UINT8 opacity, const KisCompositeOp& compositeOp, KisColorSpace * colorstrategy)
01024 {
01025     KisPaintLayer * layer;
01026     if (colorstrategy)
01027         layer = new KisPaintLayer(this, name, opacity, colorstrategy);
01028     else
01029         layer = new KisPaintLayer(this, name, opacity);
01030     Q_CHECK_PTR(layer);
01031 
01032     if (compositeOp.isValid())
01033         layer->setCompositeOp(compositeOp);
01034     layer->setVisible(true);
01035 
01036     if (m_activeLayer != 0) {
01037         addLayer(layer, m_activeLayer->parent().data(), m_activeLayer->nextSibling());
01038     }
01039     else {
01040         addLayer(layer, m_rootLayer, 0);
01041     }
01042     activate(layer);
01043 
01044     return layer;
01045 }
01046 
01047 void KisImage::setLayerProperties(KisLayerSP layer, Q_UINT8 opacity, const KisCompositeOp& compositeOp, const QString& name)
01048 {
01049     if (layer && (layer->opacity() != opacity || layer->compositeOp() != compositeOp || layer->name() != name)) {
01050         if (undo()) {
01051             QString oldname = layer->name();
01052             Q_INT32 oldopacity = layer->opacity();
01053             KisCompositeOp oldCompositeOp = layer->compositeOp();
01054             layer->setName(name);
01055             layer->setOpacity(opacity);
01056             layer->setCompositeOp(compositeOp);
01057             m_adapter->addCommand(new LayerPropsCmd(layer, this, m_adapter, oldname, oldopacity, oldCompositeOp));
01058         } else {
01059             layer->setName(name);
01060             layer->setOpacity(opacity);
01061             layer->setCompositeOp(compositeOp);
01062         }
01063     }
01064 }
01065 
01066 KisGroupLayerSP KisImage::rootLayer() const
01067 {
01068     return m_rootLayer;
01069 }
01070 
01071 KisLayerSP KisImage::activeLayer() const
01072 {
01073     return m_activeLayer;
01074 }
01075 
01076 KisPaintDeviceSP KisImage::projection()
01077 {
01078     return m_rootLayer->projection(QRect(0, 0, m_width, m_height));
01079 }
01080 
01081 KisLayerSP KisImage::activate(KisLayerSP layer)
01082 {
01083     if (layer != m_activeLayer) {
01084         if (m_activeLayer) m_activeLayer->deactivate();
01085         m_activeLayer = layer;
01086         if (m_activeLayer) m_activeLayer->activate();
01087         emit sigLayerActivated(m_activeLayer);
01088         emit sigMaskInfoChanged();
01089     }
01090 
01091     return layer;
01092 }
01093 
01094 KisLayerSP KisImage::findLayer(const QString& name) const
01095 {
01096     return rootLayer()->findLayer(name);
01097 }
01098 
01099 KisLayerSP KisImage::findLayer(int id) const
01100 {
01101     return rootLayer()->findLayer(id);
01102 }
01103 
01104 
01105 bool KisImage::addLayer(KisLayerSP layer, KisGroupLayerSP parent)
01106 {
01107     return addLayer(layer, parent, parent->firstChild());
01108 }
01109 
01110 bool KisImage::addLayer(KisLayerSP layer, KisGroupLayerSP parent, KisLayerSP aboveThis)
01111 {
01112     if (!parent)
01113         return false;
01114 
01115     const bool success = parent->addLayer(layer, aboveThis);
01116     if (success)
01117     {
01118         KisPaintLayerSP player = dynamic_cast<KisPaintLayer*>(layer.data());
01119         if (player != 0) {
01120 
01121             // XXX: This should also be done whenever a layer grows!
01122             QValueVector<KisPaintDeviceAction *> actions = KisMetaRegistry::instance() ->
01123                 csRegistry()->paintDeviceActionsFor(player->paintDevice()->colorSpace());
01124             for (uint i = 0; i < actions.count(); i++) {
01125                 actions.at(i)->act(player.data()->paintDevice(), width(), height());
01126             }
01127 
01128             connect(player, SIGNAL(sigMaskInfoChanged()), this, SIGNAL(sigMaskInfoChanged()));
01129         }
01130 
01131         if (layer->extent().isValid()) layer->setDirty();
01132 
01133         if (!layer->temporary()) {
01134             emit sigLayerAdded(layer);
01135             activate(layer);
01136         }
01137 
01138 
01139         if (!layer->temporary() && undo()) {
01140             m_adapter->addCommand(new LayerAddCmd(m_adapter, this, layer));
01141         }
01142     }
01143 
01144     return success;
01145 }
01146 
01147 bool KisImage::removeLayer(KisLayerSP layer)
01148 {
01149     if (!layer || layer->image() != this)
01150         return false;
01151 
01152     if (KisGroupLayerSP parent = layer->parent()) {
01153         // Adjustment layers should mark the layers underneath them, whose rendering
01154         // they have cached, diryt on removal. Otherwise, the group won't be re-rendered.
01155         KisAdjustmentLayer * al = dynamic_cast<KisAdjustmentLayer*>(layer.data());
01156         if (al) {
01157             QRect r = al->extent();
01158             lock(); // Lock the image, because we are going to dirty a lot of layers
01159             KisLayerSP l = layer->nextSibling();
01160             while (l) {
01161                 KisAdjustmentLayer * al2 = dynamic_cast<KisAdjustmentLayer*>(l.data());
01162                 l->setDirty(r, false);
01163                 if (al2 != 0) break;
01164                 l = l->nextSibling();
01165             }
01166             unlock();
01167         }
01168         KisPaintLayerSP player = dynamic_cast<KisPaintLayer*>(layer.data());
01169         if (player != 0) {
01170             disconnect(player, SIGNAL(sigMaskInfoChanged()),
01171                        this, SIGNAL(sigMaskInfoChanged()));
01172         }
01173         KisLayerSP l = layer->prevSibling();
01174         QRect r = layer->extent();
01175         while (l) {
01176             l->setDirty(r, false);
01177             l = l->prevSibling();
01178         }
01179 
01180         KisLayerSP wasAbove = layer->nextSibling();
01181         KisLayerSP wasBelow = layer->prevSibling();
01182         const bool wasActive = layer == activeLayer();
01183         // sigLayerRemoved can set it to 0, we don't want that in the else of wasActive!
01184         KisLayerSP actLayer = activeLayer();
01185         const bool success = parent->removeLayer(layer);
01186         if (success) {
01187             layer->setImage(0);
01188             if (!layer->temporary() && undo()) {
01189                 m_adapter->addCommand(new LayerRmCmd(m_adapter, this, layer, parent, wasAbove));
01190             }
01191             if (!layer->temporary()) {
01192                 emit sigLayerRemoved(layer, parent, wasAbove);
01193                 if (wasActive) {
01194                     if (wasBelow)
01195                         activate(wasBelow);
01196                     else if (wasAbove)
01197                         activate(wasAbove);
01198                     else if (parent != rootLayer())
01199                         activate(parent.data());
01200                     else
01201                         activate(rootLayer()->firstChild());
01202                 } else {
01203                     activate(actLayer);
01204                 }
01205             }
01206         }
01207         return success;
01208     }
01209 
01210     return false;
01211 }
01212 
01213 bool KisImage::raiseLayer(KisLayerSP layer)
01214 {
01215     if (!layer)
01216         return false;
01217     return moveLayer(layer, layer->parent().data(), layer->prevSibling());
01218 }
01219 
01220 bool KisImage::lowerLayer(KisLayerSP layer)
01221 {
01222     if (!layer)
01223         return false;
01224     if (KisLayerSP next = layer->nextSibling())
01225         return moveLayer(layer, layer->parent().data(), next->nextSibling());
01226     return false;
01227 }
01228 
01229 bool KisImage::toTop(KisLayerSP layer)
01230 {
01231     if (!layer)
01232         return false;
01233     return moveLayer(layer, rootLayer(), rootLayer()->firstChild());
01234 }
01235 
01236 bool KisImage::toBottom(KisLayerSP layer)
01237 {
01238     if (!layer)
01239         return false;
01240     return moveLayer(layer, rootLayer(), 0);
01241 }
01242 
01243 bool KisImage::moveLayer(KisLayerSP layer, KisGroupLayerSP parent, KisLayerSP aboveThis)
01244 {
01245     if (!parent)
01246         return false;
01247 
01248     KisGroupLayerSP wasParent = layer->parent();
01249     KisLayerSP wasAbove = layer->nextSibling();
01250 
01251     if (wasParent.data() == parent.data() && wasAbove.data() == aboveThis.data())
01252         return false;
01253 
01254     lock();
01255 
01256     if (!wasParent->removeLayer(layer)) {
01257         unlock();
01258         return false;
01259     }
01260 
01261     const bool success = parent->addLayer(layer, aboveThis);
01262 
01263     layer->setDirty();
01264 
01265     unlock();
01266 
01267     if (success)
01268     {
01269         emit sigLayerMoved(layer, wasParent, wasAbove);
01270         if (undo())
01271             m_adapter->addCommand(new LayerMoveCmd(m_adapter, this, layer, wasParent, wasAbove));
01272     }
01273     else //we already removed the layer above, but re-adding it failed, so...
01274     {
01275         emit sigLayerRemoved(layer, wasParent, wasAbove);
01276         if (undo())
01277             m_adapter->addCommand(new LayerRmCmd(m_adapter, this, layer, wasParent, wasAbove));
01278     }
01279 
01280     return success;
01281 }
01282 
01283 Q_INT32 KisImage::nlayers() const
01284 {
01285     return rootLayer()->numLayers() - 1;
01286 }
01287 
01288 Q_INT32 KisImage::nHiddenLayers() const
01289 {
01290     return rootLayer()->numLayers(KisLayer::Hidden);
01291 }
01292 
01293 void KisImage::flatten()
01294 {
01295     KisGroupLayerSP oldRootLayer = m_rootLayer;
01296     disconnect(oldRootLayer, SIGNAL(sigDirty(QRect)), this, SIGNAL(sigImageUpdated(QRect)));
01297 
01298     KisPaintLayer *dst = new KisPaintLayer(this, nextLayerName(), OPACITY_OPAQUE, colorSpace());
01299     Q_CHECK_PTR(dst);
01300 
01301     QRect rc = mergedImage()->extent();
01302 
01303     KisPainter gc(dst->paintDevice());
01304     gc.bitBlt(rc.x(), rc.y(), COMPOSITE_COPY, mergedImage(), OPACITY_OPAQUE, rc.left(), rc.top(), rc.width(), rc.height());
01305 
01306     m_rootLayer = new KisGroupLayer(this, "", OPACITY_OPAQUE);
01307     connect(m_rootLayer, SIGNAL(sigDirty(QRect)), this, SIGNAL(sigImageUpdated(QRect)));
01308 
01309     if (undo()) {
01310         m_adapter->beginMacro(i18n("Flatten Image"));
01311         m_adapter->addCommand(new LockImageCommand(this, true));
01312         m_adapter->addCommand(new KisChangeLayersCmd(m_adapter, this, oldRootLayer, m_rootLayer, ""));
01313     }
01314 
01315     lock();
01316 
01317     addLayer(dst, m_rootLayer, 0);
01318     activate(dst);
01319 
01320     unlock();
01321 
01322     notifyLayersChanged();
01323 
01324     if (undo()) {
01325         m_adapter->addCommand(new LockImageCommand(this, false));
01326         m_adapter->endMacro();
01327     }
01328 }
01329 
01330 
01331 void KisImage::mergeLayer(KisLayerSP layer)
01332 {
01333     KisPaintLayer *player = new KisPaintLayer(this, layer->name(), OPACITY_OPAQUE, colorSpace());
01334     Q_CHECK_PTR(player);
01335 
01336     QRect rc = layer->extent() | layer->nextSibling()->extent();
01337 
01338     undoAdapter()->beginMacro(i18n("Merge with Layer Below"));
01339 
01340     //Abuse the merge visitor to only merge two layers (if either are groups they'll recursively merge)
01341     KisMergeVisitor visitor(player->paintDevice(), rc);
01342     layer->nextSibling()->accept(visitor);
01343     layer->accept(visitor);
01344 
01345     removeLayer(layer->nextSibling());
01346     addLayer(player, layer->parent(), layer);
01347     removeLayer(layer);
01348 
01349     undoAdapter()->endMacro();
01350 }
01351 
01352 
01353 void KisImage::setModified()
01354 {
01355     emit sigImageModified();
01356 }
01357 
01358 void KisImage::renderToPainter(Q_INT32 x1,
01359                                Q_INT32 y1,
01360                                Q_INT32 x2,
01361                                Q_INT32 y2,
01362                                QPainter &painter,
01363                                KisProfile *  monitorProfile,
01364                                PaintFlags paintFlags,
01365                                float exposure)
01366 {
01367 
01368     QImage img = convertToQImage(x1, y1, x2, y2, monitorProfile, exposure);
01369 
01370     Q_INT32 w = x2 - x1 + 1;
01371     Q_INT32 h = y2 - y1 + 1;
01372 
01373 
01374     if (paintFlags & PAINT_BACKGROUND) {
01375         m_bkg->paintBackground(img, x1, y1);
01376         img.setAlphaBuffer(false);
01377     }
01378 
01379     if (paintFlags & PAINT_SELECTION) {
01380         if (m_activeLayer != 0) {
01381             m_activeLayer->paintSelection(img, x1, y1, w, h);
01382         }
01383     }
01384 
01385     if (paintFlags & PAINT_MASKINACTIVELAYERS) {
01386         if (m_activeLayer != 0) {
01387             m_activeLayer->paintMaskInactiveLayers(img, x1, y1, w, h);
01388         }
01389     }
01390 
01391     painter.drawImage(x1, y1, img, 0, 0, w, h);
01392 }
01393 
01394 QImage KisImage::convertToQImage(Q_INT32 x1,
01395                                  Q_INT32 y1,
01396                                  Q_INT32 x2,
01397                                  Q_INT32 y2,
01398                                  KisProfile * profile,
01399                                  float exposure)
01400 {
01401     Q_INT32 w = x2 - x1 + 1;
01402     Q_INT32 h = y2 - y1 + 1;
01403 
01404     KisPaintDeviceSP dev = m_rootLayer->projection(QRect(x1, y1, w, h));
01405     QImage img = dev->convertToQImage(profile, x1, y1, w, h, exposure);
01406 
01407     if (!img.isNull()) {
01408 
01409 #ifdef __BIG_ENDIAN__
01410         uchar * data = img.bits();
01411         for (int i = 0; i < w * h; ++i) {
01412             uchar r, g, b, a;
01413             a = data[0];
01414             b = data[1];
01415             g = data[2];
01416             r = data[3];
01417             data[0] = r;
01418             data[1] = g;
01419             data[2] = b;
01420             data[3] = a;
01421             data += 4;
01422         }
01423 #endif
01424 
01425         return img;
01426     }
01427 
01428     return QImage();
01429 }
01430 
01431 QImage KisImage::convertToQImage(const QRect& r, const QSize& scaledImageSize, KisProfile *profile, PaintFlags paintFlags, float exposure)
01432 {
01433 
01434     if (r.isEmpty() || scaledImageSize.isEmpty()) {
01435         return QImage();
01436     }
01437 
01438     Q_INT32 imageWidth = width();
01439     Q_INT32 imageHeight = height();
01440     Q_UINT32 pixelSize = colorSpace()->pixelSize();
01441 
01442     double xScale = static_cast<double>(imageWidth) / scaledImageSize.width();
01443     double yScale = static_cast<double>(imageHeight) / scaledImageSize.height();
01444 
01445     QRect srcRect;
01446 
01447     srcRect.setLeft(static_cast<int>(r.left() * xScale));
01448     srcRect.setRight(static_cast<int>(ceil((r.right() + 1) * xScale)) - 1);
01449     srcRect.setTop(static_cast<int>(r.top() * yScale));
01450     srcRect.setBottom(static_cast<int>(ceil((r.bottom() + 1) * yScale)) - 1);
01451 
01452     KisPaintDeviceSP mergedImage = m_rootLayer->projection(srcRect);
01453     QTime t;
01454     t.start();
01455 
01456     Q_UINT8 *scaledImageData = new Q_UINT8[r.width() * r.height() * pixelSize];
01457 
01458     Q_UINT8 *imageRow = new Q_UINT8[srcRect.width() * pixelSize];
01459     const Q_INT32 imageRowX = srcRect.x();
01460 
01461     for (Q_INT32 y = 0; y < r.height(); ++y) {
01462 
01463         Q_INT32 dstY = r.y() + y;
01464         Q_INT32 dstX = r.x();
01465         Q_INT32 srcY = (dstY * imageHeight) / scaledImageSize.height();
01466 
01467         mergedImage->readBytes(imageRow, imageRowX, srcY, srcRect.width(), 1);
01468 
01469         Q_UINT8 *dstPixel = scaledImageData + (y * r.width() * pixelSize);
01470         Q_UINT32 columnsRemaining = r.width();
01471 
01472         while (columnsRemaining > 0) {
01473 
01474             Q_INT32 srcX = (dstX * imageWidth) / scaledImageSize.width();
01475 
01476             memcpy(dstPixel, imageRow + ((srcX - imageRowX) * pixelSize), pixelSize);
01477 
01478             ++dstX;
01479             dstPixel += pixelSize;
01480             --columnsRemaining;
01481         }
01482     }
01483     kdDebug() << "Time elapsed scaling image: " << t.elapsed() << endl;
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