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 "_highgui.h"
47 #include "grfmts.h"
48
49 #if 0
50 /****************************************************************************************\
51 * Path class (list of search folders) *
52 \****************************************************************************************/
53
54 class CvFilePath
55 {
56 public:
57 CvFilePath();
58 ~CvFilePath();
59
60 // preprocess folder or file name - calculate its length,
61 // check for invalid symbols in the name and substitute
62 // all backslashes with simple slashes.
63 // the result is put into the specified buffer
64 static int Preprocess( const char* filename, char* buffer );
65
66 // add folder to the path
67 bool Add( const char* path );
68
69 // clear the path
70 void Clear();
71
72 // return the path - string, where folders are separated by ';'
73 const char* Get() const { return m_path; };
74
75 // find the file in the path
76 const char* Find( const char* filename, char* buffer ) const;
77
78 // return the first folder from the path
79 // the returned string is not terminated by '\0'!!!
80 // its length is returned via len parameter
81 const char* First( int& len ) const;
82
83 // return the folder, next in the path after the specified folder.
84 // see also note to First() method
85 const char* Next( const char* folder, int& len ) const;
86
87 protected:
88
89 char* m_path;
90 int m_maxsize;
91 int m_len;
92 };
93
94
95 void CvFilePath::Clear()
96 {
97 delete[] m_path;
98 m_maxsize = m_len = 0;
99 }
100
101
102 CvFilePath::CvFilePath()
103 {
104 m_path = 0;
105 m_maxsize = m_len = 0;
106 }
107
108
109 CvFilePath::~CvFilePath()
110 {
111 Clear();
112 }
113
114
115 bool CvFilePath::Add( const char* path )
116 {
117 char buffer[_MAX_PATH + 1];
118 int len = Preprocess( path, buffer );
119
120 if( len < 0 )
121 return false;
122
123 if( m_len + len + 3 // +1 for one more ';',
124 // another +1 for possible additional '/',
125 // and the last +1 is for '\0'
126 > m_maxsize )
127 {
128 int new_size = (m_len + len + 3 + 1023) & -1024;
129 char* new_path = new char[new_size];
130
131 if( m_path )
132 {
133 memcpy( new_path, m_path, m_len );
134 delete[] m_path;
135 }
136
137 m_path = new_path;
138 m_maxsize = new_size;
139 }
140
141 m_path[m_len++] = ';';
142 memcpy( m_path + m_len, buffer, len );
143 m_len += len;
144
145 if( m_path[m_len] != '/' )
146 m_path[m_len++] = '/';
147
148 m_path[m_len] = '\0'; // '\0' is not counted in m_len.
149
150 return true;
151 }
152
153
154 const char* CvFilePath::First( int& len ) const
155 {
156 const char* path = (const char*)(m_path ? m_path : "");
157 const char* path_end = path;
158
159 while( *path_end && *path_end != ';' )
160 path_end++;
161
162 len = path_end - path;
163 return path;
164 }
165
166
167 const char* CvFilePath::Next( const char* folder, int& len ) const
168 {
169 if( !folder || folder < m_path || folder >= m_path + m_len )
170 return 0;
171
172 folder = strchr( folder, ';' );
173 if( folder )
174 {
175 const char* folder_end = ++folder;
176 while( *folder_end && *folder_end != ';' )
177 folder_end++;
178
179 len = folder_end - folder;
180 }
181
182 return folder;
183 }
184
185
186 const char* CvFilePath::Find( const char* filename, char* buffer ) const
187 {
188 char path0[_MAX_PATH + 1];
189 int len = Preprocess( filename, path0 );
190 int folder_len = 0;
191 const char* folder = First( folder_len );
192 char* name_only = 0;
193 char* name = path0;
194 FILE* f = 0;
195
196 if( len < 0 )
197 return 0;
198
199 do
200 {
201 if( folder_len + len <= _MAX_PATH )
202 {
203 memcpy( buffer, folder, folder_len );
204 strcpy( buffer + folder_len, name );
205
206 f = fopen( buffer, "rb" );
207 if( f )
208 break;
209 }
210
211 if( name != name_only )
212 {
213 name_only = strrchr( path0, '/' );
214 if( !name_only )
215 name_only = path0;
216 else
217 name_only++;
218 len = strlen( name_only );
219 name = name_only;
220 }
221 }
222 while( (folder = Next( folder, folder_len )) != 0 );
223
224 filename = 0;
225
226 if( f )
227 {
228 filename = (const char*)buffer;
229 fclose(f);
230 }
231
232 return filename;
233 }
234
235
236 int CvFilePath::Preprocess( const char* str, char* buffer )
237 {
238 int i;
239
240 if( !str || !buffer )
241 return -1;
242
243 for( i = 0; i <= _MAX_PATH; i++ )
244 {
245 buffer[i] = str[i];
246
247 if( isalnum(str[i])) // fast check to skip most of characters
248 continue;
249
250 if( str[i] == '\0' )
251 break;
252
253 if( str[i] == '\\' ) // convert back slashes to simple slashes
254 // (for Win32-*NIX compatibility)
255 buffer[i] = '/';
256
257 if (str[i] == '*' || str[i] == '?' || str[i] == '\"' ||
258 str[i] == '>' || str[i] == '<' ||
259 str[i] == ';' || /* used as a separator in the path */
260 #ifndef WIN32
261 str[i] == ',' || str[i] == '%' ||
262 #endif
263 str[i] == '|')
264 return -1;
265 }
266
267 return i <= _MAX_PATH ? i : -1;
268 }
269 #endif
270
271 /****************************************************************************************\
272 * Image Readers & Writers Class *
273 \****************************************************************************************/
274
275 class CvImageFilters
276 {
277 public:
278
279 CvImageFilters();
280 ~CvImageFilters();
281
282 GrFmtReader* FindReader( const char* filename ) const;
283 GrFmtWriter* FindWriter( const char* filename ) const;
284
285 //const CvFilePath& Path() const { return (const CvFilePath&)m_path; };
286 //CvFilePath& Path() { return m_path; };
287
288 protected:
289
290 GrFmtFactoriesList* m_factories;
291 };
292
293
CvImageFilters()294 CvImageFilters::CvImageFilters()
295 {
296 m_factories = new GrFmtFactoriesList;
297
298 #ifdef HAVE_IMAGEIO
299 m_factories->AddFactory( new GrFmtImageIO() );
300 #endif
301 m_factories->AddFactory( new GrFmtBmp() );
302 m_factories->AddFactory( new GrFmtJpeg() );
303 m_factories->AddFactory( new GrFmtSunRaster() );
304 m_factories->AddFactory( new GrFmtPxM() );
305 m_factories->AddFactory( new GrFmtTiff() );
306 #ifdef HAVE_PNG
307 m_factories->AddFactory( new GrFmtPng() );
308 #endif
309 #ifdef HAVE_JASPER
310 m_factories->AddFactory( new GrFmtJpeg2000() );
311 #endif
312 #ifdef HAVE_ILMIMF
313 m_factories->AddFactory( new GrFmtExr() );
314 #endif
315 }
316
317
~CvImageFilters()318 CvImageFilters::~CvImageFilters()
319 {
320 delete m_factories;
321 }
322
323
FindReader(const char * filename) const324 GrFmtReader* CvImageFilters::FindReader( const char* filename ) const
325 {
326 return m_factories->FindReader( filename );
327 }
328
329
FindWriter(const char * filename) const330 GrFmtWriter* CvImageFilters::FindWriter( const char* filename ) const
331 {
332 return m_factories->FindWriter( filename );
333 }
334
335 /****************************************************************************************\
336 * HighGUI loading & saving function implementation *
337 \****************************************************************************************/
338
icvSetCXCOREBindings(void)339 static int icvSetCXCOREBindings(void)
340 {
341 return CV_SET_IMAGE_IO_FUNCTIONS();
342 }
343
344 int cxcore_bindings_initialized = icvSetCXCOREBindings();
345
346 // global image I/O filters
347 static CvImageFilters g_Filters;
348
349 #if 0
350 CV_IMPL void
351 cvAddSearchPath( const char* path )
352 {
353 CV_FUNCNAME( "cvAddSearchPath" );
354
355 __BEGIN__;
356
357 if( !path || strlen(path) == 0 )
358 CV_ERROR( CV_StsNullPtr, "Null path" );
359
360 g_Filters.AddPath( path );
361
362 __END__;
363 }
364 #endif
365
366 CV_IMPL int
cvHaveImageReader(const char * filename)367 cvHaveImageReader( const char* filename )
368 {
369 GrFmtReader* reader = g_Filters.FindReader( filename );
370 if( reader ) {
371 delete reader;
372 return 1;
373 }
374 return 0;
375 }
376
cvHaveImageWriter(const char * filename)377 CV_IMPL int cvHaveImageWriter( const char* filename )
378 {
379 GrFmtWriter* writer = g_Filters.FindWriter( filename );
380 if( writer ) {
381 delete writer;
382 return 1;
383 }
384 return 0;
385 }
386
387 static void*
icvLoadImage(const char * filename,int flags,bool load_as_matrix)388 icvLoadImage( const char* filename, int flags, bool load_as_matrix )
389 {
390 GrFmtReader* reader = 0;
391 IplImage* image = 0;
392 CvMat hdr, *matrix = 0;
393 int depth = 8;
394
395 CV_FUNCNAME( "cvLoadImage" );
396
397 __BEGIN__;
398
399 CvSize size;
400 int iscolor;
401 int cn;
402
403 if( !filename || strlen(filename) == 0 )
404 CV_ERROR( CV_StsNullPtr, "null filename" );
405
406 reader = g_Filters.FindReader( filename );
407 if( !reader )
408 EXIT;
409
410 if( !reader->ReadHeader() )
411 EXIT;
412
413 size.width = reader->GetWidth();
414 size.height = reader->GetHeight();
415
416 if( flags == -1 )
417 iscolor = reader->IsColor();
418 else
419 {
420 if( (flags & CV_LOAD_IMAGE_COLOR) != 0 ||
421 ((flags & CV_LOAD_IMAGE_ANYCOLOR) != 0 && reader->IsColor()) )
422 iscolor = 1;
423 else
424 iscolor = 0;
425
426 if( (flags & CV_LOAD_IMAGE_ANYDEPTH) != 0 )
427 {
428 reader->UseNativeDepth(true);
429 depth = reader->GetDepth();
430 }
431 }
432
433 cn = iscolor ? 3 : 1;
434
435 if( load_as_matrix )
436 {
437 int type;
438 if(reader->IsFloat() && depth != 8)
439 type = CV_32F;
440 else
441 type = ( depth <= 8 ) ? CV_8U : ( depth <= 16 ) ? CV_16U : CV_32S;
442 CV_CALL( matrix = cvCreateMat( size.height, size.width, CV_MAKETYPE(type, cn) ));
443 }
444 else
445 {
446 int type;
447 if(reader->IsFloat() && depth != 8)
448 type = IPL_DEPTH_32F;
449 else
450 type = ( depth <= 8 ) ? IPL_DEPTH_8U : ( depth <= 16 ) ? IPL_DEPTH_16U : IPL_DEPTH_32S;
451 CV_CALL( image = cvCreateImage( size, type, cn ));
452 matrix = cvGetMat( image, &hdr );
453 }
454
455 if( !reader->ReadData( matrix->data.ptr, matrix->step, iscolor ))
456 {
457 if( load_as_matrix )
458 cvReleaseMat( &matrix );
459 else
460 cvReleaseImage( &image );
461 EXIT;
462 }
463
464 __END__;
465
466 delete reader;
467
468 if( cvGetErrStatus() < 0 )
469 {
470 if( load_as_matrix )
471 cvReleaseMat( &matrix );
472 else
473 cvReleaseImage( &image );
474 }
475
476 return load_as_matrix ? (void*)matrix : (void*)image;
477 }
478
479
480 CV_IMPL IplImage*
cvLoadImage(const char * filename,int iscolor)481 cvLoadImage( const char* filename, int iscolor )
482 {
483 return (IplImage*)icvLoadImage( filename, iscolor, false );
484 }
485
486 CV_IMPL CvMat*
cvLoadImageM(const char * filename,int iscolor)487 cvLoadImageM( const char* filename, int iscolor )
488 {
489 return (CvMat*)icvLoadImage( filename, iscolor, true );
490 }
491
492
493 CV_IMPL int
cvSaveImage(const char * filename,const CvArr * arr)494 cvSaveImage( const char* filename, const CvArr* arr )
495 {
496 int origin = 0;
497 GrFmtWriter* writer = 0;
498 CvMat *temp = 0, *temp2 = 0;
499
500 CV_FUNCNAME( "cvSaveImage" );
501
502 __BEGIN__;
503
504 CvMat stub, *image;
505 int channels, ipl_depth;
506
507 if( !filename || strlen(filename) == 0 )
508 CV_ERROR( CV_StsNullPtr, "null filename" );
509
510 CV_CALL( image = cvGetMat( arr, &stub ));
511
512 if( CV_IS_IMAGE( arr ))
513 origin = ((IplImage*)arr)->origin;
514
515 channels = CV_MAT_CN( image->type );
516 if( channels != 1 && channels != 3 && channels != 4 )
517 CV_ERROR( CV_BadNumChannels, "" );
518
519 writer = g_Filters.FindWriter( filename );
520 if( !writer )
521 CV_ERROR( CV_StsError, "could not find a filter for the specified extension" );
522
523 if( origin )
524 {
525 CV_CALL( temp = cvCreateMat(image->rows, image->cols, image->type) );
526 CV_CALL( cvFlip( image, temp, 0 ));
527 image = temp;
528 }
529
530 ipl_depth = cvCvToIplDepth(image->type);
531
532 if( !writer->IsFormatSupported(ipl_depth) )
533 {
534 assert( writer->IsFormatSupported(IPL_DEPTH_8U) );
535 CV_CALL( temp2 = cvCreateMat(image->rows,
536 image->cols, CV_MAKETYPE(CV_8U,channels)) );
537 CV_CALL( cvConvertImage( image, temp2 ));
538 image = temp2;
539 ipl_depth = IPL_DEPTH_8U;
540 }
541
542 if( !writer->WriteImage( image->data.ptr, image->step, image->width,
543 image->height, ipl_depth, channels ))
544 CV_ERROR( CV_StsError, "could not save the image" );
545
546 __END__;
547
548 delete writer;
549 cvReleaseMat( &temp );
550 cvReleaseMat( &temp2 );
551
552 return cvGetErrStatus() >= 0;
553 }
554
555 /* End of file. */
556