X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=gui%2Fapisurface.cpp;h=a872c13b6b2270a27eb68685a289b4827d77057c;hb=d36c6ee24ec7d642b5bcf39f3b6a265467c8b0f3;hp=bfc6cfdf128038d6e6b18a6afb057ebeb53e50e2;hpb=dc9e9c6addb436b7b2d87984d4bd9b0a18d5c5e2;p=apitrace diff --git a/gui/apisurface.cpp b/gui/apisurface.cpp index bfc6cfd..a872c13 100644 --- a/gui/apisurface.cpp +++ b/gui/apisurface.cpp @@ -1,9 +1,14 @@ #include "apisurface.h" #include "thumbnail.h" +#include + #include #include +#include "image/image.hpp" + + ApiSurface::ApiSurface() { } @@ -18,26 +23,31 @@ void ApiSurface::setSize(const QSize &size) m_size = size; } -int ApiSurface::numChannels() const -{ - return m_numChannels; -} - -void ApiSurface::setNumChannels(int numChannels) +struct ByteArrayBuf : public std::streambuf { - m_numChannels = numChannels; -} + ByteArrayBuf(QByteArray & a) + { + setg(a.data(), a.data(), a.data() + a.size()); + } +}; void ApiSurface::contentsFromBase64(const QByteArray &base64) { - QByteArray dataArray = QByteArray::fromBase64(base64); - m_image.loadFromData(dataArray, "png"); - m_thumb = thumbnail(m_image); + m_base64Data = base64; + + /* + * We need to do the conversion to create the thumbnail + */ + image::Image *image = imageFromBase64(base64); + Q_ASSERT(image); + QImage img = qimageFromRawImage(image); + m_thumb = thumbnail(img); + delete image; } -QImage ApiSurface::image() const +QByteArray ApiSurface::base64Data() const { - return m_image; + return m_base64Data; } QImage ApiSurface::thumb() const @@ -96,3 +106,82 @@ void ApiFramebuffer::setType(const QString &str) m_type = str; } +image::Image * +ApiSurface::imageFromBase64(const QByteArray &base64) +{ + QByteArray dataArray = QByteArray::fromBase64(base64); + image::Image *image; + + /* + * Detect the PNG vs PFM images. + */ + const char pngSignature[] = {(char)0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0}; + if (dataArray.startsWith(pngSignature)) { + ByteArrayBuf buf(dataArray); + std::istream istr(&buf); + image = image::readPNG(istr); + } else { + image = image::readPNM(dataArray.data(), dataArray.size()); + } + + return image; +} + + +QImage +ApiSurface::qimageFromRawImage(const image::Image *image) +{ + QImage img; + int width = image->width; + int height = image->height; + + img = QImage(width, height, QImage::Format_ARGB32); + + const unsigned char *srcRow = image->start(); + for (int y = 0; y < height; ++y) { + QRgb *dst = (QRgb *)img.scanLine(y); + + if (image->channelType == image::TYPE_UNORM8) { + const unsigned char *src = srcRow; + for (int x = 0; x < width; ++x) { + unsigned char rgba[4] = {0, 0, 0, 0xff}; + for (int c = 0; c < image->channels; ++c) { + rgba[c] = *src++; + } + if (image->channels == 1) { + // Use gray-scale instead of red + rgba[1] = rgba[0]; + rgba[2] = rgba[0]; + } + dst[x] = qRgba(rgba[0], rgba[1], rgba[2], rgba[3]); + } + } else { + const float *src = (const float *)srcRow; + for (int x = 0; x < width; ++x) { + unsigned char rgba[4] = {0, 0, 0, 0xff}; + for (int c = 0; c < image->channels; ++c) { + float f = *src++; + unsigned char u; + if (f >= 1.0f) { + u = 255; + } else if (f <= 0.0f) { + u = 0; + } else { + u = f * 255 + 0.5; + } + rgba[c] = u; + } + if (image->channels == 1) { + // Use gray-scale instead of red + rgba[1] = rgba[0]; + rgba[2] = rgba[0]; + } + dst[x] = qRgba(rgba[0], rgba[1], rgba[2], rgba[3]); + } + } + + srcRow += image->stride(); + } + + return img; +}