TuttleOFX
1
|
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