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
Ipl()185 IplImage* Ipl() {return image_; }
Ipl()186 const IplImage* Ipl() const {return image_; }
ImageData()187 T* ImageData() { return reinterpret_cast<T*>(image_->imageData); }
ImageData()188 const T* ImageData() const {
189 return reinterpret_cast<const T*>(image_->imageData);
190 }
191
Width()192 int Width() const {return image_->width; }
Height()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
WidthStep()196 int WidthStep() const {return image_->widthStep; }
197
Channels()198 int Channels() const {return image_->nChannels; }
ChannelSize()199 int ChannelSize() const {return sizeof(T); } // number of bytes per channel
200
201 // Number of bytes per pixel
PixelSize()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
Row(int r)209 inline const T* Row(int r) const {
210 return reinterpret_cast<T*>(image_->imageData + r*image_->widthStep);
211 }
212
Row(int r)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
operator()218 inline T* operator() (int c, int r) {
219 return reinterpret_cast<T*>(image_->imageData + r*image_->widthStep) +
220 c*Channels();
221 }
222
operator()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
CopyFrom(const WImage<T> & src)229 void CopyFrom(const WImage<T>& src) { cvCopy(src.Ipl(), image_); }
230
231 // Set contents to zero which is just a convenient to cvSetZero
SetZero()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
WImage(IplImage * img)242 explicit WImage(IplImage* img) : image_(img) {
243 assert(!img || img->depth == Depth());
244 }
245
SetIpl(IplImage * image)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
WImageC(IplImage * img)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
CopyFrom(const WImageC<T,C> & src)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
Channels()282 int Channels() const {return C; }
283
284 protected:
285 // Disallow copy and assignment
286 WImageC(const WImageC&);
287 void operator=(const WImageC&);
288
SetIpl(IplImage * image)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
WImageBuffer()308 WImageBuffer() : WImage<T>(0) {}
309
WImageBuffer(int width,int height,int nchannels)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.
WImageBuffer(IplImage * img)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
SetIpl(IplImage * img)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.
CloneFrom(const WImage<T> & src)329 void CloneFrom(const WImage<T>& src) {
330 Allocate(src.Width(), src.Height());
331 CopyFrom(src);
332 }
333
~WImageBuffer()334 ~WImageBuffer() {
335 ReleaseImage();
336 }
337
338 // Release the image if it isn't null.
ReleaseImage()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
IsNull()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
WImageBufferC()365 WImageBufferC() : WImageC<T, C>(0) {}
366
WImageBufferC(int width,int height)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.
WImageBufferC(IplImage * img)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
SetIpl(IplImage * img)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.
CloneFrom(const WImageC<T,C> & src)386 void CloneFrom(const WImageC<T, C>& src) {
387 Allocate(src.Width(), src.Height());
388 CopyFrom(src);
389 }
390
~WImageBufferC()391 ~WImageBufferC() {
392 ReleaseImage();
393 }
394
395 // Release the image if it isn't null.
ReleaseImage()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
IsNull()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.
WImageView(IplImage * img)434 WImageView(IplImage* img) : WImage<T>(img) {}
435
436 // Copy constructor
WImageView(const WImage<T> & img)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
~WImageViewC()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.
WImageViewC(IplImage * img)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.
WImageViewC(const WImageC<T,C> & img)480 WImageViewC(const WImageC<T, C>& img) : WImageC<T, C>(0) {
481 header_ = *(img.Ipl());
482 WImageC<T, C>::SetIpl(&header_);
483 }
WImageViewC(const WImageViewC<T,C> & img)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<>
Depth()507 inline int WImage<uchar>::Depth() const {return IPL_DEPTH_8U; }
508 template<>
Depth()509 inline int WImage<schar>::Depth() const {return IPL_DEPTH_8S; }
510 template<>
Depth()511 inline int WImage<short>::Depth() const {return IPL_DEPTH_16S; }
512 template<>
Depth()513 inline int WImage<ushort>::Depth() const {return IPL_DEPTH_16U; }
514 template<>
Depth()515 inline int WImage<int>::Depth() const {return IPL_DEPTH_32S; }
516 template<>
Depth()517 inline int WImage<float>::Depth() const {return IPL_DEPTH_32F; }
518 template<>
Depth()519 inline int WImage<double>::Depth() const {return IPL_DEPTH_64F; }
520
521 //
522 // Pure virtual destructors still need to be defined.
523 //
~WImage()524 template<typename T> inline WImage<T>::~WImage() {}
~WImageC()525 template<typename T, int C> inline WImageC<T, C>::~WImageC() {}
526
527 //
528 // Allocate ImageData
529 //
530 template<typename T>
Allocate(int width,int height,int nchannels)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>
Allocate(int width,int height)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>
WImageView(WImage<T> * img,int c,int r,int width,int height)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>
WImageView(T * data,int width,int height,int nchannels,int width_step)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>
WImageViewC(WImageC<T,C> * img,int c,int r,int width,int height)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>
WImageViewC()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>
WImageViewC(T * data,int width,int height,int width_step)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>
View(int c,int r,int width,int height)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>
View(int c,int r,int width,int height)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