/******************************************************************** ** Image Component Library (ICL) ** ** ** ** Copyright (C) 2006-2013 CITEC, University of Bielefeld ** ** Neuroinformatics Group ** ** Website: www.iclcv.org and ** ** http://opensource.cit-ec.de/projects/icl ** ** ** ** File : ICLCore/src/ICLCore/PixelRef.h ** ** Module : ICLCore ** ** Authors: Christof Elbrechter ** ** ** ** ** ** GNU LESSER GENERAL PUBLIC LICENSE ** ** This file may be used under the terms of the GNU Lesser General ** ** Public License version 3.0 as published by the ** ** ** ** Free Software Foundation and appearing in the file LICENSE.LGPL ** ** included in the packaging of this file. Please review the ** ** following information to ensure the license requirements will ** ** be met: http://www.gnu.org/licenses/lgpl-3.0.txt ** ** ** ** The development of this software was supported by the ** ** Excellence Cluster EXC 277 Cognitive Interaction Technology. ** ** The Excellence Cluster EXC 277 is a grant of the Deutsche ** ** Forschungsgemeinschaft (DFG) in the context of the German ** ** Excellence Initiative. ** ** ** ********************************************************************/ #pragma once #include <ICLUtils/CompatMacros.h> #include <ICLCore/Types.h> #include <ICLUtils/SmartArray.h> #include <ICLUtils/Exception.h> #include <ICLUtils/Macros.h> #include <ICLMath/FixedMatrix.h> #include <ICLUtils/ClippedCast.h> namespace icl{ namespace core{ /// Pixel-Type class for copying image pixles to image pixels /** PixelRef instances are returned by an images operator()(int x, int y) It allows to write: <code> Img8u a = ...; Img8u b = ...; a(5,6) = b(3,2); </code> Furthermore it provides a list of setter functions, which allow to set up image pixels form other data types like vectors, ranges (iterator based) and even icl::FixedMatrix. Most of the functions are channel count save, i.e. they throw an ICLException if source channel count is not compatible. */ template<class T> class PixelRef{ /// Internal data std::vector<T*> m_data; public: /// Empty constructor, create a null pixel ref with 0 length inline PixelRef(){} /// returs whether this instance is null (created with the empty constructor) inline bool isNull() const { return !m_data->size(); } /// single constructor to create a pixelref instance /** This should not be used manually. Rather you should use Img<T>'s operator()(int x, int y) */ inline PixelRef(int x, int y, int width, std::vector<utils::SmartArray<T> > &data): m_data(data.size()){ int offs = x+width*y; for(unsigned int i=0;i<data.size();++i){ this->m_data[i] = data[i].get()+offs; } } /// PixelRef copy constructor (copies the reference, not the values) inline PixelRef(const PixelRef &other):m_data(other.m_data){} /// assignment operator which copies the values (most common) /** This operator allows to write <code> imageA(x,y) = imageB(a,b); </code> */ inline PixelRef &operator=(const PixelRef &other)throw (utils::ICLException){ ICLASSERT_THROW(other.m_data.size() == m_data.size(),utils::ICLException("incompatible channel count")); for(unsigned int i=0;i<m_data.size();++i){ *m_data[i] = *other.m_data[i]; } return *this; } /// assigns reference pixel values from vector data inline PixelRef &operator=(const std::vector<T> &vec)throw (utils::ICLException){ ICLASSERT_THROW(vec.size() == m_data.size(),utils::ICLException("incompatible channel count")); for(unsigned int i=0;i<m_data.size();++i){ *m_data[i] = vec[i]; } return *this; } /// assigns reference pixel values from FixedMatrix data /** This can e.g. be used to assign an icl::Color value to an image pixel (Color is a part of the ICLCore package, and it is typedef'ed to some FixedMatrix type) <code> imageA(x,y) = Color(2,3,4); </code> */ template<class MT,unsigned int COLS,unsigned int ROWS> inline PixelRef &operator=(const math::FixedMatrix<MT,COLS,ROWS> &mat)throw (utils::ICLException){ ICLASSERT_THROW((m_data.size() == math::FixedMatrix<MT,COLS,ROWS>::DIM), utils::ICLException("channel count and matrix dim are incompatible")); for(unsigned int i=0;i<m_data.size();++i){ *m_data[i] = utils::clipped_cast<MT,T>(mat[i]); } return *this; } /// copies image data into a std::vector inline std::vector<T> asVec() const{ std::vector<T> v(m_data.size()); for(unsigned int i=0;i<m_data.size();++i){ v[i] = *m_data[i]; } return v; } /// sets up the first index (unsafe) inline void set(const T &v0) { *m_data[0] = v0; } /// sets up the first two indices (unsafe) inline void set(const T &v0, const T&v1) { set(v0); *m_data[1] = v1; } /// sets up the first three indices (unsafe) inline void set(const T &v0, const T&v1, const T&v2) { set(v0,v1); *m_data[2] = v2; } /// sets up the first four indices (unsafe) inline void set(const T &v0, const T&v1, const T&v2, const T &v3) { set(v0,v1,v2); *m_data[3] = v3; } /// assigns a ranges contents to the pixel data /** An exception is only thrown of the given range is too short*/ template<class ForwardIterator> inline void setFromRange(ForwardIterator begin, ForwardIterator end) throw (utils::ICLException){ for(unsigned int i=0;i<m_data.size();++i,++begin){ if(begin == end) throw utils::ICLException("Range is longer then channel count"); *m_data[i] = *begin; } } /// references a single element (safe) T &operator[](unsigned int channel) throw (utils::ICLException){ ICLASSERT_THROW(channel < m_data.size(),utils::ICLException("invalid channel index")); return *m_data[channel]; } /// references a single element (const) (safe) const T &operator[](unsigned int channel) const throw (utils::ICLException){ ICLASSERT_THROW(channel < m_data.size(),utils::ICLException("invalid channel index")); return *m_data[channel]; } /// returns the channel count int getChannels() const { return (int)m_data.size(); } }; } // namespace core }