C#如何实现图片文件与数据流的转换

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#如何实现图片文件与数据流的转换相关的知识,希望对你有一定的参考价值。

//----引入必要的命名空间using System.IO;using System.Drawing.Imaging;//----代码部分----//powered by 25175.net private byte[] photo;//公用缓冲区public string SourFilePath;//源图片文件路径public string ObjFilePath;//目标图片路径public int FileToStream()//文件到流的转换Image img = new Bitmap(SourFilePath);MemoryStream stream = new MemoryStream();img.Save(stream, ImageFormat.Bmp);BinaryReader br = new BinaryReader(stream);photo = stream.ToArray();stream.Close();return 0;public Image ShowPic()//根据流显图byte[] bytes = photo;MemoryStream ms = new MemoryStream(bytes);ms.Position = 0;Image img = Image.FromStream(ms);ms.Close();return img;public int StreamToFile()//反向转换byte[] bytes = photo;FileStream fs = new FileStream(ObjFilePath, FileMode.Create, FileAccess.Write);fs.Write(bytes, 0, bytes.Length); 参考技术A C#如何实现图片文件与数据流的转换 需要使用文件流进行处理
以下是参考的代码:
//处理图像
string fileNmae=string.Empty;
OpenFileDialog openFileDialog1 = new OpenFileDialog();
if (openFileDialog1.ShowDialog() == DialogResult.OK)

fileNmae = openFileDialog1.FileName;

else

fileNmae = @"d:\对联1.jpg";


FileStream fs = new FileStream(fileNmae, FileMode.Open, FileAccess.Read);
Byte[] bytPic = new Byte[fs.Length];
fs.Read(bytPic, 0, bytPic.Length);
fs.Close();

数据流可以存储到数据库中,参考代码:
command.Parameters["@pic"].Value = bytPic;
connection.Open();
command.ExecuteNonQuery();

VC++使用GDI+实现HBITMAP与图片文件之间的相互转换(附源码)

       有时我们需要把图片文件加载到内存中的HBITMAP中,有时我们需要把内存中的HBITMAP位图保存成图片文件。如果仅使用GDI函数去处理,是比较难实现的,借助GDI+对象我们可以轻易的实现。本文我们就来讲述一下如何实现HBITMAP与图片文件之间的相互转换。

1、将图片文件加载到HBITMAP对象中

       先将指定路径的图片文件加载到CImage对象中,然后再将CImage对象中的图片数据绘制到HBITMAP中。其中CImage类是Visual Studio中自带的MFC类,是专门用来处理图片文件的,CImage类内部其实就是使用GDI+来实现的,所以我们当前的这种方法,本质是使用GDI+实现的。相关代码如下:

HBITMAP GetHBitmapFromFile( CString strFilePath )

	if ( !PathFileExists( strFilePath ) )
			
		return NULL;
	

	// 先将图片加载到CImage对象中
	CImage img;
	HRESULT hResult = img.Load( strFilePath );
	if ( hResult != S_OK )
	
		return NULL;
	

	// 然后将CImage对象中的图片绘制到新创建的HBITMAP对象上
	HDC hDC = GetDC( NULL ); // 获取屏幕DC
	HDC hDstDC = CreateCompatibleDC( hDC );
	HBITMAP hDstBitmap = ::CreateCompatibleBitmap( hDC, img.GetWidth(), img.GetHeight() );
	::SelectObject( hDstDC, hDstBitmap );
	img.Draw( hDstDC, 0, 0 );	

	::DeleteDC( hDstDC );
	::ReleaseDC( NULL, hDC );

    return hDstBitmap;

       有人可能会说,我当前进行的是Win32窗口编程,不使用MFC框架,使用MFC库还需要将MFC库带上,也会增大程序安装包的大小。其实Visua Studio中可以直接go到CImage类的cpp实现代码中我们完全可以将CImage类从MFC库中剥离出来的,即直接将CImage类的.h头文件和.cpp源文件拷贝出来,然后将文件中依赖MFC的接口换掉就可以了,操作起来很简单,我们就这样处理过。

2、将HBITMAP中的图片保存成多种类型的图片文件

       我们需要使用到GDI+中的Bitmap对象,先调用Bitmap::FromHBITMAP接口将HBITMAP中的图片数据加载到Bitmap对象中,然后再调用Bitmap::Save接口将Bitmap对象中的图片数据保存成图片文件。相关代码如下所示:(代码中根据要保存成的文件路径中的后缀名,确定要保存成什么类型的图片)

