]> git.cworth.org Git - apitrace/blob - gui/imageviewer.cpp
a795993fb6c7b538128e477e3b625cbff9f0a4fc
[apitrace] / gui / imageviewer.cpp
1 #include "imageviewer.h"
2 #include "pixelwidget.h"
3 #include "apisurface.h"
4
5 #include "image/image.hpp"
6
7 #include <QDebug>
8 #include <QDesktopWidget>
9 #include <QPainter>
10 #include <QPixmap>
11 #include <QScrollBar>
12
13 ImageViewer::ImageViewer(QWidget *parent)
14     : QDialog(parent),
15       m_image(0)
16 {
17     setupUi(this);
18
19     connect(lowerSpinBox, SIGNAL(valueChanged(double)),
20             SLOT(slotUpdate()));
21     connect(upperSpinBox, SIGNAL(valueChanged(double)),
22             SLOT(slotUpdate()));
23     connect(flipCheckBox, SIGNAL(stateChanged(int)),
24             SLOT(slotUpdate()));
25     connect(opaqueCheckBox, SIGNAL(stateChanged(int)),
26             SLOT(slotUpdate()));
27     connect(alphaCheckBox, SIGNAL(stateChanged(int)),
28             SLOT(slotUpdate()));
29
30     QPixmap px(32, 32);
31     QPainter p(&px);
32     p.fillRect(0, 0, 32, 32, Qt::white);
33     p.fillRect(0, 0, 16, 16, QColor(193, 193, 193));
34     p.fillRect(16, 16, 16, 16, QColor(193, 193, 193));
35     p.end();
36     QPalette pal = scrollAreaWidgetContents->palette();
37     pal.setBrush(QPalette::Background,
38                  QBrush(px));
39     pal.setBrush(QPalette::Base,
40                  QBrush(px));
41     scrollAreaWidgetContents->setPalette(pal);
42
43     m_pixelWidget = new PixelWidget(scrollAreaWidgetContents);
44     verticalLayout_2->addWidget(m_pixelWidget);
45
46     rectLabel->hide();
47     pixelLabel->hide();
48
49     connect(m_pixelWidget, SIGNAL(zoomChanged(int)),
50             zoomSpinBox, SLOT(setValue(int)));
51     connect(zoomSpinBox, SIGNAL(valueChanged(int)),
52             m_pixelWidget, SLOT(setZoom(int)));
53     connect(m_pixelWidget, SIGNAL(mousePosition(int, int)),
54             this, SLOT(showPixel(int, int)));
55     connect(m_pixelWidget, SIGNAL(gridGeometry(const QRect &)),
56             this, SLOT(showGrid(const QRect &)));
57 }
58
59 ImageViewer::~ImageViewer()
60 {
61     delete m_image;
62 }
63
64 void ImageViewer::setBase64Data(const QByteArray &base64)
65 {
66     delete m_image;
67     m_image = ApiSurface::imageFromBase64(base64);
68     m_convertedImage = ApiSurface::qimageFromRawImage(m_image);
69     m_pixelWidget->setSurface(m_convertedImage);
70     updateGeometry();
71 }
72
73 static inline int clamp(int x)
74 {
75     if (x <= 0) {
76         return 0;
77     }
78     if (x > 255) {
79         return 255;
80     }
81     return x;
82 }
83
84 void ImageViewer::slotUpdate()
85 {
86     m_convertedImage =
87         m_convertedImage.mirrored(false, flipCheckBox->isChecked());
88
89     double lowerValue = lowerSpinBox->value();
90     double upperValue = upperSpinBox->value();
91
92     bool opaque = opaqueCheckBox->isChecked();
93     bool alpha  = alphaCheckBox->isChecked();
94
95     if (lowerValue != 0.0 || upperValue != 1.0 || opaque || alpha) {
96         /*
97          * Rescale the image.
98          *
99          * XXX: This would be much more useful if done with the full precision
100          * of the original image
101          */
102
103         int offset = - lowerValue * 255;
104         int scale = 256 / (upperValue - lowerValue);
105
106         m_convertedImage =
107             m_convertedImage.convertToFormat(QImage::Format_ARGB32);
108
109         if (0) {
110             qDebug()
111                 << "offset = " << offset << "\n"
112                 << "scale = " << scale << "\n";
113         }
114
115         int width = m_convertedImage.width();
116         int height = m_convertedImage.height();
117
118         int aMask = opaque ? 0xff : 0;
119
120         for (int y = 0; y < height; ++y) {
121             QRgb *scanline = (QRgb *)m_convertedImage.scanLine(y);
122             for (int x = 0; x < width; ++x) {
123                 QRgb pixel = scanline[x];
124                 int r = qRed(pixel);
125                 int g = qGreen(pixel);
126                 int b = qBlue(pixel);
127                 int a = qAlpha(pixel);
128                 if (alpha) {
129                     a = clamp(((a + offset) * scale) >> 8);
130                     scanline[x] = qRgba(a, a, a, 0xff);
131                 } else {
132                     r = clamp(((r + offset) * scale) >> 8);
133                     g = clamp(((g + offset) * scale) >> 8);
134                     b = clamp(((b + offset) * scale) >> 8);
135                     a |= aMask;
136                     scanline[x] = qRgba(r, g, b, a);
137                 }
138             }
139         }
140     }
141
142     m_pixelWidget->setSurface(m_convertedImage);
143
144     updateGeometry();
145 }
146
147 QSize ImageViewer::sizeHint() const
148 {
149     QSize size;
150
151     int vScrollWidth = scrollArea->verticalScrollBar() ?
152                 scrollArea->verticalScrollBar()->width() : 0;
153     int hScrollHeight = scrollArea->horizontalScrollBar() ?
154                 scrollArea->horizontalScrollBar()->height() : 0;
155     QSize optimalWindowSize(m_convertedImage.width() + vScrollWidth,
156                             m_convertedImage.height() + hScrollHeight);
157
158     QRect screenRect = QApplication::desktop()->availableGeometry();
159     const float maxPercentOfDesktopSpace = 0.8f;
160     QSize maxAvailableSize(maxPercentOfDesktopSpace * screenRect.width(),
161                            maxPercentOfDesktopSpace * screenRect.height());
162
163     return QSize(qMin(optimalWindowSize.width(), maxAvailableSize.width()),
164                  qMin(optimalWindowSize.height(), maxAvailableSize.height()));
165 }
166
167 void ImageViewer::resizeEvent(QResizeEvent *e)
168 {
169     QWidget::resizeEvent(e);
170 }
171
172 template <class T>
173 QString createPixelLabel(image::Image *img, int x, int y)
174 {
175     QString pixelLabel;
176     unsigned char *pixelLocation = 0;
177     T *pixel;
178
179     pixelLocation = img->pixels + img->stride() * y;
180     pixelLocation += x * img->bytesPerPixel;
181     pixel = ((T*)pixelLocation);
182
183     pixelLabel += QLatin1String("[");
184     pixelLabel += QString::fromLatin1("%1").arg(pixel[0]);
185
186     for (int channel = 1; channel < img->channels; ++channel) {
187         pixelLabel += QString::fromLatin1(", %1").arg(pixel[channel]);
188     }
189     pixelLabel += QLatin1String("]");
190
191     return pixelLabel;
192 }
193
194 void ImageViewer::showPixel(int x, int y)
195 {
196     xSpinBox->setValue(x);
197     ySpinBox->setValue(y);
198
199     if (!m_image)
200         return;
201
202     QString label = tr("Pixel: ");
203
204     if (m_image->channelType == image::TYPE_UNORM8) {
205         label += createPixelLabel<unsigned char>(m_image, x, y);
206     } else {
207         label += createPixelLabel<float>(m_image, x, y);
208     }
209
210     pixelLabel->setText(label);
211     pixelLabel->show();
212 }
213
214 void ImageViewer::showGrid(const QRect &rect)
215 {
216     if (rect.isEmpty()) {
217         rectLabel->hide();
218         return;
219     }
220     rectLabel->setText(tr("Grid: [%1, %2, %3, %4]")
221                        .arg(rect.x())
222                        .arg(rect.y())
223                        .arg(rect.width())
224                        .arg(rect.height()));
225     rectLabel->show();
226 }
227
228 #include "imageviewer.moc"