1 /**
2  * This file is a part of Luminance HDR package.
3  * ----------------------------------------------------------------------
4  * Copyright (C) 2007 Giuseppe Rota
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  * ----------------------------------------------------------------------
20  *
21  * @author Giuseppe Rota <grota@users.sourceforge.net>
22  */
23 
24 #ifndef PREVIEWWIDGET_H
25 #define PREVIEWWIDGET_H
26 
27 #include <QColor>
28 #include <QGraphicsPixmapItem>
29 #include <QGraphicsScene>
30 #include <QImage>
31 #include <QMouseEvent>
32 #include <QResizeEvent>
33 #include <QScrollArea>
34 #include <QScrollBar>
35 #include <QToolButton>
36 #include <QVBoxLayout>
37 
38 #include "AutoAntighosting.h"  // Just for agGridSize !!!
39 
40 class IGraphicsView;
41 class IGraphicsPixmapItem;
42 class PanIconWidget;
43 
44 class PreviewWidget : public QWidget {
45     Q_OBJECT
46    public:
47     //! \brief Enum containing the list of possible view mode
48     enum ViewerMode { FIT_WINDOW = 0, FILL_WINDOW = 1, NORMAL_SIZE = 2 };
49 
50     PreviewWidget(QWidget *parent, QImage *m, const QImage *p);
51     ~PreviewWidget();
sizeHint()52     QSize sizeHint() const { return m_previewImage->size(); }
53     float getScaleFactor();
getPreviewImage()54     QImage *getPreviewImage() {
55         renderPreviewImage(blendmode);
56         return m_previewImage;
57     }
58     void setPivot(QImage *p, int p_px, int p_py);
59     void setPivot(QImage *p);
60     void setMovable(QImage *m, int p_mx, int p_my);
61     void setMovable(QImage *m);
62     void updateVertShiftMovable(int v);
63     void updateHorizShiftMovable(int h);
64     void updateHorizShiftPivot(int h);
65     void updateVertShiftPivot(int v);
66     int getWidth();
67     int getHeight();
68     bool isFittedToWindow();
69     bool isFilledToWindow();
70     bool isNormalSize();
71 
72     void setMask(QImage *mask);
73     QImage *getMask();  // Conversion to QImage to QPixmap is made for speed
74                         // optimization
75                         // we need to return a QImage from the modified QPixmap
76 
77     void setPatchesMask(QImage *mask);
setHV_offset(QPair<int,int> HV_offset)78     void setHV_offset(QPair<int, int> HV_offset) {
79         m_mx = HV_offset.first;
80         m_my = HV_offset.second;
81     }
82 
83     void setDrawWithBrush();
84     void setDrawPath();
85     // void renderPatchesMask(bool patches[][agGridSize], const int gridX, const
86     // int gridY);
87     void renderPatchesMask();
88 
89    public slots:
90     void requestedBlendMode(int);
91     void updateView();  // tells the Viewer to update the View area
92     void updatePreviewImage();
93 
94     void zoomIn();
95     void zoomOut();
96 
97     void fitToWindow();
98     void fillToWindow();
99     void normalSize();
100 
101     //! \brief get viewer mode (Fit, Fill or Normal Size)
102     ViewerMode getViewerMode();
103 
104     //! \brief set viewer mode (Fit, Fill or Normal Size)
105     void setViewerMode(ViewerMode viewer_mode);
106 
107     // selection properties!
108     bool hasSelection();
109     void setSelectionTool(bool);
110     QRect getSelectionRect();
111     void removeSelection();
112 
113     void switchAntighostingMode(bool);
114     void switchViewPatchesMode(bool, bool[][agGridSize], const int, const int);
115     void getPatches(bool[][agGridSize]);
116     void setBrushSize(const int);
117     void setBrushStrength(const int);
118     void setBrushColor(const QColor);
119     void setLassoColor(const QColor);
120     void setBrushMode(bool);
121     void saveAgMask();
122     QImage *getSavedAgMask();
123 
124    protected slots:
125     void slotPanIconSelectionMoved(QRect);
126     void slotPanIconHidden();
127     void slotCornerButtonPressed();
128     void scrollBarChanged(int /*value*/);
129 
130    signals:
131     void moved(QPoint diff);
132     void selectionReady(bool isReady);
133     void changed(
134         PreviewWidget *v);  // emitted when zoomed in/out, scrolled ....
135     void patchesEdited();
136 
137    protected:
138     bool eventFilter(QObject *object, QEvent *event);
139     virtual void timerEvent(QTimerEvent *event);
140 
141    private:
142     // 5 blending modes
computeOnlyMovable(const QRgb * Mrgba,const QRgb *)143     inline QRgb computeOnlyMovable(const QRgb *Mrgba,
144                                    const QRgb * /*Prgba*/) const {
145         return *Mrgba;
146     }
computeOnlyPivot(const QRgb *,const QRgb * Prgba)147     inline QRgb computeOnlyPivot(const QRgb * /*Mrgba*/,
148                                  const QRgb *Prgba) const {
149         return *Prgba;
150     }
computeAddRgba(const QRgb * Mrgba,const QRgb * Prgba)151     inline QRgb computeAddRgba(const QRgb *Mrgba, const QRgb *Prgba) const {
152         int ro, go, bo;
153         int Mred = qRed(*Mrgba);
154         int Mgreen = qGreen(*Mrgba);
155         int Mblue = qBlue(*Mrgba);
156         int Malpha = qAlpha(*Mrgba);
157         int Pred = qRed(*Prgba);
158         int Pgreen = qGreen(*Prgba);
159         int Pblue = qBlue(*Prgba);
160         int Palpha = qAlpha(*Prgba);
161         // blend samples using alphas as weights
162         ro = (Pred * Palpha + Mred * Malpha) / 510;
163         go = (Pgreen * Palpha + Mgreen * Malpha) / 510;
164         bo = (Pblue * Palpha + Mblue * Malpha) / 510;
165         // the output image still has alpha=255 (opaque)
166         return qRgba(ro, go, bo, 255);
167     }
computeDiffRgba(const QRgb * Mrgba,const QRgb * Prgba)168     inline QRgb computeDiffRgba(const QRgb *Mrgba, const QRgb *Prgba) const {
169         int ro, go, bo;
170         int Mred = qRed(*Mrgba);
171         int Mgreen = qGreen(*Mrgba);
172         int Mblue = qBlue(*Mrgba);
173         int Malpha = qAlpha(*Mrgba);
174         int Pred = qRed(*Prgba);
175         int Pgreen = qGreen(*Prgba);
176         int Pblue = qBlue(*Prgba);
177         int Palpha = qAlpha(*Prgba);
178         // blend samples using alphas as weights
179         ro = qAbs(Pred * Palpha - Mred * Malpha) / 255;
180         go = qAbs(Pgreen * Palpha - Mgreen * Malpha) / 255;
181         bo = qAbs(Pblue * Palpha - Mblue * Malpha) / 255;
182         // the output image still has alpha=255 (opaque)
183         return qRgba(ro, go, bo, 255);
184     }
185 
186     QRgb (PreviewWidget::*blendmode)(const QRgb *, const QRgb *) const;
187     void renderPreviewImage(QRgb (PreviewWidget::*f)(const QRgb *, const QRgb *)
188                                 const,
189                             const QRect a = QRect());
190     void renderAgMask();
191     void scrollAgMask(int, int);
192 
193     // the out and 2 in images
194     QImage *m_previewImage;
195     QImage *m_movableImage;
196     const QImage *m_pivotImage;
197     QImage *m_agMask;
198     QImage *m_originalAgMask;
199     QImage *m_patchesMask;
200     QPixmap *m_agMaskPixmap;
201     QImage *m_savedMask;
202 
203     QToolButton *mCornerButton;
204     PanIconWidget *mPanIconWidget;
205 
206     QVBoxLayout *mVBL;
207 
208     QGraphicsScene *mScene;
209     IGraphicsView *mView;
210     ViewerMode mViewerMode;
211     IGraphicsPixmapItem *mPixmap, *mAgPixmap;
212 
213     QRegion m_prevComputed;
214     QRect m_rect;
215     // movable and pivot's x,y shifts
216     int m_mx, m_my, m_px, m_py;
217     int m_old_mx, m_old_my;
218     // zoom factor
219     // float m_scaleFactor;
220 
221     int m_timerid;
222     QPixmap *m_agcursorPixmap;
223     int m_requestedPixmapSize, m_previousPixmapSize;
224     int m_requestedPixmapStrength, m_previousPixmapStrength;
225     QColor m_requestedPixmapColor, m_previousPixmapColor, m_requestedLassoColor;
226     bool m_brushAddMode;  // false means brush is in remove mode.
227     void fillAntiGhostingCursorPixmap();
228     void drawWithBrush();
229     void drawPath();
230 
231     QPointF m_mousePos;
232     QPointF m_firstPoint;
233     QPointF m_lastPoint;
234     QPointF m_currentPoint;
235     QPainterPath m_path;
236     bool m_drawingPathEnded;
237 
238     bool m_patches[agGridSize][agGridSize];
239     int m_gridX;
240     int m_gridY;
241 
242     enum { BRUSH, PATH } m_drawingMode;
243     enum { EditingMode, AntighostingMode, ViewPatches } m_mode;
244 };
245 
246 #endif
247