-
Notifications
You must be signed in to change notification settings - Fork 0
/
ImageWindow.h
334 lines (266 loc) · 10.5 KB
/
ImageWindow.h
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
332
333
334
#ifndef IMAGEWINDOW_H
#define IMAGEWINDOW_H
#include <QGraphicsView>
#include <QDateTime>
#include "ImageData.h"
#include "colormapper.h"
#include "MainDialog.h"
//Scaling governs how bitmap values are linearly remapped to display values.
enum ImageWindowScaling : int
{
Fit, //normalized according to min/max.
Centered, //normalized, but with zero at middle of the scale.
User //min/max set by user.
};
//Function governs whether the scaling is linear or logarithmic.
enum ImageWindowFunction : int
{
OneToOne,
Log10BrightenDark,
Log10DarkenLight,
BrightenDark,
DarkenLight,
NUM_WINDOFUNCTIONS
};
enum ImageWindowRotation : int
{
Zero,
CCW90,
CCW180,
CCW270
};
enum ImageCorner : int
{
TopLeft,
TopRight,
BottomLeft,
BottomRight,
Center
};
class ImageWindow : public QGraphicsView
{
Q_OBJECT
public:
ImageWindow(int ID);
bool readImage(QString filename);
void setDefaultOptions()
{
imgYOriginIsBottom = false;
imgIsZeroIndexed = true;
userMin = 0;
userMax = 255;
scaling = ImageWindowScaling::User;
function = ImageWindowFunction::OneToOne;
rotation = ImageWindowRotation::Zero;
flipHorizontal = false;
flipVertical = false;
activeChannels = chanR | chanG | chanB;
showInfoBox = true;
showCursorInfoBox = false;
showRulers = true;
showColorbar = true;
showHelp = true;
}
void resetWheelAccumulator(); // For synchronizing windows.
//Display options
bool imgYOriginIsBottom; //default is false; image origin is top left corner.
bool imgIsZeroIndexed; //default is true; first pixel is pixel zero.
// These are not in use.
// bool setSourceImage(ImageData *image) {sourceImage = image; return translateImage();}
// ImageData * getSourceImage() {return sourceImage;}
double getUserMin() {return userMin;}
double getUserMax() {return userMax;}
ImageWindowScaling getScaleMode() {return scaling; }
ImageWindowFunction getImageFunction() {return function;}
ImageWindowRotation getImageRotation() {return rotation;}
bool getImageFlipHorizontal() {return flipHorizontal;}
bool getImageFlipVertical() {return flipVertical;}
bool setUserMin(double newMin);
bool setUserMax(double newMax);
void setCustomUnit(QString &name, double unitPerPix);
bool setScaleMode(ImageWindowScaling newMode);
bool setImageFunction(ImageWindowFunction newFunction);
bool setImageRotation(ImageWindowRotation newRotation);
bool setImageFlip(bool horizontal, bool vertical);
int getImageWidth();
int getImageHeight(); //these return the dimensions according to rotation.
ColormapPalette getColormap() {return colormap->getColormap();}
QString getColormapName() {return colormap->getColormapName();}
bool setColormap(ColormapPalette newColormap);
void holdTranslation() {OKToTranslate = false;}
bool releaseTranslation() {OKToTranslate = true; return translateImage();}
void holdDraw() {OKToDraw = false;}
void releaseDraw() {OKToDraw = true; viewport()->update();}
void holdAll() {holdTranslation(); holdDraw();}
bool releaseAll() {bool r = releaseTranslation(); releaseDraw(); return r;}
void zoomFit();
void zoom1To1() {zoom(0);}
void showCentered();
void showCorner(ImageCorner corner);
void syncWithFolder();
bool readNextImage();
bool readPrevImage();
int myButtonNo;
void showWindow();
//Parent dialog
MainDialog *parent;
// HWND parenthWnd;
void setShowRulers(bool val) {if (showRulers == val) return; showRulers = val; viewport()->update();}
bool getShowRulers() {return showRulers;}
void setShowColorbar(bool val) {if (showColorbar == val) return; showColorbar = val; viewport()->update();}
bool getShowColorbar() {return showColorbar;}
void setShowInfoBox(bool val) {if (showInfoBox == val) return; showInfoBox = val; viewport()->update();}
bool getShowInfoBox() {return showInfoBox;}
void setShowCursorInfoBox(bool val) {if (showCursorInfoBox == val) return; showCursorInfoBox = val; viewport()->update();}
bool getShowCursorInfoBox() {return showCursorInfoBox;}
void setShowHelp(bool val) {if (showHelp == val) return; showHelp = val; viewport()->update();}
bool getShowHelp() {return showHelp;}
bool signalNewData() {bool r = translateImage(); if (r) viewport()->update(); return r;}
bool pasteFromClipboard();
enum snapType
{
None,
Left,
Right,
TopLeft,
TopRight,
BottomLeft,
BottomRight,
Max,
Restore,
};
void snapWindowTo(snapType snap, QScreen * screen = 0);
protected:
int ID; // ID for the main window, to communicate back when we're done.
QImage translatedImage; //need an image to access pixels directly, but...
QPixmap translatedPixmap; //...need a pixmap for display.
static constexpr int IMAGE_BUFFER_LENGTH = 10;
ImageData *sourceImageBuffer[IMAGE_BUFFER_LENGTH];
QString sourceImageBufferFilenames[IMAGE_BUFFER_LENGTH];
QDateTime sourceImageBufferModifiedDate[IMAGE_BUFFER_LENGTH];
int sourceImageBufferIndex = 0; // Stores the next available slot in the buffer.
int currentImageBufferIndex = 0; // Stores the slot that we're currently looking at.
void reportBufferContents();
QGraphicsScene *scene;
Colormapper *colormap;
// Allow people to calibrate, i.e. draw an ROI on a ruler and indicate
// how many physical units corresponds to one pixel.
double unitPerPix;
QString unitName;
double userMin, userMax;
ImageWindowScaling scaling;
double scaleMin, scaleMax;
double scale, offset;
int maxDisp;
ImageWindowFunction function;
inline double applyImageFunction(double value);
inline double imageFunctionLog10BrightenDark(double value);
inline double imageFunctionLog10DarkenLight(double value);
double dipFactor;
bool setDipFactor(double dipFactor);
inline double imageFunctionBrightenDark(double value);
inline double imageFunctionDarkenLight(double value);
inline double imageFunctionNone(double value);
ImageWindowRotation rotation;
bool flipHorizontal, flipVertical;
static const uchar chanR = 1;
static const uchar chanG = 2;
static const uchar chanB = 4;
uchar activeChannels; //bitfield; R = bit 0, G = bit 1, B = bit 2;
bool OKToTranslate;
bool translateImage();
bool translationIsFresh;
bool getTranslationParamsString(QString ¶ms);
bool OKToDraw;
QFont windowFont;
QString curFilename, curDirectory;
void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE;
//Mouse wheel does zoom.
QPoint zoomCtr;
int wheelAccumulator;
void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE;
int zoomLevel;
double zoomFactor;
static constexpr double zoomStep = 1.41421356237;//sqrt(2.0);
static const int maxZoomLevel = 16;
static const int minZoomLevel = -16;
static const int deltaThresh = 360; //mouse wheel will zoom in/out once delta exceeds this.
void zoom(int zoomIncrement);
void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
QPointF mouseDragRef, panRef;
void checkROIpoint(QPoint &point);
void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
static const int boxMargin = 5;
static const int boxPad = 25;
QPointF curMousePos;
// keep track of which parts of the viewport the info and cursor info boxes take up
// for repainting.
QRect infoUpdateRegion, cursorInfoUpdateRegion;
bool showInfoBox;
void drawInfoBox();
bool showCursorInfoBox;
void drawCursorInfoBox();
bool showRulers;
void drawRulers();
bool showColorbar;
void drawColorbar();
QImage colorbarImage;
QPoint ROI1, ROI2; //these are stored in image coordinates.
QRect ROI; //this is calculated during drawROI.
bool ROIisValid;
void drawROI();
void keyPressEvent(QKeyEvent *event) Q_DECL_OVERRIDE;
void keyReleaseEvent(QKeyEvent *event) Q_DECL_OVERRIDE;
bool showHelp;
void drawHelp();
snapType currentSnap;
QList<QString> fileList;
QString nextFile, prevFile;
int fileListPos;
bool deleteCurrentFile();
bool copyCurrentFileToBucket(int bucket);
void copyImageToClipboard();
void saveImageToFile();
bool takeScreenshot(QImage &screenshot);
void copyScreenshotToClipboard();
void saveScreenshotToFile();
void setTitle(QString title);
bool pasteFromBitmap();
bool pasteFromURL(QUrl const & url);
int clipboardTimerId;
int downloadTimerId;
QString lastClipboardText;
QList<QString> clipboardTextQueue;
void feedClipboardQueue(QString const & text);
bool inQueue;
bool processClipboardQueue();
void startMonitorClipboard();
void stopMonitorClipboard();
void toggleMonitorClipboard();
void timerEvent(QTimerEvent *event) override;
signals:
// These are connected to slots in MainDialog for inter-window syncing.
// When something happens in an ImageWindow, these signals notify the main window.
// The way we chose to do this, there's one signal per event handler.
void signalWheelEvent(QWheelEvent *event, int windowID);
void signalMousePressEvent(QMouseEvent *event, int windowID);
void signalMouseMoveEvent(QMouseEvent *event, int windowID);
void signalMouseReleaseEvent(QMouseEvent *event, int windowID);
void signalKeyPressed(QKeyEvent *event, int windowID);
void signalKeyReleased(QKeyEvent *event, int windowID);
void signalFileDeleted(QString &trashLocation);
public:
// The slots that the signals are connected to above will in turn call these functions.
// When something happens in an ImageWindow, these slots are used to replicate the behavior in all the other windows.
// These actually contain the event handling code, so they get called by the window itself as well.
// forwarded is true when the main window is calling these.
void handleWheelEvent(QWheelEvent *event, bool forwarded);
void handleMousePressEvent(QMouseEvent *event, bool forwarded);
void handleMouseMoveEvent(QMouseEvent *event, bool forwarded);
void handleMouseReleaseEvent(QMouseEvent *event, bool forwarded);
void handleKeyPress(QKeyEvent *event, bool forwarded);
void handleKeyRelease(QKeyEvent *event, bool forwarded);
};
#endif // IMAGEWINDOW_H