MFC上显示摄像头JPEG图片数据的两种方法
其一是借助opencv,其二是利用流对象。
方法一:
CvMat *mat; //创建矩阵
mat = cvCreateMat(640,480,CV_8UC1); //指定分配内存大小
cvInitMatHeader(mat,640,480,CV_8UC1,JPEGBuf);
/*初始化矩阵信息头,这里的JPEGBuf就是JPEG图像数据的地址。现在很多摄像头是支持JPEG输出的,而且JPEG图像输出节 省宽带。640*480大小的图片大小仅在20K以内。网上提到的什么视频采集卡,提供的SDK也基本提供JPEG数据,它获得的数 据就是图像数据,而不是图像文件。*/
IplImage *pIplImage = cvDecodeImage(mat,CV_LOAD_IMAGE_COLOR); //这里将JPEG图像数组转化为IplImage类,这里自动包含了解压JPEG格式图片功能。 if(pIplImage != NULL) //如果解压失败得到的是NULL { CvvImage cimg; //CvvImage类在opencv 2.2以后没有CvvImage类了,网上搜索这个类,有低版本的源代码,直接添加到工程里就可以用了。 cimg.CopyOf( pIplImage); //复制图像 cimg.DrawToHDC(pMainDlg->m_DispHDC, &pMainDlg->m_DispRECT); //显示图像 cvReleaseImage(&pIplImage);//释放图像 }
cvReleaseMat(&mat); //释放矩阵
下面这个是个学习资料。
利用opencv读取图片并在MFC上显示,链接地址:http://licong1018.blog.163.com/blog/static/9026978420129239178934/
更新:因为自己需要,想要弄这个还要去翻看原来的工程文件。索性把CvvImage类贴在这里:
一、CvvImage.h
1 #pragma once 2 3 #ifndef CVVIMAGE_CLASS_DEF 4 #define CVVIMAGE_CLASS_DEF 5 6 #include "opencv.hpp" 7 8 /* CvvImage class definition */ 9 class CvvImage 10 { 11 public: 12 CvvImage(); 13 virtual ~CvvImage(); 14 15 /* Create image (BGR or grayscale) */ 16 virtual bool Create( int width, int height, int bits_per_pixel, int image_origin = 0 ); 17 18 /* Load image from specified file */ 19 virtual bool Load( const char* filename, int desired_color = 1 ); 20 21 /* Load rectangle from the file */ 22 virtual bool LoadRect( const char* filename, 23 int desired_color, CvRect r ); 24 25 #if defined WIN32 || defined _WIN32 26 virtual bool LoadRect( const char* filename, 27 int desired_color, RECT r ) 28 { 29 return LoadRect( filename, desired_color, 30 cvRect( r.left, r.top, r.right - r.left, r.bottom - r.top )); 31 } 32 #endif 33 34 /* Save entire image to specified file. */ 35 virtual bool Save( const char* filename ); 36 37 /* Get copy of input image ROI */ 38 virtual void CopyOf( CvvImage& image, int desired_color = -1 ); 39 virtual void CopyOf( IplImage* img, int desired_color = -1 ); 40 41 IplImage* GetImage() { return m_img; }; 42 virtual void Destroy(void); 43 44 /* width and height of ROI */ 45 int Width() { return !m_img ? 0 : !m_img->roi ? m_img->width : m_img->roi->width; }; 46 int Height() { return !m_img ? 0 : !m_img->roi ? m_img->height : m_img->roi->height;}; 47 int Bpp() { return m_img ? (m_img->depth & 255)*m_img->nChannels : 0; }; 48 49 virtual void Fill( int color ); 50 51 /* draw to highgui window */ 52 virtual void Show( const char* window ); 53 54 #if defined WIN32 || defined _WIN32 55 /* draw part of image to the specified DC */ 56 virtual void Show( HDC dc, int x, int y, int width, int height, 57 int from_x = 0, int from_y = 0 ); 58 /* draw the current image ROI to the specified rectangle of the destination DC */ 59 virtual void DrawToHDC( HDC hDCDst, RECT* pDstRect ); 60 #endif 61 62 protected: 63 64 IplImage* m_img; 65 }; 66 67 typedef CvvImage CImage; 68 69 #endif
二、CvvImage.cpp
1 #include "StdAfx.h" 2 #include "CvvImage.h" 3 4 ////////////////////////////////////////////////////////////////////// 5 // Construction/Destruction 6 ////////////////////////////////////////////////////////////////////// 7 8 CV_INLINE RECT NormalizeRect( RECT r ); 9 CV_INLINE RECT NormalizeRect( RECT r ) 10 { 11 int t; 12 13 if( r.left > r.right ) 14 { 15 t = r.left; 16 r.left = r.right; 17 r.right = t; 18 } 19 20 if( r.top > r.bottom ) 21 { 22 t = r.top; 23 r.top = r.bottom; 24 r.bottom = t; 25 } 26 27 return r; 28 } 29 30 CV_INLINE CvRect RectToCvRect( RECT sr ); 31 CV_INLINE CvRect RectToCvRect( RECT sr ) 32 { 33 sr = NormalizeRect( sr ); 34 return cvRect( sr.left, sr.top, sr.right - sr.left, sr.bottom - sr.top ); 35 } 36 37 CV_INLINE RECT CvRectToRect( CvRect sr ); 38 CV_INLINE RECT CvRectToRect( CvRect sr ) 39 { 40 RECT dr; 41 dr.left = sr.x; 42 dr.top = sr.y; 43 dr.right = sr.x + sr.width; 44 dr.bottom = sr.y + sr.height; 45 46 return dr; 47 } 48 49 CV_INLINE IplROI RectToROI( RECT r ); 50 CV_INLINE IplROI RectToROI( RECT r ) 51 { 52 IplROI roi; 53 r = NormalizeRect( r ); 54 roi.xOffset = r.left; 55 roi.yOffset = r.top; 56 roi.width = r.right - r.left; 57 roi.height = r.bottom - r.top; 58 roi.coi = 0; 59 60 return roi; 61 } 62 63 void FillBitmapInfo( BITMAPINFO* bmi, int width, int height, int bpp, int origin ) 64 { 65 assert( bmi && width >= 0 && height >= 0 && (bpp == 8 || bpp == 24 || bpp == 32)); 66 67 BITMAPINFOHEADER* bmih = &(bmi->bmiHeader); 68 69 memset( bmih, 0, sizeof(*bmih)); 70 bmih->biSize = sizeof(BITMAPINFOHEADER); 71 bmih->biWidth = width; 72 bmih->biHeight = origin ? abs(height) : -abs(height); 73 bmih->biPlanes = 1; 74 bmih->biBitCount = (unsigned short)bpp; 75 bmih->biCompression = BI_RGB; 76 77 if( bpp == 8 ) 78 { 79 RGBQUAD* palette = bmi->bmiColors; 80 int i; 81 for( i = 0; i < 256; i++ ) 82 { 83 palette[i].rgbBlue = palette[i].rgbGreen = palette[i].rgbRed = (BYTE)i; 84 palette[i].rgbReserved = 0; 85 } 86 } 87 } 88 89 CvvImage::CvvImage() 90 { 91 m_img = 0; 92 } 93 94 void CvvImage::Destroy() 95 { 96 cvReleaseImage( &m_img ); 97 } 98 99 CvvImage::~CvvImage() 100 { 101 Destroy(); 102 } 103 104 bool CvvImage::Create( int w, int h, int bpp, int origin ) 105 { 106 const unsigned max_img_size = 10000; 107 108 if( (bpp != 8 && bpp != 24 && bpp != 32) || 109 (unsigned)w >= max_img_size || (unsigned)h >= max_img_size || 110 (origin != IPL_ORIGIN_TL && origin != IPL_ORIGIN_BL)) 111 { 112 assert(0); // most probably, it is a programming error 113 return false; 114 } 115 116 if( !m_img || Bpp() != bpp || m_img->width != w || m_img->height != h ) 117 { 118 if( m_img && m_img->nSize == sizeof(IplImage)) 119 Destroy(); 120 121 /* prepare IPL header */ 122 m_img = cvCreateImage( cvSize( w, h ), IPL_DEPTH_8U, bpp/8 ); 123 } 124 125 if( m_img ) 126 m_img->origin = origin == 0 ? IPL_ORIGIN_TL : IPL_ORIGIN_BL; 127 128 return m_img != 0; 129 } 130 131 void CvvImage::CopyOf( CvvImage& image, int desired_color ) 132 { 133 IplImage* img = image.GetImage(); 134 if( img ) 135 { 136 CopyOf( img, desired_color ); 137 } 138 } 139 140 141 #define HG_IS_IMAGE(img) \ 142 ((img) != 0 && ((const IplImage*)(img))->nSize == sizeof(IplImage) && \ 143 ((IplImage*)img)->imageData != 0) 144 145 146 void CvvImage::CopyOf( IplImage* img, int desired_color ) 147 { 148 if( HG_IS_IMAGE(img) ) 149 { 150 int color = desired_color; 151 CvSize size = cvGetSize( img ); 152 153 if( color < 0 ) 154 color = img->nChannels > 1; 155 156 if( Create( size.width, size.height, 157 (!color ? 1 : img->nChannels > 1 ? img->nChannels : 3)*8, 158 img->origin )) 159 { 160 cvConvertImage( img, m_img, 0 ); 161 } 162 } 163 } 164 165 166 bool CvvImage::Load( const char* filename, int desired_color ) 167 { 168 IplImage* img = cvLoadImage( filename, desired_color ); 169 if( !img ) 170 return false; 171 172 CopyOf( img, desired_color ); 173 cvReleaseImage( &img ); 174 175 return true; 176 } 177 178 179 bool CvvImage::LoadRect( const char* filename, 180 int desired_color, CvRect r ) 181 { 182 if( r.width < 0 || r.height < 0 ) return false; 183 184 IplImage* img = cvLoadImage( filename, desired_color ); 185 if( !img ) 186 return false; 187 188 if( r.width == 0 || r.height == 0 ) 189 { 190 r.width = img->width; 191 r.height = img->height; 192 r.x = r.y = 0; 193 } 194 195 if( r.x > img->width || r.y > img->height || 196 r.x + r.width < 0 || r.y + r.height < 0 ) 197 { 198 cvReleaseImage( &img ); 199 return false; 200 } 201 202 /* truncate r to source image */ 203 if( r.x < 0 ) 204 { 205 r.width += r.x; 206 r.x = 0; 207 } 208 if( r.y < 0 ) 209 { 210 r.height += r.y; 211 r.y = 0; 212 } 213 214 if( r.x + r.width > img->width ) 215 r.width = img->width - r.x; 216 217 if( r.y + r.height > img->height ) 218 r.height = img->height - r.y; 219 220 cvSetImageROI( img, r ); 221 CopyOf( img, desired_color ); 222 223 cvReleaseImage( &img ); 224 return true; 225 } 226 227 228 bool CvvImage::Save( const char* filename ) 229 { 230 if( !m_img ) 231 return false; 232 cvSaveImage( filename, m_img ); 233 return true; 234 } 235 236 237 void CvvImage::Show( const char* window ) 238 { 239 if( m_img ) 240 cvShowImage( window, m_img ); 241 } 242 243 244 void CvvImage::Show( HDC dc, int x, int y, int w, int h, int from_x, int from_y ) 245 { 246 if( m_img && m_img->depth == IPL_DEPTH_8U ) 247 { 248 uchar buffer[sizeof(BITMAPINFOHEADER) + 1024]; 249 BITMAPINFO* bmi = (BITMAPINFO*)buffer; 250 int bmp_w = m_img->width, bmp_h = m_img->height; 251 252 FillBitmapInfo( bmi, bmp_w, bmp_h, Bpp(), m_img->origin ); 253 254 from_x = MIN( MAX( from_x, 0 ), bmp_w - 1 ); 255 from_y = MIN( MAX( from_y, 0 ), bmp_h - 1 ); 256 257 int sw = MAX( MIN( bmp_w - from_x, w ), 0 ); 258 int sh = MAX( MIN( bmp_h - from_y, h ), 0 ); 259 260 SetDIBitsToDevice( 261 dc, x, y, sw, sh, from_x, from_y, from_y, sh, 262 m_img->imageData + from_y*m_img->widthStep, 263 bmi, DIB_RGB_COLORS ); 264 } 265 } 266 267 268 void CvvImage::DrawToHDC( HDC hDCDst, RECT* pDstRect ) 269 { 270 if( pDstRect && m_img && m_img->depth == IPL_DEPTH_8U && m_img->imageData ) 271 { 272 uchar buffer[sizeof(BITMAPINFOHEADER) + 1024]; 273 BITMAPINFO* bmi = (BITMAPINFO*)buffer; 274 int bmp_w = m_img->width, bmp_h = m_img->height; 275 276 CvRect roi = cvGetImageROI( m_img ); 277 CvRect dst = RectToCvRect( *pDstRect ); 278 279 if( roi.width == dst.width && roi.height == dst.height ) 280 { 281 Show( hDCDst, dst.x, dst.y, dst.width, dst.height, roi.x, roi.y ); 282 return; 283 } 284 285 if( roi.width > dst.width ) 286 { 287 SetStretchBltMode( 288 hDCDst, // handle to device context 289 HALFTONE ); 290 } 291 else 292 { 293 SetStretchBltMode( 294 hDCDst, // handle to device context 295 COLORONCOLOR ); 296 } 297 298 FillBitmapInfo( bmi, bmp_w, bmp_h, Bpp(), m_img->origin ); 299 300 ::StretchDIBits( 301 hDCDst, 302 dst.x, dst.y, dst.width, dst.height, 303 roi.x, roi.y, roi.width, roi.height, 304 m_img->imageData, bmi, DIB_RGB_COLORS, SRCCOPY ); 305 } 306 } 307 308 309 void CvvImage::Fill( int color ) 310 { 311 cvSet( m_img, cvScalar(color&255,(color>>8)&255,(color>>16)&255,(color>>24)&255) ); 312 }
方法二:
void CTestDlg::DisplayJPEG(HDC hDC,unsigned char *buf,UINT bufLen,int rectWidth,int rectHeight) { HGLOBAL hImageMemory=GlobalAlloc(GMEM_MOVEABLE, bufLen);//给图片分配全局内存 void *pImageMemory=GlobalLock(hImageMemory); //锁定内存 if(pImageMemory == NULL) { TRACE("can't Get Global Memory!\n"); goto ret; } memcpy(pImageMemory,buf,bufLen); //读取图片到全局内存当中 GlobalUnlock(hImageMemory); //解锁内存 IStream *pIStream; //创建一个IStream接口指针,用来保存图片流 IPicture *pIPicture; //创建一个IPicture接口指针,表示图片对象 CreateStreamOnHGlobal(hImageMemory, false,&pIStream); //用全局内存初使化IStream接口指针 OleLoadPicture(pIStream, 0, false, IID_IPicture,(LPVOID*)&(pIPicture));//用OleLoadPicture获得IPicture接口指针 if(pIStream == NULL) { TRACE("can't Get pIStream!\n"); goto ret; } OLE_XSIZE_HIMETRIC hmWidth; OLE_YSIZE_HIMETRIC hmHeight; if(pIPicture == NULL) { TRACE("can't Get Picture Info!\n"); goto ret; } pIPicture->get_Width(&hmWidth); //用接口方法获得图片的宽和高 pIPicture->get_Height(&hmHeight); pIPicture->Render(hDC,0,0,rectWidth,rectHeight,0,hmHeight,hmWidth,-hmHeight,NULL);//在指定的DC上绘出图片 //以下代码为了保存一张图片 /////////////////////////////////////////////////////////////////////////////////// if(m_bSavePic == TRUE) { m_SaveFile.Open("Hello.jpg",CFile::modeCreate|CFile::modeWrite); //读写方式打开 m_SaveFile.Seek(0,CFile::begin); m_SaveFile.Write(buf,bufLen); //将文件读入缓存 m_SaveFile.Close(); m_bSavePic = FALSE; } /////////////////////////////////////////////////////////////////////////////////// pIStream->Release(); //释放pIStream pIPicture->Release(); //释放pIPicture ret: GlobalFree(hImageMemory); //释放全局内存 }