Frame.hpp
00001 //
00002 // Abstraction of images for the SAL3D library.
00003 // Copyright 2008-2010 AQSENSE, S.L.
00004 //
00005 #if !defined (AQSENSE_SAL3DPP_FRAME_HPP)
00006 #define AQSENSE_SAL3DPP_FRAME_HPP
00007 
00008 #if defined (_MSC_VER) && (_MSC_VER >= 1020)
00009 #pragma once
00010 #endif
00011 
00012 #include <sal3d/frame.h>
00013 #include <cstddef>
00014 #include <stdexcept>
00015 #include <string>
00016 #include <sal3dpp/Common.hpp>
00017 
00018 namespace sal3d
00019 {
00020     // Forward declarations.
00021     class Frame;
00022 
00168     class Frame
00169     {
00170         public:
00172             typedef sal3d_frame_vpat VPAT;
00173 
00189             template <typename T>
00190             class Plane
00191             {
00192                 public:
00193                     class Row
00194                     {
00195                         public:
00196                             Row(char *baseaddr, sal3d::Frame::VPAT vpa)
00197                                 :_baseaddr(baseaddr), _vpa(vpa)
00198                             {
00199                             }
00200 
00201                             const T & operator[](int x) const
00202                             {
00203                                 return *reinterpret_cast<T *>(_baseaddr + _vpa[x].x);
00204                             }
00205 
00206                             T & operator[](int x)
00207                             {
00208                                 return const_cast<T &> (
00209                                         static_cast<const Row &>(*this).operator[](x));
00210                             }
00211 
00212                         private:
00213                             char *_baseaddr;
00214                             VPAT _vpa;
00215                     };
00216 
00222                     Plane(const Frame &f, int plane)
00223                     {
00224                         f.vpa(plane, &_baseaddr, &_vpa);
00225                         _width = f.width();
00226                         _height = f.height();
00227                     }
00228 
00232                     int width() const
00233                     {
00234                         return _width;
00235                     }
00236 
00240                     int height() const
00241                     {
00242                         return _height;
00243                     }
00244 
00248                     const Row operator[](int y) const
00249                     {
00250                         return Row(_baseaddr + _vpa[y].y, _vpa);
00251                     }
00252 
00256                     Row operator[](int y)
00257                     {
00258                         return static_cast<const Plane &>(*this)[y];
00259                     }
00260 
00264                     const T & pixel(int x, int y) const
00265                     {
00266                         return *reinterpret_cast<T *>(_baseaddr + _vpa[y].y + _vpa[x].x);
00267                     }
00268 
00272                     T & pixel(int x, int y)
00273                     {
00274                         return const_cast<T &>(
00275                                 static_cast<const Plane &>(*this).pixel(x, y));
00276                     }
00277 
00278                 private:
00279                     char *_baseaddr;
00280                     VPAT _vpa;
00281                     int _width;
00282                     int _height;
00283             };
00284 
00300             template <typename T>
00301             class RGBPlane
00302             {
00303                 public:
00308                     struct RGBPixel
00309                     {
00317                         RGBPixel(T r, T g, T b):
00318                             r(r),
00319                             g(g),
00320                             b(b)
00321                         {}
00322 
00323                         T r;
00324                         T g;
00325                         T b;
00326                     };
00327 
00337                     RGBPlane(const Frame &f):
00338                         _width(f.width()),
00339                         _height(f.height())
00340                     {
00341                         f.vpa(0, &_baseaddrR, &_vpaR);
00342                         f.vpa(1, &_baseaddrG, &_vpaG);
00343                         f.vpa(2, &_baseaddrB, &_vpaB);
00344                     }
00345 
00349                     int width() const
00350                     {
00351                         return _width;
00352                     }
00353 
00357                     int height() const
00358                     {
00359                         return _height;
00360                     }
00361 
00368                     RGBPixel getPixel(int x, int y) const
00369                     {
00370                         return RGBPixel(*reinterpret_cast<T *>(_baseaddrR + _vpaR[y].y + _vpaR[x].x),
00371                                 *reinterpret_cast<T *>(_baseaddrG + _vpaG[y].y + _vpaG[x].x),
00372                                 *reinterpret_cast<T *>(_baseaddrB + _vpaB[y].y + _vpaB[x].x));
00373                     }
00374 
00381                     void setPixel(int x, int y, const RGBPixel &p)
00382                     {
00383                         *reinterpret_cast<T *>(_baseaddrR + _vpaR[y].y + _vpaR[x].x) = p.r;
00384                         *reinterpret_cast<T *>(_baseaddrG + _vpaG[y].y + _vpaG[x].x) = p.g;
00385                         *reinterpret_cast<T *>(_baseaddrB + _vpaB[y].y + _vpaB[x].x) = p.b;
00386                     }
00387 
00388                 private:
00389                     char *_baseaddrR;
00390                     char *_baseaddrG;
00391                     char *_baseaddrB;
00392                     VPAT _vpaR;
00393                     VPAT _vpaG;
00394                     VPAT _vpaB;
00395                     int _width;
00396                     int _height;
00397             };
00398 
00403             struct Area
00404             {
00406                 int x0;
00408                 int y0;
00409 
00411                 int x1;
00413                 int y1;
00414 
00423                 Area (int x0, int y0, int x1, int y1):
00424                     x0 (x0),
00425                     y0 (y0),
00426                     x1 (x1),
00427                     y1 (y1)
00428                 {
00429                 }
00430 
00437                 Area (int width, int height):
00438                     x0 (0),
00439                     y0 (0),
00440                     x1 (width - 1),
00441                     y1 (height - 1)
00442                 {
00443                 }
00444 
00451                 explicit inline Area (const sal3d::Frame &frame):
00452                     x0 (0),
00453                     y0 (0),
00454                     x1 (frame.width () - 1),
00455                     y1 (frame.height () - 1)
00456                 {
00457                 }
00458             };
00459 
00476             Frame (int width, int height,
00477                    int dimension, int dataType = 8)
00478             {
00479                 Error e;
00480                 _frame.p = 0;
00481                 sal3d_frame_new_with_datatype (width, height, dimension,
00482                         dataType, &_frame, &e.e);
00483                 if ( 0 > e.e.value )
00484                     throw e;
00485             }
00486 
00494             explicit Frame (const std::string &fileName)
00495             {
00496                 Error e;
00497                 _frame.p = 0;
00498                 sal3d_frame_new_from_file (fileName.c_str (), &_frame, &e.e);
00499                 if ( 0 > e.e.value )
00500                     throw e;
00501             }
00502 
00551             Frame (void *data, int width, int height,
00552                    int dimension, int datatype, std::ptrdiff_t strideX,
00553                    std::ptrdiff_t strideY, std::ptrdiff_t stridePlane,
00554                    SAL3DFRAMEDELETER deleter, void *userData = 0,
00555                    const int *planeOrder = 0)
00556             {
00557                 Error e;
00558                 _frame.p = 0;
00559                 sal3d_frame_new_from_pointer (data, width, height,
00560                         dimension, datatype, strideX, strideY, stridePlane,
00561                         planeOrder, deleter, userData, &_frame, &e.e);
00562                 if ( 0 > e.e.value )
00563                     throw e;
00564             }
00565 
00578             explicit Frame (sal3d_frame frame):
00579                 _frame (frame)
00580             {
00581                 Error e;
00582                 sal3d_frame_check_validity (frame, &e.e);
00583                 if ( 0 > e.e.value )
00584                     throw e;
00585             }
00586 
00592             Frame (const Frame &frame):
00593                 _frame (frame._frame)
00594             {
00595                 Error e;
00596                 sal3d_frame_share (_frame, &e.e);
00597                 if ( 0 > e.e.value )
00598                     throw e;
00599             }
00600 
00619             Frame (const Frame &frame, float ratio)
00620             {
00621                 Error e;
00622                 _frame.p = 0;
00623                 sal3d_frame_new_from_frame_with_zoom (
00624                         frame.c_frame (), ratio, &_frame, &e.e);
00625                 if ( 0 > e.e.value )
00626                     throw e;
00627             }
00628 
00646             Frame (const Frame &frame, const Area &area)
00647             {
00648                 _frame.p = 0;
00649                 sal3d_frame_area c_area;
00650                 c_area.x0 = area.x0;
00651                 c_area.y0 = area.y0;
00652                 c_area.x1 = area.x1;
00653                 c_area.y1 = area.y1;
00654 
00655                 Error e;
00656                 sal3d_frame_new_subframe (frame.c_frame (), c_area, &_frame,
00657                         &e.e);
00658                 if ( 0 > e.e.value )
00659                     throw e;
00660             }
00661 
00665             ~Frame ()
00666             {
00667                 sal3d_frame_release (_frame);
00668             }
00669 
00679             sal3d_frame
00680             c_frame () const
00681             {
00682                 return _frame;
00683             }
00684 
00700             Frame
00701             copy () const
00702             {
00703                 sal3d_frame newframe;
00704 
00705                 Error e;
00706                 sal3d_frame_new_copy_from_frame(_frame, &newframe, &e.e);
00707                 if ( 0 > e.e.value )
00708                     throw e;
00709 
00710                 return Frame(newframe);
00711             }
00712 
00739             int
00740             dataType (int plane) const
00741             {
00742                 Error e;
00743                 int type = sal3d_frame_get_data_type (_frame, plane, &e.e);
00744                 if ( 0 > e.e.value )
00745                     throw e;
00746                 return type;
00747             }
00748 
00756             int
00757             dimension () const
00758             {
00759                 Error e;
00760                 int dim = sal3d_frame_get_dimension (_frame, &e.e);
00761                 if ( 0 > e.e.value )
00762                     throw e;
00763                 return dim;
00764             }
00765 
00773             int
00774             height () const
00775             {
00776                 Error e;
00777                 int num = sal3d_frame_get_height (_frame, &e.e);
00778                 if ( 0 > e.e.value )
00779                     throw e;
00780                 return num;
00781             }
00782 
00793             void
00794             transpose()
00795             {
00796                 Error e;
00797                 sal3d_frame_transpose(_frame, &e.e);
00798                 if ( 0 > e.e.value )
00799                     throw e;
00800             }
00801 
00811             Frame &
00812             operator= (const Frame &rhs)
00813             {
00814                 Error e;
00815                 sal3d_frame_share (rhs._frame, &e.e);
00816                 if ( 0 > e.e.value )
00817                     throw e;
00818                 sal3d_frame_release (_frame);
00819                 _frame = rhs._frame;
00820 
00821                 return *this;
00822             }
00823 
00832             void
00833             saveToFile (const std::string &fileName) const
00834             {
00835                 Error e;
00836                 sal3d_frame_save_to_file (_frame, fileName.c_str (), &e.e);
00837                 if ( 0 > e.e.value )
00838                     throw e;
00839             }
00840 
00856             void
00857             vpa (int plane, char **baseAddress, VPAT *vpat) const
00858             {
00859                 Error e;
00860                 sal3d_frame_get_vpa (_frame, plane, baseAddress, vpat, &e.e);
00861                 if ( 0 > e.e.value )
00862                     throw e;
00863             }
00864 
00872             int
00873             width () const
00874             {
00875                 Error e;
00876                 int num = sal3d_frame_get_width (_frame, &e.e);
00877                 if ( 0 > e.e.value )
00878                     throw e;
00879                 return num;
00880             }
00881 
00906             sal3d::Frame
00907             scaleDepth(int datatype, double *inputMin = 0,
00908                     double *inputMax = 0) const
00909             {
00910                 sal3d_frame c_frame;
00911                 Error e;
00912                 sal3d_frame_new_scale_depth (_frame, datatype, 0, 0, 0, 0,
00913                         &c_frame, inputMin, inputMax, &e.e);
00914                 if ( 0 > e.e.value )
00915                     throw e;
00916 
00917                 return Frame(c_frame);
00918             }
00919 
00942             sal3d::Frame
00943             scaleDepth(int datatype, double inputMin, double inputMax) const
00944             {
00945                 sal3d_frame c_frame;
00946                 Error e;
00947                 sal3d_frame_new_scale_depth (_frame, datatype, &inputMin,
00948                         &inputMax, 0, 0, &c_frame, 0, 0, &e.e);
00949                 if ( 0 > e.e.value )
00950                     throw e;
00951 
00952                 return Frame(c_frame);
00953             }
00954 
00979             sal3d::Frame
00980             scaleDepthToRange(int datatype, double outputMin, double outputMax,
00981                     double *inputMin = 0, double *inputMax = 0) const
00982             {
00983                 sal3d_frame c_frame;
00984                 Error e;
00985                 sal3d_frame_new_scale_depth (_frame, datatype, 0, 0,
00986                         &outputMin, &outputMax, &c_frame, inputMin, inputMax,
00987                         &e.e);
00988                 if ( 0 > e.e.value )
00989                     throw e;
00990 
00991                 return Frame(c_frame);
00992             }
00993 
01016             sal3d::Frame
01017             scaleDepthToRange(int datatype,double inputMin, double inputMax,
01018                     double outputMin, double outputMax) const
01019             {
01020                 sal3d_frame c_frame;
01021                 Error e;
01022                 sal3d_frame_new_scale_depth (_frame, datatype, &inputMin,
01023                         &inputMax, &outputMin, &outputMax, &c_frame, 0, 0,
01024                         &e.e);
01025                 if ( 0 > e.e.value )
01026                     throw e;
01027 
01028                 return Frame(c_frame);
01029             }
01030 
01036             template <typename T>
01037             const Plane<T>
01038             plane(int p = 0) const
01039             {
01040                 return Plane<T>(*this, p);
01041             }
01042 
01048             template <typename T>
01049             Plane<T>
01050             plane(int p = 0)
01051             {
01052                 return static_cast<const Frame &>(*this).plane<T>(p);
01053             }
01054 
01061             template <typename T>
01062             const typename Plane<T>::Row
01063             row(int y, int plane = 0) const
01064             {
01065                 char *baseaddr;
01066                 sal3d::Frame::VPAT vpat;
01067 
01068                 vpa(plane, &baseaddr, &vpat);
01069                 return typename Plane<T>::Row(baseaddr + vpat[y].y, vpat);
01070             }
01071 
01078             template <typename T>
01079             typename Plane<T>::Row
01080             row(int y, int plane = 0)
01081             {
01082                 return static_cast<const Frame &>(*this).row<T>(y, plane);
01083             }
01084 
01092             template <typename T>
01093             const T &
01094             pixel(int x, int y, int plane = 0) const
01095             {
01096                 char *baseaddr;
01097                 sal3d::Frame::VPAT vpat;
01098 
01099                 vpa(plane, &baseaddr, &vpat);
01100                 return *reinterpret_cast<T *>(baseaddr + vpat[y].y + vpat[x].x);
01101             }
01102 
01110             template <typename T>
01111             T &
01112             pixel(int x, int y, int plane = 0)
01113             {
01114                 return const_cast<T &>(
01115                         static_cast<const Frame &>(*this).pixel<T>(x, y, plane));
01116             }
01117 
01118         private:
01120             sal3d_frame _frame;
01121     };
01122 }
01123 
01124 #endif // !AQSENSE_SAL3DPP_FRAME_HPP