~charon-developers/+junk/charon-utils-structure-texture-decomp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
/************************************************************************/
/*                                                                      */
/*                  Copyright 2003-2008 by Hans Meine                   */
/*                 meine@kogs.informatik.uni-hamburg.de                 */
/*       Cognitive Systems Group, University of Hamburg, Germany        */
/*                                                                      */
/*  This file is part of the VigraQt library.                           */
/*                                                                      */
/*  VigraQt is free software; you can redistribute it and/or modify it  */
/*  under the terms of the GNU General Public License as published by   */
/*  the Free Software Foundation; either version 2 of the License, or   */
/*  (at your option) any later version.                                 */
/*                                                                      */
/*  VigraQt is distributed in the hope that it will be useful, but      */
/*  WITHOUT ANY WARRANTY; without even the implied warranty of          */
/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                */
/*  See the GNU General Public License for more details.                */
/*                                                                      */
/*  You should have received a copy of the GNU General Public License   */
/*  along with VigraQt; if not, write to the                            */
/*                   Free Software Foundation, Inc.,                    */
/*       51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA         */
/*                                                                      */
/************************************************************************/

#ifndef IMAGEVIEWER_HXX
#define IMAGEVIEWER_HXX

#include "vigraqt_export.hxx"
#include <QFrame>
#include <QImage>
#include <QKeyEvent>
#include <QMouseEvent>
#include <QPaintEvent>
#include <QPainter>
#include <QPixmap>
#include <QResizeEvent>
#include <math.h>

/**
 * Image viewer base class managing coordinate transforms and user
 * interaction.  In particular, it has two properties:
 *
 * 'zoomLevel' is an integer N where N=0 means 1:1 display, N>0 means
 * that each pixel is an (N+1)x(N+1) square and N<0 means that only
 * every (-N-1)th pixel in each dimension is displayed.
 *
 * 'upperLeft' is the widget coordinate of the upper left image corner.
 *
 * TODO: describe user interaction
 */
class VIGRAQT_EXPORT QImageViewerBase : public QFrame
{
    Q_OBJECT

    Q_PROPERTY(int zoomLevel READ zoomLevel WRITE setZoomLevel)

public:
    QImageViewerBase(QWidget *parent = 0);

public slots:
        /**
         * Change the image to be displayed.
         *
         * If retainView is true, or the new image has the same size as
         * the currently displayed one, the visible part of the image will
         * stay the same, otherwise panning position and zoom level will
         * be reset.
         */
    virtual void setImage(QImage const &image, bool retainView= false);

        /**
         * Change a ROI of the displayed image.
         *
         * The given new roiImage will be placed into the
         * originalImage() at the position given by upperLeft.
         */
    virtual void updateROI(QImage const &roiImage, QPoint const &upperLeft);

public:
        /**
         * Return a reference to the displayed image.
         */
    const QImage &originalImage() const
        { return originalImage_; }

        /**
         * Return (unzoomed, original) width of displayed image.
         */
    int originalWidth() const
        { return originalImage_.width(); }

        /**
         * Return (unzoomed, original) height of displayed image.
         */
    int originalHeight() const
        { return originalImage_.height(); }

        /**
         * Return zoomed width of displayed image.
         */
    int zoomedWidth() const;

        /**
         * Return zoomed height of displayed image.
         */
    int zoomedHeight() const;

        /**
         * Zoom the pixmap such that it fits into the widget.  (Useful
         * after the user loaded an image, especially with small
         * ones.)
         *
         * You can provide a minimum or maximum zoom factor as
         * optional arguments, e.g. minScale = 1 to make sure that
         * the image will be displayed with at least its original
         * size.
         *
         * By default, the image will be scaled to a maximum factor of
         * 64.
         */
    void autoZoom(int minLevel = -100, int maxLevel = 64);

        /**
         * Overloaded from QWidget to return a sensible default size.
         */
    virtual QSize sizeHint() const;

        /**
         * Returns widget coordinate of the upper left image corner.
         *
         * If you sub-class QImageViewerBase on your own, you might
         * want to know that this is changed in the following places:
         * slideBy() explicitly adds an offset, resizeEvent() and
         * setZoomLevel() modify it in order to effectively
         * zoom/resize avigraqt::round the widget center, and showEvent()
         * cares about initially centering the image.
         */
    QPoint upperLeft() const
        { return upperLeft_; }

    void centerOn(const QPoint &centerPixel);

        /**
         * Returns the current zoom level.
         *
         * A zoom level of N >= 0 means that the widget displays each
         * image pixel as a (N+1)x(N+1) square.  Defaults to zero
         * (i.e. no zoom).  Zoom levels of N < 0 mean that only each
         * (-N-1)th pixel in each dimension is displayed.  You can
         * change the zoom level with e.g. setZoomLevel() and query
         * the size of the zoomed image with
         * zoomedWidth()/zoomedHeight().
         */
    int zoomLevel() const
        { return zoomLevel_; }

        /**
         * Return multiplicative zoom factor (e.g. for QPainter::scale()).
         * For instance, zoomFactor() == 1.0 iff zoomLevel() == 0.
         */
    inline qreal zoomFactor() const
        { return zoomLevel() >= 0 ? 1 + zoomLevel() : 1./(1-zoomLevel()); }

