winform’s image通过MemoryStream保存进sql server的image字段后,再通过取出通过MemoryStream转化为Image,Image.Save()时报“GDI+发生一般性错误”,苦思良久,发现,在MemoryStream转化为Image时把Image存放到ImageList的Images中,然后再保存时不会出错,但imagelist最大只是255*255,后百度,google了N久,终于,在miscosoft找到了官方的解决办法:Bitmap对象或一个图像对象从一个文件构造时,该文件仍保留锁定于对象的生存期,因此,无法更改图像并将其保存会它。
替代方法:创建非索引映像和创建索引映像
创建非索引映像:
即使原始映像被索引格式中该方法要求新图像位于每像素, 此变通方法使用 Graphics.DrawImage() 方法来将映像复制到新 位图 对象:
1. 构造从流、 从内存, 或从文件原始 位图 。
2. 创建新 位图 的相同大小, 带有是超过 8 位 - - 像素 (BPP) 每像素格式。
3. 使用 Graphics.FromImage() 方法以获取有关二 位图 Graphics 对象。
4. 用于 Graphics.DrawImage() 绘制首 位图 到二 位图 。
5. 用于 Graphics.Dispose() 处置是 图形 。
6. 用于 Bitmap.Dispose() 是首 位图 处置。
创建索引映像
此解决办法在索引格式创建一个 Bitmap 对象:
1. 构造从流、 从内存, 或从文件原始 位图 。
2. 创建新 位图 具有相同的大小和像素格式作为首 位图 。
3. 使用 Bitmap.LockBits() 方法来锁定整个图像对于两 Bitmap 对象以其本机像素格式。
4. 使用 Marshal.Copy 函数或其他内存复制函数来从首 位图 复制到二 位图 图像位。
5. 使用 Bitmap.UnlockBits() 方法可以解锁两 Bitmap 对象。
6. 用于 Bitmap.Dispose() 是首 位图 处置。
以上都是理论上的,我也似懂非懂,具体解决例子如下:
private byte[] ImageConventToBytes(Image img)//image to byte[]
{
System.IO.MemoryStream ms = new System.IO.MemoryStream();
Bitmap bmp = new Bitmap(img);//克隆Bitmap对象
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] bytes = new byte[ms.Length];
ms.Seek(0, SeekOrigin.Begin);
ms.Read(bytes, 0, Convert.ToInt32(ms.Length));
ms.Close();
bmp.Dispose();
return bytes;
}
//private Image BytesConventToImage(byte[] bytes)//byte[] to image
//{
// if (bytes.Length==0)
// {
// return null;
// }
// MemoryStream ms = new MemoryStream(bytes,0,bytes.Length);
// Bitmap oBitmap = new Bitmap(ms);
// ms.Close();
// return oBitmap;
//}
private void cSave_Click(object sender, EventArgs e)//image save to jpg file
{
SaveFileDialog sfd = new SaveFileDialog();
sfd.Title = "保存图片";
sfd.Filter = "(*.jpg) |*.jpg";
sfd.ShowDialog();
if (sfd.FileName.ToString() != "")
{
Bitmap bmp = new Bitmap(ximage);
bmp.Save(sfd.FileName);
bmp.Dispose();
}
}
至于为啥ImageList可以正确保存,是因为ImageList给重新生一个固定大小的Image对象,和克隆道理相同
二、 wpf 使用winform中的image
首先wpf的控件的backGround是Bursh类型的,我们可以付给他一个ImageBursh对象ImageBursh有一个ImageSource属性;
ImageSource——————System.Window.Media
|___BitmapSource
|___BitmapImage
|___BitmapFrame中有一个Create(System.IO.Stream stream)方法
到这里,都应该知道怎么转换了:
public BitmapFrame ConvertImage(System.Drawing.Image image)
{
try
{
using (MemoryStream drawingStream = new MemoryStream())
{
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(image);
bmp.Save(drawingStream, System.Drawing.Imaging.ImageFormat.Jpeg);
drawingStream.Seek(0, SeekOrigin.Begin);
BitmapDecoder encoder = new JpegBitmapDecoder(drawingStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);//解码
bmp.Dispose();
//return System.Windows.Media.Imaging.BitmapFrame.Create(drawingStream);//具体原因未知,这样转换的图片,wpf中无法显示,至今还不知原因,有知道的朋友,望告知,万分感谢!
return encoder.Frames[0];
}
}
catch (System.Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message);
return null;
}
}