All Downloads are FREE. Search and download functionalities are using the official Maven repository.

srcnativelibs.Include.OpenCV.opencv2.core.wimage.hpp Maven / Gradle / Ivy

///////////////////////////////////////////////////////////////////////////////
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to
//  this license.  If you do not agree to this license, do not download,
//  install, copy or use the software.
//
//                           License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2008, Google, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//  * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//  * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//  * The name of Intel Corporation or contributors may not be used to endorse
//     or promote products derived from this software without specific
//     prior written permission.
//
// This software is provided by the copyright holders and contributors "as is"
// and any express or implied warranties, including, but not limited to, the
// implied warranties of merchantability and fitness for a particular purpose
// are disclaimed. In no event shall the Intel Corporation or contributors be
// liable for any direct, indirect, incidental, special, exemplary, or
// consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.


/////////////////////////////////////////////////////////////////////////////////
//
// Image class which provides a thin layer around an IplImage.  The goals
// of the class design are:
//    1. All the data has explicit ownership to avoid memory leaks
//    2. No hidden allocations or copies for performance.
//    3. Easy access to OpenCV methods (which will access IPP if available)
//    4. Can easily treat external data as an image
//    5. Easy to create images which are subsets of other images
//    6. Fast pixel access which can take advantage of number of channels
//          if known at compile time.
//
// The WImage class is the image class which provides the data accessors.
// The 'W' comes from the fact that it is also a wrapper around the popular
// but inconvenient IplImage class. A WImage can be constructed either using a
// WImageBuffer class which allocates and frees the data,
// or using a WImageView class which constructs a subimage or a view into
// external data.  The view class does no memory management.  Each class
// actually has two versions, one when the number of channels is known at
// compile time and one when it isn't.  Using the one with the number of
// channels specified can provide some compile time optimizations by using the
// fact that the number of channels is a constant.
//
// We use the convention (c,r) to refer to column c and row r with (0,0) being
// the upper left corner.  This is similar to standard Euclidean coordinates
// with the first coordinate varying in the horizontal direction and the second
// coordinate varying in the vertical direction.
// Thus (c,r) is usually in the domain [0, width) X [0, height)
//
// Example usage:
// WImageBuffer3_b  im(5,7);  // Make a 5X7 3 channel image of type uchar
// WImageView3_b  sub_im(im, 2,2, 3,3); // 3X3 submatrix
// vector vec(10, 3.0f);
// WImageView1_f user_im(&vec[0], 2, 5);  // 2X5 image w/ supplied data
//
// im.SetZero();  // same as cvSetZero(im.Ipl())
// *im(2, 3) = 15;  // Modify the element at column 2, row 3
// MySetRand(&sub_im);
//
// // Copy the second row into the first.  This can be done with no memory
// // allocation and will use SSE if IPP is available.
// int w = im.Width();
// im.View(0,0, w,1).CopyFrom(im.View(0,1, w,1));
//
// // Doesn't care about source of data since using WImage
// void MySetRand(WImage_b* im) { // Works with any number of channels
//   for (int r = 0; r < im->Height(); ++r) {
//     float* row = im->Row(r);
//     for (int c = 0; c < im->Width(); ++c) {
//        for (int ch = 0; ch < im->Channels(); ++ch, ++row) {
//          *row = uchar(rand() & 255);
//        }
//     }
//   }
// }
//
// Functions that are not part of the basic image allocation, viewing, and
// access should come from OpenCV, except some useful functions that are not
// part of OpenCV can be found in wimage_util.h
#ifndef __OPENCV_CORE_WIMAGE_HPP__
#define __OPENCV_CORE_WIMAGE_HPP__

#include "opencv2/core/core_c.h"

#ifdef __cplusplus

