From 4f2c00af46158387212c129b06951992835ecade Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 5 Aug 2016 23:38:45 -0700 Subject: [PATCH 1/3] faster TextureUsage::process2DImageColor() --- libraries/model/src/model/TextureMap.cpp | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/libraries/model/src/model/TextureMap.cpp b/libraries/model/src/model/TextureMap.cpp index 3e6016d7c0..6d96932e91 100755 --- a/libraries/model/src/model/TextureMap.cpp +++ b/libraries/model/src/model/TextureMap.cpp @@ -59,29 +59,27 @@ const QImage TextureUsage::process2DImageColor(const QImage& srcImage, bool& val const uint8 OPAQUE_ALPHA = 255; const uint8 TRANSPARENT_ALPHA = 0; if (image.hasAlphaChannel()) { - std::map alphaHistogram; - if (image.format() != QImage::Format_ARGB32) { image = image.convertToFormat(QImage::Format_ARGB32); } - - // Actual alpha channel? create the histogram - for (int y = 0; y < image.height(); ++y) { + // Count the opaque and transparent pixels + int numOpaques = 0; + int numTransparents = 0; + int height = image.height(); + int width = image.width(); + for (int y = 0; y < height; ++y) { const QRgb* data = reinterpret_cast(image.constScanLine(y)); - for (int x = 0; x < image.width(); ++x) { + for (int x = 0; x < width; ++x) { auto alpha = qAlpha(data[x]); - alphaHistogram[alpha] ++; - validAlpha = validAlpha || (alpha != OPAQUE_ALPHA); + numOpaques += (int)(alpha == OPAQUE_ALPHA); + numTransparents += (int)(alpha == TRANSPARENT_ALPHA); } } // If alpha was meaningfull refine - if (validAlpha && (alphaHistogram.size() > 1)) { - auto totalNumPixels = image.height() * image.width(); - auto numOpaques = alphaHistogram[OPAQUE_ALPHA]; - auto numTransparents = alphaHistogram[TRANSPARENT_ALPHA]; + auto totalNumPixels = height * width; + if (numOpaques != totalNumPixels) { auto numTranslucents = totalNumPixels - numOpaques - numTransparents; - alphaAsMask = ((numTranslucents / (double)totalNumPixels) < 0.05); } } From f759fd10330292982ae1ca342d4262d49bd2a176 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Sun, 7 Aug 2016 08:54:20 -0700 Subject: [PATCH 2/3] early exit when determining if alpha mask possible also don't bother scanning for alpha for cube maps --- libraries/model/src/model/TextureMap.cpp | 32 ++++++++++++------------ 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/libraries/model/src/model/TextureMap.cpp b/libraries/model/src/model/TextureMap.cpp index 6d96932e91..cceaaf6541 100755 --- a/libraries/model/src/model/TextureMap.cpp +++ b/libraries/model/src/model/TextureMap.cpp @@ -62,26 +62,27 @@ const QImage TextureUsage::process2DImageColor(const QImage& srcImage, bool& val if (image.format() != QImage::Format_ARGB32) { image = image.convertToFormat(QImage::Format_ARGB32); } - // Count the opaque and transparent pixels + + // Figure out if we can use a mask for alpha or not int numOpaques = 0; int numTransparents = 0; int height = image.height(); int width = image.width(); + const int MAX_TRANSPARENT_PIXELS_FOR_ALPHAMASK = (int)(0.05f * (float)(width * height)); for (int y = 0; y < height; ++y) { const QRgb* data = reinterpret_cast(image.constScanLine(y)); for (int x = 0; x < width; ++x) { auto alpha = qAlpha(data[x]); numOpaques += (int)(alpha == OPAQUE_ALPHA); - numTransparents += (int)(alpha == TRANSPARENT_ALPHA); + if (alpha == TRANSPARENT_ALPHA) { + if (++numTransparents > MAX_TRANSPARENT_PIXELS_FOR_ALPHAMASK) { + alphaAsMask = false; + break; + } + } } } - - // If alpha was meaningfull refine - auto totalNumPixels = height * width; - if (numOpaques != totalNumPixels) { - auto numTranslucents = totalNumPixels - numOpaques - numTransparents; - alphaAsMask = ((numTranslucents / (double)totalNumPixels) < 0.05); - } + validAlpha = (numOpaques != width * height); } if (!validAlpha && image.format() != QImage::Format_RGB888) { @@ -658,13 +659,12 @@ const CubeLayout CubeLayout::CUBEMAP_LAYOUTS[] = { const int CubeLayout::NUM_CUBEMAP_LAYOUTS = sizeof(CubeLayout::CUBEMAP_LAYOUTS) / sizeof(CubeLayout); gpu::Texture* TextureUsage::processCubeTextureColorFromImage(const QImage& srcImage, const std::string& srcImageName, bool isLinear, bool doCompress, bool generateMips, bool generateIrradiance) { - - bool validAlpha = false; - bool alphaAsMask = true; - QImage image = process2DImageColor(srcImage, validAlpha, alphaAsMask); - gpu::Texture* theTexture = nullptr; - if ((image.width() > 0) && (image.height() > 0)) { + if ((srcImage.width() > 0) && (srcImage.height() > 0)) { + QImage image = srcImage; + if (image.format() != QImage::Format_RGB888) { + image = image.convertToFormat(QImage::Format_RGB888); + } gpu::Element formatGPU; gpu::Element formatMip; @@ -672,7 +672,7 @@ gpu::Texture* TextureUsage::processCubeTextureColorFromImage(const QImage& srcIm // Find the layout of the cubemap in the 2D image int foundLayout = CubeLayout::findLayout(image.width(), image.height()); - + std::vector faces; // If found, go extract the faces as separate images if (foundLayout >= 0) { From 4e23ecfb2cd6d1ce70cb266d76e7c814f518f945 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Sun, 7 Aug 2016 10:50:25 -0700 Subject: [PATCH 3/3] count the _translucent_ pixels and fix break logic --- libraries/model/src/model/TextureMap.cpp | 28 +++++++++++------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/libraries/model/src/model/TextureMap.cpp b/libraries/model/src/model/TextureMap.cpp index cceaaf6541..bbf411b109 100755 --- a/libraries/model/src/model/TextureMap.cpp +++ b/libraries/model/src/model/TextureMap.cpp @@ -65,24 +65,22 @@ const QImage TextureUsage::process2DImageColor(const QImage& srcImage, bool& val // Figure out if we can use a mask for alpha or not int numOpaques = 0; - int numTransparents = 0; - int height = image.height(); - int width = image.width(); - const int MAX_TRANSPARENT_PIXELS_FOR_ALPHAMASK = (int)(0.05f * (float)(width * height)); - for (int y = 0; y < height; ++y) { - const QRgb* data = reinterpret_cast(image.constScanLine(y)); - for (int x = 0; x < width; ++x) { - auto alpha = qAlpha(data[x]); - numOpaques += (int)(alpha == OPAQUE_ALPHA); - if (alpha == TRANSPARENT_ALPHA) { - if (++numTransparents > MAX_TRANSPARENT_PIXELS_FOR_ALPHAMASK) { - alphaAsMask = false; - break; - } + int numTranslucents = 0; + const int NUM_PIXELS = image.width() * image.height(); + const int MAX_TRANSLUCENT_PIXELS_FOR_ALPHAMASK = (int)(0.05f * (float)(NUM_PIXELS)); + const QRgb* data = reinterpret_cast(image.constBits()); + for (int i = 0; i < NUM_PIXELS; ++i) { + auto alpha = qAlpha(data[i]); + if (alpha == OPAQUE_ALPHA) { + numOpaques++; + } else if (alpha != TRANSPARENT_ALPHA) { + if (++numTranslucents > MAX_TRANSLUCENT_PIXELS_FOR_ALPHAMASK) { + alphaAsMask = false; + break; } } } - validAlpha = (numOpaques != width * height); + validAlpha = (numOpaques != NUM_PIXELS); } if (!validAlpha && image.format() != QImage::Format_RGB888) {