WinCE平台下BMP转JPG代码备份3

安稳与你 提交于 2020-02-17 14:30:15
 
  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 }



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!