1 void GetImage::CopyByteArrayToISream( 2 BYTE *pInByteArray,//输入的字节数组 3 DWORD dwArrayLength,//字节数组的长度 4 IStream **ppOutIStream//传出的由字节转换的流 5 ) 6 { 7 try 8 { 9 HRESULT hrRet = S_FALSE;10 HGLOBAL hg = NULL;11 BYTE* pbLocked = NULL;12 13 //分配内存--此方法已经过时,现在一般都用malloc或者new了14 hg = GlobalAlloc(GMEM_MOVEABLE, dwArrayLength);15 if (NULL == hg)16 {17 CamException::WriteToFile(L"hg分配内存失败");18 goto error;19 }20 //得到已经分配的内存指针21 pbLocked = (BYTE*) GlobalLock(hg);22 if (NULL == pbLocked)23 {24 CamException::WriteToFile(L"pbLocked获取指针失败");25 goto error;26 }27 28 memcpy(pbLocked,pInByteArray,dwArrayLength);//不从文件中读取,而是直接在内存地址区间进行复制 29 GlobalUnlock(hg);//解锁已经分配全局内存,对应GlobalLock(hg) 30 hrRet = CreateStreamOnHGlobal(hg, TRUE, ppOutIStream);//创建Stream对象31 32 return;33 34 error: //错误处理,并释放内存(没有出现错误的话,不会出现在此处)35 if (pbLocked)36 GlobalUnlock(hg);37 if (hg)38 GlobalFree(hg);39 40 41 }42 catch(CString exMsg)43 {44 exMsg=L"CopyByteArrayToISream(BYTE*,DWORD,IStream **):" + exMsg;45 CamException::WriteToFile(exMsg);46 }47 catch (CException* e)48 {49 TCHAR szCause[255];50 e->GetErrorMessage(szCause, 255);51 CString exMsg=CString(szCause);52 exMsg=L"CopyByteArrayToISream(BYTE*,DWORD,IStream **):" + exMsg;53 CamException::WriteToFile(exMsg);54 }55 56 57 }58 59 60 61 62 63 64 65 BOOL GetImage::GetEnCodecCLSID(66 IImagingFactory * pImagingFactory,67 WCHAR * wszMimeType ,68 CLSID * pclsid69 )70 {71 UINT uiCount;72 ImageCodecInfo * codecs;73 HRESULT hr;74 BOOL fRet = FALSE;75 //枚举系统已经安装的编码器76 hr = pImagingFactory->GetInstalledEncoders(&uiCount, &codecs);77 //查找制定编码器的CLSID78 for (UINT i = 0; i < uiCount; i++)79 {80 if (wszMimeType && !wcscmp(wszMimeType, codecs[i].MimeType))81 {82 *pclsid = codecs[i].Clsid;83 fRet = TRUE;84 break;85 }86 }87 //释放内存88 CoTaskMemFree(codecs);89 //90 return fRet; 91 }
截止上面已经完成了在内存当中对图片的转换了。
二、使用C#项目调用DLL
里面为了防止内存泄漏,专程让这个转换做了1000次,最后发现没有问题了。
1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 using System.Runtime.InteropServices;//引入dll文件中的函数 5 6 7 // 添加新的命名空间。 8 using System.IO; 9 //using System.Drawing.Imaging;10 //using System.Drawing;11 12 13 namespace WinCeCsUseDll14 {15 class Program16 {17 18 19 [DllImport("WinCeCppCamdll.dll", CharSet = CharSet.Auto)]//WinCE平台下,居然没有ANSI这个编码选项。20 private static extern void GetCamShoot(21 int imgWidth,//图片宽度22 int imgHeight,//图片高度23 ref IntPtr ppOutMallocJpegData,//传出的JPG图片数据实体24 ref int pdwOutJpegMemSize,//传出的JPG图片数据的大小25 ref int pState //状态码:记录在执行此函数的过程中可能出现的问题26 );27 28 [DllImport("WinCeCppCamdll.dll", CharSet = CharSet.Auto)]//WinCE平台下,居然没有ANSI这个编码选项。29 private static extern void FreeMemory(ref IntPtr intPtr);30 31 32 static void Main(string[] args)33 {34 try35 {36 #region 用C#承接C++的DLL开辟的内存空间中的数据37 int imageWidth = 640;38 int imageHeight = 480;39 40 for (int i = 0; i < 10000; i++)41 {42 //下面再对内存区间进行传递43 int memSize = 0;44 int intState = 0;45 IntPtr intPtr = new IntPtr();46 47 GetCamShoot(imageWidth, imageHeight, ref intPtr, ref memSize, ref intState);48 49 ////因为采用 致远公司提供的驱动有点奇怪,每次捕捉的好像都是一一次内存中的东西50 ////如果是第一次启动程序,那么会出现没有数据的情况。所以需要进行一次容错--再读一次数据51 //if (intPtr.Equals(IntPtr.Zero))52 //{53 //// GetCamShoot(ref intPtr, ref memSize, ref intState);54 //}55 56 57 byte[] btTemp = new byte[memSize];58 Marshal.Copy(intPtr, btTemp, 0, memSize);59 60 61 //将BYTE数组写成文件--测试代码62 string path = "\\";63 string SendFileName = "recvBmpData.jpg";64 FileStream MyFileStream = new FileStream(path + SendFileName, FileMode.Create, FileAccess.Write);65 MyFileStream.Write(btTemp, 0, btTemp.Length); //将接收到的数据包写入到文件流对象 66 MyFileStream.Close();//关闭文件流 67 68 69 ////Marshal.FreeHGlobal(intPtr);70 FreeMemory(ref intPtr);71 ////Marshal.FreeCoTaskMem(intPtr);//free tha memory---用FreeHGlobal释放会出现错误,不知道这个函数是不是真正实现了释放。72 ////intPtr = IntPtr.Zero;73 if (i == 9999)74 break;75 }76 #endregion77 }catch(Exception e)78 {79 int a = 3;80 }81 82 83 }84 }85 }
虽然说今后可能再也不会碰这些东西了,但这毕竟是自己几个月的心血,所以还是贴下来吧,里面涉及的知识点太多了,今后自己有可能还有些参考价值的。
来源:https://www.cnblogs.com/elect-fans/archive/2011/12/27/2408591.html