krita

kis_birdeye_box.cc

00001 /*
00002  *  Copyright (c) 2004 Kivio Team
00003  *  Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
00004  *
00005  *  This program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2 of the License, or
00008  *  (at your option) any later version.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with this program; if not, write to the Free Software
00017  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00018  */
00019 
00020 #include "qlayout.h"
00021 #include "qlabel.h"
00022 #include "qpixmap.h"
00023 #include "qpainter.h"
00024 #include "qimage.h"
00025 #include "config.h"
00026 #include LCMS_HEADER
00027 #include "klocale.h"
00028 
00029 #include "kis_view.h"
00030 #include "kis_doc.h"
00031 #include "kis_canvas_controller.h"
00032 #include "kis_birdeye_box.h"
00033 #include "kis_double_widget.h"
00034 #include "kis_canvas.h"
00035 #include "kis_image.h"
00036 #include "kis_rect.h"
00037 #include "kis_iterators_pixel.h"
00038 
00039 #include "kobirdeyepanel.h"
00040 
00041 namespace {
00042 
00043     class CanvasAdapter : public KoCanvasAdapter {
00044     
00045     public:
00046         CanvasAdapter(KisCanvasSubject * canvasSubject) : KoCanvasAdapter(), m_canvasSubject(canvasSubject) {}
00047         virtual ~CanvasAdapter() {}
00048         
00049     public:
00050     
00051         virtual KoRect visibleArea() 
00052             {
00053                 if (!m_canvasSubject->currentImg()) return KoRect(0,0,0,0);
00054                 
00055                 KisCanvasController * c = m_canvasSubject->canvasController();
00056                 
00057                 if (c && c->kiscanvas())
00058                     return c->viewToWindow(KisRect(0, 0, c->kiscanvas()->width(), c->kiscanvas()->height()));
00059                 else
00060                     return KoRect(0,0,0,0);
00061             }
00062 
00063        virtual double zoomFactor()
00064            {
00065                return m_canvasSubject->zoomFactor();
00066            }
00067 
00068         virtual QRect size() 
00069             {
00070                 if (!m_canvasSubject->currentImg()) return QRect(0,0,0,0);
00071                 
00072                 return QRect(0, 0, m_canvasSubject->currentImg()->width(), m_canvasSubject->currentImg()->height()); 
00073             }
00074             
00075         virtual void setViewCenterPoint(double x, double y) 
00076             { 
00077                 m_canvasSubject->canvasController()->zoomAroundPoint(x, y, m_canvasSubject->zoomFactor());
00078             }
00079             
00080     private:
00081     
00082         KisCanvasSubject * m_canvasSubject;
00083     
00084     };
00085 
00086     class ZoomListener : public KoZoomAdapter {
00087 
00088         public:
00089 
00090             ZoomListener(KisCanvasController * canvasController)
00091                 : KoZoomAdapter()
00092                 , m_canvasController(canvasController) {}
00093             virtual ~ZoomListener() {}
00094 
00095         public:
00096 
00097             void zoomTo( double x, double y, double factor ) { m_canvasController->zoomAroundPoint(x, y, factor); }
00098             void zoomIn() { m_canvasController->zoomIn(); }
00099             void zoomOut() { m_canvasController->zoomOut(); }
00100             double getMinZoom() { return (1.0 / 500); }
00101             double getMaxZoom() { return 16.0; }
00102 
00103         private:
00104 
00105             KisCanvasController * m_canvasController;
00106 
00107     };
00108 
00109     class ThumbnailProvider : public KoThumbnailAdapter {
00110     
00111         public:
00112             ThumbnailProvider(KisImageSP image, KisCanvasSubject* canvasSubject)
00113                 : KoThumbnailAdapter()
00114                 , m_image(image)
00115                 , m_canvasSubject(canvasSubject) {}
00116                 
00117             virtual ~ThumbnailProvider() {}
00118             
00119         public:
00120         
00121             virtual QSize pixelSize()
00122                 {
00123                     if (!m_image) return QSize(0, 0);
00124                     return QSize(m_image->width(), m_image->height());
00125                 }
00126                 
00127             virtual QImage image(QRect r, QSize thumbnailSize)
00128                 {
00129                     if (!m_image || r.isEmpty() || thumbnailSize.width() == 0 || thumbnailSize.height() == 0) {
00130                         return QImage();
00131                     }
00132 
00133                     KisPaintDevice thumbnailRect(m_image->colorSpace(), "thumbnailRect");
00134                     KisPaintDeviceSP mergedImage = m_image->projection();
00135                     
00136                     Q_INT32 imageWidth = m_image->width();
00137                     Q_INT32 imageHeight = m_image->height();
00138                     Q_UINT32 pixelSize = m_image->colorSpace()->pixelSize();
00139 
00140                     for (Q_INT32 y = 0; y < r.height(); ++y) {
00141 
00142                         KisHLineIterator it = thumbnailRect.createHLineIterator(0, y, r.width(), true);
00143                         Q_INT32 thumbnailY = r.y() + y;
00144                         Q_INT32 thumbnailX = r.x();
00145                         Q_INT32 imageY = (thumbnailY * imageHeight) / thumbnailSize.height();
00146 
00147                         while (!it.isDone()) {
00148 
00149                             Q_INT32 imageX = (thumbnailX * imageWidth) / thumbnailSize.width();
00150 
00151                             KisColor pixelColor = mergedImage->colorAt(imageX, imageY);
00152                             memcpy(it.rawData(), pixelColor.data(), pixelSize);
00153 
00154                             ++it;
00155                             ++thumbnailX;
00156                         }
00157                     }
00158 
00159                     return thumbnailRect.convertToQImage(m_canvasSubject->monitorProfile(), 0, 0, r.width(), r.height(), 
00160                                                          m_canvasSubject->HDRExposure());
00161                 }
00162 
00163             void setImage(KisImageSP image)
00164                 {
00165                     m_image = image;
00166                 }
00167         private:
00168         
00169             KisImageSP m_image;
00170             KisCanvasSubject * m_canvasSubject;
00171     
00172     };
00173 
00174 }
00175 
00176 KisBirdEyeBox::KisBirdEyeBox(KisView * view, QWidget* parent, const char* name)
00177     : QWidget(parent, name)
00178         , m_view(view)
00179         , m_subject(view->canvasSubject())
00180 {
00181     QVBoxLayout * l = new QVBoxLayout(this);
00182 
00183     m_image = m_subject->currentImg();
00184 
00185     m_zoomAdapter = new ZoomListener(m_subject->canvasController()); // The birdeye panel deletes
00186     KoThumbnailAdapter * ktp = new ThumbnailProvider(m_image, m_subject);  // The birdeye panel deletes
00187     KoCanvasAdapter * kpc = new CanvasAdapter(m_subject);  // The birdeye panel deletes
00188 
00189     m_birdEyePanel = new KoBirdEyePanel(m_zoomAdapter, ktp, kpc, this);
00190 
00191     connect(view, SIGNAL(cursorPosition( Q_INT32, Q_INT32 )), m_birdEyePanel, SLOT(cursorPosChanged( Q_INT32, Q_INT32 )));
00192     connect(view, SIGNAL(viewTransformationsChanged()), m_birdEyePanel, SLOT(slotViewTransformationChanged()));
00193 
00194     l->addWidget(m_birdEyePanel);
00195 
00196     QHBoxLayout * hl = new QHBoxLayout(l);
00197 
00198     m_exposureLabel = new QLabel(i18n("Exposure:"), this);
00199     hl->addWidget(m_exposureLabel);
00200 
00201     m_exposureDoubleWidget = new KisDoubleWidget(-10, 10, this);
00202     m_exposureDoubleWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
00203     hl->addWidget(m_exposureDoubleWidget);
00204 
00205     l->addItem(new QSpacerItem(0, 1, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding));
00206 
00207     m_exposureDoubleWidget->setPrecision(1);
00208     m_exposureDoubleWidget->setValue(0);
00209     m_exposureDoubleWidget->setLineStep(0.1);
00210     m_exposureDoubleWidget->setPageStep(1);
00211 
00212     connect(m_exposureDoubleWidget, SIGNAL(valueChanged(double)), SLOT(exposureValueChanged(double)));
00213     connect(m_exposureDoubleWidget, SIGNAL(sliderPressed()), SLOT(exposureSliderPressed()));
00214     connect(m_exposureDoubleWidget, SIGNAL(sliderReleased()), SLOT(exposureSliderReleased()));
00215 
00216     m_draggingExposureSlider = false;
00217 
00218     Q_ASSERT(m_subject->document() != 0);
00219     connect(m_subject->document(), SIGNAL(sigCommandExecuted()), SLOT(slotDocCommandExecuted()));
00220 
00221     if (m_image) {
00222         connect(m_image, SIGNAL(sigImageUpdated(QRect)), SLOT(slotImageUpdated(QRect)));
00223     }
00224 }
00225 
00226 KisBirdEyeBox::~KisBirdEyeBox()
00227 {
00228     // Huh? Why does this cause a crash?
00229     // delete m_zoomAdapter;
00230 }
00231 
00232 void KisBirdEyeBox::setImage(KisImageSP image)
00233 {
00234     if (m_image) {
00235         m_image->disconnect(this);
00236     }
00237 
00238     m_image = image;
00239 
00240     KoThumbnailAdapter * ktp = new ThumbnailProvider(m_image, m_subject);
00241     m_birdEyePanel->setThumbnailProvider(ktp);
00242 
00243     if (m_image) {
00244         connect(m_image, SIGNAL(sigImageUpdated(QRect)), SLOT(slotImageUpdated(QRect)));
00245         connect(m_image, SIGNAL(sigSizeChanged(Q_INT32, Q_INT32)), SLOT(slotImageSizeChanged(Q_INT32, Q_INT32)));
00246         connect(m_image, SIGNAL(sigColorSpaceChanged(KisColorSpace *)), SLOT(slotImageColorSpaceChanged(KisColorSpace *)));
00247         m_birdEyePanel->slotUpdate(m_image->bounds());
00248         slotImageColorSpaceChanged(m_image->colorSpace());
00249     }
00250 }
00251 
00252 void KisBirdEyeBox::slotDocCommandExecuted()
00253 {
00254     if (m_image) {
00255         if (!m_dirtyRect.isEmpty()) {
00256             m_birdEyePanel->slotUpdate(m_dirtyRect);
00257         }
00258         m_dirtyRect = QRect();
00259     }
00260 }
00261 
00262 void KisBirdEyeBox::slotImageUpdated(QRect r)
00263 {
00264     m_dirtyRect |= r;
00265 }
00266 
00267 void KisBirdEyeBox::slotImageSizeChanged(Q_INT32 /*w*/, Q_INT32 /*h*/)
00268 {
00269     if (m_image) {
00270         m_birdEyePanel->slotUpdate(m_image->bounds());
00271     }
00272 }
00273 
00274 void KisBirdEyeBox::slotImageColorSpaceChanged(KisColorSpace *cs)
00275 {
00276     if (cs->hasHighDynamicRange()) {
00277         m_exposureDoubleWidget->show();
00278         m_exposureLabel->show();
00279     } else {
00280         m_exposureDoubleWidget->hide();
00281         m_exposureLabel->hide();
00282     }
00283 }
00284 
00285 void KisBirdEyeBox::exposureValueChanged(double exposure)
00286 {
00287     if (!m_draggingExposureSlider) {
00288         m_subject->setHDRExposure(exposure);
00289 
00290         if (m_image && m_image->colorSpace()->hasHighDynamicRange()) {
00291             m_birdEyePanel->slotUpdate(m_image->bounds());
00292         }
00293     }
00294 }
00295 
00296 void KisBirdEyeBox::exposureSliderPressed()
00297 {
00298     m_draggingExposureSlider = true;
00299 }
00300 
00301 void KisBirdEyeBox::exposureSliderReleased()
00302 {
00303     m_draggingExposureSlider = false;
00304     exposureValueChanged(m_exposureDoubleWidget->value());
00305 }
00306 
00307 #include "kis_birdeye_box.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys