Sign in
Home
Library
Wiki
Learn
Gallery
Downloads
Support
Forums
Blogs
Resources For IT Professionals
United States (English)
Россия (Pусский)
中国(简体中文)
Brasil (Português)
Skip to locale bar
Page Details
First published by
João Eduardo Sousa
(MVP, Microsoft Partner, Microsoft Community Contributor)
When:
16 Dec 2012 4:10 PM
Last revision by
Naomi N
When:
9 Oct 2013 6:54 PM
Revisions:
2
Comments:
0
Options
Original
Wiki
>
TechNet Articles
>
Change Image Format
>
Original
Change Image Format
You are currently reviewing an older revision of this page.
Go to current version
public static void ChangeImageToBlackAndWhite(string fileName)
{
Bitmap bitmap = new Bitmap(fileName);
string FileExtension = fileName.Substring(fileName.LastIndexOf("."));
string tempfileName = Guid.NewGuid().ToString() + FileExtension;
try
{
Image img = Image.FromFile(fileName);
short resolution = (short)img.HorizontalResolution;
PixelFormat convertToPixelFormat = img.PixelFormat;
img.Dispose();
if (IsColor(bitmap)) //colour image can be transform in gray or black/white
{
if (convertToPixelFormat == PixelFormat.Format1bppIndexed)
ConvertToBpp(fileName, 1, bitmap, tempfileName, resolution);
else if (convertToPixelFormat == PixelFormat.Format8bppIndexed)
ConvertToBpp(fileName, 1, bitmap, tempfileName, resolution);
else
ConvertToBpp(fileName, 1, bitmap, tempfileName, resolution);
}
else //gray image can be transform in black/white
{
if (convertToPixelFormat == PixelFormat.Format1bppIndexed)
ConvertToBpp(fileName, 1, bitmap, tempfileName, resolution);
else
ConvertToBpp(fileName, 1, bitmap, tempfileName, resolution);
}
}
catch (Exception ex)
{
bitmap.Dispose();
throw ex;
}
finally
{
bitmap.Dispose();
}
}
private static System.Drawing.Imaging.ImageCodecInfo GetCodecType()
{
System.Drawing.Imaging.ImageCodecInfo[] codecs = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders();
foreach (System.Drawing.Imaging.ImageCodecInfo cod in codecs)
{
if (cod.MimeType == "image/tiff")
return cod;
}
return null;
}
private static void ConvertToBpp(string fileName, int bpp, Bitmap newBitmap, string tempfileName, int resolution)
{
Bitmap convertedBitmap = null;
if (bpp == 1 || bpp == 8)
{
convertedBitmap = ConvertToBpp(newBitmap, bpp, resolution);
newBitmap.Dispose();
}
else
{
newBitmap.SetResolution(resolution, resolution);
convertedBitmap = newBitmap;
}
long NewColorDepth = 1;
System.Drawing.Imaging.EncoderParameters encoder = new System.Drawing.Imaging.EncoderParameters(2);
encoder.Param[0] = new System.Drawing.Imaging.EncoderParameter(new System.Drawing.Imaging.Encoder(System.Drawing.Imaging.Encoder.ColorDepth.Guid), NewColorDepth);
encoder.Param[1] = new System.Drawing.Imaging.EncoderParameter(new System.Drawing.Imaging.Encoder(System.Drawing.Imaging.Encoder.Compression.Guid),
(long)System.Drawing.Imaging.EncoderValue.CompressionCCITT4);
convertedBitmap.Save(tempfileName, GetCodecType(), encoder);
if ((File.GetAttributes(fileName) & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
File.SetAttributes(fileName, FileAttributes.Normal); convertedBitmap.Dispose();
File.Delete(fileName);
File.Move(tempfileName, fileName);
}
public static Bitmap ConvertToBpp(Bitmap b, int bpp, int resolution)
{
if (bpp != 1 && bpp != 8) throw new ArgumentException("1 or 8", "bpp");
int w = b.Width, h = b.Height;
IntPtr hbm = b.GetHbitmap();
BITMAPINFO bmi = new BITMAPINFO();
bmi.biSize = 40; // the size of the BITMAPHEADERINFO struct
bmi.biWidth = w;
bmi.biHeight = h;
bmi.biPlanes = 1; // "planes" are confusing. We always use just 1. Read MSDN for more info.
bmi.biBitCount = (short)bpp; // ie. 1bpp or 8bpp
bmi.biCompression = BI_RGB; // ie. the pixels in our RGBQUAD table are stored as RGBs, not palette indexes
bmi.biSizeImage = (uint)(((w + 7) & 0xFFFFFFF8) * h / 8);
bmi.biXPelsPerMeter = 1000000; // not really important
bmi.biYPelsPerMeter = 1000000; // not really important
uint ncols = (uint)1 << bpp; // 2 colours for 1bpp; 256 colours for 8bpp
bmi.biClrUsed = ncols;
bmi.biClrImportant = ncols;
bmi.cols = new uint[256]; // The structure always has fixed size 256, even if we end up using fewer colours
if (bpp == 1) { bmi.cols[0] = MAKERGB(0, 0, 0); bmi.cols[1] = MAKERGB(255, 255, 255); }
else { for (int i = 0; i < ncols; i++) bmi.cols[i] = MAKERGB(i, i, i); }
IntPtr bits0; // not used for our purposes. It returns a pointer to the raw bits that make up the bitmap.
IntPtr hbm0 = CreateDIBSection(IntPtr.Zero, ref bmi, DIB_RGB_COLORS, out bits0, IntPtr.Zero, 0);
IntPtr sdc = GetDC(IntPtr.Zero); // First we obtain the DC for the screen
IntPtr hdc = CreateCompatibleDC(sdc); SelectObject(hdc, hbm);
IntPtr hdc0 = CreateCompatibleDC(sdc); SelectObject(hdc0, hbm0);
BitBlt(hdc0, 0, 0, w, h, hdc, 0, 0, SRCCOPY);
Bitmap b0 = Bitmap.FromHbitmap(hbm0);
b0.SetResolution(resolution, resolution);
DeleteDC(hdc);
DeleteDC(hdc0);
ReleaseDC(IntPtr.Zero, sdc);
DeleteObject(hbm);
DeleteObject(hbm0);
return b0;
}
[DllImport("gdi32.dll")]
private static extern bool DeleteObject(IntPtr hObject);
[DllImport("user32.dll")]
private static extern int InvalidateRect(IntPtr hwnd, IntPtr rect, int bErase);
[DllImport("user32.dll")]
private static extern IntPtr GetDC(IntPtr hwnd);
[DllImport("gdi32.dll")]
private static extern IntPtr CreateCompatibleDC(IntPtr hdc);
[DllImport("user32.dll")]
private static extern int ReleaseDC(IntPtr hwnd, IntPtr hdc);
[DllImport("gdi32.dll")]
private static extern int DeleteDC(IntPtr hdc);
[DllImport("gdi32.dll")]
private static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);
[DllImport("gdi32.dll")]
private static extern int BitBlt(IntPtr hdcDst, int xDst, int yDst, int w, int h, IntPtr hdcSrc, int xSrc, int ySrc, int rop);
static int SRCCOPY = 0x00CC0020;
[DllImport("gdi32.dll")]
private static extern IntPtr CreateDIBSection(IntPtr hdc, ref BITMAPINFO bmi, uint Usage, out IntPtr bits, IntPtr hSection, uint dwOffset);
private static uint BI_RGB = 0;
private static uint DIB_RGB_COLORS = 0;
[StructLayout(LayoutKind.Sequential)]
private struct BITMAPINFO
{
public uint biSize;
public int biWidth, biHeight;
public short biPlanes, biBitCount;
public uint biCompression, biSizeImage;
public int biXPelsPerMeter, biYPelsPerMeter;
public uint biClrUsed, biClrImportant;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
public uint[] cols;
}
private static uint MAKERGB(int r, int g, int b)
{
return ((uint)(b & 255)) | ((uint)((r & 255) << 8)) | ((uint)((g & 255) << 16));
}
#endregion
#region Properties
BitmapData bitmapData = null;
Byte* pBase = null;
public bool IsWhitePixel(int X, int Y)
{
try
{
return PixelAt(X, Y);
}
catch (AccessViolationException ave)
{
throw (ave);
}
catch (Exception ex)
{
throw ex;
}
}
private bool PixelAt(int x, int y)
{
pBase = (Byte*)bitmapData.Scan0.ToPointer();
int index = y * bitmapData.Stride + (x >> 3);
byte mask = (byte)(0x80 >> (x & 0x7));
int n = pBase[index] & mask;
//branco ou preto
return (n > 0);
}