TuttleOFX  1
DPX.h
Go to the documentation of this file.
00001 // vi: ts=4
00002 
00003 /*! \file DPX.h */
00004 
00005 /*
00006  * Copyright (c) 2009, Patrick A. Palmer.
00007  * All rights reserved.
00008  *
00009  * Redistribution and use in source and binary forms, with or without 
00010  * modification, are permitted provided that the following conditions are met:
00011  *
00012  *   - Redistributions of source code must retain the above copyright notice,
00013  *     this list of conditions and the following disclaimer.
00014  *
00015  *   - Redistributions in binary form must reproduce the above copyright
00016  *     notice, this list of conditions and the following disclaimer in the
00017  *     documentation and/or other materials provided with the distribution.
00018  *
00019  *   - Neither the name of Patrick A. Palmer nor the names of its
00020  *     contributors may be used to endorse or promote products derived from
00021  *     this software without specific prior written permission.
00022  *
00023  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
00024  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
00025  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
00026  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
00027  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
00028  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
00029  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
00030  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
00031  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
00032  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
00033  * POSSIBILITY OF SUCH DAMAGE.
00034  */
00035 
00036 
00037 #ifndef _DPX_H
00038 #define _DPX_H 1
00039 
00040 #include <cstdio>
00041 #include <limits>
00042 
00043 #include "DPXHeader.h"
00044 #include "DPXStream.h"
00045 
00046 
00047 /*!
00048  * \def OPENDPX_VERSION 
00049  * \brief OpenDPX Version
00050  */
00051 #define OPENDPX_VERSION         "0.5.0"
00052 
00053 
00054 
00055         
00056 /*!
00057  * \namespace dpx
00058  * \brief OpenDPX namespace 
00059  */
00060 namespace dpx
00061 {
00062         // forward definitions
00063         class Codec;
00064         class ElementReadStream;
00065         
00066         /*! 
00067          * \enum Endian
00068          * \brief DPX files can be stored in big- or little-endian byte order 
00069          */
00070         enum Endian
00071         {
00072                 kLittleEndian,                                                          //!< increasing numeric significance with increasing memory
00073                 kBigEndian                                                                      //!< big end first
00074         };
00075         
00076 
00077         /*! \struct Block
00078          * \brief Rectangle block definition defined by two points
00079          */
00080         struct Block 
00081         {
00082                 int x1, y1, x2, y2;
00083                 
00084                 /*!
00085                  * \brief Constructor
00086                  */
00087                 inline Block();
00088 
00089                 /*!
00090                  * \brief Constructor
00091                  *
00092                  * \param x1 upper left x coordinate
00093                  * \param y1 upper left y coordinate
00094                  * \param x2 lower right x coordinate
00095                  * \param y2 lower right y coordinate
00096                  */
00097                 Block(const int x1, const int y1, const int x2, const int y2);
00098 
00099                 /*!
00100                  * \brief Set the block coordinates
00101                  *
00102                  * \param x1 upper left x coordinate
00103                  * \param y1 upper left y coordinate
00104                  * \param x2 lower right x coordinate
00105                  * \param y2 lower right y coordinate
00106                  */
00107                 void Set(const int x1, const int y1, const int x2, const int y2);
00108 
00109                 /*!
00110                  * \brief Check to see if a point is within the block
00111                  *
00112                  * \param x x coordinate
00113                  * \param y y coordinate
00114                  * \return true/false if coordinates within block
00115                  */
00116                 inline bool Inside(const int x, const int y) const;
00117 
00118                 /*!
00119                  * \brief Rearrange coordinates if necessary so the first coordinate is upper left and the second is lower right
00120                  */
00121                 inline void Check();
00122         };
00123 
00124 
00125         // Current platform endian byte order
00126         extern Endian systemByteOrder;
00127 
00128         // namespace functions
00129         
00130         /*!
00131          * \brief determine if the image file is DPX
00132          *
00133          * \param file buffer to read and search
00134          * \return true/false if identified as DPX
00135          */
00136         bool IdentifyFile(InStream *file);
00137 
00138         /*!
00139          * \brief determine if the image file is DPX
00140          *
00141          * \param data memory to search
00142          * \return true/false if identified as DPX
00143          */
00144         bool IdentifyFile(const void *data);
00145         
00146         /*!
00147          * \brief returns a char * of the default DPX file extension
00148          *
00149          * \return .dpx file extenion
00150          */
00151         inline const char *DefaultExtension();
00152 
00153         /*!
00154          * returns a string of the highest SMPTE DPX version supported by this library
00155          *
00156          * \return SMPTE DPX version
00157          */
00158         inline const char *Version();
00159 
00160 
00161         /*!
00162          * \brief returns the version string for this library
00163          *
00164          * \return OpenDPX version
00165          */
00166         inline const char *LibraryVersion();
00167 
00168 
00169 
00170 
00171 
00172         /*!
00173          * \class Reader
00174          * \brief DPX Image Reader class
00175          */
00176          
00177         class Reader
00178         {
00179 
00180         public:
00181 
00182                 /*!
00183                  * \brief DPX header
00184                  */     
00185                 Header header;
00186 
00187                 /*!
00188                  * \brief Constructor
00189                  */                     
00190                 Reader();
00191                 
00192                 /*!
00193                  * \brief Destructor
00194                  */                     
00195                 virtual ~Reader();
00196 
00197                 /*!
00198                  * \brief Set the InStream object to be used to read images
00199                  *
00200                  * \param stream Object to use for low level reads
00201                  */     
00202                 void SetInStream(InStream *stream);
00203 
00204                 /*!
00205                  * \brief clear any caching or memory allocated specific to an image
00206                  */                     
00207                 void Reset();
00208                 
00209                 /*!
00210                  * \brief Read the dpx header into the header member
00211                  *
00212                  * \return success true/false
00213                  */     
00214                 bool ReadHeader();
00215 
00216                 /*!
00217                  * \brief Read an image element into a buffer
00218                  * 
00219                  * the size of the buffer must be large enough
00220                  * simple calculation would be:
00221                  *     width * height * num_of_components * size_of_component
00222                  * 
00223                  * \param element element (0-7)
00224                  * \param data buffer
00225                  * \return success true/false
00226                  */                     
00227                 bool ReadImage(const int element, void *data);
00228 
00229                 /*!
00230                  * \brief Read an image element into a buffer that matches the image description type
00231                  *
00232                  * The DataSize allows the user to specific the buffer DataSize which can differ
00233                  * from the image element.  It is possible, for example, to read an 8-bit per
00234                  * component (3 components per pixel for RGB) into 16-bits.
00235                  *
00236                  * \param data buffer
00237                  * \param size size of the buffer component
00238                  * \param desc element description type
00239                  * \return success true/false
00240                  */     
00241                 bool ReadImage(void *data, const DataSize size = kWord,  
00242                         const Descriptor desc = kRGB);
00243 
00244                 /*!
00245                  * \brief Read a rectangular image block into a buffer from the specified image element
00246                  *
00247                  * \param element element (0-7)
00248                  * \param data buffer
00249                  * \param block image area to read
00250                  * \return success true/false
00251                  */     
00252                 bool ReadBlock(const int element, unsigned char *data, Block &block);
00253 
00254                 /*!
00255                  * \brief Read a rectangular image block into a buffer from the image element
00256                  * specified by the Descriptor type
00257                  *
00258                  * \param data buffer
00259                  * \param size size of the buffer component
00260                  * \param block image area to read
00261                  * \param desc element description type
00262                  * \return success true/false
00263                  */                     
00264                 bool ReadBlock(void *data, const DataSize size, Block &block,
00265                         const Descriptor desc = kRGB);
00266 
00267                 /*!
00268                  * \brief Read the user data into a buffer.  
00269                  *
00270                  * Buffer must be large enough to hold the user data.
00271                  *
00272                  * \param data buffer
00273                  * \return success true/false
00274                  */     
00275                 bool ReadUserData(unsigned char *data);
00276                 
00277 
00278         protected:                      
00279                 InStream *fd;
00280                 
00281                 Codec *codex[MAX_ELEMENTS];
00282                 ElementReadStream *rio;
00283         };
00284         
00285         
00286         
00287         
00288 
00289 
00290 
00291 
00292 
00293         /*!
00294          * \class Writer
00295          * \brief DPX Image Writer class
00296          */
00297          
00298         class Writer
00299         {
00300         
00301         public:
00302         
00303                 /*!
00304                  * \brief DPX Header
00305                  */             
00306                 Header header;
00307 
00308                 /*!
00309                  * \brief Constructor
00310                  */                     
00311                 Writer();
00312                 
00313                 /*!
00314                  * \brief Destructor
00315                  */     
00316                 virtual ~Writer();
00317                 
00318                 /*!
00319                  * \brief Start defining the header and writing the images
00320                  */             
00321                 void Start();
00322 
00323                 /*!
00324                  * \brief Set the basic file information about DPX
00325                  *
00326                  * \param fileName name of this created file (100 characters max)
00327                  * \param creationTimeDate creation time and date - format is "YYYY:MM:DD:HH:MM:SSLTZ"
00328                  *               where HH is 24 hour time, LTZ is local time zone using either
00329                  *               three character notation (i.e., -04) or five character notation
00330                  *               representing hours and minutes offset from Greenwich Mean time
00331                  *               (i.e., -0700) (24 characters max)
00332                  * \param creator creator (100 characters max)
00333                  * \param project project name (200 characters max)
00334                  * \param copyright copyright statement (200 characters max)
00335                  * \param encryptKey encryption key
00336                  * \param swapEndian whether to write the image header in reverse to native endianness
00337                  */                     
00338                 void SetFileInfo(const char *fileName, const char *creationTimeDate = 0, const char *creator = 0,
00339                         const char *project = 0, const char *copyright = 0, const U32 encryptKey = ~0,
00340                         const bool swapEndian = false);
00341 
00342                 /*!
00343                  * \brief Set the Width and Height of the images
00344                  *
00345                  * \param width width of the image
00346                  * \param height height of the image
00347                  */                     
00348                 void SetImageInfo(const U32 width, const U32 height);
00349 
00350                 /*!
00351                  * \brief Get the next available element
00352                  * \return next available
00353                  */
00354                 int NextAvailElement() const;
00355 
00356 
00357                 /*!
00358                  * \brief Set the parameters on an element  
00359                  *
00360                  * There are 8 elements maximum in an single DPX and each element used must be set before writing the header
00361                  *
00362                  * \param element element number (0-7)
00363                  * \param desc image descriptor
00364                  * \param bitDepth bit depth of image, valid values are [8,10,12,16,32,64]
00365                  * \param transfer transfer characteristic
00366                  * \param colorimetric colorimetric specification
00367                  * \param packing packing type
00368                  * \param encoding encoding type
00369                  * \param dataSign
00370                  * \param lowData
00371                  * \param lowQuantity
00372                  * \param highData
00373                  * \param highQuantity
00374                  * \param eolnPadding end of line padding (in bytes)
00375                  * \param eoimPadding end of image padding (in bytes)
00376                  */                     
00377                 void SetElement(const int element = 0, 
00378                         const Descriptor desc = kRGB, 
00379                         const U8 bitDepth = 10,
00380                         const Characteristic transfer = kLogarithmic, 
00381                         const Characteristic colorimetric = kLogarithmic,
00382                         const Packing packing = kFilledMethodA, 
00383                         const Encoding encoding = kNone,
00384                         const U32 dataSign = 0, 
00385                         const U32 lowData = ~0, const R32 lowQuantity = std::numeric_limits<float>::quiet_NaN(),
00386                         const U32 highData = ~0, const R32 highQuantity = std::numeric_limits<float>::quiet_NaN(),
00387                         const U32 eolnPadding = 0, const U32 eoimPadding = 0);
00388 
00389                 /*!
00390                  * \brief Set the OutStream object will use to write the files
00391                  *
00392                  * \param stream OutStream object
00393                  */     
00394                 void SetOutStream(OutStream *stream);
00395 
00396                 /*!
00397                  * \brief Set the size of the user data area
00398                  * 
00399                  * \param size size of user data
00400                  */     
00401                 void SetUserData(const long size);
00402 
00403                 /*!
00404                  * \brief Write the header
00405                  *
00406                  * \return success true/false
00407                  */     
00408                 bool WriteHeader();
00409                 
00410                 /*!
00411                  * \brief Write the user data
00412                  *
00413                  * \param data buffer - must match size set in Writer::SetUserData()
00414                  * \return success true/false
00415                  */
00416                 bool WriteUserData(void *data);
00417 
00418                 /*!
00419                  * \brief Write the entire element to the dpx file
00420                  *
00421                  * \param element element number (0-7)
00422                  * \param data buffer
00423                  * \return success true/false
00424                  */                     
00425                 bool WriteElement(const int element, void *data);
00426                 bool WriteElement(const int element, void *data, const DataSize size);
00427                 bool WriteElement(const int element, void *data, const long count);
00428 
00429                 /**
00430                  * \brief Finish up writing image
00431                  *
00432                  * \return success true/false
00433                  */                     
00434                 bool Finish();
00435 
00436 
00437         protected:
00438                 long fileLoc;
00439                 OutStream *fd;
00440                 
00441                 bool WriteThrough(void *, const U32, const U32, const int, const int, const U32, const U32, char *);
00442                 
00443         };
00444         
00445 }
00446 
00447 
00448 
00449 inline const char *dpx::DefaultExtension()
00450 {
00451         return "dpx";
00452 }
00453 
00454 
00455 inline const char *dpx::Version()
00456 {
00457         return SMPTE_VERSION;
00458 }
00459 
00460 
00461 inline const char *dpx::LibraryVersion()
00462 {
00463         return OPENDPX_VERSION;
00464 }
00465 
00466 
00467 inline dpx::Block::Block() : x1(0), y1(0), x2(0), y2(0)
00468 { 
00469 }
00470 
00471 
00472 inline dpx::Block::Block(const int x1, const int y1, const int x2, const int y2) : x1(x1), y1(y1), x2(x2), y2(y2)
00473 { 
00474         this->Check();
00475 }
00476 
00477 
00478 inline void dpx::Block::Set(const int x1, const int y1, const int x2, const int y2)
00479 {
00480         this->x1 = x1; 
00481         this->y1 = y1; 
00482         this->x2 = x2;
00483         this->y2 = y2;
00484 }
00485 
00486 
00487 // check the coordinates that x1 < x2 and y1 < y2
00488 inline void dpx::Block::Check()
00489 {
00490         if (this->x1 > this->x2)
00491         {
00492                 int t = x1;
00493                 this->x1 = this->x2;
00494                 this->x2 = t;
00495         }
00496         if (this->y1 > this->y2)
00497         {
00498                 int t = y1;
00499                 this->y1 = this->y2;
00500                 this->y2 = t;
00501         }
00502 }
00503 
00504 
00505 inline bool dpx::Block::Inside(const int x, const int y) const
00506 {
00507         if (x >= this->x1 && x <= this->x2 && y >= this->y1 && y <= this->y2)
00508                         return true;
00509         return false;
00510 }
00511 
00512 
00513 #endif
00514