X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=gui%2Fapisurface.cpp;h=22de5f0b0d873ab877c4c7dbd89fcdd7268e4fc6;hb=cad5d619dcb5e1c6349bfff69176660668402622;hp=105532e9a2c07cc9dfc5b07fca644a828382a211;hpb=952e9d4fe14932da90c8478ed8883bb043d702ff;p=apitrace diff --git a/gui/apisurface.cpp b/gui/apisurface.cpp index 105532e..22de5f0 100644 --- a/gui/apisurface.cpp +++ b/gui/apisurface.cpp @@ -1,8 +1,14 @@ #include "apisurface.h" +#include "thumbnail.h" + +#include #include #include +#include "image/image.hpp" + + ApiSurface::ApiSurface() { } @@ -17,94 +23,199 @@ void ApiSurface::setSize(const QSize &size) m_size = size; } -static inline int -rgbaf2argb(float r, float g, float b, float a) +struct ByteArrayBuf : public std::streambuf { - quint8 rb = r * 255; - quint8 gb = g * 255; - quint8 bb = b * 255; - quint8 ab = a * 255; + ByteArrayBuf(QByteArray & a) + { + setg(a.data(), a.data(), a.data() + a.size()); + } +}; - return (ab << 24 | rb << 16 | gb << 8 | bb); +void ApiSurface::contentsFromBase64(const QByteArray &base64) +{ + 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; } -void ApiSurface::contentsFromBase64(const QByteArray &base64) +QByteArray ApiSurface::base64Data() const { - QByteArray dataArray = QByteArray::fromBase64(base64); - const float *data = (const float*)dataArray.data(); - int width = m_size.width(); - int height = m_size.height(); + return m_base64Data; +} - if (width <= 0 || height <= 0) - return; +QImage ApiSurface::thumb() const +{ + return m_thumb; +} - int *pixelData = (int*)malloc(sizeof(int) * width * height); +int ApiSurface::depth() const +{ + return m_depth; +} - //XXX not sure if this will work when - // QSysInfo::ByteOrder == QSysInfo::BigEndian +void ApiSurface::setDepth(int depth) +{ + m_depth = depth; +} - for (int y = 0; y < height; ++y) { - for (int x = 0; x < width; ++x) { - int pixel = rgbaf2argb(data[(y * width + x) * 4 + 0], - data[(y * width + x) * 4 + 1], - data[(y * width + x) * 4 + 2], - data[(y * width + x) * 4 + 3]); - pixelData[y * width + x] = pixel; - } - } +QString ApiSurface::formatName() const +{ + return m_formatName; +} + +void ApiSurface::setFormatName(const QString &str) +{ + m_formatName = str; +} - m_image = QImage((uchar*)pixelData, - width, height, - QImage::Format_ARGB32).mirrored(); - m_thumb = m_image.scaled(64, 64, Qt::KeepAspectRatio); - //m_image.save("testoutput.png"); - free(pixelData); +ApiTexture::ApiTexture() + : ApiSurface() +{ } -QImage ApiSurface::image() const +QString ApiTexture::label() const { - return m_image; + return m_label; } -QImage ApiSurface::thumb() const +void ApiTexture::setLabel(const QString &str) { - return m_thumb; + m_label = str; } -ApiTexture::ApiTexture() - : ApiSurface(), - m_unit(0), - m_level(0) +ApiFramebuffer::ApiFramebuffer() + : ApiSurface() { } -int ApiTexture::unit() const +QString ApiFramebuffer::type() const { - return m_unit; + return m_type; } -void ApiTexture::setUnit(int un) +void ApiFramebuffer::setType(const QString &str) { - m_unit = un; + m_type = str; } -QString ApiTexture::target() const +image::Image * +ApiSurface::imageFromBase64(const QByteArray &base64) { - return m_target; + 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; } -void ApiTexture::setTarget(const QString &str) + +static inline unsigned char clamp(int x) { - m_target = str; + if (x <= 0) { + return 0; + } + if (x > 255) { + return 255; + } + return (unsigned char) x; } -int ApiTexture::level() const +static inline unsigned char clamp(float x) { - return m_level; + if (x <= 0.0f) { + return 0; + } + if (x > 255.0f) { + return 255; + } + return (unsigned char) (x + 0.5f); } -void ApiTexture::setLevel(int l) + +QImage +ApiSurface::qimageFromRawImage(const image::Image *image, + float lowerValue, + float upperValue, + bool opaque, + bool alpha) { - m_level = l; + QImage img; + int width = image->width; + int height = image->height; + + img = QImage(width, height, QImage::Format_ARGB32); + + int offset = - lowerValue * 255; + int scale = 256 / (upperValue - lowerValue); + + float offset_f = - lowerValue; + float scale_f = 255.0f / (upperValue - lowerValue); + + int aMask = (opaque || alpha) ? 0xff : 0; + + 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] = clamp(((*src++ + offset) * scale) >> 8); + } + if (image->channels == 1) { + // Use gray-scale instead of red + rgba[1] = rgba[0]; + rgba[2] = rgba[0]; + } + if (alpha) { + rgba[2] = rgba[1] = rgba[0] = rgba[3]; + } + rgba[3] |= aMask; + 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) { + rgba[c] = clamp((*src++ + offset_f)*scale_f); + } + if (image->channels == 1) { + // Use gray-scale instead of red + rgba[1] = rgba[0]; + rgba[2] = rgba[0]; + } + if (alpha) { + rgba[2] = rgba[1] = rgba[0] = rgba[3]; + } + rgba[3] |= aMask; + dst[x] = qRgba(rgba[0], rgba[1], rgba[2], rgba[3]); + } + } + + srcRow += image->stride(); + } + + return img; }