image_data.C

00001 /*
00002  * This file is part of the "Archon" framework.
00003  * (http://files3d.sourceforge.net)
00004  *
00005  * Copyright © 2006 by Kristian Spangsege and Brian Kristiansen.
00006  *
00007  * Permission to use, copy, modify, and distribute this software and
00008  * its documentation under the terms of the GNU General Public License is
00009  * hereby granted. No representations are made about the suitability of
00010  * this software for any purpose. It is provided "as is" without express
00011  * or implied warranty. See the GNU General Public License
00012  * (http://www.gnu.org/copyleft/gpl.html) for more details.
00013  *
00014  * The characters in this file are ISO8859-1 encoded.
00015  *
00016  * The documentation in this file is in "Doxygen" style
00017  * (http://www.doxygen.org).
00018  */
00019 
00020 #include <map>
00021 
00022 #include <archon/util/text.H>
00023 #include <archon/util/image_data.H>
00024 
00025 
00026 namespace Archon
00027 {
00028   namespace Utilities
00029   {
00030     /*
00031      * The objective for this constructor is to transform the
00032      * specified set of input parameters into a new set of parameters
00033      * that will minimize the number of calculations required by the
00034      * pixel data accessor methods of this class.
00035      */
00036     ImageData::ImageData(void *buffer, int numberOfStrips, int pixelsPerStrip,
00037                          const PixelFormat &pixelFormat,
00038                          const BufferFormat &bufferFormat,
00039                          int left, int bottom, int width, int height,
00040                          const vector<bool> &endianness)
00041       throw(PixelFormat::UnsupportedWordTypeException,
00042             PixelFormat::InconsistencyException, invalid_argument):
00043       buffer(reinterpret_cast<char *>(buffer)),
00044       rightToLeft(bufferFormat.rightToLeft),
00045       topToBottom(bufferFormat.topToBottom),
00046       verticalStrips(bufferFormat.verticalStrips)
00047     {
00048       PixelFormat expandedPixelFormat = pixelFormat.getExpandedFormat();
00049 
00050       // Determine pixel format type
00051       pixelFormatType = expandedPixelFormat.formatType;
00052 
00053       // Determine word type
00054       wordType = expandedPixelFormat.wordType;
00055 cerr << "ImageData::ImageData: word type: " << wordType << endl;
00056 
00057       // Determine number of bits and bytes per word
00058       bitsPerWord = expandedPixelFormat.bitsPerWord;
00059 cerr << "ImageData::ImageData: bits per word: " << bitsPerWord << endl;
00060       bytesPerWord = bitsPerWord / numeric_limits<unsigned char>::digits;
00061 cerr << "ImageData::ImageData: bytes per word: " << bytesPerWord << endl;
00062 
00063       // Determine byte permutation unless the requested endianness is
00064       // compatible with the native endianess up through the relevant
00065       // levels.
00066       {
00067         int levels = findMostSignificantBit(bytesPerWord);
00068 cerr << "ImageData::ImageData: byte order levels: " << levels << endl;
00069         if(!compareEndianness(endianness, vector<bool>(), levels))
00070           bytePermutation = computeBytePermutation(endianness, levels);
00071 if(bytePermutation.empty()) cerr << "ImageData::ImageData: Using native endianess" << endl;
00072 else
00073 {
00074   cerr << "ImageData::ImageData: byte reorder map:";
00075   for(int i=0; i<static_cast<int>(bytePermutation.size()); ++i) cerr << " " << bytePermutation[i];
00076   cerr << endl;
00077 }
00078       }
00079 
00080       mostSignificantBitsFirst = expandedPixelFormat.mostSignificantBitsFirst;
00081 
00082       // Determine number of channels
00083       numberOfChannels = expandedPixelFormat.channelLayout.size();
00084 
00085       // Determine bits per pixel
00086       bitsPerPixel = pixelFormatType == PixelFormat::tight ? expandedPixelFormat.pixelSize : expandedPixelFormat.pixelSize * bitsPerWord;
00087 
00088       // Compute memory field list
00089       vector<int> memoryMap(pixelFormatType == PixelFormat::direct ? expandedPixelFormat.pixelSize : bitsPerPixel);
00090       for(int i=0; i<numberOfChannels; ++i) memoryMap[expandedPixelFormat.channelLayout[i].offset] = i;
00091       if(pixelFormatType == PixelFormat::direct)
00092       {
00093         for(int i=0; i<static_cast<int>(memoryMap.size()); ++i)
00094         {
00095           int j = memoryMap[i];
00096           if(j < 0)
00097           {
00098             memoryFields.push_back(MemoryField());
00099             continue;
00100           }
00101           memoryFields.push_back(MemoryField(j, expandedPixelFormat.channelLayout[j].width));
00102         }
00103       }
00104       else // packed and tight formats
00105       {
00106         int i=0;
00107         while(i < static_cast<int>(memoryMap.size()))
00108         {
00109           int j = -1;
00110           int w = 0;
00111           // Check for a gap of unused bit
00112           while(i+w < static_cast<int>(memoryMap.size()) && memoryMap[i+w] < 0) ++w;
00113           if(!w) // No gap this time
00114           {
00115             j = memoryMap[i];
00116             w = expandedPixelFormat.channelLayout[j].width;
00117           }
00118           memoryFields.push_back(MemoryField(j, w));
00119           i += w;
00120         }
00121       }
00122 cerr << "ImageData::ImageData: pixel fields:";
00123 for(int i=0; i<static_cast<int>(memoryFields.size()); ++i)
00124 {
00125   cerr << " (" << memoryFields[i].channelIndex << ", " << memoryFields[i].bitWidth << ")";
00126 }
00127 cerr << endl;
00128 
00129 
00130       // Determine number of bits between strips (the stride)
00131       {
00132         bitsPerStrip = bitsPerPixel * pixelsPerStrip;
00133         if(bufferFormat.wordAlignStrip)
00134         {
00135           long r = bitsPerStrip % bitsPerWord;
00136           if(r) bitsPerStrip += bitsPerWord-r;
00137         }
00138 cerr << "ImageData::ImageData: bits per strip: " << bitsPerStrip << endl;
00139       }
00140 
00141 
00142       // Determine the width and height of the frame of interest
00143       int fullWidth  = verticalStrips ? numberOfStrips : pixelsPerStrip;
00144       int fullHeight = verticalStrips ? pixelsPerStrip : numberOfStrips;
00145       interestWidth  = width  ? width  : fullWidth  - left;
00146       interestHeight = height ? height : fullHeight - bottom;
00147 cerr << "ImageData::ImageData: width  of interest frame: " << interestWidth  << endl;
00148 cerr << "ImageData::ImageData: height of interest frame: " << interestHeight << endl;
00149 
00150 
00151       // Determine the offset of the pricipal bit. The principal bit
00152       // is the bit with the lowest bit-level index of all the bits
00153       // that are part of pixels that fall withing the selected
00154       // sub-section of the underlaying pixel buffer. Bit-level
00155       // indexes increases with significance of pit position.
00156       {
00157         int x = rightToLeft ? fullWidth  - interestWidth  - left   : left;
00158         int y = topToBottom ? fullHeight - interestHeight - bottom : bottom;
00159         if(verticalStrips) swap(x, y);
00160         principalBitOffset = x * bitsPerPixel + y * bitsPerStrip;
00161 cerr << "ImageData::ImageData: principal bit offset: " << principalBitOffset << endl;
00162       }
00163     }
00164 
00170     template<typename T> inline void
00171     ImageData::unpackPixelSequenceDirectInteger(const char *data,
00172                                                 long n,
00173                                                 long double *pixels) const
00174     {
00175       int m = memoryFields.size();
00176       const T *p = reinterpret_cast<const T *>(data);
00177       for(int i=0; i<n; ++i) // For each requested pixel
00178       {
00179         for(int j=0; j<m; ++j)
00180         {
00181           const ImageData::MemoryField &f = memoryFields[j];
00182           if(f.channelIndex < 0) continue;
00183           PixelFormat::MaxInt v = p[j];
00184           if(mostSignificantBitsFirst) v >>= bitsPerWord-f.bitWidth;
00185           pixels[f.channelIndex] = static_cast<long double>(v & f.bitMask)/f.bitMask;
00186         }
00187         pixels += numberOfChannels;
00188         p += m;
00189       }
00190     }
00191 
00197     template<typename T> inline void
00198     ImageData::unpackPixelSequenceDirectFloat(const char *data,
00199                                               long n,
00200                                               long double *pixels) const
00201     {
00202       int m = memoryFields.size();
00203       const T *p = reinterpret_cast<const T *>(data);
00204       for(int i=0; i<n; ++i) // For each requested pixel
00205       {
00206         for(int j=0; j<m; ++j)
00207         {
00208           const ImageData::MemoryField &f = memoryFields[j];
00209           if(f.channelIndex < 0) continue;
00210           pixels[f.channelIndex] = (static_cast<long double>(p[j])-f.min)/(f.max-f.min);
00211         }
00212         pixels += numberOfChannels;
00213         p += m;
00214       }
00215     }
00216 
00217     void ImageData::decodePixelSequence(const char *data, int bitOffset,
00218                                         long n, long double *pixels) const
00219     {
00220       switch(pixelFormatType)
00221       {
00222       case PixelFormat::direct:
00223         switch(wordType)
00224         {
00225         case PixelFormat::std_char:
00226           unpackPixelSequenceDirectInteger<unsigned char>(data, n, pixels);
00227           return;
00228 
00229         case PixelFormat::std_short:
00230           unpackPixelSequenceDirectInteger<unsigned short>(data, n, pixels);
00231           return;
00232 
00233         case PixelFormat::std_int:
00234           unpackPixelSequenceDirectInteger<unsigned int>(data, n, pixels);
00235           return;
00236 
00237         case PixelFormat::std_long:
00238           unpackPixelSequenceDirectInteger<unsigned long>(data, n, pixels);
00239           return;
00240 
00241         case PixelFormat::std_max_int:
00242           unpackPixelSequenceDirectInteger<PixelFormat::MaxInt>(data, n, pixels);
00243           return;
00244 
00245         case PixelFormat::std_float:
00246           unpackPixelSequenceDirectFloat<float>(data, n, pixels);
00247           return;
00248           
00249         case PixelFormat::std_double:
00250           unpackPixelSequenceDirectFloat<double>(data, n, pixels);
00251           return;
00252 
00253         case PixelFormat::std_long_double:
00254           unpackPixelSequenceDirectFloat<long double>(data, n, pixels);
00255           return;
00256 
00257         default: return; // Never
00258         }
00259 
00260       default: // packed and tight pixel format types
00261         unpackPixelSequence(data, bitOffset, n, pixels);
00262       }
00263     }
00264 
00265     void ImageData::unpackPixelSequence(const char *data, int wordBitOffset,
00266                                         long n, long double *pixels) const
00267     {
00268       vector<MemoryField>::const_iterator field = memoryFields.end()-1;
00269 
00270       // Skip initial unused bit fields
00271       int bitAdvance = 0;
00272       for(;;)
00273       {
00274         if(field == memoryFields.end())
00275         {
00276           if(!--n) return;
00277           field = memoryFields.begin();
00278         }
00279         if(field->channelIndex < 0) bitAdvance += field->bitWidth;
00280         ++field;
00281       }
00282       long wordAdvance;
00283       wordBitOffset = Math::modulo(wordBitOffset + bitAdvance, bitsPerWord, wordAdvance);
00284       if(wordAdvance) data += bytesPerWord * wordAdvance;
00285 
00286       // Load the first word from memory
00287       PixelFormat::MaxInt word = readIntegerWord(data);
00288 
00289       // Prepare for assembly of first channel
00290       int channelBitWidth = field->bitWidth;
00291       int channelBitOffset = 0;
00292       PixelFormat::MaxInt channel = 0;
00293 
00294       // Iterate over channels
00295       for(;;)
00296       {
00297         // Iterate over bit chunk transfers
00298         for(;;)
00299         {
00300           // The number of unparsed bits remaining in the current input word
00301           int remainingWordBits = bitsPerWord - wordBitOffset;
00302           int remainingChannelBits = channelBitWidth - channelBitOffset;
00303 
00304           // The number of bits we can transfer as one chunk
00305           int m = min(remainingWordBits, remainingChannelBits);
00306 
00307           // Transfer m bits from word to channel (special trick to
00308           // support shifts by N bits where N is the number of bits in
00309           // PixelFormat::MaxInt)
00310           PixelFormat::MaxInt mask = (static_cast<PixelFormat::MaxInt>(1)<<m-1<<1) - 1;
00311           if(mostSignificantBitsFirst) channel |= (word>>remainingWordBits-m & mask) << remainingChannelBits-m;
00312           else channel |= (word>>wordBitOffset & mask) << channelBitOffset;
00313           channelBitOffset += m;
00314 
00315           // Is the channel complete
00316           if(channelBitWidth == channelBitOffset) break;
00317 
00318           // Do we have more unused bits in current word
00319           if(m < remainingWordBits)
00320           {
00321             wordBitOffset += m;
00322             continue;
00323           }
00324 
00325           // Advance to next word of the image data
00326           data += bytesPerWord;
00327           word = readIntegerWord(data);
00328           wordBitOffset = 0;
00329         }
00330 
00331         // Store completed channel
00332         pixels[field->channelIndex] = static_cast<long double>(channel)/field->bitMask;
00333 
00334 
00335         // Skip unused bit fields
00336         bitAdvance = 0;
00337         for(;;)
00338         {
00339           if(++field == memoryFields.end())
00340           {
00341             if(!--n) return;
00342             field = memoryFields.begin();
00343           }
00344           if(field->channelIndex < 0) bitAdvance += field->bitWidth;
00345         }
00346         if(bitAdvance)
00347         {
00348           wordBitOffset = Math::modulo(wordBitOffset + bitAdvance, bitsPerWord, wordAdvance);
00349           if(wordAdvance)
00350           {
00351             data += bytesPerWord * wordAdvance;
00352 
00353             // Load the next word from memory
00354             word = readIntegerWord(data);
00355           }
00356         }
00357 
00358         // Prepare for assembly of next channel
00359         channelBitWidth = field->bitWidth;
00360         channelBitOffset = 0;
00361         channel = 0;
00362       }
00363     }
00364   }
00365 }

Generated on Sun Jul 30 22:55:43 2006 for Archon by  doxygen 1.4.4