请问怎样把 byte[ ]转换为 Bitmap对象?

atlone 2003-10-21 12:04:54
以下是把bitmap b转换为byte[]然后传输出去的,现在我想把byte[] bytes转换回Bitmap对象,请问怎样实现? 谢谢.

MemoryStream ms = new MemoryStream();
b.Save(ms ,System.Drawing.Imaging.ImageFormat.Gif);
byte[] bytes= ms.GetBuffer();
...全文
1713 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
atlone 2003-10-21
  • 打赏
  • 举报
回复
xixigongzhu(夕夕公主),谢谢你,你的方法也可以,效果差不多:)
saucer 2003-10-21
  • 打赏
  • 举报
回复
do the reverse

byte[] bytelist;
MemoryStream ms = new MemoryStream(bytelist);
Bitmap bm = (Bitmap)Image.FromStream(ms);
xixigongzhu 2003-10-21
  • 打赏
  • 举报
回复
Bitmap b = new Bitmap("test.bmp");
MemoryStream ms = new MemoryStream();
b.Save(ms,System.Drawing.Imaging.ImageFormat.Bmp);
byte[] bytes= ms.ToArray();

b.Save("c:\\dd3.jpg");

byte[] bytelist=bytes;
MemoryStream ms1 = new MemoryStream(bytelist);
Bitmap bm = (Bitmap)Image.FromStream(ms1);

bm.Save("c:\\dd4.jpg");

1、因为如果不用Bmp的方式转换字节的话,在转换到字节的时候将会丢失数据;
2、MemoryStream的GetBuffer并不是得到这个流所存储的内容,而是返回这个流的基础字节数组,可能包括在扩充的时候一些没有使用到的字节。
atlone 2003-10-21
  • 打赏
  • 举报
回复
yes,you are right,temporary i found the code below can give me the smallest size for dd4.

MemoryStream ms = new MemoryStream();
ms.Position = 0;
b.Save(ms ,System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] bytes= ms.GetBuffer();

b.Save("c:\\dd3.bmp");

byte[] bytelist=bytes;
MemoryStream ms1 = new MemoryStream(bytelist);
ms1.Position = 0;
Bitmap bm = (Bitmap)Bitmap.FromStream(ms1);

bm.Save("c:\\dd4.bmp", System.Drawing.Imaging.ImageFormat.Jpeg);

wishing these is another better way,anyway,thank you very much.
saucer 2003-10-21
  • 打赏
  • 举报
回复
you missed the point, with

Bitmap b=new Bitmap(800,600);

the pixelformat is Format32bppARGB, when you call

b.Save("c:\\dd3.jpg");

it is saved as the ImageFormat.Bmp even if you specified ".jpg"

if you want to compare, you need to make them have same format
atlone 2003-10-21
  • 打赏
  • 举报
回复
我把Bitmap bm = (Bitmap)Image.FromStream(ms1);改成:

Bitmap bm = (Bitmap)Bitmap.FromStream(ms1);

那样有时候dd4.jpg就比dd3.jpg小了,真是奇怪啊.
atlone 2003-10-21
  • 打赏
  • 举报
回复
如果把b.Save("c:\\dd3.jpg");改成

b.Save("c:\\dd3.jpg",System.Drawing.Imaging.ImageFormat.Jpeg);

那样dd3.jpg就和dd4.jpg一样大了,但那是dd3.jpg的size变大,所以我还是选b.Save("c:\\dd3.jpg");

但是在dd4.jpg部分,如果改成是b.Save("c:\\dd4.jpg");dd4.jpg的size还是和没改一样的.
saucer 2003-10-21
  • 打赏
  • 举报
回复
look at your code, the first time you were doing

b.Save("c:\\dd3.jpg");

the second time, you were doing

bm.Save("c:\\dd4.jpg",System.Drawing.Imaging.ImageFormat.Jpeg);
atlone 2003-10-21
  • 打赏
  • 举报
回复
sorry,还是不行,调换了顺序后就出错,改成Bmp后,dd3.bmp的size相比于原来的jpeg format好象还少了,但dd4.bmp或dd4.jpg就不得了了,竟然是dd3.bmp的30倍.
saucer 2003-10-21
  • 打赏
  • 举报
