Skip to content

Commit

Permalink
Rewrite ColorQuantizer based on KGySoft.Drawing code (for saving imag…
Browse files Browse the repository at this point in the history
…es in GIF format)
  • Loading branch information
zenden2k committed Jul 20, 2024
1 parent 8eda4c0 commit 1c65cdd
Show file tree
Hide file tree
Showing 10 changed files with 572 additions and 729 deletions.
576 changes: 0 additions & 576 deletions Source/3rdpart/QColorQuantizer.cpp

This file was deleted.

146 changes: 0 additions & 146 deletions Source/3rdpart/QColorQuantizer.h

This file was deleted.

6 changes: 4 additions & 2 deletions Source/Core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,9 @@ if(WIN32)
Images/WebpImageReader.cpp
Images/HeifImageReader.cpp
Images/ImageLoader.cpp
../3rdpart/QColorQuantizer.cpp
Images/GdiPlusImage.cpp
Images/ColorQuantizer.cpp
Images/OctreeColorQuantizer.cpp
../Func/GdiPlusInitializer.cpp
)

Expand Down Expand Up @@ -236,7 +237,8 @@ if(WIN32)
Images/HeifImageReader.h
Images/AbstractImageReader.h
Images/ImageLoader.h
../3rdpart/QColorQuantizer.h
Images/ColorQuantizer.h
Images/OctreeColorQuantizer.h
)
else()
list(APPEND SRC_LIST
Expand Down
91 changes: 91 additions & 0 deletions Source/Core/Images/ColorQuantizer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#include "ColorQuantizer.h"

#include "OctreeColorQuantizer.h"

using namespace Gdiplus;

std::unique_ptr<Bitmap> ColorQuantizer::getQuantized(Bitmap* sourceBitmap, Gdiplus::Color backgroundColor, UINT nMaxColors /* = 256 */)
{
BYTE alphaThreshold = 0;
UINT width = sourceBitmap->GetWidth();
UINT height = sourceBitmap->GetHeight();
Rect rc(0, 0, width, height);
std::unique_ptr<Bitmap> destBitmap;
BitmapData dataSource;

if (sourceBitmap->LockBits(&rc, ImageLockModeRead, PixelFormat32bppARGB, &dataSource) == Ok) {
BYTE* pScan0Source = (BYTE*)dataSource.Scan0;
UINT strideSource;

if (dataSource.Stride > 0) {
strideSource = dataSource.Stride;
} else {
pScan0Source += height * dataSource.Stride;
strideSource = -dataSource.Stride;
}

BYTE* pRowSource = pScan0Source;
OctreeColorQuantizer quantizer(nMaxColors, 8, &dataSource);
destBitmap = std::make_unique<Bitmap>(width, height, PixelFormat8bppIndexed);

for (UINT y = 0; y < height; y++) {
BYTE* pPixelSource = pRowSource;

for (UINT x = 0; x < width; x++) {
BYTE b = *pPixelSource++;
BYTE g = *pPixelSource++;
BYTE r = *pPixelSource++;
BYTE a = *pPixelSource++;
Gdiplus::Color c(a, r, g, b);
if (c.GetA() != 255) {
c = c.GetA() < alphaThreshold ? Color() : BlendWithBackgroundSrgb(c, backgroundColor);
}

quantizer.addColor(c);
}

pRowSource += strideSource;
}

auto pallete = quantizer.generatePalette();
MyPalette mypal(pallete.get(), backgroundColor, alphaThreshold);

BitmapData dataDest;
destBitmap->SetPalette(pallete.get());
if (destBitmap->LockBits(&rc, ImageLockModeWrite, PixelFormat8bppIndexed, &dataDest) == Ok) {
BYTE* pRowSource = pScan0Source;

BYTE* pRowDest = (BYTE*)dataDest.Scan0;
UINT strideDest;

if (dataDest.Stride > 0) {
strideDest = dataDest.Stride;
} else {
pRowDest += height * dataDest.Stride;
strideDest = -dataDest.Stride;
}

for (UINT y = 0; y < height; y++) {
BYTE* pPixelSource = pRowSource;
BYTE* pPixelDest = pRowDest;

for (UINT x = 0; x < width; x++) {
BYTE b = *pPixelSource++;
BYTE g = *pPixelSource++;
BYTE r = *pPixelSource++;
BYTE a = *pPixelSource++;

BYTE index = (BYTE)mypal.getNearestColorIndex(Gdiplus::Color(a, r, g, b));

*pPixelDest++ = index;
}

pRowSource += strideSource;
pRowDest += strideDest;
}
destBitmap->UnlockBits(&dataDest);
}
sourceBitmap->UnlockBits(&dataSource);
}
return destBitmap;
}
11 changes: 11 additions & 0 deletions Source/Core/Images/ColorQuantizer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

#pragma once
#include <memory>

#include <windows.h>
#include "3rdpart/GdiplusH.h"

class ColorQuantizer {
public:
std::unique_ptr<Gdiplus::Bitmap> getQuantized(Gdiplus::Bitmap* pSource, Gdiplus::Color backgroundColor, UINT nMaxColors = 256);
};
Loading

0 comments on commit 1c65cdd

Please sign in to comment.