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 107namespace cv { 108 109template <typename T> class WImage; 110template <typename T> class WImageBuffer; 111template <typename T> class WImageView; 112 113template<typename T, int C> class WImageC; 114template<typename T, int C> class WImageBufferC; 115template<typename T, int C> class WImageViewC; 116 117// Commonly used typedefs. 118typedef WImage<uchar> WImage_b; 119typedef WImageView<uchar> WImageView_b; 120typedef WImageBuffer<uchar> WImageBuffer_b; 121 122typedef WImageC<uchar, 1> WImage1_b; 123typedef WImageViewC<uchar, 1> WImageView1_b; 124typedef WImageBufferC<uchar, 1> WImageBuffer1_b; 125 126typedef WImageC<uchar, 3> WImage3_b; 127typedef WImageViewC<uchar, 3> WImageView3_b; 128typedef WImageBufferC<uchar, 3> WImageBuffer3_b; 129 130typedef WImage<float> WImage_f; 131typedef WImageView<float> WImageView_f; 132typedef WImageBuffer<float> WImageBuffer_f; 133 134typedef WImageC<float, 1> WImage1_f; 135typedef WImageViewC<float, 1> WImageView1_f; 136typedef WImageBufferC<float, 1> WImageBuffer1_f; 137 138typedef WImageC<float, 3> WImage3_f; 139typedef WImageViewC<float, 3> WImageView3_f; 140typedef 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. 144typedef WImage<short> WImage_16s; 145typedef WImageView<short> WImageView_16s; 146typedef WImageBuffer<short> WImageBuffer_16s; 147 148typedef WImageC<short, 1> WImage1_16s; 149typedef WImageViewC<short, 1> WImageView1_16s; 150typedef WImageBufferC<short, 1> WImageBuffer1_16s; 151 152typedef WImageC<short, 3> WImage3_16s; 153typedef WImageViewC<short, 3> WImageView3_16s; 154typedef WImageBufferC<short, 3> WImageBuffer3_16s; 155 156typedef WImage<ushort> WImage_16u; 157typedef WImageView<ushort> WImageView_16u; 158typedef WImageBuffer<ushort> WImageBuffer_16u; 159 160typedef WImageC<ushort, 1> WImage1_16u; 161typedef WImageViewC<ushort, 1> WImageView1_16u; 162typedef WImageBufferC<ushort, 1> WImageBuffer1_16u; 163 164typedef WImageC<ushort, 3> WImage3_16u; 165typedef WImageViewC<ushort, 3> WImageView3_16u; 166typedef 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. 174template<typename T> 175class WImage 176{ 177public: 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 237protected: 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. 259template<typename T, int C> 260class WImageC : public WImage<T> 261{ 262public: 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 284protected: 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// 301template<typename T> 302class WImageBuffer : public WImage<T> 303{ 304public: 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 349private: 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. 357template<typename T, int C> 358class WImageBufferC : public WImageC<T, C> 359{ 360public: 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 406private: 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// 418template<typename T> 419class WImageView : public WImage<T> 420{ 421public: 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 448protected: 449 IplImage header_; 450}; 451 452 453template<typename T, int C> 454class WImageViewC : public WImageC<T, C> 455{ 456public: 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 500protected: 501 IplImage header_; 502}; 503 504 505// Specializations for depth 506template<> 507inline int WImage<uchar>::Depth() const {return IPL_DEPTH_8U; } 508template<> 509inline int WImage<schar>::Depth() const {return IPL_DEPTH_8S; } 510template<> 511inline int WImage<short>::Depth() const {return IPL_DEPTH_16S; } 512template<> 513inline int WImage<ushort>::Depth() const {return IPL_DEPTH_16U; } 514template<> 515inline int WImage<int>::Depth() const {return IPL_DEPTH_32S; } 516template<> 517inline int WImage<float>::Depth() const {return IPL_DEPTH_32F; } 518template<> 519inline int WImage<double>::Depth() const {return IPL_DEPTH_64F; } 520 521// 522// Pure virtual destructors still need to be defined. 523// 524template<typename T> inline WImage<T>::~WImage() {} 525template<typename T, int C> inline WImageC<T, C>::~WImageC() {} 526 527// 528// Allocate ImageData 529// 530template<typename T> 531inline 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 541template<typename T, int C> 542inline 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// 553template<typename T> 554WImageView<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 564template<typename T> 565WImageView<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 576template<typename T, int C> 577WImageViewC<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 587template<typename T, int C> 588WImageViewC<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 594template<typename T, int C> 595WImageViewC<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 607template<typename T> 608WImageView<T> WImage<T>::View(int c, int r, int width, int height) { 609 return WImageView<T>(this, c, r, width, height); 610} 611 612template<typename T, int C> 613WImageViewC<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