Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/imgcodecs/src/loadsave.cpp
16337 views
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
#include "utils.hpp"
49
#include "exif.hpp"
50
#undef min
51
#undef max
52
#include <iostream>
53
#include <fstream>
54
55
/****************************************************************************************\
56
* Image Codecs *
57
\****************************************************************************************/
58
59
namespace cv {
60
61
// TODO Add runtime configuration
62
#define CV_IO_MAX_IMAGE_PARAMS (50)
63
#define CV_IO_MAX_IMAGE_WIDTH (1<<20)
64
#define CV_IO_MAX_IMAGE_HEIGHT (1<<20)
65
#define CV_IO_MAX_IMAGE_PIXELS (1<<30) // 1 Gigapixel
66
67
static Size validateInputImageSize(const Size& size)
68
{
69
CV_Assert(size.width > 0);
70
CV_Assert(size.width <= CV_IO_MAX_IMAGE_WIDTH);
71
CV_Assert(size.height > 0);
72
CV_Assert(size.height <= CV_IO_MAX_IMAGE_HEIGHT);
73
uint64 pixels = (uint64)size.width * (uint64)size.height;
74
CV_Assert(pixels <= CV_IO_MAX_IMAGE_PIXELS);
75
return size;
76
}
77
78
79
namespace {
80
81
class ByteStreamBuffer: public std::streambuf
82
{
83
public:
84
ByteStreamBuffer(char* base, size_t length)
85
{
86
setg(base, base, base + length);
87
}
88
89
protected:
90
virtual pos_type seekoff( off_type offset,
91
std::ios_base::seekdir dir,
92
std::ios_base::openmode ) CV_OVERRIDE
93
{
94
char* whence = eback();
95
if (dir == std::ios_base::cur)
96
{
97
whence = gptr();
98
}
99
else if (dir == std::ios_base::end)
100
{
101
whence = egptr();
102
}
103
char* to = whence + offset;
104
105
// check limits
106
if (to >= eback() && to <= egptr())
107
{
108
setg(eback(), to, egptr());
109
return gptr() - eback();
110
}
111
112
return -1;
113
}
114
};
115
116
}
117
118
/**
119
* @struct ImageCodecInitializer
120
*
121
* Container which stores the registered codecs to be used by OpenCV
122
*/
123
struct ImageCodecInitializer
124
{
125
/**
126
* Default Constructor for the ImageCodeInitializer
127
*/
128
ImageCodecInitializer()
129
{
130
/// BMP Support
131
decoders.push_back( makePtr<BmpDecoder>() );
132
encoders.push_back( makePtr<BmpEncoder>() );
133
134
#ifdef HAVE_IMGCODEC_HDR
135
decoders.push_back( makePtr<HdrDecoder>() );
136
encoders.push_back( makePtr<HdrEncoder>() );
137
#endif
138
#ifdef HAVE_JPEG
139
decoders.push_back( makePtr<JpegDecoder>() );
140
encoders.push_back( makePtr<JpegEncoder>() );
141
#endif
142
#ifdef HAVE_WEBP
143
decoders.push_back( makePtr<WebPDecoder>() );
144
encoders.push_back( makePtr<WebPEncoder>() );
145
#endif
146
#ifdef HAVE_IMGCODEC_SUNRASTER
147
decoders.push_back( makePtr<SunRasterDecoder>() );
148
encoders.push_back( makePtr<SunRasterEncoder>() );
149
#endif
150
#ifdef HAVE_IMGCODEC_PXM
151
decoders.push_back( makePtr<PxMDecoder>() );
152
encoders.push_back( makePtr<PxMEncoder>(PXM_TYPE_AUTO) );
153
encoders.push_back( makePtr<PxMEncoder>(PXM_TYPE_PBM) );
154
encoders.push_back( makePtr<PxMEncoder>(PXM_TYPE_PGM) );
155
encoders.push_back( makePtr<PxMEncoder>(PXM_TYPE_PPM) );
156
decoders.push_back( makePtr<PAMDecoder>() );
157
encoders.push_back( makePtr<PAMEncoder>() );
158
#endif
159
#ifdef HAVE_IMGCODEC_PFM
160
decoders.push_back( makePtr<PFMDecoder>() );
161
encoders.push_back( makePtr<PFMEncoder>() );
162
#endif
163
#ifdef HAVE_TIFF
164
decoders.push_back( makePtr<TiffDecoder>() );
165
encoders.push_back( makePtr<TiffEncoder>() );
166
#endif
167
#ifdef HAVE_PNG
168
decoders.push_back( makePtr<PngDecoder>() );
169
encoders.push_back( makePtr<PngEncoder>() );
170
#endif
171
#ifdef HAVE_GDCM
172
decoders.push_back( makePtr<DICOMDecoder>() );
173
#endif
174
#ifdef HAVE_JASPER
175
decoders.push_back( makePtr<Jpeg2KDecoder>() );
176
encoders.push_back( makePtr<Jpeg2KEncoder>() );
177
#endif
178
#ifdef HAVE_OPENEXR
179
decoders.push_back( makePtr<ExrDecoder>() );
180
encoders.push_back( makePtr<ExrEncoder>() );
181
#endif
182
183
#ifdef HAVE_GDAL
184
/// Attach the GDAL Decoder
185
decoders.push_back( makePtr<GdalDecoder>() );
186
#endif/*HAVE_GDAL*/
187
}
188
189
std::vector<ImageDecoder> decoders;
190
std::vector<ImageEncoder> encoders;
191
};
192
193
static ImageCodecInitializer codecs;
194
195
/**
196
* Find the decoders
197
*
198
* @param[in] filename File to search
199
*
200
* @return Image decoder to parse image file.
201
*/
202
static ImageDecoder findDecoder( const String& filename ) {
203
204
size_t i, maxlen = 0;
205
206
/// iterate through list of registered codecs
207
for( i = 0; i < codecs.decoders.size(); i++ )
208
{
209
size_t len = codecs.decoders[i]->signatureLength();
210
maxlen = std::max(maxlen, len);
211
}
212
213
/// Open the file
214
FILE* f= fopen( filename.c_str(), "rb" );
215
216
/// in the event of a failure, return an empty image decoder
217
if( !f )
218
return ImageDecoder();
219
220
// read the file signature
221
String signature(maxlen, ' ');
222
maxlen = fread( (void*)signature.c_str(), 1, maxlen, f );
223
fclose(f);
224
signature = signature.substr(0, maxlen);
225
226
/// compare signature against all decoders
227
for( i = 0; i < codecs.decoders.size(); i++ )
228
{
229
if( codecs.decoders[i]->checkSignature(signature) )
230
return codecs.decoders[i]->newDecoder();
231
}
232
233
/// If no decoder was found, return base type
234
return ImageDecoder();
235
}
236
237
static ImageDecoder findDecoder( const Mat& buf )
238
{
239
size_t i, maxlen = 0;
240
241
if( buf.rows*buf.cols < 1 || !buf.isContinuous() )
242
return ImageDecoder();
243
244
for( i = 0; i < codecs.decoders.size(); i++ )
245
{
246
size_t len = codecs.decoders[i]->signatureLength();
247
maxlen = std::max(maxlen, len);
248
}
249
250
String signature(maxlen, ' ');
251
size_t bufSize = buf.rows*buf.cols*buf.elemSize();
252
maxlen = std::min(maxlen, bufSize);
253
memcpy( (void*)signature.c_str(), buf.data, maxlen );
254
255
for( i = 0; i < codecs.decoders.size(); i++ )
256
{
257
if( codecs.decoders[i]->checkSignature(signature) )
258
return codecs.decoders[i]->newDecoder();
259
}
260
261
return ImageDecoder();
262
}
263
264
static ImageEncoder findEncoder( const String& _ext )
265
{
266
if( _ext.size() <= 1 )
267
return ImageEncoder();
268
269
const char* ext = strrchr( _ext.c_str(), '.' );
270
if( !ext )
271
return ImageEncoder();
272
int len = 0;
273
for( ext++; len < 128 && isalnum(ext[len]); len++ )
274
;
275
276
for( size_t i = 0; i < codecs.encoders.size(); i++ )
277
{
278
String description = codecs.encoders[i]->getDescription();
279
const char* descr = strchr( description.c_str(), '(' );
280
281
while( descr )
282
{
283
descr = strchr( descr + 1, '.' );
284
if( !descr )
285
break;
286
int j = 0;
287
for( descr++; j < len && isalnum(descr[j]) ; j++ )
288
{
289
int c1 = tolower(ext[j]);
290
int c2 = tolower(descr[j]);
291
if( c1 != c2 )
292
break;
293
}
294
if( j == len && !isalnum(descr[j]))
295
return codecs.encoders[i]->newEncoder();
296
descr += j;
297
}
298
}
299
300
return ImageEncoder();
301
}
302
303
304
enum { LOAD_CVMAT=0, LOAD_IMAGE=1, LOAD_MAT=2 };
305
306
static void ExifTransform(int orientation, Mat& img)
307
{
308
switch( orientation )
309
{
310
case IMAGE_ORIENTATION_TL: //0th row == visual top, 0th column == visual left-hand side
311
//do nothing, the image already has proper orientation
312
break;
313
case IMAGE_ORIENTATION_TR: //0th row == visual top, 0th column == visual right-hand side
314
flip(img, img, 1); //flip horizontally
315
break;
316
case IMAGE_ORIENTATION_BR: //0th row == visual bottom, 0th column == visual right-hand side
317
flip(img, img, -1);//flip both horizontally and vertically
318
break;
319
case IMAGE_ORIENTATION_BL: //0th row == visual bottom, 0th column == visual left-hand side
320
flip(img, img, 0); //flip vertically
321
break;
322
case IMAGE_ORIENTATION_LT: //0th row == visual left-hand side, 0th column == visual top
323
transpose(img, img);
324
break;
325
case IMAGE_ORIENTATION_RT: //0th row == visual right-hand side, 0th column == visual top
326
transpose(img, img);
327
flip(img, img, 1); //flip horizontally
328
break;
329
case IMAGE_ORIENTATION_RB: //0th row == visual right-hand side, 0th column == visual bottom
330
transpose(img, img);
331
flip(img, img, -1); //flip both horizontally and vertically
332
break;
333
case IMAGE_ORIENTATION_LB: //0th row == visual left-hand side, 0th column == visual bottom
334
transpose(img, img);
335
flip(img, img, 0); //flip vertically
336
break;
337
default:
338
//by default the image read has normal (JPEG_ORIENTATION_TL) orientation
339
break;
340
}
341
}
342
343
static void ApplyExifOrientation(const String& filename, Mat& img)
344
{
345
int orientation = IMAGE_ORIENTATION_TL;
346
347
if (filename.size() > 0)
348
{
349
std::ifstream stream( filename.c_str(), std::ios_base::in | std::ios_base::binary );
350
ExifReader reader( stream );
351
if( reader.parse() )
352
{
353
ExifEntry_t entry = reader.getTag( ORIENTATION );
354
if (entry.tag != INVALID_TAG)
355
{
356
orientation = entry.field_u16; //orientation is unsigned short, so check field_u16
357
}
358
}
359
stream.close();
360
}
361
362
ExifTransform(orientation, img);
363
}
364
365
static void ApplyExifOrientation(const Mat& buf, Mat& img)
366
{
367
int orientation = IMAGE_ORIENTATION_TL;
368
369
if( buf.isContinuous() )
370
{
371
ByteStreamBuffer bsb( reinterpret_cast<char*>(buf.data), buf.total() * buf.elemSize() );
372
std::istream stream( &bsb );
373
ExifReader reader( stream );
374
if( reader.parse() )
375
{
376
ExifEntry_t entry = reader.getTag( ORIENTATION );
377
if (entry.tag != INVALID_TAG)
378
{
379
orientation = entry.field_u16; //orientation is unsigned short, so check field_u16
380
}
381
}
382
}
383
384
ExifTransform(orientation, img);
385
}
386
387
/**
388
* Read an image into memory and return the information
389
*
390
* @param[in] filename File to load
391
* @param[in] flags Flags
392
* @param[in] hdrtype { LOAD_CVMAT=0,
393
* LOAD_IMAGE=1,
394
* LOAD_MAT=2
395
* }
396
* @param[in] mat Reference to C++ Mat object (If LOAD_MAT)
397
* @param[in] scale_denom Scale value
398
*
399
*/
400
static void*
401
imread_( const String& filename, int flags, int hdrtype, Mat* mat=0 )
402
{
403
CV_Assert(mat || hdrtype != LOAD_MAT); // mat is required in LOAD_MAT case
404
405
IplImage* image = 0;
406
CvMat *matrix = 0;
407
Mat temp, *data = &temp;
408
409
/// Search for the relevant decoder to handle the imagery
410
ImageDecoder decoder;
411
412
#ifdef HAVE_GDAL
413
if(flags != IMREAD_UNCHANGED && (flags & IMREAD_LOAD_GDAL) == IMREAD_LOAD_GDAL ){
414
decoder = GdalDecoder().newDecoder();
415
}else{
416
#endif
417
decoder = findDecoder( filename );
418
#ifdef HAVE_GDAL
419
}
420
#endif
421
422
/// if no decoder was found, return nothing.
423
if( !decoder ){
424
return 0;
425
}
426
427
int scale_denom = 1;
428
if( flags > IMREAD_LOAD_GDAL )
429
{
430
if( flags & IMREAD_REDUCED_GRAYSCALE_2 )
431
scale_denom = 2;
432
else if( flags & IMREAD_REDUCED_GRAYSCALE_4 )
433
scale_denom = 4;
434
else if( flags & IMREAD_REDUCED_GRAYSCALE_8 )
435
scale_denom = 8;
436
}
437
438
/// set the scale_denom in the driver
439
decoder->setScale( scale_denom );
440
441
/// set the filename in the driver
442
decoder->setSource( filename );
443
444
CV_TRY
445
{
446
// read the header to make sure it succeeds
447
if( !decoder->readHeader() )
448
return 0;
449
}
450
CV_CATCH (cv::Exception, e)
451
{
452
std::cerr << "imread_('" << filename << "'): can't read header: " << e.what() << std::endl << std::flush;
453
return 0;
454
}
455
CV_CATCH_ALL
456
{
457
std::cerr << "imread_('" << filename << "'): can't read header: unknown exception" << std::endl << std::flush;
458
return 0;
459
}
460
461
462
// established the required input image size
463
Size size = validateInputImageSize(Size(decoder->width(), decoder->height()));
464
465
// grab the decoded type
466
int type = decoder->type();
467
if( (flags & IMREAD_LOAD_GDAL) != IMREAD_LOAD_GDAL && flags != IMREAD_UNCHANGED )
468
{
469
if( (flags & CV_LOAD_IMAGE_ANYDEPTH) == 0 )
470
type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type));
471
472
if( (flags & CV_LOAD_IMAGE_COLOR) != 0 ||
473
((flags & CV_LOAD_IMAGE_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1) )
474
type = CV_MAKETYPE(CV_MAT_DEPTH(type), 3);
475
else
476
type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1);
477
}
478
479
if( hdrtype == LOAD_CVMAT || hdrtype == LOAD_MAT )
480
{
481
if( hdrtype == LOAD_CVMAT )
482
{
483
matrix = cvCreateMat( size.height, size.width, type );
484
temp = cvarrToMat( matrix );
485
}
486
else
487
{
488
mat->create( size.height, size.width, type );
489
data = mat;
490
}
491
}
492
else
493
{
494
image = cvCreateImage(cvSize(size), cvIplDepth(type), CV_MAT_CN(type));
495
temp = cvarrToMat( image );
496
}
497
498
// read the image data
499
bool success = false;
500
CV_TRY
501
{
502
if (decoder->readData(*data))
503
success = true;
504
}
505
CV_CATCH (cv::Exception, e)
506
{
507
std::cerr << "imread_('" << filename << "'): can't read data: " << e.what() << std::endl << std::flush;
508
}
509
CV_CATCH_ALL
510
{
511
std::cerr << "imread_('" << filename << "'): can't read data: unknown exception" << std::endl << std::flush;
512
}
513
if (!success)
514
{
515
cvReleaseImage( &image );
516
cvReleaseMat( &matrix );
517
if( mat )
518
mat->release();
519
return 0;
520
}
521
522
if( decoder->setScale( scale_denom ) > 1 ) // if decoder is JpegDecoder then decoder->setScale always returns 1
523
{
524
resize( *mat, *mat, Size( size.width / scale_denom, size.height / scale_denom ), 0, 0, INTER_LINEAR_EXACT);
525
}
526
527
return hdrtype == LOAD_CVMAT ? (void*)matrix :
528
hdrtype == LOAD_IMAGE ? (void*)image : (void*)mat;
529
}
530
531
532
/**
533
* Read an image into memory and return the information
534
*
535
* @param[in] filename File to load
536
* @param[in] flags Flags
537
* @param[in] mats Reference to C++ vector<Mat> object to hold the images
538
*
539
*/
540
static bool
541
imreadmulti_(const String& filename, int flags, std::vector<Mat>& mats)
542
{
543
/// Search for the relevant decoder to handle the imagery
544
ImageDecoder decoder;
545
546
#ifdef HAVE_GDAL
547
if (flags != IMREAD_UNCHANGED && (flags & IMREAD_LOAD_GDAL) == IMREAD_LOAD_GDAL){
548
decoder = GdalDecoder().newDecoder();
549
}
550
else{
551
#endif
552
decoder = findDecoder(filename);
553
#ifdef HAVE_GDAL
554
}
555
#endif
556
557
/// if no decoder was found, return nothing.
558
if (!decoder){
559
return 0;
560
}
561
562
/// set the filename in the driver
563
decoder->setSource(filename);
564
565
// read the header to make sure it succeeds
566
CV_TRY
567
{
568
// read the header to make sure it succeeds
569
if( !decoder->readHeader() )
570
return 0;
571
}
572
CV_CATCH (cv::Exception, e)
573
{
574
std::cerr << "imreadmulti_('" << filename << "'): can't read header: " << e.what() << std::endl << std::flush;
575
return 0;
576
}
577
CV_CATCH_ALL
578
{
579
std::cerr << "imreadmulti_('" << filename << "'): can't read header: unknown exception" << std::endl << std::flush;
580
return 0;
581
}
582
583
for (;;)
584
{
585
// grab the decoded type
586
int type = decoder->type();
587
if( (flags & IMREAD_LOAD_GDAL) != IMREAD_LOAD_GDAL && flags != IMREAD_UNCHANGED )
588
{
589
if ((flags & CV_LOAD_IMAGE_ANYDEPTH) == 0)
590
type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type));
591
592
if ((flags & CV_LOAD_IMAGE_COLOR) != 0 ||
593
((flags & CV_LOAD_IMAGE_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1))
594
type = CV_MAKETYPE(CV_MAT_DEPTH(type), 3);
595
else
596
type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1);
597
}
598
599
// established the required input image size
600
Size size = validateInputImageSize(Size(decoder->width(), decoder->height()));
601
602
// read the image data
603
Mat mat(size.height, size.width, type);
604
bool success = false;
605
CV_TRY
606
{
607
if (decoder->readData(mat))
608
success = true;
609
}
610
CV_CATCH (cv::Exception, e)
611
{
612
std::cerr << "imreadmulti_('" << filename << "'): can't read data: " << e.what() << std::endl << std::flush;
613
}
614
CV_CATCH_ALL
615
{
616
std::cerr << "imreadmulti_('" << filename << "'): can't read data: unknown exception" << std::endl << std::flush;
617
}
618
if (!success)
619
break;
620
621
// optionally rotate the data if EXIF' orientation flag says so
622
if( (flags & IMREAD_IGNORE_ORIENTATION) == 0 && flags != IMREAD_UNCHANGED )
623
{
624
ApplyExifOrientation(filename, mat);
625
}
626
627
mats.push_back(mat);
628
if (!decoder->nextPage())
629
{
630
break;
631
}
632
}
633
634
return !mats.empty();
635
}
636
637
/**
638
* Read an image
639
*
640
* This function merely calls the actual implementation above and returns itself.
641
*
642
* @param[in] filename File to load
643
* @param[in] flags Flags you wish to set.
644
*/
645
Mat imread( const String& filename, int flags )
646
{
647
CV_TRACE_FUNCTION();
648
649
/// create the basic container
650
Mat img;
651
652
/// load the data
653
imread_( filename, flags, LOAD_MAT, &img );
654
655
/// optionally rotate the data if EXIF' orientation flag says so
656
if( !img.empty() && (flags & IMREAD_IGNORE_ORIENTATION) == 0 && flags != IMREAD_UNCHANGED )
657
{
658
ApplyExifOrientation(filename, img);
659
}
660
661
/// return a reference to the data
662
return img;
663
}
664
665
/**
666
* Read a multi-page image
667
*
668
* This function merely calls the actual implementation above and returns itself.
669
*
670
* @param[in] filename File to load
671
* @param[in] mats Reference to C++ vector<Mat> object to hold the images
672
* @param[in] flags Flags you wish to set.
673
*
674
*/
675
bool imreadmulti(const String& filename, std::vector<Mat>& mats, int flags)
676
{
677
CV_TRACE_FUNCTION();
678
679
return imreadmulti_(filename, flags, mats);
680
}
681
682
static bool imwrite_( const String& filename, const std::vector<Mat>& img_vec,
683
const std::vector<int>& params, bool flipv )
684
{
685
bool isMultiImg = img_vec.size() > 1;
686
std::vector<Mat> write_vec;
687
688
ImageEncoder encoder = findEncoder( filename );
689
if( !encoder )
690
CV_Error( CV_StsError, "could not find a writer for the specified extension" );
691
692
for (size_t page = 0; page < img_vec.size(); page++)
693
{
694
Mat image = img_vec[page];
695
CV_Assert( image.channels() == 1 || image.channels() == 3 || image.channels() == 4 );
696
697
Mat temp;
698
if( !encoder->isFormatSupported(image.depth()) )
699
{
700
CV_Assert( encoder->isFormatSupported(CV_8U) );
701
image.convertTo( temp, CV_8U );
702
image = temp;
703
}
704
705
if( flipv )
706
{
707
flip(image, temp, 0);
708
image = temp;
709
}
710
711
write_vec.push_back(image);
712
}
713
714
encoder->setDestination( filename );
715
CV_Assert(params.size() <= CV_IO_MAX_IMAGE_PARAMS*2);
716
bool code = false;
717
try
718
{
719
if (!isMultiImg)
720
code = encoder->write( write_vec[0], params );
721
else
722
code = encoder->writemulti( write_vec, params ); //to be implemented
723
}
724
catch (const cv::Exception& e)
725
{
726
std::cerr << "imwrite_('" << filename << "'): can't write data: " << e.what() << std::endl << std::flush;
727
}
728
catch (...)
729
{
730
std::cerr << "imwrite_('" << filename << "'): can't write data: unknown exception" << std::endl << std::flush;
731
}
732
733
// CV_Assert( code );
734
return code;
735
}
736
737
bool imwrite( const String& filename, InputArray _img,
738
const std::vector<int>& params )
739
{
740
CV_TRACE_FUNCTION();
741
std::vector<Mat> img_vec;
742
if (_img.isMatVector() || _img.isUMatVector())
743
_img.getMatVector(img_vec);
744
else
745
img_vec.push_back(_img.getMat());
746
747
CV_Assert(!img_vec.empty());
748
return imwrite_(filename, img_vec, params, false);
749
}
750
751
static void*
752
imdecode_( const Mat& buf, int flags, int hdrtype, Mat* mat=0 )
753
{
754
CV_Assert(!buf.empty() && buf.isContinuous());
755
IplImage* image = 0;
756
CvMat *matrix = 0;
757
Mat temp, *data = &temp;
758
String filename;
759
760
ImageDecoder decoder = findDecoder(buf);
761
if( !decoder )
762
return 0;
763
764
if( !decoder->setSource(buf) )
765
{
766
filename = tempfile();
767
FILE* f = fopen( filename.c_str(), "wb" );
768
if( !f )
769
return 0;
770
size_t bufSize = buf.cols*buf.rows*buf.elemSize();
771
if( fwrite( buf.ptr(), 1, bufSize, f ) != bufSize )
772
{
773
fclose( f );
774
CV_Error( CV_StsError, "failed to write image data to temporary file" );
775
}
776
if( fclose(f) != 0 )
777
{
778
CV_Error( CV_StsError, "failed to write image data to temporary file" );
779
}
780
decoder->setSource(filename);
781
}
782
783
bool success = false;
784
CV_TRY
785
{
786
if (decoder->readHeader())
787
success = true;
788
}
789
CV_CATCH (cv::Exception, e)
790
{
791
std::cerr << "imdecode_('" << filename << "'): can't read header: " << e.what() << std::endl << std::flush;
792
}
793
CV_CATCH_ALL
794
{
795
std::cerr << "imdecode_('" << filename << "'): can't read header: unknown exception" << std::endl << std::flush;
796
}
797
if (!success)
798
{
799
decoder.release();
800
if (!filename.empty())
801
{
802
if (0 != remove(filename.c_str()))
803
{
804
std::cerr << "unable to remove temporary file:" << filename << std::endl << std::flush;
805
}
806
}
807
return 0;
808
}
809
810
// established the required input image size
811
Size size = validateInputImageSize(Size(decoder->width(), decoder->height()));
812
813
int type = decoder->type();
814
if( (flags & IMREAD_LOAD_GDAL) != IMREAD_LOAD_GDAL && flags != IMREAD_UNCHANGED )
815
{
816
if( (flags & CV_LOAD_IMAGE_ANYDEPTH) == 0 )
817
type = CV_MAKETYPE(CV_8U, CV_MAT_CN(type));
818
819
if( (flags & CV_LOAD_IMAGE_COLOR) != 0 ||
820
((flags & CV_LOAD_IMAGE_ANYCOLOR) != 0 && CV_MAT_CN(type) > 1) )
821
type = CV_MAKETYPE(CV_MAT_DEPTH(type), 3);
822
else
823
type = CV_MAKETYPE(CV_MAT_DEPTH(type), 1);
824
}
825
826
if( hdrtype == LOAD_CVMAT || hdrtype == LOAD_MAT )
827
{
828
if( hdrtype == LOAD_CVMAT )
829
{
830
matrix = cvCreateMat( size.height, size.width, type );
831
temp = cvarrToMat(matrix);
832
}
833
else
834
{
835
mat->create( size.height, size.width, type );
836
data = mat;
837
}
838
}
839
else
840
{
841
image = cvCreateImage(cvSize(size), cvIplDepth(type), CV_MAT_CN(type));
842
temp = cvarrToMat(image);
843
}
844
845
success = false;
846
CV_TRY
847
{
848
if (decoder->readData(*data))
849
success = true;
850
}
851
CV_CATCH (cv::Exception, e)
852
{
853
std::cerr << "imdecode_('" << filename << "'): can't read data: " << e.what() << std::endl << std::flush;
854
}
855
CV_CATCH_ALL
856
{
857
std::cerr << "imdecode_('" << filename << "'): can't read data: unknown exception" << std::endl << std::flush;
858
}
859
decoder.release();
860
if (!filename.empty())
861
{
862
if (0 != remove(filename.c_str()))
863
{
864
std::cerr << "unable to remove temporary file:" << filename << std::endl << std::flush;
865
}
866
}
867
868
if (!success)
869
{
870
cvReleaseImage( &image );
871
cvReleaseMat( &matrix );
872
if( mat )
873
mat->release();
874
return 0;
875
}
876
877
return hdrtype == LOAD_CVMAT ? (void*)matrix :
878
hdrtype == LOAD_IMAGE ? (void*)image : (void*)mat;
879
}
880
881
882
Mat imdecode( InputArray _buf, int flags )
883
{
884
CV_TRACE_FUNCTION();
885
886
Mat buf = _buf.getMat(), img;
887
imdecode_( buf, flags, LOAD_MAT, &img );
888
889
/// optionally rotate the data if EXIF' orientation flag says so
890
if( !img.empty() && (flags & IMREAD_IGNORE_ORIENTATION) == 0 && flags != IMREAD_UNCHANGED )
891
{
892
ApplyExifOrientation(buf, img);
893
}
894
895
return img;
896
}
897
898
Mat imdecode( InputArray _buf, int flags, Mat* dst )
899
{
900
CV_TRACE_FUNCTION();
901
902
Mat buf = _buf.getMat(), img;
903
dst = dst ? dst : &img;
904
imdecode_( buf, flags, LOAD_MAT, dst );
905
906
/// optionally rotate the data if EXIF' orientation flag says so
907
if( !dst->empty() && (flags & IMREAD_IGNORE_ORIENTATION) == 0 && flags != IMREAD_UNCHANGED )
908
{
909
ApplyExifOrientation(buf, *dst);
910
}
911
912
return *dst;
913
}
914
915
bool imencode( const String& ext, InputArray _image,
916
std::vector<uchar>& buf, const std::vector<int>& params )
917
{
918
CV_TRACE_FUNCTION();
919
920
Mat image = _image.getMat();
921
922
int channels = image.channels();
923
CV_Assert( channels == 1 || channels == 3 || channels == 4 );
924
925
ImageEncoder encoder = findEncoder( ext );
926
if( !encoder )
927
CV_Error( CV_StsError, "could not find encoder for the specified extension" );
928
929
if( !encoder->isFormatSupported(image.depth()) )
930
{
931
CV_Assert( encoder->isFormatSupported(CV_8U) );
932
Mat temp;
933
image.convertTo(temp, CV_8U);
934
image = temp;
935
}
936
937
bool code;
938
if( encoder->setDestination(buf) )
939
{
940
code = encoder->write(image, params);
941
encoder->throwOnEror();
942
CV_Assert( code );
943
}
944
else
945
{
946
String filename = tempfile();
947
code = encoder->setDestination(filename);
948
CV_Assert( code );
949
950
code = encoder->write(image, params);
951
encoder->throwOnEror();
952
CV_Assert( code );
953
954
FILE* f = fopen( filename.c_str(), "rb" );
955
CV_Assert(f != 0);
956
fseek( f, 0, SEEK_END );
957
long pos = ftell(f);
958
buf.resize((size_t)pos);
959
fseek( f, 0, SEEK_SET );
960
buf.resize(fread( &buf[0], 1, buf.size(), f ));
961
fclose(f);
962
remove(filename.c_str());
963
}
964
return code;
965
}
966
967
}
968
969
/****************************************************************************************\
970
* Imgcodecs loading & saving function implementation *
971
\****************************************************************************************/
972
973
CV_IMPL int
974
cvHaveImageReader( const char* filename )
975
{
976
cv::ImageDecoder decoder = cv::findDecoder(filename);
977
return !decoder.empty();
978
}
979
980
CV_IMPL int cvHaveImageWriter( const char* filename )
981
{
982
cv::ImageEncoder encoder = cv::findEncoder(filename);
983
return !encoder.empty();
984
}
985
986
CV_IMPL IplImage*
987
cvLoadImage( const char* filename, int iscolor )
988
{
989
return (IplImage*)cv::imread_(filename, iscolor, cv::LOAD_IMAGE );
990
}
991
992
CV_IMPL CvMat*
993
cvLoadImageM( const char* filename, int iscolor )
994
{
995
return (CvMat*)cv::imread_( filename, iscolor, cv::LOAD_CVMAT );
996
}
997
998
CV_IMPL int
999
cvSaveImage( const char* filename, const CvArr* arr, const int* _params )
1000
{
1001
int i = 0;
1002
if( _params )
1003
{
1004
for( ; _params[i] > 0; i += 2 )
1005
CV_Assert(i < CV_IO_MAX_IMAGE_PARAMS*2); // Limit number of params for security reasons
1006
}
1007
return cv::imwrite_(filename, cv::cvarrToMat(arr),
1008
i > 0 ? std::vector<int>(_params, _params+i) : std::vector<int>(),
1009
CV_IS_IMAGE(arr) && ((const IplImage*)arr)->origin == IPL_ORIGIN_BL );
1010
}
1011
1012
/* decode image stored in the buffer */
1013
CV_IMPL IplImage*
1014
cvDecodeImage( const CvMat* _buf, int iscolor )
1015
{
1016
CV_Assert( _buf && CV_IS_MAT_CONT(_buf->type) );
1017
cv::Mat buf(1, _buf->rows*_buf->cols*CV_ELEM_SIZE(_buf->type), CV_8U, _buf->data.ptr);
1018
return (IplImage*)cv::imdecode_(buf, iscolor, cv::LOAD_IMAGE );
1019
}
1020
1021
CV_IMPL CvMat*
1022
cvDecodeImageM( const CvMat* _buf, int iscolor )
1023
{
1024
CV_Assert( _buf && CV_IS_MAT_CONT(_buf->type) );
1025
cv::Mat buf(1, _buf->rows*_buf->cols*CV_ELEM_SIZE(_buf->type), CV_8U, _buf->data.ptr);
1026
return (CvMat*)cv::imdecode_(buf, iscolor, cv::LOAD_CVMAT );
1027
}
1028
1029
CV_IMPL CvMat*
1030
cvEncodeImage( const char* ext, const CvArr* arr, const int* _params )
1031
{
1032
int i = 0;
1033
if( _params )
1034
{
1035
for( ; _params[i] > 0; i += 2 )
1036
CV_Assert(i < CV_IO_MAX_IMAGE_PARAMS*2); // Limit number of params for security reasons
1037
}
1038
cv::Mat img = cv::cvarrToMat(arr);
1039
if( CV_IS_IMAGE(arr) && ((const IplImage*)arr)->origin == IPL_ORIGIN_BL )
1040
{
1041
cv::Mat temp;
1042
cv::flip(img, temp, 0);
1043
img = temp;
1044
}
1045
std::vector<uchar> buf;
1046
1047
bool code = cv::imencode(ext, img, buf,
1048
i > 0 ? std::vector<int>(_params, _params+i) : std::vector<int>() );
1049
if( !code )
1050
return 0;
1051
CvMat* _buf = cvCreateMat(1, (int)buf.size(), CV_8U);
1052
memcpy( _buf->data.ptr, &buf[0], buf.size() );
1053
1054
return _buf;
1055
}
1056
1057
/* End of file. */
1058
1059