        /**
         * Position the pointer over the specified image pixel.
         */
    virtual void setCursorPos(QPoint const &imagePoint) const;

        /**
         * Map position relative to window to position in displayed image.
         */
    virtual QPoint imageCoordinate(QPoint const &windowPoint) const;

        /**
         * Map position relative to window to sub-pixel position in
         * displayed image.
         */
    virtual QPointF imageCoordinateF(QPoint const &windowPoint) const;

        /**
         * Map position in displayed image to position relative to window.
         */
    virtual QPoint windowCoordinate(QPoint const &imagePoint) const;

        /**
         * Map sub-pixel position in displayed image to position
         * relative to window.
         */
    inline QPoint windowCoordinate(QPointF const &imagePoint) const;
    virtual QPoint windowCoordinate(double x, double y) const;

        /**
         * Map range relative to window to range in displayed image.
         *
         * (Upper left and lower right corners are mapped differently
         * to ensure that the resulting QRect contains all pixels
         * whose displayed rect in high zoom levels intersect with the
         * given windowRect.)
         */
    virtual QRect imageCoordinates(QRect const &windowRect) const;

        /**
         * Map range relative to window to range in displayed image.
         */
    virtual QRectF imageCoordinatesF(QRect const &windowRect) const;

        /**
         * Map range in displayed image to range relative to window.
         *
         * (Upper left and lower right corners are mapped differently
         * to ensure that the resulting QRect contains the complete
         * displayed squares of all image pixels in high zoom levels.)
         */
    virtual QRect windowCoordinates(QRect const &imageRect) const;

public slots:
        /**
         * Changes the current zoom level.
         *
         * See zoomLevel(), zoomUp(), zoomDown()
         */
    virtual void setZoomLevel(int level = 0);

        /**
         * Changes the zoom level to (zoomLevel()+1) (useful for
         * connecting UI signals to this slot).
         */
    virtual void zoomUp();

        /**
         * Changes the zoom level to (zoomLevel()-1) (useful for
         * connecting UI signals to this slot).
         */
    virtual void zoomDown();

        /**
         * Changes upperLeft() by diff.
         */
    virtual void slideBy(QPoint const &diff);

	virtual void drawHighline(const QPoint &pos,bool draw = false) ;

signals:
    void mouseOver(int x, int y,Qt::MouseButtons buttons);
	void mouseReleased() ;

    void imageChanged(); // FIXME: add ROI param
    void zoomLevelChanged(int zoomLevel);

protected:
    inline static int zoom(int value, int level)
        { return (level >= 0) ? (value * (level+1)) : (value / (-level+1)); }
    inline static double zoomF(double value, int level)
        { return (level >= 0) ? (value * (level+1)) : (value / (-level+1)); }

    virtual void checkImagePosition();
    virtual void setCrosshairCursor();

    virtual void mouseMoveEvent(QMouseEvent *e);
    virtual void mousePressEvent(QMouseEvent *e);
    virtual void mouseReleaseEvent(QMouseEvent *e);
//     virtual void mouseDoubleClickEvent(QMouseEvent *e);
    virtual void wheelEvent(QWheelEvent *e);
    virtual void keyPressEvent(QKeyEvent *e);
    virtual void resizeEvent(QResizeEvent *e);
    virtual void showEvent(QShowEvent *e);

    QImage  originalImage_;
    QPoint  upperLeft_; // position of image origin in widget coordinates
    QPointF centerPixel_;
    int     zoomLevel_;

	bool _drawHighline ;
	QPoint _highlinePos ;

  private:
    inline void computeUpperLeft()
    {
        upperLeft_ = contentsRect().center() -
                     QPoint((int)vigraqt::round(zoomF(centerPixel_.x(), zoomLevel_)),
                            (int)vigraqt::round(zoomF(centerPixel_.y(), zoomLevel_)));
    }

    bool    inSlideState_;
    bool    pendingAutoZoom_;
    int     minAutoZoom_, maxAutoZoom_;
    QPoint  lastMousePosition_;

};

QPoint QImageViewerBase::windowCoordinate(QPointF const & imagePoint) const
{
    return windowCoordinate(imagePoint.x(), imagePoint.y());
}

class VIGRAQT_EXPORT QImageViewer : public QImageViewerBase
{
    Q_OBJECT

public:
    QImageViewer(QWidget *parent = 0);

    virtual void setImage(QImage const &image, bool retainView= false);
    virtual void updateROI(QImage const &roiImage, QPoint const &upperLeft);

    virtual void slideBy(QPoint const &diff);

protected slots:
    virtual void createDrawingPixmap();

protected:
        // return ROI of originalImage_ which should be buffered in
        // drawingPixmap_
    QRect cachedImageROI();

        // zoom originalImage_ from pixel pos (left, top) into dest
        // to a *target* size of (w, h)
    virtual void zoomImage(int left, int top,
                           QImage & dest, int w, int h);

    virtual void paintEvent(QPaintEvent *);
    virtual void paintImage(QPainter &p, const QRect &r);

    virtual void resizeEvent(QResizeEvent *e);

    QPixmap drawingPixmap_;
    QRect drawingPixmapDomain_;
};

#endif /* IMAGEVIEWER_HXX */