blob: 8d95db90ddfb67b0197212fbdc6b909620bc5cb3 [file] [log] [blame]
Zack Rusin952e9d42011-04-09 23:37:21 -04001#include "apisurface.h"
José Fonseca3f456402012-03-25 20:59:24 +01002#include "thumbnail.h"
Zack Rusin952e9d42011-04-09 23:37:21 -04003
José Fonseca52398312013-09-11 18:42:07 +01004#include <sstream>
5
Zack Rusin952e9d42011-04-09 23:37:21 -04006#include <QDebug>
7#include <QSysInfo>
8
José Fonseca52398312013-09-11 18:42:07 +01009#include "image/image.hpp"
10
11
Zack Rusin952e9d42011-04-09 23:37:21 -040012ApiSurface::ApiSurface()
13{
14}
15
16QSize ApiSurface::size() const
17{
18 return m_size;
19}
20
21void ApiSurface::setSize(const QSize &size)
22{
23 m_size = size;
24}
25
José Fonseca52398312013-09-11 18:42:07 +010026struct ByteArrayBuf : public std::streambuf
27{
Jose Fonsecac296a3e2015-05-01 17:43:54 +010028 ByteArrayBuf(const QByteArray & a)
José Fonseca52398312013-09-11 18:42:07 +010029 {
Jose Fonsecac296a3e2015-05-01 17:43:54 +010030 setg((char *)a.data(), (char *)a.data(), (char *)a.data() + a.size());
José Fonseca52398312013-09-11 18:42:07 +010031 }
32};
33
Zack Rusin952e9d42011-04-09 23:37:21 -040034void ApiSurface::contentsFromBase64(const QByteArray &base64)
35{
Zack Rusina69f0de2013-09-12 17:21:51 -040036 m_base64Data = base64;
José Fonseca994535d2013-09-12 17:26:34 +010037
José Fonseca52398312013-09-11 18:42:07 +010038 /*
Zack Rusina69f0de2013-09-12 17:21:51 -040039 * We need to do the conversion to create the thumbnail
José Fonseca52398312013-09-11 18:42:07 +010040 */
Zack Rusina69f0de2013-09-12 17:21:51 -040041 image::Image *image = imageFromBase64(base64);
José Fonseca52398312013-09-11 18:42:07 +010042 Q_ASSERT(image);
Zack Rusina69f0de2013-09-12 17:21:51 -040043 QImage img = qimageFromRawImage(image);
44 m_thumb = thumbnail(img);
José Fonseca52398312013-09-11 18:42:07 +010045 delete image;
Zack Rusin952e9d42011-04-09 23:37:21 -040046}
47
Zack Rusina69f0de2013-09-12 17:21:51 -040048QByteArray ApiSurface::base64Data() const
Zack Rusin952e9d42011-04-09 23:37:21 -040049{
Zack Rusina69f0de2013-09-12 17:21:51 -040050 return m_base64Data;
Zack Rusin952e9d42011-04-09 23:37:21 -040051}
52
53QImage ApiSurface::thumb() const
54{
55 return m_thumb;
56}
57
Zack Rusinb25c4b92011-11-16 22:43:34 -050058int ApiSurface::depth() const
59{
60 return m_depth;
61}
62
63void ApiSurface::setDepth(int depth)
64{
65 m_depth = depth;
66}
67
Zack Rusine181b992011-11-17 16:00:41 -050068QString ApiSurface::formatName() const
69{
70 return m_formatName;
71}
72
73void ApiSurface::setFormatName(const QString &str)
74{
75 m_formatName = str;
76}
77
78
Zack Rusin952e9d42011-04-09 23:37:21 -040079ApiTexture::ApiTexture()
José Fonseca18081d52011-05-07 00:10:25 +010080 : ApiSurface()
Zack Rusin952e9d42011-04-09 23:37:21 -040081{
82}
83
José Fonseca18081d52011-05-07 00:10:25 +010084QString ApiTexture::label() const
Zack Rusin952e9d42011-04-09 23:37:21 -040085{
José Fonseca18081d52011-05-07 00:10:25 +010086 return m_label;
Zack Rusin952e9d42011-04-09 23:37:21 -040087}
88
José Fonseca18081d52011-05-07 00:10:25 +010089void ApiTexture::setLabel(const QString &str)
Zack Rusin952e9d42011-04-09 23:37:21 -040090{
José Fonseca18081d52011-05-07 00:10:25 +010091 m_label = str;
Zack Rusin952e9d42011-04-09 23:37:21 -040092}
Zack Rusina6846412011-04-10 19:51:44 -040093
94ApiFramebuffer::ApiFramebuffer()
95 : ApiSurface()
96{
97}
98
99QString ApiFramebuffer::type() const
100{
101 return m_type;
102}
103
104void ApiFramebuffer::setType(const QString &str)
105{
106 m_type = str;
107}
Zack Rusinb25c4b92011-11-16 22:43:34 -0500108
Zack Rusina69f0de2013-09-12 17:21:51 -0400109image::Image *
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100110ApiSurface::imageFromBase64(const QByteArray &dataArray)
Zack Rusina69f0de2013-09-12 17:21:51 -0400111{
Jose Fonsecac296a3e2015-05-01 17:43:54 +0100112 //QByteArray dataArray = QByteArray::fromBase64(base64);
Zack Rusina69f0de2013-09-12 17:21:51 -0400113 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
José Fonseca36509be2013-09-17 15:22:50 +0100131static inline unsigned char clamp(int x)
132{
133 if (x <= 0) {
134 return 0;
135 }
136 if (x > 255) {
137 return 255;
138 }
139 return (unsigned char) x;
140}
141
142static inline unsigned char clamp(float x)
143{
144 if (x <= 0.0f) {
145 return 0;
146 }
147 if (x > 255.0f) {
148 return 255;
149 }
150 return (unsigned char) (x + 0.5f);
151}
152
153
Zack Rusina69f0de2013-09-12 17:21:51 -0400154QImage
José Fonseca36509be2013-09-17 15:22:50 +0100155ApiSurface::qimageFromRawImage(const image::Image *image,
156 float lowerValue,
157 float upperValue,
158 bool opaque,
159 bool alpha)
Zack Rusina69f0de2013-09-12 17:21:51 -0400160{
161 QImage img;
162 int width = image->width;
163 int height = image->height;
164
165 img = QImage(width, height, QImage::Format_ARGB32);
166
José Fonseca36509be2013-09-17 15:22:50 +0100167 int offset = - lowerValue * 255;
168 int scale = 256 / (upperValue - lowerValue);
169
170 float offset_f = - lowerValue;
171 float scale_f = 255.0f / (upperValue - lowerValue);
172
173 int aMask = (opaque || alpha) ? 0xff : 0;
174
Zack Rusina69f0de2013-09-12 17:21:51 -0400175 const unsigned char *srcRow = image->start();
176 for (int y = 0; y < height; ++y) {
177 QRgb *dst = (QRgb *)img.scanLine(y);
178
179 if (image->channelType == image::TYPE_UNORM8) {
180 const unsigned char *src = srcRow;
181 for (int x = 0; x < width; ++x) {
Zack Rusind36c6ee2013-09-12 17:41:57 -0400182 unsigned char rgba[4] = {0, 0, 0, 0xff};
Zack Rusina69f0de2013-09-12 17:21:51 -0400183 for (int c = 0; c < image->channels; ++c) {
José Fonseca36509be2013-09-17 15:22:50 +0100184 rgba[c] = clamp(((*src++ + offset) * scale) >> 8);
Zack Rusina69f0de2013-09-12 17:21:51 -0400185 }
186 if (image->channels == 1) {
187 // Use gray-scale instead of red
188 rgba[1] = rgba[0];
189 rgba[2] = rgba[0];
190 }
José Fonseca36509be2013-09-17 15:22:50 +0100191 if (alpha) {
192 rgba[2] = rgba[1] = rgba[0] = rgba[3];
193 }
194 rgba[3] |= aMask;
Zack Rusina69f0de2013-09-12 17:21:51 -0400195 dst[x] = qRgba(rgba[0], rgba[1], rgba[2], rgba[3]);
196 }
197 } else {
198 const float *src = (const float *)srcRow;
199 for (int x = 0; x < width; ++x) {
200 unsigned char rgba[4] = {0, 0, 0, 0xff};
201 for (int c = 0; c < image->channels; ++c) {
José Fonseca36509be2013-09-17 15:22:50 +0100202 rgba[c] = clamp((*src++ + offset_f)*scale_f);
Zack Rusina69f0de2013-09-12 17:21:51 -0400203 }
204 if (image->channels == 1) {
205 // Use gray-scale instead of red
206 rgba[1] = rgba[0];
207 rgba[2] = rgba[0];
208 }
José Fonseca36509be2013-09-17 15:22:50 +0100209 if (alpha) {
210 rgba[2] = rgba[1] = rgba[0] = rgba[3];
211 }
212 rgba[3] |= aMask;
Zack Rusina69f0de2013-09-12 17:21:51 -0400213 dst[x] = qRgba(rgba[0], rgba[1], rgba[2], rgba[3]);
214 }
215 }
216
217 srcRow += image->stride();
218 }
219
220 return img;
221}