namespace cv {

template  class WImage;
template  class WImageBuffer;
template  class WImageView;

template class WImageC;
template class WImageBufferC;
template class WImageViewC;

// Commonly used typedefs.
typedef WImage            WImage_b;
typedef WImageView        WImageView_b;
typedef WImageBuffer      WImageBuffer_b;

typedef WImageC        WImage1_b;
typedef WImageViewC    WImageView1_b;
typedef WImageBufferC  WImageBuffer1_b;

typedef WImageC        WImage3_b;
typedef WImageViewC    WImageView3_b;
typedef WImageBufferC  WImageBuffer3_b;

typedef WImage            WImage_f;
typedef WImageView        WImageView_f;
typedef WImageBuffer      WImageBuffer_f;

typedef WImageC        WImage1_f;
typedef WImageViewC    WImageView1_f;
typedef WImageBufferC  WImageBuffer1_f;

typedef WImageC        WImage3_f;
typedef WImageViewC    WImageView3_f;
typedef WImageBufferC  WImageBuffer3_f;

// There isn't a standard for signed and unsigned short so be more
// explicit in the typename for these cases.
typedef WImage            WImage_16s;
typedef WImageView        WImageView_16s;
typedef WImageBuffer      WImageBuffer_16s;

typedef WImageC        WImage1_16s;
typedef WImageViewC    WImageView1_16s;
typedef WImageBufferC  WImageBuffer1_16s;

typedef WImageC        WImage3_16s;
typedef WImageViewC    WImageView3_16s;
typedef WImageBufferC  WImageBuffer3_16s;

typedef WImage            WImage_16u;
typedef WImageView        WImageView_16u;
typedef WImageBuffer      WImageBuffer_16u;

typedef WImageC        WImage1_16u;
typedef WImageViewC    WImageView1_16u;
typedef WImageBufferC  WImageBuffer1_16u;

typedef WImageC        WImage3_16u;
typedef WImageViewC    WImageView3_16u;
typedef WImageBufferC  WImageBuffer3_16u;

//
// WImage definitions
//
// This WImage class gives access to the data it refers to.  It can be
// constructed either by allocating the data with a WImageBuffer class or
// using the WImageView class to refer to a subimage or outside data.
template
class WImage
{
public:
    typedef T BaseType;

    // WImage is an abstract class with no other virtual methods so make the
    // destructor virtual.
    virtual ~WImage() = 0;

    // Accessors
    IplImage* Ipl() {return image_; }
    const IplImage* Ipl() const {return image_; }
    T* ImageData() { return reinterpret_cast(image_->imageData); }
    const T* ImageData() const {
        return reinterpret_cast(image_->imageData);
    }

    int Width() const {return image_->width; }
    int Height() const {return image_->height; }

    // WidthStep is the number of bytes to go to the pixel with the next y coord
    int WidthStep() const {return image_->widthStep; }

    int Channels() const {return image_->nChannels; }
    int ChannelSize() const {return sizeof(T); }  // number of bytes per channel

    // Number of bytes per pixel
    int PixelSize() const {return Channels() * ChannelSize(); }

    // Return depth type (e.g. IPL_DEPTH_8U, IPL_DEPTH_32F) which is the number
    // of bits per channel and with the signed bit set.
    // This is known at compile time using specializations.
    int Depth() const;

    inline const T* Row(int r) const {
        return reinterpret_cast(image_->imageData + r*image_->widthStep);
    }

    inline T* Row(int r) {
        return reinterpret_cast(image_->imageData + r*image_->widthStep);
    }

    // Pixel accessors which returns a pointer to the start of the channel
    inline T* operator() (int c, int r)  {
        return reinterpret_cast(image_->imageData + r*image_->widthStep) +
            c*Channels();
    }

    inline const T* operator() (int c, int r) const  {
        return reinterpret_cast(image_->imageData + r*image_->widthStep) +
            c*Channels();
    }

    // Copy the contents from another image which is just a convenience to cvCopy
    void CopyFrom(const WImage& src) { cvCopy(src.Ipl(), image_); }

    // Set contents to zero which is just a convenient to cvSetZero
    void SetZero() { cvSetZero(image_); }

    // Construct a view into a region of this image
    WImageView View(int c, int r, int width, int height);

protected:
    // Disallow copy and assignment
    WImage(const WImage&);
    void operator=(const WImage&);

    explicit WImage(IplImage* img) : image_(img) {
        assert(!img || img->depth == Depth());
    }

    void SetIpl(IplImage* image) {
        assert(!image || image->depth == Depth());
        image_ = image;
    }

    IplImage* image_;
};



// Image class when both the pixel type and number of channels
// are known at compile time.  This wrapper will speed up some of the operations
// like accessing individual pixels using the () operator.
template
class WImageC : public WImage
{
public:
    typedef typename WImage::BaseType BaseType;
    enum { kChannels = C };

    explicit WImageC(IplImage* img) : WImage(img) {
        assert(!img || img->nChannels == Channels());
    }

    // Construct a view into a region of this image
    WImageViewC View(int c, int r, int width, int height);

    // Copy the contents from another image which is just a convenience to cvCopy
    void CopyFrom(const WImageC& src) {
        cvCopy(src.Ipl(), WImage::image_);
    }

    // WImageC is an abstract class with no other virtual methods so make the
    // destructor virtual.
    virtual ~WImageC() = 0;

    int Channels() const {return C; }

protected:
    // Disallow copy and assignment
    WImageC(const WImageC&);
    void operator=(const WImageC&);

