Quick how to: Reduce number of colors programmatically
My colleague just asked me about how to reduce a number of colors in image programmatically. This is very simple task and contains of 43
steps:

First of all, you have to read a source image
using (var img = Image.FromFile(name)) {
var bmpEncoder = ImageCodecInfo.GetImageDecoders().FirstOrDefault(e => e.FormatID == ImageFormat.Bmp.Guid);
Then create your own encoder with certain color depth (32 bits in this case)
var myEncoder = System.Drawing.Imaging.Encoder.ColorDepth;
var myEncoderParameter = new EncoderParameter(myEncoder, 32L);
var myEncoderParameters = new EncoderParameters(1) { Param = new EncoderParameter[] { myEncoderParameter } };
Then save it
img.Save(name.Replace(“.png”, “.bmp”), bmpEncoder, myEncoderParameters);
It it enough? Not really, because if you’re going to loose colors (by reducing color depth), it makes sense to avoid letting default WIX decoder to do this, thus you have to find nearest base colors manually. How to do this? By using simple math
Color GetNearestBaseColor(Color exactColor) {
Color nearestColor = Colors.Black;
int cnt = baseColors.Count;
for (int i = 0; i < cnt; i++) {
int rRed = baseColors[i].R – exactColor.R;
int rGreen = baseColors[i].G – exactColor.G;
int rBlue = baseColors[i].B – exactColor.B;int rDistance =
(rRed * rRed) +
(rGreen * rGreen) +
(rBlue * rBlue);
if (rDistance == 0.0) {
return baseColors[i];
} else if (rDistance < maxDistance) {
maxDistance = rDistance;
nearestColor = baseColors[i];
}
}
return nearestColor;
}
Now, you can either change colors on base image directly
unsafe {
uint* pBuffer = (uint*)hMap;
for (int iy = 0; iy < (int)ColorMapSource.PixelHeight; ++iy)
{
for (int ix = 0; ix < nWidth; ++ix)
{
Color nc = GetNearestBaseColor(pBuffer[0].FromOle());pBuffer[0] &= (uint)((uint)nc.A << 24) | //A
(uint)(nc.R << 16 ) | //R
(uint)(nc.G << 8 ) | //G
(uint)(nc.B ); //B
++pBuffer;
}
pBuffer += nOffset;
}
}
Or, if you’re in WPF and .NET 3.5 create simple pixel shader effect to do it for you in hardware. Now, my colleague can do it himself in about 5 minutes
. Have a nice day and be good people.
You may also be interested with:
- Real singleton approach in WPF application
- INotifyPropertyChanged auto wiring or how to get rid of redundant code
February 9th, 2009 · Comments (2)
2 Responses to “Quick how to: Reduce number of colors programmatically”
Leave a Reply
Discover other tags
My tools
- .NET Framework Detector
- Duplicate images finder
- Exchange Security Policy for Windows Mobile Devices Fix
- Gas Price Windows Vista SideBar gadget
- Israel Traffic Information Windows Vista SideBar gadget
- Localization fix for SAP ES Explorer for Visual Studio
- LocTester
- RTL and LTR in Windows Live Writer
- Silverlight controls library
- Snipping tool integration plugin for WLW
- USB FM receiver library
- Vista Battery Saver
- WebCam control for WPF
- Windows Live SkyDrive attachment for Windows Live Writer
- Wireless Migrator
- WPF Virtual Keyboard




February 9th, 2009 at 11:35 am
Not so easy:
1. Using encoders/decoders won’t help because they ignore ColorDepth parameter (only GIF/TIFF use it and only 4bit/24bit values)
2. For the manual version – you first need to create baseColors palette – your target X-bit palette somehow.
April 15th, 2009 at 4:16 am
Hey, nice tips. Perhaps I’ll buy a bottle of beer to the person from that chat who told me to go to your blog