diff --git a/nQuantCpp/DivQuantizer.cpp b/nQuantCpp/DivQuantizer.cpp index b6dfaf5..6371c66 100644 --- a/nQuantCpp/DivQuantizer.cpp +++ b/nQuantCpp/DivQuantizer.cpp @@ -1066,7 +1066,8 @@ namespace DivQuant pixelMap.clear(); nearestMap.clear(); - return ProcessImagePixels(pDest, pPalette, qPixels.get(), m_transparentPixelIndex >= 0); + pDest->SetPalette(pPalette); + return ProcessImagePixels(pDest, qPixels.get(), m_transparentPixelIndex >= 0); } } \ No newline at end of file diff --git a/nQuantCpp/Dl3Quantizer.cpp b/nQuantCpp/Dl3Quantizer.cpp index 26d3659..f9db2d6 100644 --- a/nQuantCpp/Dl3Quantizer.cpp +++ b/nQuantCpp/Dl3Quantizer.cpp @@ -372,7 +372,9 @@ namespace Dl3Quant else if (pPalette->Entries[k] != m_transparentColor) swap(pPalette->Entries[0], pPalette->Entries[1]); } - return ProcessImagePixels(pDest, pPalette, qPixels.get(), m_transparentPixelIndex >= 0); + + pDest->SetPalette(pPalette); + return ProcessImagePixels(pDest, qPixels.get(), m_transparentPixelIndex >= 0); } } diff --git a/nQuantCpp/EdgeAwareSQuantizer.cpp b/nQuantCpp/EdgeAwareSQuantizer.cpp index ce2da2a..17ecb51 100644 --- a/nQuantCpp/EdgeAwareSQuantizer.cpp +++ b/nQuantCpp/EdgeAwareSQuantizer.cpp @@ -772,7 +772,8 @@ namespace EdgeAwareSQuant } pixelMap.clear(); - return ProcessImagePixels(pDest, pPalette, qPixels.get(), m_transparentPixelIndex >= 0); + pDest->SetPalette(pPalette); + return ProcessImagePixels(pDest, qPixels.get(), m_transparentPixelIndex >= 0); } } \ No newline at end of file diff --git a/nQuantCpp/MedianCut.cpp b/nQuantCpp/MedianCut.cpp index 3164596..a66be2f 100644 --- a/nQuantCpp/MedianCut.cpp +++ b/nQuantCpp/MedianCut.cpp @@ -1561,6 +1561,7 @@ namespace MedianCutQuant closestMap.clear(); nearestMap.clear(); - return ProcessImagePixels(pDest, pPalette, qPixels.get(), m_transparentPixelIndex >= 0); + pDest->SetPalette(pPalette); + return ProcessImagePixels(pDest, qPixels.get(), m_transparentPixelIndex >= 0); } } diff --git a/nQuantCpp/MoDEQuantizer.cpp b/nQuantCpp/MoDEQuantizer.cpp index 2652666..c3e0398 100644 --- a/nQuantCpp/MoDEQuantizer.cpp +++ b/nQuantCpp/MoDEQuantizer.cpp @@ -536,7 +536,8 @@ namespace MoDEQuant } closestMap.clear(); - return ProcessImagePixels(pDest, pPalette, qPixels.get(), m_transparentPixelIndex >= 0); + pDest->SetPalette(pPalette); + return ProcessImagePixels(pDest, qPixels.get(), m_transparentPixelIndex >= 0); } } \ No newline at end of file diff --git a/nQuantCpp/NeuQuantizer.cpp b/nQuantCpp/NeuQuantizer.cpp index c4e6541..efb578f 100644 --- a/nQuantCpp/NeuQuantizer.cpp +++ b/nQuantCpp/NeuQuantizer.cpp @@ -595,6 +595,7 @@ namespace NeuralNet } Clear(); - return ProcessImagePixels(pDest, pPalette, qPixels.get(), m_transparentPixelIndex >= 0); + pDest->SetPalette(pPalette); + return ProcessImagePixels(pDest, qPixels.get(), m_transparentPixelIndex >= 0); } } diff --git a/nQuantCpp/Otsu.cpp b/nQuantCpp/Otsu.cpp index daca747..59362a6 100644 --- a/nQuantCpp/Otsu.cpp +++ b/nQuantCpp/Otsu.cpp @@ -278,6 +278,7 @@ namespace OtsuThreshold } nearestMap.clear(); - return ProcessImagePixels(pDest, pPalette, qPixels.get(), m_transparentPixelIndex >= 0); + pDest->SetPalette(pPalette); + return ProcessImagePixels(pDest, qPixels.get(), m_transparentPixelIndex >= 0); } } diff --git a/nQuantCpp/PnnLABQuantizer.cpp b/nQuantCpp/PnnLABQuantizer.cpp index d14143a..2f84578 100644 --- a/nQuantCpp/PnnLABQuantizer.cpp +++ b/nQuantCpp/PnnLABQuantizer.cpp @@ -625,12 +625,7 @@ namespace PnnLABQuant pixelMap.clear(); clear(); - auto pPaletteBytes = make_unique(sizeof(ColorPalette) + nMaxColors * sizeof(ARGB)); - auto pPals = (ColorPalette*) pPaletteBytes.get(); - pPals->Count = nMaxColors; - for (UINT k = 0; k < nMaxColors; ++k) - pPals->Entries[k] = pPalette[k]; - return ProcessImagePixels(pDest, pPals, qPixels.get(), m_transparentPixelIndex >= 0); + return ProcessImagePixels(pDest, qPixels.get(), m_transparentPixelIndex >= 0); } bool PnnLABQuantizer::QuantizeImage(Bitmap* pSource, Bitmap* pDest, UINT& nMaxColors, bool dither) @@ -643,10 +638,18 @@ namespace PnnLABQuant int semiTransCount = 0; grabPixels(pSource, pixels, nMaxColors, hasSemiTransparency); - auto pPalettes = make_unique(nMaxColors); - auto pPalette = pPalettes.get(); - - return QuantizeImage(pixels, bitmapWidth, pPalette, pDest, nMaxColors, dither); + if (nMaxColors > 256) { + auto pPalettes = make_unique(nMaxColors); + auto pPalette = pPalettes.get(); + return QuantizeImage(pixels, bitmapWidth, pPalette, pDest, nMaxColors, dither); + } + + auto pPaletteBytes = make_unique(sizeof(ColorPalette) + nMaxColors * sizeof(ARGB)); + auto pPalette = (ColorPalette*)pPaletteBytes.get(); + pPalette->Count = nMaxColors; + auto result = QuantizeImage(pixels, bitmapWidth, pPalette->Entries, pDest, nMaxColors, dither); + pDest->SetPalette(pPalette); + return result; } } diff --git a/nQuantCpp/PnnQuantizer.cpp b/nQuantCpp/PnnQuantizer.cpp index cbb049c..51ee086 100644 --- a/nQuantCpp/PnnQuantizer.cpp +++ b/nQuantCpp/PnnQuantizer.cpp @@ -378,28 +378,18 @@ namespace PnnQuant BlueNoise::dither(width, height, pixels, pPalette->Entries, nMaxColors, ditherFn, GetColorIndex, qPixels); return true; - } + } - bool PnnQuantizer::QuantizeImage(Bitmap* pSource, Bitmap* pDest, UINT& nMaxColors, bool dither) + bool PnnQuantizer::QuantizeImage(const vector& pixels, const UINT bitmapWidth, ARGB* pPalette, Bitmap* pDest, UINT& nMaxColors, bool dither) { - const auto bitmapWidth = pSource->GetWidth(); - const auto bitmapHeight = pSource->GetHeight(); - const auto area = (size_t) (bitmapWidth * bitmapHeight); - - vector pixels(area); - int semiTransCount = 0; - GrabPixels(pSource, pixels, semiTransCount, m_transparentPixelIndex, m_transparentColor, alphaThreshold, nMaxColors); - hasSemiTransparency = semiTransCount > 0; - - auto pPalettes = make_unique(nMaxColors); - auto pPalette = pPalettes.get(); - if (nMaxColors <= 32) PR = PG = PB = PA = 1; else { PR = coeffs[0][0]; PG = coeffs[0][1]; PB = coeffs[0][2]; } + const auto bitmapHeight = pixels.size() / bitmapWidth; + if (nMaxColors > 2) pnnquan(pixels, pPalette, nMaxColors); else { @@ -412,15 +402,15 @@ namespace PnnQuant pPalette[1] = Color::White; } } - + DitherFn ditherFn = dither ? nearestColorIndex : closestColorIndex; if (hasSemiTransparency) weight *= -1; - vector saliencies; + vector saliencies; if (nMaxColors > 256) { - auto qPixels = make_unique(area); + auto qPixels = make_unique(pixels.size()); Peano::GilbertCurve::dither(bitmapWidth, bitmapHeight, pixels.data(), pPalette, nMaxColors, ditherFn, GetColorIndex, qPixels.get(), saliencies.data(), weight); closestMap.clear(); @@ -431,7 +421,7 @@ namespace PnnQuant auto qPixels = make_unique(pixels.size()); Peano::GilbertCurve::dither(bitmapWidth, bitmapHeight, pixels.data(), pPalette, nMaxColors, ditherFn, GetColorIndex, qPixels.get(), saliencies.data(), weight); - if(!dither) + if (!dither) BlueNoise::dither(bitmapWidth, bitmapHeight, pixels.data(), pPalette, nMaxColors, ditherFn, GetColorIndex, qPixels.get()); if (m_transparentPixelIndex >= 0) { @@ -444,12 +434,32 @@ namespace PnnQuant closestMap.clear(); nearestMap.clear(); + return ProcessImagePixels(pDest, qPixels.get(), m_transparentPixelIndex >= 0); + } + + bool PnnQuantizer::QuantizeImage(Bitmap* pSource, Bitmap* pDest, UINT& nMaxColors, bool dither) + { + const auto bitmapWidth = pSource->GetWidth(); + const auto bitmapHeight = pSource->GetHeight(); + const auto area = (size_t) (bitmapWidth * bitmapHeight); + + vector pixels(area); + int semiTransCount = 0; + GrabPixels(pSource, pixels, semiTransCount, m_transparentPixelIndex, m_transparentColor, alphaThreshold, nMaxColors); + hasSemiTransparency = semiTransCount > 0; + + if (nMaxColors > 256) { + auto pPalettes = make_unique(nMaxColors); + auto pPalette = pPalettes.get(); + return QuantizeImage(pixels, bitmapWidth, pPalette, pDest, nMaxColors, dither); + } + auto pPaletteBytes = make_unique(sizeof(ColorPalette) + nMaxColors * sizeof(ARGB)); - auto pPals = (ColorPalette*)pPaletteBytes.get(); - pPals->Count = nMaxColors; - for (UINT k = 0; k < nMaxColors; ++k) - pPals->Entries[k] = pPalette[k]; - return ProcessImagePixels(pDest, pPals, qPixels.get(), m_transparentPixelIndex >= 0); + auto pPalette = (ColorPalette*)pPaletteBytes.get(); + pPalette->Count = nMaxColors; + auto result = QuantizeImage(pixels, bitmapWidth, pPalette->Entries, pDest, nMaxColors, dither); + pDest->SetPalette(pPalette); + return result; } } diff --git a/nQuantCpp/PnnQuantizer.h b/nQuantCpp/PnnQuantizer.h index 1489be5..08c0f46 100644 --- a/nQuantCpp/PnnQuantizer.h +++ b/nQuantCpp/PnnQuantizer.h @@ -24,6 +24,7 @@ namespace PnnQuant class PnnQuantizer { public: + bool QuantizeImage(const vector& pixels, const UINT bitmapWidth, ARGB* pPalette, Bitmap* pDest, UINT& nMaxColors, bool dither = true); bool QuantizeImage(Bitmap* pSource, Bitmap* pDest, UINT& nMaxColors, bool dither = true); }; } \ No newline at end of file diff --git a/nQuantCpp/SpatialQuantizer.cpp b/nQuantCpp/SpatialQuantizer.cpp index a74d8fe..c8ad2dd 100644 --- a/nQuantCpp/SpatialQuantizer.cpp +++ b/nQuantCpp/SpatialQuantizer.cpp @@ -1059,7 +1059,8 @@ namespace SpatialQuant } pixelMap.clear(); - return ProcessImagePixels(pDest, pPalette, qPixels.get(), m_transparentPixelIndex >= 0); + pDest->SetPalette(pPalette); + return ProcessImagePixels(pDest, qPixels.get(), m_transparentPixelIndex >= 0); } } \ No newline at end of file diff --git a/nQuantCpp/WuQuantizer.cpp b/nQuantCpp/WuQuantizer.cpp index 55bb923..4261834 100644 --- a/nQuantCpp/WuQuantizer.cpp +++ b/nQuantCpp/WuQuantizer.cpp @@ -929,7 +929,8 @@ namespace nQuant closestMap.clear(); nearestMap.clear(); - return ProcessImagePixels(pDest, pPalette, qPixels.get(), m_transparentPixelIndex >= 0); + pDest->SetPalette(pPalette); + return ProcessImagePixels(pDest, qPixels.get(), m_transparentPixelIndex >= 0); } } diff --git a/nQuantCpp/bitmapUtilities.cpp b/nQuantCpp/bitmapUtilities.cpp index d5c480c..befad41 100644 --- a/nQuantCpp/bitmapUtilities.cpp +++ b/nQuantCpp/bitmapUtilities.cpp @@ -736,7 +736,7 @@ bool ProcessImagePixels(Bitmap* pDest, const ARGB* qPixels, const bool& hasSemiT return pDest->GetLastStatus() == Ok; } -bool ProcessImagePixels(Bitmap* pDest, const ColorPalette* pPalette, const unsigned short* qPixels, const bool hasTransparent) +bool ProcessImagePixels(Bitmap* pDest, const unsigned short* qPixels, const bool hasTransparent) { if (hasTransparent) { BYTE value = 0; @@ -748,9 +748,7 @@ bool ProcessImagePixels(Bitmap* pDest, const ColorPalette* pPalette, const unsig pPropertyItem.get()->value = &value; pDest->SetPropertyItem(pPropertyItem.get()); - } - - pDest->SetPalette(pPalette); + } BitmapData targetData; UINT w = pDest->GetWidth(); diff --git a/nQuantCpp/bitmapUtilities.h b/nQuantCpp/bitmapUtilities.h index 2bc6f22..884d4a5 100644 --- a/nQuantCpp/bitmapUtilities.h +++ b/nQuantCpp/bitmapUtilities.h @@ -71,7 +71,7 @@ bool dithering_image(const ARGB* pixels, const ColorPalette* pPalette, DitherFn bool ProcessImagePixels(Bitmap* pDest, const ARGB* qPixels, const bool& hasSemiTransparency, const int& transparentPixelIndex); -bool ProcessImagePixels(Bitmap* pDest, const ColorPalette* pPalette, const unsigned short* qPixels, const bool hasTransparent); +bool ProcessImagePixels(Bitmap* pDest, const unsigned short* qPixels, const bool hasTransparent); bool GrabPixels(Bitmap* pSource, vector& pixels, int& semiTransCount, int& transparentPixelIndex, ARGB& transparentColor, const BYTE alphaThreshold, const UINT nMaxColors = 2);