感谢原作者提供该代码,因为我的图形只有黑白两色,所以对代码进行了简单的修改,即注释部分为原代码。
class BmpAdjuster
{
public delegate ColorPalette PaletteAdjustEvent(ColorPalette plt);
public unsafe delegate void ConvertScanLineEvent(IntPtr srcLine, IntPtr dstLine, int width, int srcPixBit, int dstPixBit, Bitmap srcBmp, Bitmap dstBmp);
public static void AdjustColor(ref Bitmap bmp, PixelFormat format, PaletteAdjustEvent PalleteAdjust, ConvertScanLineEvent ConvertScanLine)
{
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
Bitmap bmpOut = new Bitmap(bmp.Width, bmp.Height, format);
Graphics g=Graphics.FromImage(bmp);
bmpOut.SetResolution(g.DpiX, g.DpiY);
g.Dispose();
bmpOut.Palette = PalleteAdjust(bmpOut.Palette);
PixelFormat srcFmt = bmp.PixelFormat;
PixelFormat dstFmt = bmpOut.PixelFormat;
int srcPixBit = GetPixelSize(srcFmt);
int dstPixBit = GetPixelSize(dstFmt);
BitmapData srcData = null;
BitmapData dstData = null;
try
{
srcData = bmp.LockBits(rect, ImageLockMode.ReadOnly, srcFmt);
dstData = bmpOut.LockBits(rect, ImageLockMode.WriteOnly, dstFmt);
unsafe
{
byte* srcLine = (byte*)srcData.Scan0.ToPointer();
byte* dstLine = (byte*)dstData.Scan0.ToPointer();
for (int L = 0; L < srcData.Height; L++)
{
ConvertScanLine((IntPtr)srcLine, (IntPtr)dstLine, srcData.Width, srcPixBit, dstPixBit, bmp, bmpOut);
srcLine += srcData.Stride;
dstLine += dstData.Stride;
}
}
}
finally
{
bmp.UnlockBits(srcData);
bmpOut.UnlockBits(dstData);
}
bmp = bmpOut;
}
internal static int GetPixelSize(PixelFormat format)
{
switch (format)
{
case PixelFormat.Format16bppRgb555: return 16;
case PixelFormat.Format16bppRgb565: return 16;
case PixelFormat.Format24bppRgb: return 24;
case PixelFormat.Format32bppRgb: return 32;
case PixelFormat.Format1bppIndexed: return 1;
case PixelFormat.Format4bppIndexed: return 4;
case PixelFormat.Format8bppIndexed: return 8;
case PixelFormat.Format16bppArgb1555: return 16;
case PixelFormat.Format32bppPArgb: return 32;
case PixelFormat.Format16bppGrayScale: return 16;
case PixelFormat.Format48bppRgb: return 48;
case PixelFormat.Format64bppPArgb: return 64;
case PixelFormat.Canonical: return 32;
case PixelFormat.Format32bppArgb: return 32;
case PixelFormat.Format64bppArgb: return 64;
}
return 0;
}
public unsafe static void Monochrome(ref Bitmap bmp)
{
AdjustColor(ref bmp, PixelFormat.Format1bppIndexed,
new PaletteAdjustEvent(SetBlackWhitePallete),
new ConvertScanLineEvent(ConvertBlackWhiteScanLine));
}
static ColorPalette SetBlackWhitePallete(ColorPalette plt)
{
plt.Entries[0] = Color.Black;
plt.Entries[1] = Color.White;
return plt;
}
unsafe static void ConvertBlackWhiteScanLine(IntPtr srcLine, IntPtr dstLine, int width, int srcPixBit, int dstPixBit, Bitmap srcBmp, Bitmap dstBmp)
{
byte* src = (byte*)srcLine.ToPointer();
byte* dst = (byte*)dstLine.ToPointer();
int srcPixByte = srcPixBit / 8;
int x, t = 0;
//int v = 0;
//int middle=200 * 256;
for (x = 0; x < width; x++)
{
t = (t << 1) | (src[0] == 0 ? 0 : 1);
//v = 28 * src[0] + 151 * src[1] + 77 * src[2];
//t = (t << 1) | (v > middle ? 1 : 0);
src += srcPixByte;
if (x % 8 == 7)
{
*dst = (byte)t;
dst++;
t = 0;
}
}
if ((x %= 8) != 7)
{
t <<= 8 - x;
*dst = (byte)t;
}
}
public static void Gray(ref Bitmap bmp)
{
AdjustColor(ref bmp, PixelFormat.Format8bppIndexed,
new PaletteAdjustEvent(SetGrayPallete),
new ConvertScanLineEvent(ConvertGaryScanLine));
}
static ColorPalette SetGrayPallete(ColorPalette plt)
{
for (int i = plt.Entries.Length - 1; i >= 0; i--)
plt.Entries[i] = Color.FromArgb(i, i, i);
return plt;
}
unsafe static void ConvertGaryScanLine(IntPtr srcLine, IntPtr dstLine, int width, int srcPixBit, int dstPixBit, Bitmap srcBmp, Bitmap dstBmp)
{
byte* src = (byte*)srcLine.ToPointer();
byte* dst = (byte*)dstLine.ToPointer();
int srcPixByte = srcPixBit / 8;
for (int x = 0; x < width; x++)
{
*dst = (byte)((28 * src[0] + 151 * src[1] + 77 * src[2]) >> 8);
src += srcPixByte;
dst++;
}
}
}