TuttleOFX  1
RunLengthEncoding.cpp
Go to the documentation of this file.
00001 // -*- mode: C++; tab-width: 4 -*-
00002 // vi: ts=4
00003 
00004 /*
00005  * Copyright (c) 2009, Patrick A. Palmer.
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without 
00009  * modification, are permitted provided that the following conditions are met:
00010  *
00011  *   - Redistributions of source code must retain the above copyright notice,
00012  *     this list of conditions and the following disclaimer.
00013  *
00014  *   - Redistributions in binary form must reproduce the above copyright
00015  *     notice, this list of conditions and the following disclaimer in the
00016  *     documentation and/or other materials provided with the distribution.
00017  *
00018  *   - Neither the name of Patrick A. Palmer nor the names of its
00019  *     contributors may be used to endorse or promote products derived from
00020  *     this software without specific prior written permission.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
00023  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
00024  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
00025  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
00026  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
00027  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
00028  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
00029  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
00030  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
00031  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
00032  * POSSIBILITY OF SUCH DAMAGE.
00033  */
00034 
00035 #include "DPX.h"
00036 #include "RunLengthEncoding.h"
00037 #include "ElementReadStream.h"
00038 #include "ReaderInternal.h"
00039 
00040 
00041 
00042 // Basic size of a packet is the number of bytes that all data packing methods will fit into that are whole and complete
00043 #define PACKET_REPEAT                   (10 * sizeof(U32))                                      // 320 bits repeating pattern
00044 #define BUFFER_SIZE                             (PACKET_REPEAT * 1002)                          // read in temp buffer size
00045 #define EXPANDED_BUFFER_SIZE    (BUFFER_SIZE + (BUFFER_SIZE / 3))       // expaded size after unpacking (max)
00046 
00047 
00048 dpx::RunLengthEncoding::RunLengthEncoding() : buf(0)
00049 {
00050 }
00051 
00052 
00053 dpx::RunLengthEncoding::~RunLengthEncoding()
00054 {
00055         if (this->buf)
00056                 delete [] buf;
00057 }
00058 
00059 
00060 void dpx::RunLengthEncoding::Reset()
00061 {
00062         if (this->buf)
00063         {
00064                 delete [] buf;
00065                 this->buf = 0;
00066         }
00067 }
00068 
00069 
00070 bool dpx::RunLengthEncoding::Read(const Header &dpxHeader, ElementReadStream *fd, const int element, const Block &block, void *data, const DataSize size)
00071 {
00072         int i;
00073         
00074         // just check to make sure that this element is RLE
00075         if (dpxHeader.ImageEncoding(element) != kRLE)
00076                 return false;
00077 
00078         
00079         // get the number of components for this element descriptor
00080         const int numberOfComponents = dpxHeader.ImageElementComponentCount(element);
00081         const int width = dpxHeader.Width();
00082         const int height = dpxHeader.Height();
00083         const int byteCount = dpxHeader.ComponentByteCount(element);
00084         const U32 eolnPad = dpxHeader.EndOfLinePadding(element);
00085         //DataSize srcSize = dpxHeader.ComponentDataSize(element);
00086         
00087         // has the buffer been read in and decoded?
00088         if (this->buf == 0)
00089         {
00090                 // not yet
00091                                 
00092                 // bit depth of the image element
00093                 const int bitDepth = dpxHeader.BitDepth(element);
00094         
00095                 // error out if the bit depth 10 or 12 and have eoln bytes
00096                 // this is particularly slow to parse and eoln padding bytes
00097                 // are not needed for those formats
00098                 // also if end of padding makes the line length odd, error out for that as well 
00099                 if (bitDepth != 8 && bitDepth != 16 && eolnPad > 0)
00100                         return false;
00101                 else if (bitDepth == 16 && eolnPad != 2 && eolnPad != 0)
00102                         return false;
00103                 
00104                 // error out for real types since bit operations don't really make sense
00105                 if (size == kFloat || size == kDouble)
00106                         return false;
00107                         
00108                 // find start and possible end of the element
00109                 U32 startOffset = dpxHeader.DataOffset(element);
00110                 U32 endOffset = 0xffffffff;
00111                 U32 currentOffset = startOffset;
00112                 
00113                 for (i = 0; i < MAX_ELEMENTS; i++)
00114                 {
00115                         if (i == element)
00116                                 continue;
00117                         U32 doff = dpxHeader.DataOffset(i);
00118                         if (doff == 0xffffffff)
00119                                 continue;
00120                         if (doff > startOffset && (endOffset == 0xffffffff || doff < endOffset))
00121                                 endOffset = doff - 1;
00122                 }
00123 
00124 
00125                 // size of the image
00126                 const size_t imageSize = width * height * numberOfComponents;
00127                 const size_t imageByteSize = imageSize * byteCount;
00128                 
00129                 // allocate the buffer that will store the entire image
00130                 this->buf = new U8[imageByteSize];
00131 
00132                 // allocate the temporary buffer that will read in the encoded image
00133                 U8 *tempBuf = new U8[EXPANDED_BUFFER_SIZE];
00134                 
00135                 // xpos, ypos in decoding
00136                 /*int xpos = 0;
00137                 int ypos = 0;*/
00138                 
00139                 // read in the encoded image block at a time
00140                 bool done = false;
00141                 while (!done)
00142                 {
00143                         // read in temp buffer
00144                         size_t rs = fd->ReadDirect(dpxHeader, element, (currentOffset - startOffset), tempBuf, BUFFER_SIZE);
00145                         currentOffset += rs;
00146                         if (rs != BUFFER_SIZE)
00147                                 done = true;
00148                         else if (endOffset != 0xffffffff && currentOffset >= endOffset)
00149                                 done = true;
00150 
00151                         // if 10-bit, 12-bit, unpack or unfill
00152                         
00153                         // step through and decode
00154                         
00155                         
00156                 }
00157                 
00158                 // no longer need temp buffer
00159                 delete [] tempBuf;
00160         }
00161 
00162 
00163 #ifdef RLE_WORKING
00164         // NOT COMPLETE YET
00165         // copy buffer
00166         CopyImageBlock(dpxHeader, element, buf, srcSize, data, size, dstSize, block);
00167 #endif
00168     return true;
00169 }       
00170 
00171