fixed many warnings from GCC 4.6.1
[profile/ivi/opencv.git] / modules / highgui / src / loadsave.cpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                        Intel License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 //   * Redistribution's of source code must retain the above copyright notice,
20 //     this list of conditions and the following disclaimer.
21 //
22 //   * Redistribution's in binary form must reproduce the above copyright notice,
23 //     this list of conditions and the following disclaimer in the documentation
24 //     and/or other materials provided with the distribution.
25 //
26 //   * The name of Intel Corporation may not be used to endorse or promote products
27 //     derived from this software without specific prior written permission.
28 //
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 //M*/
41
42 //
43 //  Loading and saving IPL images.
44 //
45
46 #include "precomp.hpp"
47 #include "grfmts.hpp"
48 #undef min
49 #undef max
50
51 /****************************************************************************************\
52 *                                      Image Codecs                                      *
53 \****************************************************************************************/
54 namespace cv
55 {
56
57 static vector<ImageDecoder> decoders;
58 static vector<ImageEncoder> encoders;
59
60 ImageDecoder findDecoder( const string& filename )
61 {
62     size_t i, maxlen = 0;
63     for( i = 0; i < decoders.size(); i++ )
64     {
65         size_t len = decoders[i]->signatureLength();
66         maxlen = std::max(maxlen, len);
67     }
68
69     FILE* f= fopen( filename.c_str(), "rb" );
70     if( !f )
71         return ImageDecoder();
72     string signature(maxlen, ' ');
73     maxlen = fread( &signature[0], 1, maxlen, f );
74     fclose(f);
75     signature = signature.substr(0, maxlen);
76
77     for( i = 0; i < decoders.size(); i++ )
78     {
79         if( decoders[i]->checkSignature(signature) )
80             return decoders[i]->newDecoder();
81     }
82
83     return ImageDecoder();
84 }
85
86 ImageDecoder findDecoder( const Mat& buf )
87 {
88     size_t i, maxlen = 0;
89
90     if( buf.rows*buf.cols < 1 || !buf.isContinuous() )
91         return ImageDecoder();
92
93     for( i = 0; i < decoders.size(); i++ )
94     {
95         size_t len = decoders[i]->signatureLength();
96         maxlen = std::max(maxlen, len);
97     }
98
99     size_t bufSize = buf.rows*buf.cols*buf.elemSize();
100     maxlen = std::min(maxlen, bufSize);
101     string signature(maxlen, ' ');
102     memcpy( &signature[0], buf.data, maxlen );
103
104     for( i = 0; i < decoders.size(); i++ )
105     {
106         if( decoders[i]->checkSignature(signature) )
107             return decoders[i]->newDecoder();
108     }
109
110     return ImageDecoder();
111 }
112
113 ImageEncoder findEncoder( const string& _ext )
114 {
115     if( _ext.size() <= 1 )
116         return ImageEncoder();
117
118     const char* ext = strrchr( _ext.c_str(), '.' );
119     if( !ext )
120         return ImageEncoder();
121     int len = 0;
122     for( ext++; isalnum(ext[len]) && len < 128; len++ )
123         ;
124
125     for( size_t i = 0; i < encoders.size(); i++ )
126     {
127         string description = encoders[i]->getDescription();
128         const char* descr = strchr( description.c_str(), '(' );
129
130         while( descr )
131         {
132             descr = strchr( descr + 1, '.' );
133             if( !descr )
134                 break;
135             int j = 0;
136             for( descr++; isalnum(descr[j]) && j < len; j++ )
137             {
138                 int c1 = tolower(ext[j]);
139                 int c2 = tolower(descr[j]);
140                 if( c1 != c2 )
141                     break;
142             }
143             if( j == len && !isalnum(descr[j]))
144                 return encoders[i]->newEncoder();
145             descr += j;
146         }
147     }
148
149     return ImageEncoder();
150 }
151
152 struct ImageCodecInitializer
153 {
154     ImageCodecInitializer()
155     {
156         decoders.push_back( new BmpDecoder );
157         encoders.push_back( new BmpEncoder );
158     #ifdef HAVE_JPEG
159         decoders.push_back( new JpegDecoder );
160         encoders.push_back( new JpegEncoder );
161     #endif
162         decoders.push_back( new SunRasterDecoder );
163         encoders.push_back( new SunRasterEncoder );
164         decoders.push_back( new PxMDecoder );
165         encoders.push_back( new PxMEncoder );
166     #ifdef HAVE_TIFF
167         decoders.push_back( new TiffDecoder );
168     #endif
169         encoders.push_back( new TiffEncoder );
170     #ifdef HAVE_PNG
171         decoders.push_back( new PngDecoder );
172         encoders.push_back( new PngEncoder );
173     #endif
174     #ifdef HAVE_JASPER
175         decoders.push_back( new Jpeg2KDecoder );
176         encoders.push_back( new Jpeg2KEncoder );
177     #endif
178     #ifdef HAVE_OPENEXR
179         decoders.push_back( new ExrDecoder );
180         encoders.push_back( new ExrEncoder );
181     #endif
182     // because it is a generic image I/O API, supporting many formats,
183     // it should be last in the list.
184     #ifdef HAVE_IMAGEIO
185         decoders.push_back( new ImageIODecoder );
186         encoders.push_back( new ImageIOEncoder );
187     #endif
188     }
189 };
190
191 static ImageCodecInitializer initialize_codecs;
192
193
194 enum { LOAD_CVMAT=0, LOAD_IMAGE=1, LOAD_MAT=2 };
195
196 static void*
197 imread_( const string& filename, int flags, int hdrtype, Mat* mat=0 )
198 {
199     IplImage* image = 0;
200     CvMat *matrix = 0;
201     Mat temp, *data = &temp;
202
203     ImageDecoder decoder = findDecoder(filename);
204     if( decoder.empty() )
205         return 0;
206     decoder->setSource(filename);
207     if( !decoder->readHeader() )
208         return 0;
209
210     CvSize size;
211     size.width = decoder->width();
212     size.height = decoder->height();
213
214     int type = decoder->type();
215     if( flags != -1 )
216     {
217         if( (flags & CV_LOAD_IMAGE_ANYDEPTH) == 0 )
218             type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type));
219
220         if( (flags & CV_LOAD_IMAGE_COLOR) != 0 ||
221            ((flags & CV_LOAD_IMAGE_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1) )
222             type = CV_MAKETYPE(CV_MAT_DEPTH(type), 3);
223         else
224             type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1);
225     }
226
227     if( hdrtype == LOAD_CVMAT || hdrtype == LOAD_MAT )
228     {
229         if( hdrtype == LOAD_CVMAT )
230         {
231             matrix = cvCreateMat( size.height, size.width, type );
232             temp = cvarrToMat(matrix);
233         }
234         else
235         {
236             mat->create( size.height, size.width, type );
237             data = mat;
238         }
239     }
240     else
241     {
242         image = cvCreateImage( size, cvIplDepth(type), CV_MAT_CN(type) );
243         temp = cvarrToMat(image);
244     }
245
246     if( !decoder->readData( *data ))
247     {
248         cvReleaseImage( &image );
249         cvReleaseMat( &matrix );
250         if( mat )
251             mat->release();
252         return 0;
253     }
254
255     return hdrtype == LOAD_CVMAT ? (void*)matrix :
256         hdrtype == LOAD_IMAGE ? (void*)image : (void*)mat;
257 }
258
259 Mat imread( const string& filename, int flags )
260 {
261     Mat img;
262     imread_( filename, flags, LOAD_MAT, &img );
263     return img;
264 }
265
266 static bool imwrite_( const string& filename, const Mat& image,
267                       const vector<int>& params, bool flipv )
268 {
269     Mat temp;
270     const Mat* pimage = &image;
271
272     CV_Assert( image.channels() == 1 || image.channels() == 3 || image.channels() == 4 );
273
274     ImageEncoder encoder = findEncoder( filename );
275     if( encoder.empty() )
276         CV_Error( CV_StsError, "could not find a writer for the specified extension" );
277
278     if( !encoder->isFormatSupported(image.depth()) )
279     {
280         CV_Assert( encoder->isFormatSupported(CV_8U) );
281         image.convertTo( temp, CV_8U );
282         pimage = &temp;
283     }
284
285     if( flipv )
286     {
287         flip(*pimage, temp, 0);
288         pimage = &temp;
289     }
290
291     encoder->setDestination( filename );
292     bool code = encoder->write( *pimage, params );
293
294     //    CV_Assert( code );
295     return code;
296 }
297
298 bool imwrite( const string& filename, InputArray _img,
299               const vector<int>& params )
300 {
301     Mat img = _img.getMat();
302     return imwrite_(filename, img, params, false);
303 }
304
305 static void*
306 imdecode_( const Mat& buf, int flags, int hdrtype, Mat* mat=0 )
307 {
308     CV_Assert(buf.data && buf.isContinuous());
309     IplImage* image = 0;
310     CvMat *matrix = 0;
311     Mat temp, *data = &temp;
312     string filename = tempfile();
313     bool removeTempFile = false;
314
315     ImageDecoder decoder = findDecoder(buf);
316     if( decoder.empty() )
317         return 0;
318
319     if( !decoder->setSource(buf) )
320     {
321         FILE* f = fopen( filename.c_str(), "wb" );
322         if( !f )
323             return 0;
324         removeTempFile = true;
325         size_t bufSize = buf.cols*buf.rows*buf.elemSize();
326         fwrite( &buf.data[0], 1, bufSize, f );
327         fclose(f);
328         decoder->setSource(filename);
329     }
330
331     if( !decoder->readHeader() )
332     {
333         if( removeTempFile )
334             remove(filename.c_str());
335         return 0;
336     }
337
338     CvSize size;
339     size.width = decoder->width();
340     size.height = decoder->height();
341
342     int type = decoder->type();
343     if( flags != -1 )
344     {
345         if( (flags & CV_LOAD_IMAGE_ANYDEPTH) == 0 )
346             type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type));
347
348         if( (flags & CV_LOAD_IMAGE_COLOR) != 0 ||
349            ((flags & CV_LOAD_IMAGE_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1) )
350             type = CV_MAKETYPE(CV_MAT_DEPTH(type), 3);
351         else
352             type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1);
353     }
354
355     if( hdrtype == LOAD_CVMAT || hdrtype == LOAD_MAT )
356     {
357         if( hdrtype == LOAD_CVMAT )
358         {
359             matrix = cvCreateMat( size.height, size.width, type );
360             temp = cvarrToMat(matrix);
361         }
362         else
363         {
364             mat->create( size.height, size.width, type );
365             data = mat;
366         }
367     }
368     else
369     {
370         image = cvCreateImage( size, cvIplDepth(type), CV_MAT_CN(type) );
371         temp = cvarrToMat(image);
372     }
373
374     bool code = decoder->readData( *data );
375     if( removeTempFile )
376         remove(filename.c_str());
377
378     if( !code )
379     {
380         cvReleaseImage( &image );
381         cvReleaseMat( &matrix );
382         if( mat )
383             mat->release();
384         return 0;
385     }
386
387     return hdrtype == LOAD_CVMAT ? (void*)matrix :
388         hdrtype == LOAD_IMAGE ? (void*)image : (void*)mat;
389 }
390
391
392 Mat imdecode( InputArray _buf, int flags )
393 {
394     Mat buf = _buf.getMat(), img;
395     imdecode_( buf, flags, LOAD_MAT, &img );
396     return img;
397 }
398     
399 bool imencode( const string& ext, InputArray _image,
400                vector<uchar>& buf, const vector<int>& params )
401 {
402     Mat image = _image.getMat();
403
404     int channels = image.channels();
405     CV_Assert( channels == 1 || channels == 3 || channels == 4 );
406
407     ImageEncoder encoder = findEncoder( ext );
408     if( encoder.empty() )
409         CV_Error( CV_StsError, "could not find encoder for the specified extension" );
410
411     if( !encoder->isFormatSupported(image.depth()) )
412     {
413         CV_Assert( encoder->isFormatSupported(CV_8U) );
414         Mat temp;
415         image.convertTo(temp, CV_8U);
416         image = temp;
417     }
418
419     bool code;
420     if( encoder->setDestination(buf) )
421     {
422         code = encoder->write(image, params);
423         CV_Assert( code );
424     }
425     else
426     {
427         string filename = tempfile();
428         code = encoder->setDestination(filename);
429         CV_Assert( code );
430         code = encoder->write(image, params);
431         CV_Assert( code );
432         FILE* f = fopen( filename.c_str(), "rb" );
433         CV_Assert(f != 0);
434         fseek( f, 0, SEEK_END );
435         long pos = ftell(f);
436         buf.resize((size_t)pos);
437         fseek( f, 0, SEEK_SET );
438         buf.resize(fread( &buf[0], 1, buf.size(), f ));
439         fclose(f);
440         remove(filename.c_str());
441     }
442     return code;
443 }
444
445 }
446
447 /****************************************************************************************\
448 *                         HighGUI loading & saving function implementation               *
449 \****************************************************************************************/
450
451 CV_IMPL int
452 cvHaveImageReader( const char* filename )
453 {
454     cv::ImageDecoder decoder = cv::findDecoder(filename);
455     return !decoder.empty();
456 }
457
458 CV_IMPL int cvHaveImageWriter( const char* filename )
459 {
460     cv::ImageEncoder encoder = cv::findEncoder(filename);
461     return !encoder.empty();
462 }
463
464 CV_IMPL IplImage*
465 cvLoadImage( const char* filename, int iscolor )
466 {
467     return (IplImage*)cv::imread_(filename, iscolor, cv::LOAD_IMAGE );
468 }
469
470 CV_IMPL CvMat*
471 cvLoadImageM( const char* filename, int iscolor )
472 {
473     return (CvMat*)cv::imread_( filename, iscolor, cv::LOAD_CVMAT );
474 }
475
476 CV_IMPL int
477 cvSaveImage( const char* filename, const CvArr* arr, const int* _params )
478 {
479     int i = 0;
480     if( _params )
481     {
482         for( ; _params[i] > 0; i += 2 )
483             ;
484     }
485     return cv::imwrite_(filename, cv::cvarrToMat(arr),
486         i > 0 ? cv::vector<int>(_params, _params+i) : cv::vector<int>(),
487         CV_IS_IMAGE(arr) && ((const IplImage*)arr)->origin == IPL_ORIGIN_BL );
488 }
489
490 /* decode image stored in the buffer */
491 CV_IMPL IplImage*
492 cvDecodeImage( const CvMat* _buf, int iscolor )
493 {
494     CV_Assert( _buf && CV_IS_MAT_CONT(_buf->type) );
495     cv::Mat buf(1, _buf->rows*_buf->cols*CV_ELEM_SIZE(_buf->type), CV_8U, _buf->data.ptr);
496     return (IplImage*)cv::imdecode_(buf, iscolor, cv::LOAD_IMAGE );
497 }
498
499 CV_IMPL CvMat*
500 cvDecodeImageM( const CvMat* _buf, int iscolor )
501 {
502     CV_Assert( _buf && CV_IS_MAT_CONT(_buf->type) );
503     cv::Mat buf(1, _buf->rows*_buf->cols*CV_ELEM_SIZE(_buf->type), CV_8U, _buf->data.ptr);
504     return (CvMat*)cv::imdecode_(buf, iscolor, cv::LOAD_CVMAT );
505 }
506
507 CV_IMPL CvMat*
508 cvEncodeImage( const char* ext, const CvArr* arr, const int* _params )
509 {
510     int i = 0;
511     if( _params )
512     {
513         for( ; _params[i] > 0; i += 2 )
514             ;
515     }
516     cv::Mat img = cv::cvarrToMat(arr);
517     if( CV_IS_IMAGE(arr) && ((const IplImage*)arr)->origin == IPL_ORIGIN_BL )
518     {
519         cv::Mat temp;
520         cv::flip(img, temp, 0);
521         img = temp;
522     }
523     cv::vector<uchar> buf;
524
525     bool code = cv::imencode(ext, img, buf,
526         i > 0 ? std::vector<int>(_params, _params+i) : std::vector<int>() );
527     if( !code )
528         return 0;
529     CvMat* _buf = cvCreateMat(1, (int)buf.size(), CV_8U);
530     memcpy( _buf->data.ptr, &buf[0], buf.size() );
531
532     return _buf;
533 }
534
535 /* End of file. */