回复
b.Save(ms ,System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] bytes= ms.GetBuffer();
b.Save("c:\\dd3.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);

or try to save it as System.Drawing.Imaging.ImageFormat.Bmp

atlone 2003-10-21
  • 打赏
  • 举报
回复
因为我是直接从屏幕截图,而且所截的图随着mouse移动而改变,dd3.jpg和dd4.jpg有时候只是相差几k,但有时候就相差一半,但经过你的修改后,基本没有相差一倍的出现了.
atlone 2003-10-21
  • 打赏
  • 举报
回复
我的也是vs.net2003 with 1.1 in win2003,你上面那例子是没问题,虽然变换前后的size还有些许不同. 但我的Bitmap b是直接从Graphic处来的,所以经过以下改变后,还是一样,不过好象变换后的size不是多一倍了,只是多1/2,真奇怪啊.

Bitmap b=new Bitmap(800,600);
Graphics graphics = Graphics.FromImage(b);

IntPtr hDCPanel = graphics.GetHdc();
IntPtr hDCDesktop = Win32.GetDC(hWndDesktop);

Win32.StretchBlt(hDCPanel, 0, 0, 800, 600,
hDCDesktop, 0, 0,800 / zoomRate, 600 / zoomRate,Win32.SRCCOPY);

graphics.ReleaseHdc(hDCPanel);
Win32.ReleaseDC(hWndDesktop, hDCDesktop);

MemoryStream ms = new MemoryStream();
ms.Position = 0;
b.Save(ms ,System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] bytes= ms.GetBuffer();

b.Save("c:\\dd3.jpg");

byte[] bytelist=bytes;
MemoryStream ms1 = new MemoryStream(bytelist);
ms1.Position = 0;
Bitmap bm = (Bitmap)Image.FromStream(ms1);

bm.Save("c:\\dd4.jpg",System.Drawing.Imaging.ImageFormat.Jpeg);

是不是因为Bitmap和Image的区别所造成的?
xixigongzhu 2003-10-21
  • 打赏
  • 举报
回复
斑竹,如果你用了MemoryStream,就不能说效果差不多。因为我用java重新开发了MemoryStream这个类,所以象这样的并且应该注意的问题基本上都很清楚,其中GetBuffer就是,有很多人认为用这个方法就是得到写入MemoryStream的字节,其实不是这样的。因为MemoryStream是用byte[]来存储数据,在写入数据的时候就有个扩充的过程,也就是说这个流的长度并不是它的byte[]字段的长度。而GetBuffer返回的就是byte[]这个字段。
下面是GetBuffer的部分实现方法,也许看了这个会更明白:
public byte[] GetBuffer() {
return this._buffer;
}
下面是ToArray的实现方法:
public byte[] ToArray() {
byte[] bs = new byte[this._length - this._origin];
for (int i = this._origin, j = 0; i < this._length; i++)
bs[j++] = this._buffer[i];
return bs;
}

我写这么多并不是想证明什么,只是觉得如果不说明白,斑竹总有一天会走入这个误区。:)
saucer 2003-10-21
  • 打赏
  • 举报
回复
I am using .NET 1.1 with vs.net 2003, what are you using?

string sFile = "test.jpg";
Image img = Image.FromFile(sFile);

MemoryStream ms = new MemoryStream();
img.Save(ms ,System.Drawing.Imaging.ImageFormat.Jpeg);
ms.Position = 0;
byte[] bytes= ms.GetBuffer();
//Console.WriteLine(bytes.Length);

byte[] bytelist=bytes;
MemoryStream ms1 = new MemoryStream(bytelist);
ms1.Position = 0;
Bitmap bm = (Bitmap)Image.FromStream(ms1);

bm.Save("test5.jpg",System.Drawing.Imaging.ImageFormat.Jpeg);
atlone 2003-10-21
  • 打赏
  • 举报
回复
我试过你上面的例子,test3.jpg 也是比test.jpg 增大了一倍有多:)
saucer 2003-10-21
  • 打赏
  • 举报
回复
I cannot reproduce your problems


string sFile = "test.jpg";
Image img = Image.FromFile(sFile);

MemoryStream ms = new MemoryStream();
img.Save(ms ,System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] bytes= ms.GetBuffer();
//Console.WriteLine(bytes.Length);

byte[] bytelist=bytes;
MemoryStream ms1 = new MemoryStream(bytelist);
Bitmap bm = (Bitmap)Image.FromStream(ms1);

bm.Save("test3.jpg");

test3.jpg and test.jpg are identical
atlone 2003-10-21
  • 打赏
  • 举报
回复
我把b.Save(ms ,System.Drawing.Imaging.ImageFormat.Gif)改成是

b.Save(ms ,System.Drawing.Imaging.ImageFormat.Jpeg),或者

