]> git.cworth.org Git - apitrace/blob - gui/apisurface.cpp
gui: make sure that the alpha channel is initialized
[apitrace] / gui / apisurface.cpp
1 #include "apisurface.h"
2 #include "thumbnail.h"
3
4 #include <sstream>
5
6 #include <QDebug>
7 #include <QSysInfo>
8
9 #include "image/image.hpp"
10
11
12 ApiSurface::ApiSurface()
13 {
14 }
15
16 QSize ApiSurface::size() const
17 {
18     return m_size;
19 }
20
21 void ApiSurface::setSize(const QSize &size)
22 {
23     m_size = size;
24 }
25
26 struct ByteArrayBuf : public std::streambuf
27 {
28     ByteArrayBuf(QByteArray & a)
29     {
30         setg(a.data(), a.data(), a.data() + a.size());
31     }
32 };
33
34 void ApiSurface::contentsFromBase64(const QByteArray &base64)
35 {
36     m_base64Data = base64;
37
38     /*
39      * We need to do the conversion to create the thumbnail
40      */
41     image::Image *image = imageFromBase64(base64);
42     Q_ASSERT(image);
43     QImage img = qimageFromRawImage(image);
44     m_thumb = thumbnail(img);
45     delete image;
46 }
47
48 QByteArray ApiSurface::base64Data() const
49 {
50     return m_base64Data;
51 }
52
53 QImage ApiSurface::thumb() const
54 {
55     return m_thumb;
56 }
57
58 int ApiSurface::depth() const
59 {
60     return m_depth;
61 }
62
63 void ApiSurface::setDepth(int depth)
64 {
65     m_depth = depth;
66 }
67
68 QString ApiSurface::formatName() const
69 {
70     return m_formatName;
71 }
72
73 void ApiSurface::setFormatName(const QString &str)
74 {
75     m_formatName = str;
76 }
77
78
79 ApiTexture::ApiTexture()
80     : ApiSurface()
81 {
82 }
83
84 QString ApiTexture::label() const
85 {
86     return m_label;
87 }
88
89 void ApiTexture::setLabel(const QString &str)
90 {
91     m_label = str;
92 }
93
94 ApiFramebuffer::ApiFramebuffer()
95     : ApiSurface()
96 {
97 }
98
99 QString ApiFramebuffer::type() const
100 {
101     return m_type;
102 }
103
104 void ApiFramebuffer::setType(const QString &str)
105 {
106     m_type = str;
107 }
108
109 image::Image *
110 ApiSurface::imageFromBase64(const QByteArray &base64)
111 {
112     QByteArray dataArray = QByteArray::fromBase64(base64);
113     image::Image *image;
114
115     /*
116      * Detect the PNG vs PFM images.
117      */
118     const char pngSignature[] = {(char)0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0};
119     if (dataArray.startsWith(pngSignature)) {
120         ByteArrayBuf buf(dataArray);
121         std::istream istr(&buf);
122         image = image::readPNG(istr);
123     } else {
124         image = image::readPNM(dataArray.data(), dataArray.size());
125     }
126
127     return image;
128 }
129
130
131 QImage
132 ApiSurface::qimageFromRawImage(const image::Image *image)
133 {
134     QImage img;
135     int width = image->width;
136     int height = image->height;
137
138     img = QImage(width, height, QImage::Format_ARGB32);
139
140     const unsigned char *srcRow = image->start();
141     for (int y = 0; y < height; ++y) {
142         QRgb *dst = (QRgb *)img.scanLine(y);
143
144         if (image->channelType == image::TYPE_UNORM8) {
145             const unsigned char *src = srcRow;
146             for (int x = 0; x < width; ++x) {
147                 unsigned char rgba[4] = {0, 0, 0, 0xff};
148                 for (int c = 0; c < image->channels; ++c) {
149                     rgba[c] = *src++;
150                 }
151                 if (image->channels == 1) {
152                     // Use gray-scale instead of red
153                     rgba[1] = rgba[0];
154                     rgba[2] = rgba[0];
155                 }
156                 dst[x] = qRgba(rgba[0], rgba[1], rgba[2], rgba[3]);
157             }
158         } else {
159             const float *src = (const float *)srcRow;
160             for (int x = 0; x < width; ++x) {
161                 unsigned char rgba[4] = {0, 0, 0, 0xff};
162                 for (int c = 0; c < image->channels; ++c) {
163                     float f = *src++;
164                     unsigned char u;
165                     if (f >= 1.0f) {
166                         u = 255;
167                     } else if (f <= 0.0f) {
168                         u = 0;
169                     } else {
170                         u = f * 255 + 0.5;
171                     }
172                     rgba[c] = u;
173                 }
174                 if (image->channels == 1) {
175                     // Use gray-scale instead of red
176                     rgba[1] = rgba[0];
177                     rgba[2] = rgba[0];
178                 }
179                 dst[x] = qRgba(rgba[0], rgba[1], rgba[2], rgba[3]);
180             }
181         }
182
183         srcRow += image->stride();
184     }
185
186     return img;
187 }