java生成bmp单色位图,关于GDI+生成单色BMP图片的问题,请高手进!

用GDI+生成的BMP图片颜色位数一般都是24位,我要怎样生成1位的BMP图片呢?

我在网上找了几种方法,有的方法效果是达到了,但是效率非常低,我是要生成几万张甚至几十万张的,所以要求速度要够快。

不知道大家是否有这方面的经验请多多指教,非常感谢大家!

我现在知道实现的思路有两种,但是两种都有问题。

思路1及问题:

新建BMP对象的时候直接就定义它是1位的,Bitmap b = new System.Drawing.Bitmap(30, 30, PixelFormat.Format1bppIndexed); 但是这样定义后,图片是使用索引颜色,所以不能在它的基础上创建Graphics画图。

思路2及问题:先生成普通24位色的BMP图片,然后将它转换成1位色的BMP,我在网上找了这么一段代码来转换,但是转换的效率很低。

Image img = Image.FromFile("r.bmp");

ImageAttributes ta = new ImageAttributes();

/* 下面用Graphics类改变像点颜色,是靠ImageAttributes来把

* 彩色变成灰度,或者颠倒黑白,发现用矩阵处理还是很方便的

*/

//如实际发现几个简单又好用的矩阵:

float[][] mm = new float[][]{ //彩色变灰度的矩阵

new float[]{0.4f, 0.4f, 0.4f, 0, 0},

new float[]{0.3f, 0.3f, 0.3f, 0, 0},

new float[]{0.3f, 0.3f, 0.3f, 0, 0},

new float[]{0, 0, 0, 1, 0},

new float[]{0, 0, 0, 0, 1}

};

/*

float[][] mm1=new float[][]{ //彩色反相的矩阵

new float[]{0, 0.3f, 0.5f, 0, 0},

new float[]{0.5f, 0.3f, 0.5f, 0, 0},

new float[]{0.5f, 0.4f, 0, 0, 0},

new float[]{0, 0, 0, 1, 0},

new float[]{0, 0, 0, 0, 1}

};

float[][] mm2=new float[][]{ //彩色变反相灰度的矩阵

new float[]{-0.4f, -0.4f, -0.4f, 0, 0},

new float[]{-0.3f, -0.3f, -0.3f, 0, 0},

new float[]{-0.3f, -0.3f, -0.3f, 0, 0},

new float[]{1, 1, 1, 1, 0},

new float[]{0, 0, 0, 0, 1}

};

*/

ColorMatrix cmt = new ColorMatrix(mm);

ta.SetColorMatrix(cmt);

/* //如果确知图像里仅有纯黑白二色,也可用ColorMap来反相,它可逐色改变

ColorMap map1=new ColorMap();

map1.OldColor=Color.Black;

map1.NewColor=Color.White;

ColorMap map2=new ColorMap();

map2.OldColor=Color.White;

map2.NewColor=Color.Black;

ta.SetRemapTable(new ColorMap[]{map1,map2},ColorAdjustType.Bitmap);

*/

/* 有的图像比如索引格式的位图或GIF是无法创建Graphics的,

* 需要新建一非索引色位图取得Graphics对象以便做画或改变像点颜色。

*/

Bitmap bmp = new Bitmap(img.Width, img.Height);

Graphics g = Graphics.FromImage(bmp);

g.DrawImage(img, new Rectangle(0, 0, bmp.Width, bmp.Height), 0, 0, img.Width, img.Height, GraphicsUnit.Pixel, ta);

//g.DrawString("Foxit PDF Reader",new Font("宋体",8),new SolidBrush(Color.White),0,0);

g.Dispose();

/* 在如下构造图像数据之前,也可以先创建一单色位图并锁定数据,

* 利用它现成的Stride简单计算出实际每行有效数据之后的填充字节数,而且可

* 在下面循环里直接写点Marshal.WriteByte(dt.Scan0,k,val);而不用数组拷贝

*/

//以下,把反相或者涂画后的像点数据每一行的每8点简单合并成1byte存储

int midrgb = Color.FromArgb(128, 128, 128).ToArgb();

int stride;//简单公式((width/8)+3)&(~3)

stride = (bmp.Width % 8) == 0 ? (bmp.Width / 8) : (bmp.Width / 8) + 1;

stride = (stride % 4) == 0 ? stride : ((stride / 4) + 1) * 4;

int k = bmp.Height * stride;

byte[] buf = new byte[k];

for (int j = 0; j 

{

k = j * stride;//因图像宽度不同、有的可能有填充字节需要跳越

int x = 0, ab = 0;

for (int i = 0; i 

{

//从灰度变单色(下法如果直接从彩色变单色效果不太好,不过反相也可以在这里控制)

if ((bmp.GetPixel(i, j)).ToArgb() > midrgb) ab = ab * 2 + 1; else ab = ab * 2;

x++;

if (x == 8)

{

buf[k++] = (byte)ab;

ab = 0;

x = 0;

}

}

if (x > 0)

{

//循环实现:剩余有效数据不满1字节的情况下须把它们移往字节的高位部分

for (int t = x; t 

buf[k++] = (byte)ab;

}

}

Bitmap bb = new Bitmap(img.Width, img.Height, PixelFormat.Format1bppIndexed);

BitmapData dt = bb.LockBits(new Rectangle(0, 0, bb.Width, bb.Height), ImageLockMode.ReadWrite, bb.PixelFormat);

Marshal.Copy(buf, 0, dt.Scan0, buf.Length);

bb.UnlockBits(dt);

bb.Save("w.bmp", ImageFormat.Bmp);

bb.Dispose();

bmp.Dispose();

img.Dispose();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值