把b.Save("c:\\dd3.jpg");bm.Save("c:\\dd4.jpg");里面的jpg改成Gif,结果还是一样:(
saucer 2003-10-21
  • 打赏
  • 举报
回复
b.Save(ms ,System.Drawing.Imaging.ImageFormat.Gif);???
atlone 2003-10-21
  • 打赏
  • 举报
回复
saucer(思归),谢谢你,你的方法是可以转换,但转换后,Bitmap的size 增大了一倍有多,例如以下:没转换前得到的dd3.jpg是60k, 但是dd4.jpg就变成了130k,而且图像质量也比dd3.jpg差,请问为什么?

MemoryStream ms = new MemoryStream();
b.Save(ms ,System.Drawing.Imaging.ImageFormat.Gif);
byte[] bytes= ms.GetBuffer();

b.Save("c:\\dd3.jpg");

byte[] bytelist=bytes;
MemoryStream ms1 = new MemoryStream(bytelist);
Bitmap bm = (Bitmap)Image.FromStream(ms1);

bm.Save("c:\\dd4.jpg");
class CSBitmap //Bitmap类,特点紧约型数据结构,GetPixel效率高,放弃调色板,自动支持4种色深,特有的12位颜色更接近人眼可识别颜色数目;有多种缩放,色深转换,拷贝,剪切,和hBitmap转换,显示等功能;支持串行化。支持1,12,24,32位位图,对应适用于所有函数,相比于HBitmap和CSBitmap对象要简单,可直接操作数据区;同时可用于1,4,8,12,16,24,32位二维数列的储存,部分基本函数(GetPixel,SetPixel)支持; { public: CSBitmap(void); ~CSBitmap(void); unsigned int Width; //Bitmap的宽 unsigned int Height; //Bitmap的高 DWORD BitSize; //Bitmap的数据区大小(字节) BYTE* pBitData; //Bitmap的数据区指针 unsigned int BitCount; //Bitmap的色深 bool SetAttribute(unsigned int mWidth=NULL, unsigned int mHeight=NULL, unsigned int mBitCount=NULL); //设置Bitmap的属性,Bitmap会被清除 mWidth Bitmap的宽度,为NULL则不改变 mHeight Bitmap的高度,为NULL则不改变 mBitCount Bitmap的色深,为NULL则不改变 bool ImportBits(BYTE* lpBits, int mBitSize=NULL); //拷贝Bits数据进对象数据区 lpBits 拷贝数据的指针 mBitSize 拷贝数据的字节数 COLORREF GetPixel(unsigned int x, unsigned int y); //获得某点的原始数值,当为12,24,32位数时,则为RGB值 X,y 需要获取点的坐标 bool SetPixel(unsigned int x, unsigned int y, COLORREF clr); //获得某点的原始数值,当为12,24,32位数时,则为RGB值 X,y 需要设置点的坐标 bool StretchDIB(CSBitmap* DestBmp, unsigned int mWidth, unsigned int mHeight, unsigned int mFlag=0); //缩放 DestBmp用于获取缩放后图片的指针 mWidth, mHeight缩放后大小 mFlag缩放算法 取值 算法 缩小 放大 0 逆向寻点算法 效率高,质量一般 效率高,质量中 1 双线性补点 效率低,质量一般 效率低,质量高 2 平均值算法 效率低,质量好 效率高,质量差 static BYTE GetRValue12(COLORREF Clr12Bit); static BYTE GetGValue12(COLORREF Clr12Bit); static BYTE GetBValue12(COLORREF Clr12Bit); //用于12位图的获取RGB分量,24位图,32位图的COLOR分离请用GDI的GetPixel() Clr12Bit 对12位图GetPixel获得的原始值 static COLORREF RGB12(BYTE R, BYTE G, BYTE B); //用于12位图的RGB合成,24位图,32位图的COLOR合成请用GDI的RGB() static COLORREF Color24To1(COLORREF Color24); //24位色深COLORREF转1位色深(黑白)值 static COLORREF Color24To12(COLORREF Color24); //24位色深COLORREF转12位色深值 static COLORREF Color1To24(COLORREF Color2); //1位色深COLORREF转24位,32位色深(黑白)值 static COLORREF Color12To24(COLORREF Color12); //12位色深COLORREF转24位,32位色深(黑白)值 bool ConvertTo1Bit(CSBitmap* DestBmp); //12,24,36位图片转换成1位色深图 DestBmp用于接收数据的DestBmp指针,转换过程中包括自动参数重置 bool ConvertTo12Bit(CSBitmap* DestBmp); //1,24,36位图片转换成12位色深图 DestBmp用于接收数据的DestBmp指针,转换过程中包括自动参数重置 bool ConvertTo24Bit(CSBitmap* DestBmp); //1,12,36位图片转换成24位色深图 DestBmp用于接收数据的DestBmp指针,转换过程中包括自动参数重置 bool FromHandle(HBITMAP hBitmap); //从HBITMAP中获得CSBitmap对象 bool CopyPaste(CSBitmap* DestBmp, unsigned int x, unsigned int y); //复制本CSBitmap至另一DestBmp的指定位置 DestBmp 目标,对象 X,y复制后图片左上角位置 bool PaintDIB(CDC* dcDest, int x,int y,unsigned int mWidth, unsigned int mHeight); //把本图片显示至CDC对象上,支持1,12,24,26位图 dcDest 目标dc(兼容DC) x,y 拷贝到dc上的位置 mWidth,mHeight拷贝后的大小 const CSBitmap& operator=(const CSBitmap &SBmp); }; //重载了 = 赋值操作符

110,536

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