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 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 318 CvImageFilters::~CvImageFilters() 319 { 320 delete m_factories; 321 } 322 323 324 GrFmtReader* CvImageFilters::FindReader( const char* filename ) const 325 { 326 return m_factories->FindReader( filename ); 327 } 328 329 330 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 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 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 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* 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* 481 cvLoadImage( const char* filename, int iscolor ) 482 { 483 return (IplImage*)icvLoadImage( filename, iscolor, false ); 484 } 485 486 CV_IMPL CvMat* 487 cvLoadImageM( const char* filename, int iscolor ) 488 { 489 return (CvMat*)icvLoadImage( filename, iscolor, true ); 490 } 491 492 493 CV_IMPL int 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