    void SetIpl(IplImage* image) {
        assert(!image || image->depth == WImage::Depth());
        WImage::SetIpl(image);
    }
};

//
// WImageBuffer definitions
//
// Image class which owns the data, so it can be allocated and is always
// freed.  It cannot be copied but can be explicity cloned.
//
template
class WImageBuffer : public WImage
{
public:
    typedef typename WImage::BaseType BaseType;

    // Default constructor which creates an object that can be
    WImageBuffer() : WImage(0) {}

    WImageBuffer(int width, int height, int nchannels) : WImage(0) {
        Allocate(width, height, nchannels);
    }

    // Constructor which takes ownership of a given IplImage so releases
    // the image on destruction.
    explicit WImageBuffer(IplImage* img) : WImage(img) {}

    // Allocate an image.  Does nothing if current size is the same as
    // the new size.
    void Allocate(int width, int height, int nchannels);

    // Set the data to point to an image, releasing the old data
    void SetIpl(IplImage* img) {
        ReleaseImage();
        WImage::SetIpl(img);
    }

    // Clone an image which reallocates the image if of a different dimension.
    void CloneFrom(const WImage& src) {
        Allocate(src.Width(), src.Height(), src.Channels());
        CopyFrom(src);
    }

    ~WImageBuffer() {
        ReleaseImage();
    }

    // Release the image if it isn't null.
    void ReleaseImage() {
        if (WImage::image_) {
            IplImage* image = WImage::image_;
            cvReleaseImage(&image);
            WImage::SetIpl(0);
        }
    }

    bool IsNull() const {return WImage::image_ == NULL; }

private:
    // Disallow copy and assignment
    WImageBuffer(const WImageBuffer&);
    void operator=(const WImageBuffer&);
};

// Like a WImageBuffer class but when the number of channels is known
// at compile time.
template
class WImageBufferC : public WImageC
{
public:
    typedef typename WImage::BaseType BaseType;
    enum { kChannels = C };

    // Default constructor which creates an object that can be
    WImageBufferC() : WImageC(0) {}

    WImageBufferC(int width, int height) : WImageC(0) {
        Allocate(width, height);
    }

    // Constructor which takes ownership of a given IplImage so releases
    // the image on destruction.
    explicit WImageBufferC(IplImage* img) : WImageC(img) {}

    // Allocate an image.  Does nothing if current size is the same as
    // the new size.
    void Allocate(int width, int height);

    // Set the data to point to an image, releasing the old data
    void SetIpl(IplImage* img) {
        ReleaseImage();
        WImageC::SetIpl(img);
    }

    // Clone an image which reallocates the image if of a different dimension.
    void CloneFrom(const WImageC& src) {
        Allocate(src.Width(), src.Height());
        CopyFrom(src);
    }

    ~WImageBufferC() {
        ReleaseImage();
    }

    // Release the image if it isn't null.
    void ReleaseImage() {
        if (WImage::image_) {
            IplImage* image = WImage::image_;
            cvReleaseImage(&image);
            WImageC::SetIpl(0);
        }
    }

    bool IsNull() const {return WImage::image_ == NULL; }

private:
    // Disallow copy and assignment
    WImageBufferC(const WImageBufferC&);
    void operator=(const WImageBufferC&);
};

//
// WImageView definitions
//
// View into an image class which allows treating a subimage as an image
// or treating external data as an image
//
template
class WImageView : public WImage
{
public:
    typedef typename WImage::BaseType BaseType;

    // Construct a subimage.  No checks are done that the subimage lies
    // completely inside the original image.
    WImageView(WImage* img, int c, int r, int width, int height);

    // Refer to external data.
    // If not given width_step assumed to be same as width.
    WImageView(T* data, int width, int height, int channels, int width_step = -1);

    // Refer to external data.  This does NOT take ownership
    // of the supplied IplImage.
    WImageView(IplImage* img) : WImage(img) {}

    // Copy constructor
    WImageView(const WImage& img) : WImage(0) {
        header_ = *(img.Ipl());
        WImage::SetIpl(&header_);
    }

    WImageView& operator=(const WImage& img) {
        header_ = *(img.Ipl());
        WImage::SetIpl(&header_);
        return *this;
    }

protected:
    IplImage header_;
};


template
class WImageViewC : public WImageC
{
public:
    typedef typename WImage::BaseType BaseType;
    enum { kChannels = C };

    // Default constructor needed for vectors of views.
    WImageViewC();

    virtual ~WImageViewC() {}

    // Construct a subimage.  No checks are done that the subimage lies
    // completely inside the original image.
    WImageViewC(WImageC* img,
        int c, int r, int width, int height);

