1 //带参数的保存位图函数 2 BOOL FileOperate::bmpSaveImage(PTSTR pstrFileName, BITMAPFILEHEADER *pbmfh) 3 { 4 BOOL bSuccess ; 5 DWORD dwBytesWritten ; 6 HANDLE hFile; 7 8 hFile = CreateFile ( pstrFileName, GENERIC_WRITE, 0, NULL, 9 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL) ; 10 11 if (hFile == INVALID_HANDLE_VALUE) { 12 return FALSE ; 13 } 14 15 bSuccess = WriteFile (hFile, pbmfh, pbmfh->bfSize, &dwBytesWritten, NULL); 16 17 CloseHandle (hFile) ; 18 19 if (!bSuccess || (dwBytesWritten != pbmfh->bfSize)) { 20 DeleteFile (pstrFileName) ; 21 return FALSE ; 22 } 23 return TRUE ; 24 } 25 26 //************************************ 27 // Method: SaveBmp 28 // FullName: FileOperate::SaveBmp 29 // Access: public static 30 // Returns: CString 位图的名称 31 // Qualifier: 保存位图 32 // Parameter: char * pcBmpDataTemp 位图数据区内容 33 //************************************ 34 CString FileOperate::SaveBmp0(BYTE *pcBmpDataTemp) 35 { 36 // TODO: Add your control notification handler code here 37 IMAGE_SIZE tDispSize = {0}; 38 DWORD dwPreMode; 39 PINGPONG_PR DataAddr; 40 BITMAPFILEHEADER *pFileHead = NULL; /* 位图文件的头指针 */ 41 BITMAPINFO *pBmpInfo = NULL; /* 位图信息的指针 */ 42 char *pcBmpData = NULL; /* 位图数据区的指针 */ 43 DWORD dwImgeX; /* 位图水平像素 */ 44 DWORD dwImgeY; /* 位图垂直像素 */ 45 46 DWORD dwFileHeadSize = sizeof(BITMAPFILEHEADER); /* 位图文件的头区域大小 */ 47 DWORD dwInfoSize = sizeof(BITMAPINFO) + 4 * 2; /* 位图文件的信息区大小 */ 48 DWORD dwBipMapSize; /* 位图文件的数据区大小 */ 49 CString cstrPathname; 50 51 cstrPathname+="\\FlashDisk2\\bmp\\"; 52 cstrPathname+=GetTimeTag(); 53 cstrPathname+=".bmp"; 54 dwImgeX = 320; 55 dwImgeY = 240; 56 57 dwBipMapSize = 2 * dwImgeX * dwImgeY; /* 文件头指针指向整个位图的空间 320*240*2/1024 =150K*/ 58 pFileHead = (BITMAPFILEHEADER*)malloc(dwFileHeadSize + dwInfoSize + dwBipMapSize); 59 pBmpInfo = (BITMAPINFO *)malloc(dwInfoSize); 60 61 pFileHead->bfOffBits = dwFileHeadSize + dwInfoSize; /* 以下为填充位图的空间 */ 62 pFileHead->bfSize = dwFileHeadSize + dwInfoSize + dwBipMapSize; 63 pFileHead->bfType = 0x4D42; 64 65 pcBmpData = (char *) pFileHead + pFileHead->bfOffBits; 66 67 pBmpInfo->bmiHeader.biHeight = 0 - (signed)dwImgeY; 68 pBmpInfo->bmiHeader.biWidth = dwImgeX ; 69 pBmpInfo->bmiHeader.biBitCount = 16; 70 pBmpInfo->bmiHeader.biClrImportant = 0; 71 pBmpInfo->bmiHeader.biClrUsed = 0; 72 pBmpInfo->bmiHeader.biCompression = BI_BITFIELDS; 73 pBmpInfo->bmiHeader.biPlanes = 1; 74 pBmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 75 pBmpInfo->bmiHeader.biSizeImage = dwBipMapSize; 76 77 pBmpInfo->bmiColors[0].rgbBlue = 0x00; 78 pBmpInfo->bmiColors[0].rgbGreen = 0xF8; 79 pBmpInfo->bmiColors[0].rgbRed = 0x00; 80 pBmpInfo->bmiColors[0].rgbReserved = 0x00; 81 pBmpInfo->bmiColors[1].rgbBlue = 0xE0; 82 pBmpInfo->bmiColors[1].rgbGreen = 0x07; 83 pBmpInfo->bmiColors[1].rgbRed = 0x00; 84 pBmpInfo->bmiColors[1].rgbReserved = 0x00; 85 pBmpInfo->bmiColors[2].rgbBlue = 0x1F; 86 pBmpInfo->bmiColors[2].rgbGreen = 0x00; 87 pBmpInfo->bmiColors[2].rgbRed = 0x00; 88 pBmpInfo->bmiColors[2].rgbReserved = 0x00; 89 90 memcpy((void*)(pFileHead + 1), (void*)pBmpInfo, dwInfoSize); 91 92 93 //最后将RGB565的图片数据全部COPY到pcBmpData中了----这里可以通过读文件的形式将这些数据读上来。!!!!!! 94 //只需要在此处将那个RGB565的文件用二进制的格式读进来就OK了!!! 95 /*CFile hFile; 96 hFile.Open(_T("\\2010-9-23.bins"),CFile::modeRead); 97 hFile.Read(pcBmpData,dwBipMapSize);*/ 98 memcpy(pcBmpData,pcBmpDataTemp,dwBipMapSize);//将图片数据区值COPY过来 99 100 101 // memcpy(bmpFileData,pFileHead,153666);//当程序运行到此处,C#程序中的临时数组已经有值了。102 103 104 bmpSaveImage((PTSTR)cstrPathname.GetBuffer(0), pFileHead); /* 保存成BMP图片 */105 cstrPathname.ReleaseBuffer();106 107 free(pFileHead);108 free(pBmpInfo);109 110 return cstrPathname;111 }112 113 114 115 116 //************************************117 // Method: SaveBmp118 // FullName: FileOperate::SaveBmp119 // Access: public static120 // Returns: CString 位图的名称121 // Qualifier: 保存位图122 // Parameter: char * pcBmpDataTemp 位图数据区内容123 //************************************124 CString FileOperate::SaveBmp(char *pcBmpDataTemp,char *bmpFileData)125 {126 // TODO: Add your control notification handler code here127 IMAGE_SIZE tDispSize = {0};128 DWORD dwPreMode;129 PINGPONG_PR DataAddr;130 BITMAPFILEHEADER *pFileHead = NULL; /* 位图文件的头指针 */131 BITMAPINFO *pBmpInfo = NULL; /* 位图信息的指针 */132 char *pcBmpData = NULL; /* 位图数据区的指针 */133 DWORD dwImgeX; /* 位图水平像素 */134 DWORD dwImgeY; /* 位图垂直像素 */135 136 DWORD dwFileHeadSize = sizeof(BITMAPFILEHEADER); /* 位图文件的头区域大小 */137 DWORD dwInfoSize = sizeof(BITMAPINFO) + 4 * 2; /* 位图文件的信息区大小 */138 DWORD dwBipMapSize; /* 位图文件的数据区大小 */139 CString cstrPathname;140 141 cstrPathname+="\\FlashDisk2\\bmp\\";142 cstrPathname+=GetTimeTag();143 cstrPathname+=".bmp";144 dwImgeX = 320;145 dwImgeY = 240;146 147 dwBipMapSize = 2 * dwImgeX * dwImgeY; /* 文件头指针指向整个位图的空间 320*240*2/1024 =150K*/148 pFileHead = (BITMAPFILEHEADER*)malloc(dwFileHeadSize + dwInfoSize + dwBipMapSize);149 pBmpInfo = (BITMAPINFO *)malloc(dwInfoSize);150 151 pFileHead->bfOffBits = dwFileHeadSize + dwInfoSize; /* 以下为填充位图的空间 */152 pFileHead->bfSize = dwFileHeadSize + dwInfoSize + dwBipMapSize;153 pFileHead->bfType = 0x4D42;154 155 pcBmpData = (char *) pFileHead + pFileHead->bfOffBits;156 157 pBmpInfo->bmiHeader.biHeight = 0 - (signed)dwImgeY;158 pBmpInfo->bmiHeader.biWidth = dwImgeX ; 159 pBmpInfo->bmiHeader.biBitCount = 16;160 pBmpInfo->bmiHeader.biClrImportant = 0;161 pBmpInfo->bmiHeader.biClrUsed = 0;162 pBmpInfo->bmiHeader.biCompression = BI_BITFIELDS;163 pBmpInfo->bmiHeader.biPlanes = 1;164 pBmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);165 pBmpInfo->bmiHeader.biSizeImage = dwBipMapSize;166 167 pBmpInfo->bmiColors[0].rgbBlue = 0x00;168 pBmpInfo->bmiColors[0].rgbGreen = 0xF8;169 pBmpInfo->bmiColors[0].rgbRed = 0x00;170 pBmpInfo->bmiColors[0].rgbReserved = 0x00;171 pBmpInfo->bmiColors[1].rgbBlue = 0xE0;172 pBmpInfo->bmiColors[1].rgbGreen = 0x07;173 pBmpInfo->bmiColors[1].rgbRed = 0x00;174 pBmpInfo->bmiColors[1].rgbReserved = 0x00;175 pBmpInfo->bmiColors[2].rgbBlue = 0x1F;176 pBmpInfo->bmiColors[2].rgbGreen = 0x00;177 pBmpInfo->bmiColors[2].rgbRed = 0x00;178 pBmpInfo->bmiColors[2].rgbReserved = 0x00;179 180 memcpy((void*)(pFileHead + 1), (void*)pBmpInfo, dwInfoSize);181 182 183 //最后将RGB565的图片数据全部COPY到pcBmpData中了----这里可以通过读文件的形式将这些数据读上来。!!!!!!184 //只需要在此处将那个RGB565的文件用二进制的格式读进来就OK了!!!185 /*CFile hFile;186 hFile.Open(_T("\\2010-9-23.bins"),CFile::modeRead);187 hFile.Read(pcBmpData,dwBipMapSize);*/188 memcpy(pcBmpData,pcBmpDataTemp,dwBipMapSize);//将图片数据区值COPY过来189 190 191 memcpy(bmpFileData,pFileHead,153666);//当程序运行到此处,C#程序中的临时数组已经有值了。192 193 194 bmpSaveImage((PTSTR)cstrPathname.GetBuffer(0), pFileHead); /* 保存成BMP图片 */195 cstrPathname.ReleaseBuffer();196 197 free(pFileHead);198 free(pBmpInfo);199 200 return cstrPathname;201 }202 203 204 205 206 207 208 #endif209 210 211 212 //pcBmpDataTemp--从摄像头中得到的565数据区内容213 void FileOperate::ImageConvertDemo(BYTE *pInBmp565Data,//输入的RGB565位图的数据实体部分--不包括位图文件等信息214 DWORD dwBitMapDataSize,//位图数据实体长度(不包括文件头等信息)153600215 BYTE **ppOutMallocData,//传出的JPG图片数据实体216 DWORD * pdwOutJpegMemSize,//传出的JPG图片数据的大小217 int * pState //状态码:记录在执行此函数的过程中可能出现的问题 218 )219 {220 221 BYTE * pOutRgb555BmpData=NULL;//输出的555格式的位图数据实体222 DWORD dwRgb555BmpFileDataLength=0;//153666;//暂时先赋一个值,最终还是要通过传递得到的----######223 224 225 dwRgb555BmpFileDataLength=sizeof(BITMAPFILEHEADER) //位图文件信息头:14226 + sizeof(BITMAPINFOHEADER) //位图信息头:40227 + 3*sizeof(RGBQUAD)//RGB掩码:12228 + dwBitMapDataSize;//数据实体部分:153600229 230 IImageDemo imgDemo;231 232 //FileOperate::SaveBmp0(pInBmp565Data);//测试代码:此处测试表明,可以取得到实时的数据了233 imgDemo.ConvertBmpRgb565To555(pInBmp565Data,dwRgb555BmpFileDataLength,&pOutRgb555BmpData);//测试转码 234 235 BYTE * pJpegData=NULL;236 DWORD dwpJpegDataLength;//Jpeg数组的长度237 imgDemo.ConvertRgb555BmpToJpgInMem(pOutRgb555BmpData,dwRgb555BmpFileDataLength,&pJpegData,&dwpJpegDataLength);//因为是在函数内部动态分配的内存,所以需要用指针的指针238 239 //传出数据240 *pdwOutJpegMemSize=dwpJpegDataLength;//传出长度---在最终代码中要简化241 *ppOutMallocData=pJpegData;242 243 }
1.3转换图片格式
GetImage.h
1 #pragma once 2 3 4 #include "initguid.h "//如果不引用此头文件,就会出现 无法解析外部符号的错误 5 #include "imaging.h"//图片转码测试 6 7 8 9 10 class GetImage11 {12 public:13 GetImage(DWORD dwRGB_Width,DWORD dwRGB_Height);14 GetImage(void);15 ~GetImage(void);16 17 18 public:19 DWORD dwRGB_Width; /* RGB 通道的输出图像的宽度 */20 DWORD dwRGB_Height; /* RGB 通道的输出图像的高度 */21 22 public:23 //转换图片格式,并得到jpeg文件的数组24 void GetJpegBytes(25 BYTE *pInBmp565Data,//输入的RGB565位图的数据实体部分(不包括文件头等信息)26 DWORD dwBitMapDataSize,//位图数据实体长度(不包括文件头等信息)27 BYTE **ppOutMallocData,//传出的JPG图片数据实体的指针28 DWORD * pdwOutJpegMemSize,//传出的JPG图片数据的大小29 int * pState //状态码:记录在执行此函数的过程中可能出现的问题 30 );31 32 33 private:34 35 //将Rgb565编码格式的位图转成Rgb555的位图36 void ConvertBmpRgb565To555(37 BYTE * pInRgb565BmpData, //输入的565格式的位图数据实体38 DWORD dwRgb555BmpFileDataLength,//位图文件大小39 BYTE ** ppOutRgb555BmpData//输出的555格式的位图数据实体40 );41 42 //将数组转换到IStream中43 void CopyByteArrayToISream(44 BYTE *pInByteArray,//输入的字节数组45 DWORD dwArrayLength,//字节数组的长度46 IStream **ppOutIStream//传出的由字节转换的流47 );48 49 /*50 *函数介绍:根据编码器类型名称,得到指定的编码器CLSID51 *入口参数:pImagingFactory: Image工厂接口对象52 wszMimeType : Image编码格式名称53 *出口参数:pclsid :编码器的CLSID54 *返回值:TRUE : 成功; FALSE: 失败55 */56 BOOL GetEnCodecCLSID(IImagingFactory * pImagingFactory, WCHAR * wszMimeType , CLSID * pclsid);57 58 59 //Rgb555编码的BMP位图转JPG--在内存中进行60 void ConvertRgb555BmpToJpgInMem(61 BYTE * pInRgb555BmpFileData, //输入的RGB555位图文件流--包括位图数据实体及文件和位图信息62 DWORD dwRgb555BmpFileDataLength,//RGB555位图文件流的长度63 BYTE ** ppOutJpegData,//输出的JPG位图文件数据流64 DWORD * dwpOutJpegDataLegth//转码后的JPG位图大小65 );66 67 };
GetImage.cpp
1 #include "StdAfx.h" 2 #include "GetImage.h" 3 4 #include "CamException.h" 5 6 //#include "epccameralib.h"//摄像头驱动 7 8 9 GetImage::GetImage(void) 10 { 11 } 12 13 14 GetImage::GetImage(DWORD dwWidth,DWORD dwHeight) 15 { 16 dwRGB_Height=dwHeight; 17 dwRGB_Width=dwWidth; 18 } 19 20 21 GetImage::~GetImage(void) 22 { 23 } 24 25 26 void GetImage::GetJpegBytes( 27 BYTE *pInBmp565Data,//输入的RGB565位图的数据实体部分--不包括位图文件等信息 28 DWORD dwBitMapDataSize,//位图数据实体长度(不包括文件头等信息)153600 29 BYTE **ppOutMallocData,//传出的JPG图片数据实体 30 DWORD * pdwOutJpegMemSize,//传出的JPG图片数据的大小 31 int * pState //状态码:记录在执行此函数的过程中可能出现的问题 32 ) 33 { 34 35 try 36 { 37 BYTE * pOutRgb555BmpData=NULL;//输出的555格式的位图数据实体 38 DWORD dwRgb555BmpFileDataLength=0;//位图文件长度153666 39 40 41 dwRgb555BmpFileDataLength=sizeof(BITMAPFILEHEADER) //位图文件信息头:14 42 + sizeof(BITMAPINFOHEADER) //位图信息头:40 43 + 3*sizeof(RGBQUAD)//RGB掩码:12 44 + dwBitMapDataSize;//数据实体部分:153600 45 46 //将位图数据转码成555数据,并加上相关文件头,最后形成555位图文件 47 ConvertBmpRgb565To555(pInBmp565Data,dwRgb555BmpFileDataLength,&pOutRgb555BmpData); 48 49 50 #pragma region //测试没有取到图片的情况 51 52 53 //CFile hSaveFile; 54 //hSaveFile.Open(L"\\565bmp.bin",CFile::modeCreate | CFile::modeWrite |CFile::modeNoTruncate); 55 ////创立一个txt文件。 56 //hSaveFile.SeekToEnd(); //文件末尾 57 58 //hSaveFile.Write(pInBmp565Data,dwBitMapDataSize); 59 //hSaveFile.Close(); 60 61 #pragma endregion 62 63 64 65 66 67 if (pOutRgb555BmpData==NULL) 68 { 69 throw CString("ConvertBmpRgb565To555位图图片格式转码失败"); 70 } 71 72 BYTE * pJpegData=NULL; 73 DWORD dwpJpegDataLength;//Jpeg数组的长度 74 ConvertRgb555BmpToJpgInMem(pOutRgb555BmpData,dwRgb555BmpFileDataLength,&pJpegData,&dwpJpegDataLength); 75 //因为是在函数内部动态分配的内存,所以需要用指针的指针 76 77 if (pOutRgb555BmpData!=NULL) 78 { 79 free(pOutRgb555BmpData);//555位图数据使用完毕后,就释放 80 pOutRgb555BmpData=NULL; 81 } 82 83 if (pJpegData==NULL) 84 { 85 throw CString("ConvertRgb555BmpToJpgInMem位图压缩失败"); 86 } 87 88 //传出数据 89 *pdwOutJpegMemSize=dwpJpegDataLength;//传出长度---在最终代码中要简化 90 *ppOutMallocData=pJpegData; 91 } 92 catch(CString exMsg) 93 { 94 exMsg=L"GetJpegBytes(BYTE*,DWORD,BYTE**,DWORD*,int*):" + exMsg; 95 CamException::WriteToFile(exMsg); 96 } 97 catch (CException* e) 98 { 99 TCHAR szCause[255];100 e->GetErrorMessage(szCause, 255);101 CString exMsg=CString(szCause);102 exMsg=L"GetJpegBytes(BYTE*,DWORD,BYTE**,DWORD*,int*):" + exMsg;103 CamException::WriteToFile(exMsg);104 }105 106 }107 108 109 110 //将Rgb565编码格式的位图转成Rgb555的位图---位图的大小不会变化,只是数据的编码方式发生变化111 void GetImage::ConvertBmpRgb565To555(112 BYTE * pInRgb565BmpData,//输入的565格式的位图数据实体----不包括位图文件信息113 DWORD dwRgb555BmpFileDataLength,//位图文件大小153666114 BYTE ** ppOutRgb555BmpFileData//输出的555格式的位图文件数据流--可以形成完整文件115 )116 {117 118 try119 {120 #pragma region //设置位图文件121 BITMAPFILEHEADER *pFileHead = NULL; /* 位图文件的头指针 */122 BITMAPINFO *pBmpInfo = NULL; /* 位图信息的指针 */123 char *pcBmpData = NULL; /* 位图数据区的指针 */124 DWORD dwImgeX; /* 位图水平像素 */125 DWORD dwImgeY; /* 位图垂直像素 */126 127 DWORD dwFileHeadSize = sizeof(BITMAPFILEHEADER); /* 位图文件的头区域大小 */128 DWORD dwInfoSize = sizeof(BITMAPINFO) + 4 * 2; /* 位图文件的信息区大小 */129 DWORD dwBipMapSize; /* 位图文件的数据区大小 */130 131 132 133 dwBipMapSize = 2 * dwRGB_Height * dwRGB_Width; //文件头指针指向整个位图的空间 320*240*2/1024 =150K 134 pFileHead = (BITMAPFILEHEADER*)malloc(dwFileHeadSize + dwInfoSize + dwBipMapSize);135 if (pFileHead==NULL)136 {137 throw CString("pFileHead位图信息头内存分配失败");138 }139 140 pBmpInfo = (BITMAPINFO *)malloc(dwInfoSize);141 142 if (pBmpInfo==NULL)143 {144 free(pFileHead);145 pFileHead==NULL;//释放已经申请到的内存146 throw CString("pBmpInfo位图信息头内存分配失败");147 }148 149 pFileHead->bfOffBits = dwFileHeadSize + dwInfoSize; /* 以下为填充位图的空间 */150 pFileHead->bfSize = dwFileHeadSize + dwInfoSize + dwBipMapSize;151 pFileHead->bfType = 0x4D42;//位图文件的 类型代码152 153 pcBmpData = (char *) pFileHead + pFileHead->bfOffBits;154 155 pBmpInfo->bmiHeader.biHeight = 0 - (signed)dwRGB_Height;156 pBmpInfo->bmiHeader.biWidth = dwRGB_Width ; 157 158 pBmpInfo->bmiHeader.biBitCount = 16;159 pBmpInfo->bmiHeader.biClrImportant = 0;160 pBmpInfo->bmiHeader.biClrUsed = 0;161 //pBmpInfo->bmiHeader.biCompression = BI_BITFIELDS;//RGB565格式162 pBmpInfo->bmiHeader.biCompression = BI_RGB;//RGB555格式163 pBmpInfo->bmiHeader.biPlanes = 1;164 pBmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);165 pBmpInfo->bmiHeader.biSizeImage = dwBipMapSize;166 167 168 memcpy((void*)(pFileHead + 1), (void*)pBmpInfo, dwInfoSize);169 memcpy(pcBmpData,pInRgb565BmpData,dwBipMapSize);//将摄像头数据复制到位图文件内存缓冲区中170 171 #pragma endregion172 173 #pragma region //进行颜色分量提取,并转码成RGB555174 175 176 char * p555Data=NULL;177 p555Data=(char*)malloc(dwBipMapSize);//申请一片数据作为555数据的缓冲区178 179 if (p555Data==NULL)180 {181 free(pFileHead);182 pFileHead=NULL;183 free(pBmpInfo);184 pBmpInfo=NULL;185 throw CString("p555Data内存分配失败");186 }187 188 DWORD width=dwRGB_Width;//320189 DWORD height=dwRGB_Height;//240190 int pitch=width+width%2;//偏移量191 192 for (int i=0;i<height;i++)//图片的高度是240193 {194 for (int j=0;j<width;j++)195 {196 197 //分解出RGB三分量---RGB565的198 UCHAR b=pcBmpData[(i*pitch+j)*2]&0x1F; 199 UCHAR g=((((pcBmpData[(i*pitch+j)*2+1]<<5)&0xFF)>>2) & 0x38) +((pcBmpData[(i*pitch+j)*2]>>5)&0x07);200 UCHAR r=(pcBmpData[(i*pitch+j)*2+1]>>3)&0x1F;201 202 g=g/2;//把g分量从RGB565标准转码成RGB555标准203 204 205 //将新的RGB分量弄到RGB555的图片数据区中.206 p555Data[(i*pitch+j)*2] = ((g<<5)&0xE0)+b;//gb分量207 p555Data[(i*pitch+j)*2+1] = (r<<2)+(g/8);//rg分量208 209 }210 }211 212 memcpy(pcBmpData,p555Data,dwBipMapSize);//将新的数据区内容复制到原来的数据区中进行了数据覆盖213 214 #pragma endregion215 216 //---*****传出参数 217 *ppOutRgb555BmpFileData=(BYTE *)malloc(dwRgb555BmpFileDataLength);218 if (*ppOutRgb555BmpFileData==NULL)219 {220 free(pFileHead);221 pFileHead=NULL;222 free(pBmpInfo);223 pBmpInfo=NULL;224 free(p555Data);225 p555Data=NULL;226 throw CString("*ppOutRgb555BmpFileData内存分配失败");227 }228 memcpy(*ppOutRgb555BmpFileData,pFileHead,dwRgb555BmpFileDataLength);229 230 231 free(pFileHead);232 free(pBmpInfo);233 free(p555Data);234 }235 catch(CString exMsg)236 {237 exMsg=L"ConvertBmpRgb565To555(BYTE*,DWORD,BYTE**):" + exMsg;238 CamException::WriteToFile(exMsg);239 }240 catch (CException* e)241 {242 TCHAR szCause[255];243 e->GetErrorMessage(szCause, 255);244 CString exMsg=CString(szCause);245 exMsg=L"ConvertBmpRgb565To555(BYTE*,DWORD,BYTE**):" + exMsg;246 CamException::WriteToFile(exMsg);247 }248 249 250 }251 252 253 254 255 // //Rgb555编码的BMP位图转JPG--在内存中进行256 void GetImage::ConvertRgb555BmpToJpgInMem(257 BYTE * pInRgb555BmpFileData, //输入的RGB555位图文件流--包括位图数据实体及文件和位图信息258 DWORD dwRgb555BmpFileDataLength,//RGB555位图文件流的长度259 BYTE ** ppOutJpegData,//传出的JPG文件数据流260 DWORD * dwpOutJpegDataLegth//JPG文件流大小261 )262 {263 264 try265 {266 #pragma region267 HRESULT hr;//保存每个步骤的中间结果,判断过程运行是否正确----到时候有必要写个异常日志记录268 TCHAR *tszMime;//输出图片格式269 tszMime = L"image/jpeg"; //指定转换后,图象文件的格式270 271 IStream *pRgb555BmpStream = NULL; // 流接口对象---读取BMP文件,然后在内存中保存此文件数据272 IStream * pJpegStream=NULL;//用来保存转换的JPG文件 273 IImagingFactory * pImagingFactory = NULL ; //Image工厂接口对象274 IImageSink *pImageSink = NULL; //Image Sink接口对象275 IImageDecoder *pImageDecoder = NULL; //解码器接口对象276 IImageEncoder *pImageEncoder = NULL; //编码器接口对象277 CLSID clsidEncoder; //编码器CLSID278 279 280 281 //小技巧:有些变量虽然只在函数体里局部用到,但是因为是动态分配的内存,需要最后手动释放内存,最好放在最前面声明,防止最后遗忘了。282 STATSTG * pIStreamState=NULL;//得到pJpegStream的状态283 BYTE * pJpegData=NULL;//用来存储从文件流中剥出来的数据。284 285 286 287 //初始化COM环境288 if (FAILED(hr = CoInitializeEx(NULL, COINIT_MULTITHREADED)))289 {290 TRACE(L"COINIT_MULTITHREADED ERROR");291 return;292 }293 294 CopyByteArrayToISream(pInRgb555BmpFileData,dwRgb555BmpFileDataLength,&pRgb555BmpStream);//承接数据295 296 297 //将流指针移到流起点。-----一般都要进行一下这样的测试298 LARGE_INTEGER dlibMove0;299 dlibMove0.HighPart=0;300 dlibMove0.LowPart=0;301 pRgb555BmpStream->Seek(dlibMove0,STREAM_SEEK_SET,NULL);302 303 304 //得到Image工厂接口对象---用指定的类标识符创建一个Com对象,用指定的类标识符创建一个未初始化的对象。305 hr = CoCreateInstance(CLSID_ImagingFactory,//创建的Com对象的类标识符(CLSID)306 NULL,//指向接口IUnknown的指针307 CLSCTX_INPROC_SERVER,//运行可执行代码的上下文308 IID_IImagingFactory,//创建的Com对象的接口标识符309 (void**) &pImagingFactory);//用来接收指向Com对象接口地址的指针变量310 311 if (FAILED(hr))312 {313 TRACE(L"IMAGE FACTORY CREATED ERROR");314 goto finish;315 } 316 317 318 //创建解码器接口319 if (FAILED(hr = pImagingFactory->CreateImageDecoder(pRgb555BmpStream, DecoderInitFlagBuiltIn1st, &pImageDecoder)))320 {321 goto finish;322 }323 324 325 //根据编码器类型名称得到编码器CLSID326 if (!GetEnCodecCLSID(pImagingFactory,tszMime, &clsidEncoder ))//tszMime = L"image/jpeg"; //指定转换后,图象文件的格式327 {328 goto finish;329 }330 331 if (FAILED(hr = CreateStreamOnHGlobal(NULL,TRUE,&pJpegStream)))//必需要和某个内存区域关联,或者进行一次实例化,比如用COleStreamFile332 {333 goto finish;334 }335 336 if (FAILED(hr = pImagingFactory->CreateImageEncoderToStream(&clsidEncoder, pJpegStream, &pImageEncoder)))337 {338 goto finish;339 }340 341 //得到编码器接口的sink对象。此ImageSink接口作为一个槽或者管道来理解;342 //是用于负责pImageEncoder和pImageDecoder之间的传输343 if (FAILED(hr = pImageEncoder->GetEncodeSink(&pImageSink)))344 {345 goto finish;346 }347 //开始解码348 if (FAILED(hr = pImageDecoder->BeginDecode(pImageSink, NULL)))349 {350 goto finish;351 }352 //循环解码,直到结束353 for(;;)//for循环其实只运行了一个周期354 {355 //解码356 hr = pImageDecoder->Decode();//解码后,生成一个8K的文件357 //继续解码后面的部分358 if (E_PENDING == hr)359 {360 Sleep(500);361 } //失败362 else if (FAILED(hr))363 {364 //终止解码365 pImageDecoder->EndDecode(hr);366 goto finish;367 }368 else369 {370 //解码成功371 break;372 }373 }374 375 pImageDecoder->EndDecode(hr);//结束解码 376 pImageSink->Release();//释放pImageSink对象377 pImageSink = NULL; 378 pImageEncoder->TerminateEncoder();//结束编码,此时就已经完成了文件格式的转换379 380 #pragma region //从流中提取数据到BYTE数组中381 382 DWORD dwStreamLengthLowPart;//状态中的长度分量--低位(因为实际图片数据不需要高位那么长)383 //得到pJpegStream的长度--然后提取出数据,保存到BYTE数组中384 pIStreamState=(STATSTG *)malloc(sizeof(STATSTG));//如果不动态开辟空间,将无法传值进来。385 if (NULL == pIStreamState)//如果申请内存没有成功386 { 387 CamException::WriteToFile(L"pIStreamState申请内存失败");388 goto finish;389 }390 391 if (FAILED(hr=pJpegStream->Stat(pIStreamState,STATFLAG_NONAME)))392 {393 CamException::WriteToFile(L"pJpegStream获取状态失败");394 goto finish;395 }396 dwStreamLengthLowPart = pIStreamState->cbSize.LowPart;//取出流状态中的长度分量397 free(pIStreamState);398 pIStreamState=NULL;//指针置空,防止野指针出现399 400 401 pJpegData = (BYTE *)malloc(dwStreamLengthLowPart);//用来存储从文件流中剥出来的数据。402 if (NULL == pJpegData)//如果申请内存没有成功403 {404 goto finish;405 }406 407 //将流指针移到流起点。408 LARGE_INTEGER dlibMove;409 dlibMove.HighPart=0;410 dlibMove.LowPart=0;411 pJpegStream->Seek(dlibMove,STREAM_SEEK_SET,NULL);412 413 hr=pJpegStream->Read(pJpegData,dwStreamLengthLowPart,NULL);//将流文件内容放置到数据中414 if (FAILED(hr))415 {416 goto finish;417 }418 419 #pragma endregion420 421 *ppOutJpegData=pJpegData;//将图片数据指针传递出去422 *dwpOutJpegDataLegth = dwStreamLengthLowPart;//此处传值可能出了点小故障,明天就干脆把这两个参数封装到一个自定义的结构里面,然后动态生成吧。423 424 425 finish:426 427 //释放pRgb555BmpStream对象428 if (pRgb555BmpStream)429 pRgb555BmpStream->Release();430 if (pJpegStream)431 pJpegStream->Release();432 433 //释放pImageSink对象434 if (pImageSink)435 pImageSink->Release();436 //释放pImageDecoder对象437 if (pImageDecoder)438 pImageDecoder->Release();439 //释放pImageEncoder对象440 if (pImageEncoder)441 pImageEncoder->Release();442 //释放IImagingFactory接口对象443 if (pImagingFactory)444 pImagingFactory->Release();445 //释放程序占用的COM资源446 CoUninitialize(); 447 #pragma endregion448 }449 catch(CString exMsg)450 {451 exMsg=L"ConvertBmpRgb565To555(BYTE*,DWORD,BYTE**):" + exMsg;452 CamException::WriteToFile(exMsg);453 }454 catch (CException* e)455 {456 TCHAR szCause[255];457 e->GetErrorMessage(szCause, 255); 458 CString exMsg=CString(szCause);459 exMsg=L"ConvertBmpRgb565To555(BYTE*,DWORD,BYTE**):" + exMsg;460 CamException::WriteToFile(exMsg);461 }462 463 464 }
来源:https://www.cnblogs.com/elect-fans/archive/2011/12/27/2408592.html