From: José Fonseca Date: Tue, 17 Sep 2013 14:22:50 +0000 (+0100) Subject: Rescale the image pixels using the full precision. X-Git-Url: https://git.cworth.org/git?a=commitdiff_plain;h=36509be82b82382adeb8b320405f35636ecf72e7;p=apitrace Rescale the image pixels using the full precision. --- diff --git a/gui/apisurface.cpp b/gui/apisurface.cpp index a872c13..22de5f0 100644 --- a/gui/apisurface.cpp +++ b/gui/apisurface.cpp @@ -128,8 +128,35 @@ ApiSurface::imageFromBase64(const QByteArray &base64) } +static inline unsigned char clamp(int x) +{ + if (x <= 0) { + return 0; + } + if (x > 255) { + return 255; + } + return (unsigned char) x; +} + +static inline unsigned char clamp(float x) +{ + if (x <= 0.0f) { + return 0; + } + if (x > 255.0f) { + return 255; + } + return (unsigned char) (x + 0.5f); +} + + QImage -ApiSurface::qimageFromRawImage(const image::Image *image) +ApiSurface::qimageFromRawImage(const image::Image *image, + float lowerValue, + float upperValue, + bool opaque, + bool alpha) { QImage img; int width = image->width; @@ -137,6 +164,14 @@ ApiSurface::qimageFromRawImage(const image::Image *image) 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); @@ -146,13 +181,17 @@ ApiSurface::qimageFromRawImage(const image::Image *image) 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++; + 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 { @@ -160,22 +199,17 @@ ApiSurface::qimageFromRawImage(const image::Image *image) 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; + 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]); } } diff --git a/gui/apisurface.h b/gui/apisurface.h index 79afaf9..ed6debe 100644 --- a/gui/apisurface.h +++ b/gui/apisurface.h @@ -29,7 +29,11 @@ public: QImage thumb() const; static image::Image *imageFromBase64(const QByteArray &data); - static QImage qimageFromRawImage(const image::Image *img); + static QImage qimageFromRawImage(const image::Image *img, + float lowerValue = 0.0f, + float upperValue = 1.0f, + bool opaque = false, + bool alpha = false); private: QSize m_size; diff --git a/gui/imageviewer.cpp b/gui/imageviewer.cpp index a795993..eced83b 100644 --- a/gui/imageviewer.cpp +++ b/gui/imageviewer.cpp @@ -70,17 +70,6 @@ void ImageViewer::setBase64Data(const QByteArray &base64) updateGeometry(); } -static inline int clamp(int x) -{ - if (x <= 0) { - return 0; - } - if (x > 255) { - return 255; - } - return x; -} - void ImageViewer::slotUpdate() { m_convertedImage = @@ -92,51 +81,12 @@ void ImageViewer::slotUpdate() bool opaque = opaqueCheckBox->isChecked(); bool alpha = alphaCheckBox->isChecked(); - if (lowerValue != 0.0 || upperValue != 1.0 || opaque || alpha) { - /* - * Rescale the image. - * - * XXX: This would be much more useful if done with the full precision - * of the original image - */ - - int offset = - lowerValue * 255; - int scale = 256 / (upperValue - lowerValue); - - m_convertedImage = - m_convertedImage.convertToFormat(QImage::Format_ARGB32); - - if (0) { - qDebug() - << "offset = " << offset << "\n" - << "scale = " << scale << "\n"; - } - - int width = m_convertedImage.width(); - int height = m_convertedImage.height(); - - int aMask = opaque ? 0xff : 0; - - for (int y = 0; y < height; ++y) { - QRgb *scanline = (QRgb *)m_convertedImage.scanLine(y); - for (int x = 0; x < width; ++x) { - QRgb pixel = scanline[x]; - int r = qRed(pixel); - int g = qGreen(pixel); - int b = qBlue(pixel); - int a = qAlpha(pixel); - if (alpha) { - a = clamp(((a + offset) * scale) >> 8); - scanline[x] = qRgba(a, a, a, 0xff); - } else { - r = clamp(((r + offset) * scale) >> 8); - g = clamp(((g + offset) * scale) >> 8); - b = clamp(((b + offset) * scale) >> 8); - a |= aMask; - scanline[x] = qRgba(r, g, b, a); - } - } - } + m_convertedImage = ApiSurface::qimageFromRawImage(m_image, + lowerValue, upperValue, + opaque, alpha); + + if (flipCheckBox->isChecked()) { + m_convertedImage = m_convertedImage.mirrored(false, true); } m_pixelWidget->setSurface(m_convertedImage);