Move the sources to trunk
[opencv] / apps / Common / Image.cpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////\r
2 //\r
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.\r
4 //\r
5 //  By downloading, copying, installing or using the software you agree to this license.\r
6 //  If you do not agree to this license, do not download, install,\r
7 //  copy or use the software.\r
8 //\r
9 //\r
10 //                        Intel License Agreement\r
11 //                For Open Source Computer Vision Library\r
12 //\r
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.\r
14 // Third party copyrights are property of their respective owners.\r
15 //\r
16 // Redistribution and use in source and binary forms, with or without modification,\r
17 // are permitted provided that the following conditions are met:\r
18 //\r
19 //   * Redistribution's of source code must retain the above copyright notice,\r
20 //     this list of conditions and the following disclaimer.\r
21 //\r
22 //   * Redistribution's in binary form must reproduce the above copyright notice,\r
23 //     this list of conditions and the following disclaimer in the documentation\r
24 //     and/or other materials provided with the distribution.\r
25 //\r
26 //   * The name of Intel Corporation may not be used to endorse or promote products\r
27 //     derived from this software without specific prior written permission.\r
28 //\r
29 // This software is provided by the copyright holders and contributors "as is" and\r
30 // any express or implied warranties, including, but not limited to, the implied\r
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.\r
32 // In no event shall the Intel Corporation or contributors be liable for any direct,\r
33 // indirect, incidental, special, exemplary, or consequential damages\r
34 // (including, but not limited to, procurement of substitute goods or services;\r
35 // loss of use, data, or profits; or business interruption) however caused\r
36 // and on any theory of liability, whether in contract, strict liability,\r
37 // or tort (including negligence or otherwise) arising in any way out of\r
38 // the use of this software, even if advised of the possibility of such damage.\r
39 //\r
40 //M*/\r
41 \r
42 //\r
43 // Image.cpp: implementation of the CImage class.\r
44 //\r
45 //////////////////////////////////////////////////////////////////////\r
46 \r
47 #include "stdafx.h"\r
48 #include "Image.h"\r
49 #include "vlgrfmts.h"\r
50 #include "cv.h"\r
51 #include <assert.h>\r
52 \r
53 #ifdef _DEBUG\r
54 #undef THIS_FILE\r
55 static char THIS_FILE[]=__FILE__;\r
56 #define new DEBUG_NEW\r
57 #endif\r
58 \r
59 //////////////////////////////////////////////////////////////////////\r
60 // Construction/Destruction\r
61 //////////////////////////////////////////////////////////////////////\r
62 \r
63 CImage::CImage()\r
64 {\r
65     Clear();\r
66 }\r
67 \r
68 void CImage::Clear()\r
69\r
70     memset( &m_img, 0, sizeof(m_img));\r
71 \r
72     m_memDC = 0; \r
73     m_old = 0;\r
74 }\r
75 \r
76 void CImage::Destroy()\r
77 {\r
78     if( m_memDC )\r
79     {\r
80         DeleteObject( SelectObject( m_memDC, m_old ));\r
81         DeleteDC( m_memDC );\r
82     }\r
83     Clear();\r
84 }\r
85 \r
86 CImage::~CImage()\r
87 {\r
88     Destroy();\r
89 }\r
90 \r
91 \r
92 void  FillBitmapInfo( BITMAPINFO* bmi, int width, int height, int bpp )\r
93 {\r
94     assert( bmi && width > 0 && height > 0 &&\r
95             (bpp == 8 || bpp == 24 || bpp == 32) );\r
96 \r
97     BITMAPINFOHEADER* bmih = &(bmi->bmiHeader);\r
98 \r
99     memset( bmih, 0, sizeof(*bmih));\r
100     bmih->biSize   = sizeof(BITMAPINFOHEADER); \r
101     bmih->biWidth  = width;\r
102     bmih->biHeight = -abs(height);\r
103     bmih->biPlanes = 1; \r
104     bmih->biBitCount = bpp;\r
105     bmih->biCompression = BI_RGB;\r
106 \r
107     if( bpp == 8 )\r
108     {\r
109         RGBQUAD* palette = bmi->bmiColors;\r
110         int i;\r
111         for( i = 0; i < 256; i++ )\r
112         {\r
113             palette[i].rgbBlue = palette[i].rgbGreen = palette[i].rgbRed = (BYTE)i;\r
114             palette[i].rgbReserved = 0;\r
115         }\r
116     }\r
117 }\r
118 \r
119 \r
120 bool  CImage::Create( int w, int h, int bpp )\r
121 {\r
122     char buffer[sizeof(BITMAPINFOHEADER) + 1024];\r
123     BITMAPINFO* bmi = (BITMAPINFO*)buffer;\r
124     void* data = 0;\r
125     int new_step = (w*(bpp/8) + 3) & -4;\r
126     \r
127     assert( bpp == 8 || bpp == 24 || bpp == 32 );\r
128 \r
129     if( (m_img.depth & 255)*m_img.nChannels == bpp && \r
130         m_img.width == w && m_img.height == h )\r
131     {\r
132         return true;\r
133     }\r
134 \r
135     Destroy();\r
136     \r
137     m_memDC = CreateCompatibleDC(0);\r
138     FillBitmapInfo( bmi, w, h, bpp );\r
139 \r
140     HBITMAP hbmp = CreateDIBSection( m_memDC, bmi, DIB_RGB_COLORS, &data, 0, 0 );\r
141     if( !hbmp )\r
142     {\r
143         DeleteDC( m_memDC );\r
144         m_memDC = 0;\r
145     }\r
146     else\r
147     {\r
148         BITMAP bmp;\r
149         m_old = SelectObject( m_memDC, hbmp );\r
150 \r
151         GetObject( hbmp, sizeof(bmp), &bmp );\r
152 \r
153         /* prepare IPL header */\r
154         memset( &m_img, 0, sizeof(m_img));\r
155         m_img.nSize = sizeof( m_img );\r
156         m_img.nChannels = bpp/8;\r
157         m_img.depth = IPL_DEPTH_8U;\r
158         strncpy( m_img.colorModel, bpp > 8 ? "RGB\0" : "GRAY", 4 );\r
159         strncpy( m_img.channelSeq, bpp > 8 ? "BGR\0" : "GRAY", 4 );\r
160         m_img.align = 4;\r
161         m_img.width = w;\r
162         m_img.height = abs(h);\r
163         m_img.roi  = 0;\r
164         m_img.widthStep = (w*(bpp/8) + 3)& -4;\r
165         m_img.imageSize = m_img.widthStep*m_img.height;\r
166         m_img.imageData = m_img.imageDataOrigin = (char*)bmp.bmBits;\r
167 \r
168         //iplSetBorderMode( &m_img, IPL_BORDER_REPLICATE, IPL_SIDE_ALL, 0 ); \r
169     }\r
170     return m_old != 0;\r
171 }\r
172 \r
173 \r
174 void  CImage::CopyOf( CImage& image, int desired_color )\r
175 {\r
176     IplImage* img = image.GetImage();\r
177     if( img )\r
178     {\r
179         CopyOf( img, desired_color );\r
180     }\r
181 }\r
182 \r
183 void  CImage::CopyOf( IplImage* img, int desired_color )\r
184 {\r
185     if( img )\r
186     {\r
187         int color = desired_color;\r
188         if( color < 0 ) color = img->nChannels > 1;\r
189         Create( iplWidth( img ), iplHeight( img ), color ? 24 : 8 );\r
190         if( m_img.nChannels == img->nChannels )\r
191         {\r
192             if( img->origin != m_img.origin )\r
193             {\r
194                 long OldOrg = img->origin;\r
195                 img->origin = m_img.origin;\r
196                 cvMirror( img, &m_img, 0 );\r
197                 img->origin = OldOrg;\r
198             }\r
199             else\r
200             {\r
201                 cvCopy( img, &m_img );\r
202             }\r
203         }\r
204         else\r
205         {\r
206             CImage tmp_image;\r
207             \r
208             tmp_image.Create( m_img.width, m_img.height, img->nChannels*8 );\r
209 \r
210             IplImage* tmp_img = tmp_image.GetImage();\r
211             if( img->origin != m_img.origin )\r
212             {\r
213                 long OldOrg = img->origin;\r
214                 img->origin = tmp_img->origin;\r
215                 cvMirror( img, tmp_img, 0 );\r
216                 img->origin = OldOrg;\r
217             }\r
218             else\r
219             {\r
220                 cvCopy( img, tmp_img );\r
221             }\r
222 \r
223             if( color )\r
224                 cvCvtColor( tmp_img, &m_img, CV_GRAY2BGR );\r
225             else\r
226                 cvCvtColor( tmp_img, &m_img, CV_BGR2GRAY );\r
227         }\r
228     }\r
229 }\r
230 \r
231 #if 0\r
232 static HINSTANCE hdll = 0;\r
233 static int (__cdecl *gr_fmt_find_filter)( const char* file_name ) = 0; \r
234 static int (__cdecl *gr_fmt_read_header)( int filter, int* width, int* height, int* color ) = 0;\r
235 static int (__cdecl *gr_fmt_read_data)( int filter, void* data, int pitch, int color ) = 0;\r
236 static int (__cdecl *gr_fmt_close_filter)( int filter ) = 0;\r
237 static int (__cdecl *gr_fmt_write_image)( void* data, int pitch,\r
238                                           int width, int height, int color,\r
239                                           const char* filename, const char* format ) = 0;\r
240 \r
241 bool  LoadGrFmtLib()\r
242 {\r
243     if( hdll != 0 ) return true;\r
244 \r
245     // load image formats dll\r
246     hdll = LoadLibrary( "vlgrfmts.dll");\r
247     if( !hdll ) return false;\r
248 \r
249     (FARPROC&)gr_fmt_find_filter = GetProcAddress( hdll, "gr_fmt_find_filter" );\r
250     (FARPROC&)gr_fmt_read_header = GetProcAddress( hdll, "gr_fmt_read_header" );\r
251     (FARPROC&)gr_fmt_read_data   = GetProcAddress( hdll, "gr_fmt_read_data" );\r
252     (FARPROC&)gr_fmt_close_filter= GetProcAddress( hdll, "gr_fmt_close_filter" );\r
253     (FARPROC&)gr_fmt_write_image = GetProcAddress( hdll, "gr_fmt_write_image" );\r
254 \r
255     if( !gr_fmt_find_filter || !gr_fmt_read_header || !gr_fmt_read_data )\r
256     {\r
257         FreeLibrary( hdll );\r
258         hdll = 0;\r
259         return false;\r
260     }\r
261     return true;\r
262 }\r
263 #endif\r
264 \r
265 bool  CImage::Load( const char* filename, int desired_color )\r
266 {\r
267     int filter = 0;\r
268     int width = 0, height = 0;\r
269     bool result = false;\r
270     int color = 0;\r
271     \r
272     if( gr_fmt_find_filter == 0 ) return false;\r
273 \r
274     if( !(filter = gr_fmt_find_filter( filename ))) goto exit;\r
275     if( !gr_fmt_read_header( filter, &width, &height, &color )) goto exit;\r
276 \r
277     color = desired_color >= 0 ? desired_color : color > 0;\r
278     \r
279     Create( width, height, color ? 24 : 8);\r
280     if( m_memDC == 0 ) goto exit;\r
281 \r
282     result = gr_fmt_read_data( filter, m_img.imageData, m_img.widthStep, color ) != 0;\r
283 exit:\r
284     gr_fmt_close_filter( filter );\r
285     return result;\r
286 }\r
287 \r
288 \r
289 \r
290 bool  CImage::LoadRect( const char* filename,\r
291                         int desired_color, RECT r )\r
292 {\r
293     int filter = 0;\r
294     int width = 0, height = 0;\r
295     bool result = false;\r
296     int color = 0;\r
297     int r_width = r.right - r.left;\r
298     int r_height = r.bottom - r.top;\r
299     int tmp_step = 0;\r
300     char* tmp = 0;\r
301     \r
302     if( r_width < 0 || r_height < 0 ) return false;\r
303     if( gr_fmt_find_filter == 0 ) return false;\r
304 \r
305     if( !(filter = gr_fmt_find_filter( filename ))) goto exit;\r
306     if( !gr_fmt_read_header( filter, &width, &height, &color )) goto exit;\r
307 \r
308     if( r_width == 0 || r_height == 0 )\r
309     {\r
310         r_width = width;\r
311         r_height = height;\r
312     }\r
313 \r
314     if( (unsigned)r.left >= (unsigned)width ||\r
315         (unsigned)r.top >= (unsigned)height ||\r
316         (unsigned)r.right >= (unsigned)width ||\r
317         (unsigned)r.bottom >= (unsigned)height ) goto exit;\r
318 \r
319     color = desired_color >= 0 ? desired_color : color > 0;\r
320     \r
321     Create( r_width, r_height, color ? 24 : 8);\r
322     if( m_memDC == 0 ) goto exit;\r
323 \r
324     if( r.left == 0 && r.top == 0 &&\r
325         (r_width == 0 || r_width == width) &&\r
326         (r_height == 0 || r_height == height))\r
327     {\r
328         tmp = m_img.imageData;\r
329         tmp_step = m_img.widthStep;\r
330     }\r
331     else\r
332     {\r
333         tmp_step = (width*m_img.nChannels + 3) & -4;\r
334         tmp = (char*)malloc( tmp_step * height );\r
335         if( !tmp ) goto exit;\r
336     }\r
337 \r
338     result = gr_fmt_read_data( filter, tmp, tmp_step, color ) != 0;\r
339 \r
340     if( result && tmp != m_img.imageData )\r
341     {\r
342         int y;\r
343         for( y = 0; y < r_height; y++ )\r
344         {\r
345             memcpy( m_img.imageData + y*m_img.widthStep,\r
346                     tmp + (r.top + y)*tmp_step + r.left*m_img.nChannels,\r
347                     r_width * m_img.nChannels );\r
348         }\r
349     }\r
350 \r
351 exit:\r
352     gr_fmt_close_filter( filter );\r
353     if( tmp != 0 && tmp != m_img.imageData ) free( tmp );\r
354     return result;\r
355 }\r
356 \r
357 \r
358 bool  CImage::Save( const char* filename )\r
359 {\r
360     if( !m_memDC || (m_img.nChannels != 3 && m_img.nChannels != 1) ||\r
361         m_img.depth != IPL_DEPTH_8U ) return false;\r
362 \r
363     return gr_fmt_write_image( m_img.imageData, m_img.widthStep,\r
364                                iplWidth( &m_img ), iplHeight( &m_img ),\r
365                                m_img.nChannels == 3, filename, "BMP" ) != 0;\r
366 }\r
367 \r
368 \r
369 IplImage* CImage::GetImage()\r
370 {\r
371     return m_memDC != 0 ? &m_img : 0;\r
372 }\r
373 \r
374 \r
375 HDC  CImage::GetDC()\r
376 {\r
377     return m_memDC;\r
378 }\r
379 \r
380 \r
381 void CImage::Show( HDC dc, int x, int y, int w, int h, int from_x, int from_y )\r
382 {\r
383     if( m_img.width > 0 )\r
384     {\r
385         uchar buffer[sizeof(BITMAPINFOHEADER) + 1024];\r
386         BITMAPINFO* bmi = (BITMAPINFO*)buffer;\r
387         int bmp_w = Width();\r
388         int bmp_h = Height();\r
389 \r
390         FillBitmapInfo( bmi, bmp_w, bmp_h, m_img.nChannels*8 );\r
391 \r
392         int sw = MAX( MIN( bmp_w - from_x, w ), 0 );\r
393         int sh = MAX( MIN( bmp_h - from_y, h ), 0 );\r
394 \r
395         int res = SetDIBitsToDevice(\r
396               dc,                        // handle to DC\r
397               x,                         // x-coord of destination upper-left corner\r
398               y,                         // y-coord of destination upper-left corner \r
399               sw,                        // source rectangle width\r
400               sh,                        // source rectangle height\r
401               from_x,                    // x-coord of source lower-left corner\r
402               from_y,                    // y-coord of source lower-left corner\r
403               from_y,                    // first scan line in array\r
404               sh,                        // number of scan lines\r
405               m_img.imageData + from_y*m_img.widthStep/* +\r
406               from_x*m_img.nChannels*/,    // array of DIB bits\r
407               (BITMAPINFO*)bmi,          // bitmap information\r
408               DIB_RGB_COLORS );          // RGB or palette indexes\r
409     }\r
410 }\r
411 \r
412 void  CImage::Fill( COLORREF color )\r
413 {\r
414     if( m_memDC )\r
415     {\r
416         HBRUSH br = CreateSolidBrush( color );\r
417         RECT rect;\r
418         GetClipBox( m_memDC, &rect );\r
419         FillRect( m_memDC, &rect, br );\r
420         DeleteObject( br );\r
421     }\r
422 }\r
423 \r
424 void  CImage::DrawToHDC( HDC hDCDst, RECT* pDstRect ) \r
425 {\r
426     HDC hDCSrc = GetDC();\r
427 \r
428     if( pDstRect == NULL ) return;\r
429     if( hDCDst == NULL ) return;\r
430     if( hDCSrc == NULL ) return;\r
431 \r
432     if( Width() > pDstRect->right - pDstRect->left )\r
433     {\r
434         SetStretchBltMode(\r
435                hDCDst,           // handle to device context\r
436                HALFTONE );\r
437     }\r
438     else\r
439     {\r
440         SetStretchBltMode(\r
441                hDCDst,           // handle to device context\r
442                COLORONCOLOR );\r
443     }\r
444 \r
445     ::StretchBlt( \r
446         hDCDst,\r
447         pDstRect->left, pDstRect->top,\r
448         pDstRect->right - pDstRect->left, pDstRect->bottom - pDstRect->top,\r
449         hDCSrc,\r
450         m_img.roi ? m_img.roi->xOffset:0 ,\r
451         m_img.roi ? m_img.roi->yOffset:0,\r
452         Width(),\r
453         Height(),\r
454         SRCCOPY );\r
455 }\r