Groups | Blog | Home
all groups > dotnet drawing api > august 2003 >

dotnet drawing api : 1bpp color reduction


Franco Gustavo
8/11/2003 3:26:45 PM
Hi,

How can I convert a 24bits Bitmap to a 1bpp indexed Bitmap??
Basically, from color to Black and White

Does GDI++ have some class support to do that?

if GDI++ doesn't support it, somebody has some algorithm to do this?

Basically my problem is that I have a color image and I need store it on a
..tiff file with CompressionCCITT3 (G3 or fax) compression.

Thanks.

P.S: I know how to manipulate 1bpp images, so if somebody doesn't have the
full source code, but at least has the alghoritm to do it, I think I can
implement it.

Thanks again.

Franco Gustavo
8/11/2003 5:59:15 PM
I was looking before that URL, but I'm looking for a good color reduction
algorithm.
Right now I'm implementing Floyd-Steinberg Algorithm I think it is a good
aproach for what I'm looking for.

When I finish I'll reply to my self with the source code.

Thanks for the answer,
Gustavo.

[quoted text, click to view]

Bob Powell [MVP]
8/12/2003 1:22:24 AM
There is an article in the GDI+ FAQ that deals with the conversion of RGB to
1bpp..

--
Bob Powell [MVP]
C#, System.Drawing

ANNOUNCING: Well Formed.
The monthy electronic magazine for
Windows Forms and GDI+ engineers
http://www.bobpowell.net/wellformed.htm

Check out the GDI+ FAQ
http://www.bobpowell.net/gdiplus_faq.htm


[quoted text, click to view]

Franco Gustavo
8/13/2003 12:18:32 PM
I couldn't find any source code for this then I implemented the
Floyd-Stenberg Algoritmh.

Just in case somebody else need it here it is.
It is for 32bpp colors as Input whith a small change can work for different
formats

public unsafe static Bitmap MakeBitmapBW(Bitmap source)
{
DateTime t1 = DateTime.Now;
Console.WriteLine("In: Ticks[" + t1.Ticks + "]");
int[,] matrix = new int[source.Width + 2, source.Height + 2];
BitmapData bitmapDataSource = source.LockBits(new Rectangle(0,0,
source.Width, source.Height), ImageLockMode.ReadOnly, source.PixelFormat);

uint* pixelSource = (uint*)bitmapDataSource.Scan0.ToPointer();
uint* pixelSourceF = pixelSource;
byte* pixelSourceB = (byte*) pixelSourceF;

//First we Convert to Gray Scale and get the right luminance for each
pixel;
for (int x = 1; x <= source.Width; x++)
{
for (int y = 1; y <= source.Height; y++)
{
pixelSourceB = (byte*) ((pixelSource + (x - 1)) +
(source.Width * (y - 1)));
matrix[x,y] = (*(pixelSourceB + 2) * 299 + *(pixelSourceB
+ 1) * 587 + *(pixelSourceB + 0) * 114);
}
}

source.UnlockBits(bitmapDataSource);

Bitmap target;
target = new Bitmap(source.Width, source.Height,
PixelFormat.Format1bppIndexed);

BitmapData bitmapDataTarget = target.LockBits(new Rectangle(0,0,
source.Width, source.Height), ImageLockMode.WriteOnly,
PixelFormat.Format1bppIndexed);
byte* pixelTarget = (byte*)bitmapDataTarget.Scan0.ToPointer();
byte* pTF = pixelTarget;

//Now We change the matrix and Transform to B/W
int e;
int finalPoint;
int a = 437;
int b = 187;
int c = 312;
int d = 62;
for (int x = 1; x <= source.Width; x++)
{
for (int y = 1; y <= source.Height; y++)
{

if (matrix[x,y] > 127000)
finalPoint = 255000;
else
finalPoint = 0;

e = (matrix[x,y] - finalPoint) >> 10;

matrix[x,y] = finalPoint;
matrix[x,y+1] += (a * e);
matrix[x+1,y-1] += (b * e);
matrix[x+1,y] += (c * e);
matrix[x+1,y+1] += (d * e);

pTF = (pixelTarget + ((x - 1) >> 3)) +
(bitmapDataTarget.Stride * (y - 1));
byte mask=(byte)(0x80>>((x - 1)&0x7));
if(matrix[x,y] == 255000)
(*pTF)|=mask;
else
(*pTF)&=(byte)(mask^0xff);
}
}

target.UnlockBits(bitmapDataTarget);

ColorPalette pal = target.Palette;
pal.Entries[0] = Color.FromArgb(255,0,0,0);
pal.Entries[1] = Color.FromArgb(255,255,255,255);
target.Palette = pal;

DateTime t2 = DateTime.Now;
Console.WriteLine("Out: " + (t2.Ticks - t1.Ticks));

return target;
}

[quoted text, click to view]

AddThis Social Bookmark Button