// 获取jpeg等编码Clsid
// 这是一个中间函数,下面的主函数SaveHBitmapToFile会调用到该函数
int GetEncoderClsid( const WCHAR* format, CLSID* pClsid )   
  
	UINT num = 0;                    // number of image encoders  
	UINT size = 0;                   // size of the image encoder array in bytes  
	ImageCodecInfo* pImageCodecInfo = NULL;  

	GetImageEncodersSize( &num, &size );  
	if( size == 0 ) 
	
		return -1;     
	

	pImageCodecInfo = (ImageCodecInfo*)(malloc(size));  
	if( pImageCodecInfo == NULL )  
	
		return -1;     
	

	GetImageEncoders( num, size, pImageCodecInfo );  

	for( UINT j = 0; j < num; ++j )  
	  
		if( wcscmp( pImageCodecInfo[j].MimeType, format ) == 0 )  
		  
			*pClsid = pImageCodecInfo[j].Clsid;  
			free(pImageCodecInfo);  
			return j;     
		          
	  

	free( pImageCodecInfo );  

	return -1;     




// 使用gdi+将HBITMAP位图句柄图片资源保存成图片文件,图片文件的类型包括bmp、jpg、png、gif和tiff
BOOL SaveHBitmapToFile( HBITMAP hBmp, LPCTSTR lpfilename )

	if ( hBmp == NULL || lpfilename == NULL )
	
		WriteLog( _T("[SaveHBitmapToFile] hBmp或lpfilename为空,return") );
		return FALSE;
	

	CUIString strLog;
	int nLastErrCode = 0;
	Bitmap *pSrcBmp = Bitmap::FromHBITMAP( hBmp, NULL );
	if ( pSrcBmp == NULL )
	
		nLastErrCode = ::GetLastError();
		strLog.Format( _T("[SaveHBitmapToFile] Bitmap::FromHBITMAP失败,GetLastError: %d"), 
			nLastErrCode );
		WriteLog( strLog );
		return FALSE;
	

	// 获取文件的扩展名,根据文件名中的扩展名确定要保存成什么类型的图片
	CUIString strExtName = _T("");
	CUIString strFilePatch = lpfilename;
	int nPos = strFilePatch.ReverseFind(_T('.'));
	if ( nPos != -1)
	
		strExtName = strFilePatch.Right( strFilePatch.GetLength() - nPos - 1 );
	

	// GDI+中有五种编码:bmp、jpeg、gif、tiff和png,下面根据
	// 文件名的扩展部分来获取对应的编码CLSID
	CLSID encoderClsid;
	if ( strExtName == _T("bmp") )
	
		GetEncoderClsid( L"image/bmp", &encoderClsid );
	
	else if ( strExtName == _T("jpg") )
	
		GetEncoderClsid( L"image/jpeg", &encoderClsid );
	
	else if ( strExtName == _T("png") )
	
		GetEncoderClsid( L"image/png", &encoderClsid );
	
	else if ( strExtName == _T("gif") )
	
		GetEncoderClsid( L"image/gif", &encoderClsid );
	
	else if ( strExtName == _T("tiff") )
	
		GetEncoderClsid( L"image/tiff", &encoderClsid );
	
	else // 没有指定类型的扩展名,则默认使用png
	
		GetEncoderClsid( L"image/png", &encoderClsid );
	

	LPWSTR lpWStrFileName = NULL; // 注意:Bitmap::Save接口第一个参数是宽字节参数
#ifdef _UNICODE
	lpWStrFileName = const_cast<LPTSTR>(lpfilename); // 如果是_UNICODE模式,直接使用
#else
	WCHAR wchFileName[MAX_PATH*2] = 0;
	MultiByteToWideChar( CP_ACP, 0, lpfilename, -1, wchFileName, sizeof(wchFileName)/sizeof(WCHAR) ); // 将窄字符转化为宽字符
	lpWStrFileName = wchFileName;
#endif

	Gdiplus::Status statusRet = pSrcBmp->Save( lpWStrFileName, &encoderClsid );
	if ( statusRet != Gdiplus::Ok )
	
		nLastErrCode = ::GetLastError();
		strLog.Format( _T("[SaveHBitmapToFile] Bitmap::FromHBITMAP失败,,Gdiplus错误码:%d, GetLastError: %d"), 
			statusRet, nLastErrCode );
		WriteLog( strLog );

		// 释放内存
		delete pSrcBmp;
		return FALSE;
	

	// 释放内存
	delete pSrcBmp;
	return TRUE;

以上是关于C#如何实现图片文件与数据流的转换的主要内容,如果未能解决你的问题,请参考以下文章

如何用javascript或jquery实现图片与二进制的转换

C#如何实现上传头像,最好能够代码加文字阐述一下实现原理

求用C#程序实现的将各种文件word、excel、ppt、pdf、dwg(CAD文件)转换成图片JPG方法或者程序

如何实现图片与像素值矩阵(或坐标)的互换

如何使用C#实现Listview显示图片与文字

C# winform如何通过按钮事件实现图片的放大与缩小