    // Refer to external data
    WImageViewC(T* data, int width, int height, int width_step = -1);

    // Refer to external data.  This does NOT take ownership
    // of the supplied IplImage.
    WImageViewC(IplImage* img) : WImageC(img) {}

    // Copy constructor which does a shallow copy to allow multiple views
    // of same data.  gcc-4.1.1 gets confused if both versions of
    // the constructor and assignment operator are not provided.
    WImageViewC(const WImageC& img) : WImageC(0) {
        header_ = *(img.Ipl());
        WImageC::SetIpl(&header_);
    }
    WImageViewC(const WImageViewC& img) : WImageC(0) {
        header_ = *(img.Ipl());
        WImageC::SetIpl(&header_);
    }

    WImageViewC& operator=(const WImageC& img) {
        header_ = *(img.Ipl());
        WImageC::SetIpl(&header_);
        return *this;
    }
    WImageViewC& operator=(const WImageViewC& img) {
        header_ = *(img.Ipl());
        WImageC::SetIpl(&header_);
        return *this;
    }

protected:
    IplImage header_;
};


// Specializations for depth
template<>
inline int WImage::Depth() const {return IPL_DEPTH_8U; }
template<>
inline int WImage::Depth() const {return IPL_DEPTH_8S; }
template<>
inline int WImage::Depth() const {return IPL_DEPTH_16S; }
template<>
inline int WImage::Depth() const {return IPL_DEPTH_16U; }
template<>
inline int WImage::Depth() const {return IPL_DEPTH_32S; }
template<>
inline int WImage::Depth() const {return IPL_DEPTH_32F; }
template<>
inline int WImage::Depth() const {return IPL_DEPTH_64F; }

//
// Pure virtual destructors still need to be defined.
//
template inline WImage::~WImage() {}
template inline WImageC::~WImageC() {}

//
// Allocate ImageData
//
template
inline void WImageBuffer::Allocate(int width, int height, int nchannels)
{
    if (IsNull() || WImage::Width() != width ||
        WImage::Height() != height || WImage::Channels() != nchannels) {
        ReleaseImage();
        WImage::image_ = cvCreateImage(cvSize(width, height),
            WImage::Depth(), nchannels);
    }
}

template
inline void WImageBufferC::Allocate(int width, int height)
{
    if (IsNull() || WImage::Width() != width || WImage::Height() != height) {
        ReleaseImage();
        WImageC::SetIpl(cvCreateImage(cvSize(width, height),WImage::Depth(), C));
    }
}

//
// ImageView methods
//
template
WImageView::WImageView(WImage* img, int c, int r, int width, int height)
        : WImage(0)
{
    header_ = *(img->Ipl());
    header_.imageData = reinterpret_cast((*img)(c, r));
    header_.width = width;
    header_.height = height;
    WImage::SetIpl(&header_);
}

template
WImageView::WImageView(T* data, int width, int height, int nchannels, int width_step)
          : WImage(0)
{
    cvInitImageHeader(&header_, cvSize(width, height), WImage::Depth(), nchannels);
    header_.imageData = reinterpret_cast(data);
    if (width_step > 0) {
        header_.widthStep = width_step;
    }
    WImage::SetIpl(&header_);
}

template
WImageViewC::WImageViewC(WImageC* img, int c, int r, int width, int height)
        : WImageC(0)
{
    header_ = *(img->Ipl());
    header_.imageData = reinterpret_cast((*img)(c, r));
    header_.width = width;
    header_.height = height;
    WImageC::SetIpl(&header_);
}

template
WImageViewC::WImageViewC() : WImageC(0) {
    cvInitImageHeader(&header_, cvSize(0, 0), WImage::Depth(), C);
    header_.imageData = reinterpret_cast(0);
    WImageC::SetIpl(&header_);
}

template
WImageViewC::WImageViewC(T* data, int width, int height, int width_step)
    : WImageC(0)
{
    cvInitImageHeader(&header_, cvSize(width, height), WImage::Depth(), C);
    header_.imageData = reinterpret_cast(data);
    if (width_step > 0) {
        header_.widthStep = width_step;
    }
    WImageC::SetIpl(&header_);
}

// Construct a view into a region of an image
template
WImageView WImage::View(int c, int r, int width, int height) {
    return WImageView(this, c, r, width, height);
}

template
WImageViewC WImageC::View(int c, int r, int width, int height) {
    return WImageViewC(this, c, r, width, height);
}

}  // end of namespace

#endif // __cplusplus

#endif




© 2015 - 2025 Weber Informatics LLC | Privacy Policy