DataAccessorImpl.h

Go to the documentation of this file.
00001 /*
00002  * The information in this file is
00003  * Copyright(c) 2007 Ball Aerospace & Technologies Corporation
00004  * and is subject to the terms and conditions of the
00005  * GNU Lesser General Public License Version 2.1
00006  * The license text is available from   
00007  * http://www.gnu.org/licenses/lgpl.html
00008  */
00009 
00010 #ifndef DATA_ACCESSOR_IMPL_H
00011 #define DATA_ACCESSOR_IMPL_H
00012 
00013 #include "AppConfig.h"
00014 #include "RasterElement.h"
00015 #include "RasterPager.h"
00016 #include "DataRequest.h"
00017 #include "TypesFile.h"
00018 #include "ObjectResource.h"
00019 #include <exception>
00020 #include <stdexcept>
00021 
00022 class RasterPage;
00023 
00024 typedef double (*convertToDouble)(const void*, int, ComplexComponent);
00025 typedef int64_t (*convertToInteger)(const void*, int, ComplexComponent);
00026 
00027 /**
00028  * Provides a generic interface to the dataset.
00029  *
00030  * This class provides an efficient, generic interface to the raw dataset.  To 
00031  * provide efficient access to the raw data, range checking can not occur 
00032  * within this class.  It is up to the user of the DataAcessor to make 
00033  * sure the bounds of the dataset are not exceeded.  This class provides 
00034  * row-major access to the data.  All of the standard interleaves (BIP, 
00035  * BIL, or BSQ) are row-major, so this class doesn't provide column-major access. 
00036  *
00037  * @code 
00038  * The following is the in the order for the dataset:
00039  *    BIP: ( Maj, Mid, Min = Row, Col, Band )
00040  *    BIL: ( Maj, Mid, Min = Row, Band, Col  (NOT IMPLEMENTED))
00041  *    BSQ: ( Maj, Mid, Min = Band, Row, Col )
00042  * @endcode
00043  *
00044  * This class is not instantiated by a plug-in directly.  The plug-in developer
00045  * can get access to this class through the RasterElement::getDataAccessor() 
00046  * method.  One example is to call getDataAccessor() with a DataRequest with 
00047  * concurrentColumns == total columns, concurrentBands == 1, and 
00048  * the default interleave.
00049  *
00050  * @code
00051  *   for each row
00052  *      for each column
00053  *         value = *getColumn()
00054  *         // Do something useful with the value.
00055  *       nextColumn()
00056  *    nextRow()
00057  * @endcode
00058  *
00059  * @see      RasterElement::getDataAccessor()
00060  */
00061 class DataAccessorImpl
00062 {
00063 public:
00064    /**
00065     *  DataAcessorImpl constructor.
00066     *
00067     *  This is the constructor for the data accessor.  This constructor should
00068     *  not be called directly from a plug-in.  Use RasterElement::getDataAccessor()
00069     *  to get a DataAccessor instance.
00070     *
00071     *  @param   pPage
00072     *           A pointer to a page of the raw dataset.  The size and ownership 
00073     *           of the data pointed to by mpPage is dependent on the interleave, 
00074     *           the concurrent elements and whether the data is loaded into memory 
00075     *           or not.
00076     *  @param   pRequest
00077     *           The DataRequest for this accessor.  DataAccessorImpl takes ownership
00078     *           of the request.
00079     *  @param   concurrentRows
00080     *           The number of rows provided by the RasterPager.
00081     *  @param   interLineBytes
00082     *           The number of bytes following a row of data in the dataset. This includes bytes that come before the next line.
00083     *  @param   concurrentColumns
00084     *           The number of columns provided by the RasterPager.
00085     *  @param   concurrentBands
00086     *           The number of bands provided by the RasterPager.
00087     *  @param   elementSize
00088     *           The size of the individual type referenced in the dataset 'matrix'.  For 
00089     *           example, sizeof(long), sizeof(float), etc.
00090     *  @param   pRasterElement
00091     *           This is a reference to the RasterElement class "owning" this DataAccessor.
00092     */
00093    DataAccessorImpl(char *pPage, DataRequest *pRequest, size_t concurrentRows,
00094       size_t interLineBytes, size_t concurrentColumns,
00095       size_t concurrentBands, 
00096       size_t elementSize, RasterElement* pRasterElement) :
00097       mbValid(true),
00098       mpPage(pPage),
00099       mpRasterElement(pRasterElement),
00100       mpRasterPage(NULL),
00101       mpRasterPager(NULL),
00102       mpRequest(pRequest),
00103       mConcurrentRows(concurrentRows),
00104       mConcurrentColumns(concurrentColumns),
00105       mConcurrentBands(concurrentBands),
00106       mCurrentRow(0),
00107       mCurrentColumn(0),
00108       mRowOffset(0),
00109       mColumnOffset(0),
00110       mRefCount(0),
00111       mConvertToDoubleFunc(NULL),
00112       mConvertToIntegerFunc(NULL)
00113    {
00114       if (pPage == NULL || mpRasterElement == NULL || mpRequest.get() == NULL)
00115       {
00116          throw std::logic_error("DataAccessorImpl constructor received NULL pointer");
00117       }
00118       mAccessorRow = mpRequest->getStartRow().getActiveNumber();
00119       mAccessorColumn = mpRequest->getStartColumn().getActiveNumber();
00120       mAccessorBand = mpRequest->getStartBand().getActiveNumber();
00121       updateDataSizes(elementSize, interLineBytes);
00122    }
00123 
00124    /**
00125     *  DataAcessorImpl destructor.
00126     */
00127    ~DataAccessorImpl()
00128    {
00129       if ( (mpRasterPager) && (mpRasterPage) )
00130       {
00131          mpRasterPager->releasePage(mpRasterPage);
00132       }
00133    }
00134 
00135    /**
00136     *  Gets a row of values.
00137     *
00138     *  This method returns a pointer to the first element in an array that is
00139     *  guaranteed to be at least (concurrent columns * number of bands) in size
00140     *  for BIP data and (concurrent columns) in size for BSQ data.
00141     *
00142     *  @return  Pointer to the raw block of row data from the dataset.
00143     */
00144    inline void *getRow()
00145    { 
00146       return &mpPage[mRowOffset];
00147    }
00148 
00149    /**
00150     *  Advances to the next row in the dataset.
00151     *
00152     *  This method increments to the next row based on the interleave
00153     *  BIP, BSQ, or BIL.
00154     *
00155     *  @param   resetColumn
00156     *           Whether or not to reset the column to the beginning column of the accessor.
00157     */
00158    inline void nextRow(bool resetColumn=true) 
00159    {
00160       ++mCurrentRow; 
00161       mRowOffset += mRowSize; 
00162       if (resetColumn) 
00163       {
00164          mCurrentColumn = mColumnOffset = 0;
00165       } 
00166       updateIfNeeded();
00167    }
00168 
00169    /**
00170     *  Advances to a succeeding row in the dataset.
00171     *
00172     *  This method increments to a later row based on the interleave
00173     *  BIP, BSQ, or BIL.
00174     *
00175     *  @param   count
00176     *           The number of rows to advance
00177     *  @param   resetColumn
00178     *           Whether or not to reset the column to the beginning column of the accessor.
00179     */
00180    inline void nextRow(int count, bool resetColumn=true) 
00181    { 
00182       if (count==1) 
00183       { 
00184          nextRow(); 
00185       } 
00186       else 
00187       {
00188          mCurrentRow+=count; 
00189          mRowOffset += mRowSize*count; 
00190          if (resetColumn) 
00191          {
00192             mCurrentColumn=mColumnOffset=0;
00193          } 
00194          updateIfNeeded(); 
00195       } 
00196    }
00197 
00198    /**
00199     *  Gets a column of values.
00200     *
00201     *  This method returns a pointer to the first element in an array
00202     *  that is guaranteed to be at least the number of bands in size
00203     *  for BIP data and one in size for BSQ data.
00204     *
00205     *  @return  Pointer to the raw block of column data from the data set.
00206     */
00207    inline void *getColumn() 
00208    { 
00209       return &mpPage[mRowOffset + mColumnOffset]; 
00210    }
00211 
00212    /**
00213     * Returns the data for the current column position as a double.
00214     *
00215     * @param iIndex
00216     *        The number of elements past the current column position to access.
00217     *        No bounds checking is performed on the provided index.
00218     * @param component
00219     *        For complex data, this specifies the component of the complex
00220     *        data that should be returned. If an invalid enum value is used
00221     *        for complex data, a value of 0 will be returned.  For non-complex data, this
00222     *        value is ignored.
00223     * @return The value at the given iIndex past the current column, returned as a double.
00224     */
00225    inline double getColumnAsDouble(int iIndex = 0, ComplexComponent component = COMPLEX_MAGNITUDE) const
00226    {
00227       return mConvertToDoubleFunc(&mpPage[mRowOffset + mColumnOffset], iIndex, component);
00228    }
00229 
00230    /**
00231     * Returns the data for the current column position as an integer.
00232     * This method will truncate the value if the underlying data is stored in floating point.
00233     *
00234     * @param iIndex
00235     *        The number of elements past the current column position to access.
00236     *        No bounds checking is performed on the provided index.
00237     * @param component
00238     *        For complex data, this specifies the component of the complex
00239     *        data that should be returned. If an invalid enum value is used
00240     *        for complex data, a value of 0 will be returned.  For non-complex data, this
00241     *        value is ignored.
00242     * @return The value at the given iIndex past the current column, returned as an integer.
00243     */
00244    int64_t getColumnAsInteger(int iIndex = 0, ComplexComponent component = COMPLEX_MAGNITUDE) const
00245    {
00246       return mConvertToIntegerFunc(&mpPage[mRowOffset + mColumnOffset], iIndex, component);
00247    }
00248 
00249    /**
00250     *  Advances to the next column in the dataset.
00251     *
00252     *  This method increments to the next column based on the interleave
00253     *  BIP, BSQ, or BIL.
00254     */
00255    inline void nextColumn() 
00256    { 
00257       ++mCurrentColumn; 
00258       mColumnOffset += mColumnSize; 
00259    }
00260 
00261    /**
00262     *  Advances to a succeeding column in the dataset.
00263     *
00264     *  This method increments to a later column based on the interleave
00265     *  BIP, BSQ, or BIL.
00266     *
00267     *  @param   count
00268     *           The number of columns to advance.
00269     */
00270    inline void nextColumn(int count) 
00271    { 
00272       if (count==1) 
00273       { 
00274          nextColumn(); 
00275       } 
00276       else 
00277       {
00278          mCurrentColumn+=count; 
00279          mColumnOffset += mColumnSize*count; 
00280       } 
00281    }
00282 
00283    /**
00284     *  Jumps to the specified pixel in the current band.
00285     *
00286     *  This method updates the current offset to the given pixel at row, column
00287     *  in the current band.
00288     *
00289     *  @param   row
00290     *           The row to access in the current band.  This must be non-negative
00291     *           and less than the total number of rows.
00292     *  @param   column
00293     *           The column to access in the current band.  This must be 
00294     *           non-negative and less than the total number of columns.
00295     */
00296    inline void toPixel(int row, int column) 
00297    { 
00298       mCurrentRow = row-mAccessorRow; 
00299       mCurrentColumn = column-mAccessorColumn; 
00300       mRowOffset = mCurrentRow * mRowSize;
00301       mColumnOffset = mCurrentColumn * mColumnSize;
00302       updateIfNeeded(); 
00303    }
00304 
00305    /**
00306     *  Returns the RasterElement associated with this DataAccessor.
00307     *
00308     *  @return  Returns the RasterElement associated with this class.
00309     */
00310    inline RasterElement *getAssociatedRasterElement()
00311    {
00312       return mpRasterElement;
00313    }
00314 
00315    /**
00316     *  Returns whether this is a valid data accessor.
00317     *
00318     *  A valid data accessor means that calls to getRow() and getColumn() will point
00319     *  to a valid location in memory.  This method can be called between nextRow()
00320     *  and getRow() or getColumn() calls.
00321     *
00322     *  @return  Returns whether this data accessor is valid, and subsequent calls to
00323     *           getRow() or getColumn() are valid pointers in memory.
00324     *
00325     *  @see     DataAccessor::isValid()
00326     */
00327    inline bool isValid() const 
00328    { 
00329       return mbValid; 
00330    }
00331 
00332    /**
00333     *  Increases the number of users of this data accessor.
00334     *
00335     *  This is simple reference counting mechanism to track the number
00336     *  of users of the data accessor.
00337     *
00338     *  @return  Returns the current number of users of this data accessor.
00339     */
00340    inline int incrementRefCount() 
00341    { 
00342       mRefCount++;
00343       return mRefCount; 
00344    }
00345 
00346    /**
00347     *  Decreases the number of users of this data accessor.
00348     *
00349     *  This is simple reference counting mechanism to track the number
00350     *  of users of the data accessor.
00351     *
00352     *  @return  Returns the current number of users of this data accessor.
00353     */
00354    inline int decrementRefCount()
00355    { 
00356       mRefCount--; 
00357       return mRefCount; 
00358    }
00359 
00360    /**
00361     *  Access the size in bytes of a row of data.
00362     *
00363     *  This includes the number of bytes of actual data in a row
00364     *  and excludes preline and postline bytes.
00365     *
00366     *  @note If using this information to access an entire row
00367     *        of data with getRow(), you must ensure that the DataAccessor's
00368     *        concurrent columns (and concurrent bands if the accessor is BIP)
00369     *        is equal to the number of columns in the data set.
00370     *
00371     *  @return The number of bytes in a row of data excluding preline and postline bytes.
00372     */
00373    inline size_t getRowSize() const
00374    {
00375       return mRowSize - mInterlineBytes;
00376    }
00377 
00378    /**
00379     *  Access the number of columns available concurrently.
00380     *
00381     *  @return The number of concurrent columns.
00382     *
00383     *  @see getRow()
00384     */
00385    inline size_t getConcurrentColumns() const
00386    {
00387       return mConcurrentColumns;
00388    }
00389 
00390 private:
00391    friend class RasterElementImp;
00392 
00393    /**
00394     *  Jumps to the next column and row.
00395     *
00396     *  This method enables the DataAccessor to update the view into the dataset
00397     *  or read in the next block of data, if necessary.
00398     */
00399    inline void updateIfNeeded()
00400    {
00401       if (mCurrentRow >= mConcurrentRows)
00402       {
00403          if (mpRasterElement == NULL)
00404          {
00405             throw std::logic_error("DataAccessor back-pointer to data cube has become corrupted");
00406          }
00407          mpRasterElement->incrementDataAccessor(*this);
00408          mCurrentRow = 0;
00409          mRowOffset = 0;
00410       }
00411    }
00412 
00413    /**
00414     *  Calculate the column and row size depending on the interleave format
00415     *  and number of concurrentColumns, concurrentRows and concurrentBands.
00416     *
00417     *  @param elementSize
00418     *         the number of bytes needed to represent a single pixel in memory.
00419     *
00420     *  @param interLineBytes
00421     *         the number of bytes between each line that do not contain
00422     *         raw data. This includes bytes which come before the next line.
00423     */
00424    void updateDataSizes(size_t elementSize, size_t interLineBytes)
00425    {
00426       mInterlineBytes = interLineBytes;
00427       switch(mpRequest->getInterleaveFormat())
00428       {
00429       case BIP:
00430          mColumnSize = elementSize * mConcurrentBands;
00431          mRowSize = mColumnSize * mConcurrentColumns + interLineBytes;
00432          break;
00433       case BIL:
00434          mColumnSize = elementSize;
00435          mRowSize = mColumnSize * mConcurrentColumns * mConcurrentBands + interLineBytes;
00436          break;
00437       case BSQ:
00438          mColumnSize = elementSize;
00439          mRowSize = mColumnSize * mConcurrentColumns + interLineBytes;
00440          break;
00441       default:
00442          throw std::logic_error("DataAccessorImpl constructor received unknown interleave");
00443       }
00444    }
00445 
00446    bool mbValid;
00447    char *mpPage;
00448    RasterElement *mpRasterElement;
00449    RasterPage* mpRasterPage;
00450    RasterPager* mpRasterPager;
00451    FactoryResource<DataRequest> mpRequest;
00452    size_t mConcurrentRows;             // Number of rows currently available in memory at once.
00453    size_t mConcurrentColumns;          // Number of columns currently available in memory at once.
00454    size_t mConcurrentBands;            // Number of bands currently available in memory at once.
00455    size_t mCurrentRow;                 // Current processing row
00456    size_t mCurrentColumn;              // Current processing column
00457    size_t mRowSize;                    // Size of a full row
00458    size_t mColumnSize;                 // Size of a full column
00459    size_t mRowOffset;                  // Row offset into the cube
00460    size_t mColumnOffset;               // Column offset into the cube
00461    size_t mInterlineBytes;             // Number of bytes of non-data between rows
00462 
00463    size_t mAccessorColumn;
00464    size_t mAccessorRow;
00465    size_t mAccessorBand;
00466 
00467    int mRefCount;
00468    convertToDouble mConvertToDoubleFunc;
00469    convertToInteger mConvertToIntegerFunc;
00470 };
00471 
00472 #endif

Software Development Kit - Opticks 4.9.0 Build 16218