1 /////////////////////////////////////////////////////////////////////////////// 2 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. 3 // 4 // By downloading, copying, installing or using the software you agree to 5 // this license. If you do not agree to this license, do not download, 6 // install, copy or use the software. 7 // 8 // License Agreement 9 // For Open Source Computer Vision Library 10 // 11 // Copyright (C) 2008, Google, all rights reserved. 12 // Third party copyrights are property of their respective owners. 13 // 14 // Redistribution and use in source and binary forms, with or without 15 // modification, are permitted provided that the following conditions are met: 16 // 17 // * Redistribution's of source code must retain the above copyright notice, 18 // this list of conditions and the following disclaimer. 19 // 20 // * Redistribution's in binary form must reproduce the above copyright notice, 21 // this list of conditions and the following disclaimer in the documentation 22 // and/or other materials provided with the distribution. 23 // 24 // * The name of Intel Corporation or contributors may not be used to endorse 25 // or promote products derived from this software without specific 26 // prior written permission. 27 // 28 // This software is provided by the copyright holders and contributors "as is" 29 // and any express or implied warranties, including, but not limited to, the 30 // implied warranties of merchantability and fitness for a particular purpose 31 // are disclaimed. In no event shall the Intel Corporation or contributors be 32 // liable for any direct, indirect, incidental, special, exemplary, or 33 // 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 41 ///////////////////////////////////////////////////////////////////////////////// 42 // 43 // Image class which provides a thin layer around an IplImage. The goals 44 // of the class design are: 45 // 1. All the data has explicit ownership to avoid memory leaks 46 // 2. No hidden allocations or copies for performance. 47 // 3. Easy access to OpenCV methods (which will access IPP if available) 48 // 4. Can easily treat external data as an image 49 // 5. Easy to create images which are subsets of other images 50 // 6. Fast pixel access which can take advantage of number of channels 51 // if known at compile time. 52 // 53 // The WImage class is the image class which provides the data accessors. 54 // The 'W' comes from the fact that it is also a wrapper around the popular 55 // but inconvenient IplImage class. A WImage can be constructed either using a 56 // WImageBuffer class which allocates and frees the data, 57 // or using a WImageView class which constructs a subimage or a view into 58 // external data. The view class does no memory management. Each class 59 // actually has two versions, one when the number of channels is known at 60 // compile time and one when it isn't. Using the one with the number of 61 // channels specified can provide some compile time optimizations by using the 62 // fact that the number of channels is a constant. 63 // 64 // We use the convention (c,r) to refer to column c and row r with (0,0) being 65 // the upper left corner. This is similar to standard Euclidean coordinates 66 // with the first coordinate varying in the horizontal direction and the second 67 // coordinate varying in the vertical direction. 68 // Thus (c,r) is usually in the domain [0, width) X [0, height) 69 // 70 // Example usage: 71 // WImageBuffer3_b im(5,7); // Make a 5X7 3 channel image of type uchar 72 // WImageView3_b sub_im(im, 2,2, 3,3); // 3X3 submatrix 73 // vector<float> vec(10, 3.0f); 74 // WImageView1_f user_im(&vec[0], 2, 5); // 2X5 image w/ supplied data 75 // 76 // im.SetZero(); // same as cvSetZero(im.Ipl()) 77 // *im(2, 3) = 15; // Modify the element at column 2, row 3 78 // MySetRand(&sub_im); 79 // 80 // // Copy the second row into the first. This can be done with no memory 81 // // allocation and will use SSE if IPP is available. 82 // int w = im.Width(); 83 // im.View(0,0, w,1).CopyFrom(im.View(0,1, w,1)); 84 // 85 // // Doesn't care about source of data since using WImage 86 // void MySetRand(WImage_b* im) { // Works with any number of channels 87 // for (int r = 0; r < im->Height(); ++r) { 88 // float* row = im->Row(r); 89 // for (int c = 0; c < im->Width(); ++c) { 90 // for (int ch = 0; ch < im->Channels(); ++ch, ++row) { 91 // *row = uchar(rand() & 255); 92 // } 93 // } 94 // } 95 // } 96 // 97 // Functions that are not part of the basic image allocation, viewing, and 98 // access should come from OpenCV, except some useful functions that are not 99 // part of OpenCV can be found in wimage_util.h 100 #ifndef _CV_WIMAGE_H_ 101 #define _CV_WIMAGE_H_ 102 103 #include "cxcore.h" 104 105 #ifdef __cplusplus 106 107 namespace cv { 108 109 template <typename T> class WImage; 110 template <typename T> class WImageBuffer; 111 template <typename T> class WImageView; 112 113 template<typename T, int C> class WImageC; 114 template<typename T, int C> class WImageBufferC; 115 template<typename T, int C> class WImageViewC; 116 117 // Commonly used typedefs. 118 typedef WImage<uchar> WImage_b; 119 typedef WImageView<uchar> WImageView_b; 120 typedef WImageBuffer<uchar> WImageBuffer_b; 121 122 typedef WImageC<uchar, 1> WImage1_b; 123 typedef WImageViewC<uchar, 1> WImageView1_b; 124 typedef WImageBufferC<uchar, 1> WImageBuffer1_b; 125 126 typedef WImageC<uchar, 3> WImage3_b; 127 typedef WImageViewC<uchar, 3> WImageView3_b; 128 typedef WImageBufferC<uchar, 3> WImageBuffer3_b; 129 130 typedef WImage<float> WImage_f; 131 typedef WImageView<float> WImageView_f; 132 typedef WImageBuffer<float> WImageBuffer_f; 133 134 typedef WImageC<float, 1> WImage1_f; 135 typedef WImageViewC<float, 1> WImageView1_f; 136 typedef WImageBufferC<float, 1> WImageBuffer1_f; 137 138 typedef WImageC<float, 3> WImage3_f; 139 typedef WImageViewC<float, 3> WImageView3_f; 140 typedef WImageBufferC<float, 3> WImageBuffer3_f; 141 142 // There isn't a standard for signed and unsigned short so be more 143 // explicit in the typename for these cases. 144 typedef WImage<short> WImage_16s; 145 typedef WImageView<short> WImageView_16s; 146 typedef WImageBuffer<short> WImageBuffer_16s; 147 148 typedef WImageC<short, 1> WImage1_16s; 149 typedef WImageViewC<short, 1> WImageView1_16s; 150 typedef WImageBufferC<short, 1> WImageBuffer1_16s; 151 152 typedef WImageC<short, 3> WImage3_16s; 153 typedef WImageViewC<short, 3> WImageView3_16s; 154 typedef WImageBufferC<short, 3> WImageBuffer3_16s; 155 156 typedef WImage<ushort> WImage_16u; 157 typedef WImageView<ushort> WImageView_16u; 158 typedef WImageBuffer<ushort> WImageBuffer_16u; 159 160 typedef WImageC<ushort, 1> WImage1_16u; 161 typedef WImageViewC<ushort, 1> WImageView1_16u; 162 typedef WImageBufferC<ushort, 1> WImageBuffer1_16u; 163 164 typedef WImageC<ushort, 3> WImage3_16u; 165 typedef WImageViewC<ushort, 3> WImageView3_16u; 166 typedef WImageBufferC<ushort, 3> WImageBuffer3_16u; 167 168 // 169 // WImage definitions 170 // 171 // This WImage class gives access to the data it refers to. It can be 172 // constructed either by allocating the data with a WImageBuffer class or 173 // using the WImageView class to refer to a subimage or outside data. 174 template<typename T> 175 class WImage 176 { 177 public: 178 typedef T BaseType; 179 180 // WImage is an abstract class with no other virtual methods so make the 181 // destructor virtual. 182 virtual ~WImage() = 0; 183 184 // Accessors 185 IplImage* Ipl() {return image_; } 186 const IplImage* Ipl() const {return image_; } 187 T* ImageData() { return reinterpret_cast<T*>(image_->imageData); } 188 const T* ImageData() const { 189 return reinterpret_cast<const T*>(image_->imageData); 190 } 191 192 int Width() const {return image_->width; } 193 int Height() const {return image_->height; } 194 195 // WidthStep is the number of bytes to go to the pixel with the next y coord 196 int WidthStep() const {return image_->widthStep; } 197 198 int Channels() const {return image_->nChannels; } 199 int ChannelSize() const {return sizeof(T); } // number of bytes per channel 200 201 // Number of bytes per pixel 202 int PixelSize() const {return Channels() * ChannelSize(); } 203 204 // Return depth type (e.g. IPL_DEPTH_8U, IPL_DEPTH_32F) which is the number 205 // of bits per channel and with the signed bit set. 206 // This is known at compile time using specializations. 207 int Depth() const; 208 209 inline const T* Row(int r) const { 210 return reinterpret_cast<T*>(image_->imageData + r*image_->widthStep); 211 } 212 213 inline T* Row(int r) { 214 return reinterpret_cast<T*>(image_->imageData + r*image_->widthStep); 215 } 216 217 // Pixel accessors which returns a pointer to the start of the channel 218 inline T* operator() (int c, int r) { 219 return reinterpret_cast<T*>(image_->imageData + r*image_->widthStep) + 220 c*Channels(); 221 } 222 223 inline const T* operator() (int c, int r) const { 224 return reinterpret_cast<T*>(image_->imageData + r*image_->widthStep) + 225 c*Channels(); 226 } 227 228 // Copy the contents from another image which is just a convenience to cvCopy 229 void CopyFrom(const WImage<T>& src) { cvCopy(src.Ipl(), image_); } 230 231 // Set contents to zero which is just a convenient to cvSetZero 232 void SetZero() { cvSetZero(image_); } 233 234 // Construct a view into a region of this image 235 WImageView<T> View(int c, int r, int width, int height); 236 237 protected: 238 // Disallow copy and assignment 239 WImage(const WImage&); 240 void operator=(const WImage&); 241 242 explicit WImage(IplImage* img) : image_(img) { 243 assert(!img || img->depth == Depth()); 244 } 245 246 void SetIpl(IplImage* image) { 247 assert(!image || image->depth == Depth()); 248 image_ = image; 249 } 250 251 IplImage* image_; 252 }; 253 254 255 256 // Image class when both the pixel type and number of channels 257 // are known at compile time. This wrapper will speed up some of the operations 258 // like accessing individual pixels using the () operator. 259 template<typename T, int C> 260 class WImageC : public WImage<T> 261 { 262 public: 263 typedef typename WImage<T>::BaseType BaseType; 264 enum { kChannels = C }; 265 266 explicit WImageC(IplImage* img) : WImage<T>(img) { 267 assert(!img || img->nChannels == Channels()); 268 } 269 270 // Construct a view into a region of this image 271 WImageViewC<T, C> View(int c, int r, int width, int height); 272 273 // Copy the contents from another image which is just a convenience to cvCopy 274 void CopyFrom(const WImageC<T, C>& src) { 275 cvCopy(src.Ipl(), WImage<T>::image_); 276 } 277 278 // WImageC is an abstract class with no other virtual methods so make the 279 // destructor virtual. 280 virtual ~WImageC() = 0; 281 282 int Channels() const {return C; } 283 284 protected: 285 // Disallow copy and assignment 286 WImageC(const WImageC&); 287 void operator=(const WImageC&); 288 289 void SetIpl(IplImage* image) { 290 assert(!image || image->depth == WImage<T>::Depth()); 291 WImage<T>::SetIpl(image); 292 } 293 }; 294 295 // 296 // WImageBuffer definitions 297 // 298 // Image class which owns the data, so it can be allocated and is always 299 // freed. It cannot be copied but can be explicity cloned. 300 // 301 template<typename T> 302 class WImageBuffer : public WImage<T> 303 { 304 public: 305 typedef typename WImage<T>::BaseType BaseType; 306 307 // Default constructor which creates an object that can be 308 WImageBuffer() : WImage<T>(0) {} 309 310 WImageBuffer(int width, int height, int nchannels) : WImage<T>(0) { 311 Allocate(width, height, nchannels); 312 } 313 314 // Constructor which takes ownership of a given IplImage so releases 315 // the image on destruction. 316 explicit WImageBuffer(IplImage* img) : WImage<T>(img) {} 317 318 // Allocate an image. Does nothing if current size is the same as 319 // the new size. 320 void Allocate(int width, int height, int nchannels); 321 322 // Set the data to point to an image, releasing the old data 323 void SetIpl(IplImage* img) { 324 ReleaseImage(); 325 WImage<T>::SetIpl(img); 326 } 327 328 // Clone an image which reallocates the image if of a different dimension. 329 void CloneFrom(const WImage<T>& src) { 330 Allocate(src.Width(), src.Height()); 331 CopyFrom(src); 332 } 333 334 ~WImageBuffer() { 335 ReleaseImage(); 336 } 337 338 // Release the image if it isn't null. 339 void ReleaseImage() { 340 if (WImage<T>::image_) { 341 IplImage* image = WImage<T>::image_; 342 cvReleaseImage(&image); 343 WImage<T>::SetIpl(0); 344 } 345 } 346 347 bool IsNull() const {return WImage<T>::image_ == NULL; } 348 349 private: 350 // Disallow copy and assignment 351 WImageBuffer(const WImageBuffer&); 352 void operator=(const WImageBuffer&); 353 }; 354 355 // Like a WImageBuffer class but when the number of channels is known 356 // at compile time. 357 template<typename T, int C> 358 class WImageBufferC : public WImageC<T, C> 359 { 360 public: 361 typedef typename WImage<T>::BaseType BaseType; 362 enum { kChannels = C }; 363 364 // Default constructor which creates an object that can be 365 WImageBufferC() : WImageC<T, C>(0) {} 366 367 WImageBufferC(int width, int height) : WImageC<T, C>(0) { 368 Allocate(width, height); 369 } 370 371 // Constructor which takes ownership of a given IplImage so releases 372 // the image on destruction. 373 explicit WImageBufferC(IplImage* img) : WImageC<T, C>(img) {} 374 375 // Allocate an image. Does nothing if current size is the same as 376 // the new size. 377 void Allocate(int width, int height); 378 379 // Set the data to point to an image, releasing the old data 380 void SetIpl(IplImage* img) { 381 ReleaseImage(); 382 WImageC<T, C>::SetIpl(img); 383 } 384 385 // Clone an image which reallocates the image if of a different dimension. 386 void CloneFrom(const WImageC<T, C>& src) { 387 Allocate(src.Width(), src.Height()); 388 CopyFrom(src); 389 } 390 391 ~WImageBufferC() { 392 ReleaseImage(); 393 } 394 395 // Release the image if it isn't null. 396 void ReleaseImage() { 397 if (WImage<T>::image_) { 398 IplImage* image = WImage<T>::image_; 399 cvReleaseImage(&image); 400 WImageC<T, C>::SetIpl(0); 401 } 402 } 403 404 bool IsNull() const {return WImage<T>::image_ == NULL; } 405 406 private: 407 // Disallow copy and assignment 408 WImageBufferC(const WImageBufferC&); 409 void operator=(const WImageBufferC&); 410 }; 411 412 // 413 // WImageView definitions 414 // 415 // View into an image class which allows treating a subimage as an image 416 // or treating external data as an image 417 // 418 template<typename T> 419 class WImageView : public WImage<T> 420 { 421 public: 422 typedef typename WImage<T>::BaseType BaseType; 423 424 // Construct a subimage. No checks are done that the subimage lies 425 // completely inside the original image. 426 WImageView(WImage<T>* img, int c, int r, int width, int height); 427 428 // Refer to external data. 429 // If not given width_step assumed to be same as width. 430 WImageView(T* data, int width, int height, int channels, int width_step = -1); 431 432 // Refer to external data. This does NOT take ownership 433 // of the supplied IplImage. 434 WImageView(IplImage* img) : WImage<T>(img) {} 435 436 // Copy constructor 437 WImageView(const WImage<T>& img) : WImage<T>(0) { 438 header_ = *(img.Ipl()); 439 WImage<T>::SetIpl(&header_); 440 } 441 442 WImageView& operator=(const WImage<T>& img) { 443 header_ = *(img.Ipl()); 444 WImage<T>::SetIpl(&header_); 445 return *this; 446 } 447 448 protected: 449 IplImage header_; 450 }; 451 452 453 template<typename T, int C> 454 class WImageViewC : public WImageC<T, C> 455 { 456 public: 457 typedef typename WImage<T>::BaseType BaseType; 458 enum { kChannels = C }; 459 460 // Default constructor needed for vectors of views. 461 WImageViewC(); 462 463 virtual ~WImageViewC() {} 464 465 // Construct a subimage. No checks are done that the subimage lies 466 // completely inside the original image. 467 WImageViewC(WImageC<T, C>* img, 468 int c, int r, int width, int height); 469 470 // Refer to external data 471 WImageViewC(T* data, int width, int height, int width_step = -1); 472 473 // Refer to external data. This does NOT take ownership 474 // of the supplied IplImage. 475 WImageViewC(IplImage* img) : WImageC<T, C>(img) {} 476 477 // Copy constructor which does a shallow copy to allow multiple views 478 // of same data. gcc-4.1.1 gets confused if both versions of 479 // the constructor and assignment operator are not provided. 480 WImageViewC(const WImageC<T, C>& img) : WImageC<T, C>(0) { 481 header_ = *(img.Ipl()); 482 WImageC<T, C>::SetIpl(&header_); 483 } 484 WImageViewC(const WImageViewC<T, C>& img) : WImageC<T, C>(0) { 485 header_ = *(img.Ipl()); 486 WImageC<T, C>::SetIpl(&header_); 487 } 488 489 WImageViewC& operator=(const WImageC<T, C>& img) { 490 header_ = *(img.Ipl()); 491 WImageC<T, C>::SetIpl(&header_); 492 return *this; 493 } 494 WImageViewC& operator=(const WImageViewC<T, C>& img) { 495 header_ = *(img.Ipl()); 496 WImageC<T, C>::SetIpl(&header_); 497 return *this; 498 } 499 500 protected: 501 IplImage header_; 502 }; 503 504 505 // Specializations for depth 506 template<> 507 inline int WImage<uchar>::Depth() const {return IPL_DEPTH_8U; } 508 template<> 509 inline int WImage<schar>::Depth() const {return IPL_DEPTH_8S; } 510 template<> 511 inline int WImage<short>::Depth() const {return IPL_DEPTH_16S; } 512 template<> 513 inline int WImage<ushort>::Depth() const {return IPL_DEPTH_16U; } 514 template<> 515 inline int WImage<int>::Depth() const {return IPL_DEPTH_32S; } 516 template<> 517 inline int WImage<float>::Depth() const {return IPL_DEPTH_32F; } 518 template<> 519 inline int WImage<double>::Depth() const {return IPL_DEPTH_64F; } 520 521 // 522 // Pure virtual destructors still need to be defined. 523 // 524 template<typename T> inline WImage<T>::~WImage() {} 525 template<typename T, int C> inline WImageC<T, C>::~WImageC() {} 526 527 // 528 // Allocate ImageData 529 // 530 template<typename T> 531 inline void WImageBuffer<T>::Allocate(int width, int height, int nchannels) 532 { 533 if (IsNull() || WImage<T>::Width() != width || 534 WImage<T>::Height() != height || WImage<T>::Channels() != nchannels) { 535 ReleaseImage(); 536 WImage<T>::image_ = cvCreateImage(cvSize(width, height), 537 WImage<T>::Depth(), nchannels); 538 } 539 } 540 541 template<typename T, int C> 542 inline void WImageBufferC<T, C>::Allocate(int width, int height) 543 { 544 if (IsNull() || WImage<T>::Width() != width || WImage<T>::Height() != height) { 545 ReleaseImage(); 546 WImageC<T, C>::SetIpl(cvCreateImage(cvSize(width, height),WImage<T>::Depth(), C)); 547 } 548 } 549 550 // 551 // ImageView methods 552 // 553 template<typename T> 554 WImageView<T>::WImageView(WImage<T>* img, int c, int r, int width, int height) 555 : WImage<T>(0) 556 { 557 header_ = *(img->Ipl()); 558 header_.imageData = reinterpret_cast<char*>((*img)(c, r)); 559 header_.width = width; 560 header_.height = height; 561 WImage<T>::SetIpl(&header_); 562 } 563 564 template<typename T> 565 WImageView<T>::WImageView(T* data, int width, int height, int nchannels, int width_step) 566 : WImage<T>(0) 567 { 568 cvInitImageHeader(&header_, cvSize(width, height), WImage<T>::Depth(), nchannels); 569 header_.imageData = reinterpret_cast<char*>(data); 570 if (width_step > 0) { 571 header_.widthStep = width_step; 572 } 573 WImage<T>::SetIpl(&header_); 574 } 575 576 template<typename T, int C> 577 WImageViewC<T, C>::WImageViewC(WImageC<T, C>* img, int c, int r, int width, int height) 578 : WImageC<T, C>(0) 579 { 580 header_ = *(img->Ipl()); 581 header_.imageData = reinterpret_cast<char*>((*img)(c, r)); 582 header_.width = width; 583 header_.height = height; 584 WImageC<T, C>::SetIpl(&header_); 585 } 586 587 template<typename T, int C> 588 WImageViewC<T, C>::WImageViewC() : WImageC<T, C>(0) { 589 cvInitImageHeader(&header_, cvSize(0, 0), WImage<T>::Depth(), C); 590 header_.imageData = reinterpret_cast<char*>(0); 591 WImageC<T, C>::SetIpl(&header_); 592 } 593 594 template<typename T, int C> 595 WImageViewC<T, C>::WImageViewC(T* data, int width, int height, int width_step) 596 : WImageC<T, C>(0) 597 { 598 cvInitImageHeader(&header_, cvSize(width, height), WImage<T>::Depth(), C); 599 header_.imageData = reinterpret_cast<char*>(data); 600 if (width_step > 0) { 601 header_.widthStep = width_step; 602 } 603 WImageC<T, C>::SetIpl(&header_); 604 } 605 606 // Construct a view into a region of an image 607 template<typename T> 608 WImageView<T> WImage<T>::View(int c, int r, int width, int height) { 609 return WImageView<T>(this, c, r, width, height); 610 } 611 612 template<typename T, int C> 613 WImageViewC<T, C> WImageC<T, C>::View(int c, int r, int width, int height) { 614 return WImageViewC<T, C>(this, c, r, width, height); 615 } 616 617 } // end of namespace 618 619 #endif // __cplusplus 620 621 #endif // _CV_WIMAGE_H_ 622