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