image_data.H

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 #ifndef ARCHON_UTILITIES_IMAGE_DATA_H
00021 #define ARCHON_UTILITIES_IMAGE_DATA_H
00022 
00023 #include <inttypes.h>
00024 
00025 #include <cmath>
00026 #include <vector>
00027 #include <stdexcept>
00028 
00029 #include <archon/math/functions.H>
00030 #include <archon/util/memory.H>
00031 #include <archon/util/pixel_format.H>
00032 
00033 namespace Archon
00034 {
00035   namespace Utilities
00036   {
00037     using namespace std;
00038 
00039 
00204     struct ImageData
00205     {
00206       struct BufferFormat
00207       {
00212         bool rightToLeft;
00213 
00218         bool topToBottom;
00219 
00224         bool verticalStrips;
00225 
00234         bool wordAlignStrip;
00235 
00236         BufferFormat(bool rightToLeft = false, bool topToBottom = false,
00237                      bool verticalStrips = false, bool wordAlignStrip = false):
00238           rightToLeft(rightToLeft), topToBottom(topToBottom),
00239           verticalStrips(verticalStrips), wordAlignStrip(wordAlignStrip) {}
00240       };
00241 
00242 
00302       ImageData(void *buffer, int numberOfStrips, int pixelsPerStrip,
00303                 const PixelFormat &pixelFormat = PixelFormat(),
00304                 const BufferFormat &bufferFormat = BufferFormat(),
00305                 int left = 0, int bottom = 0, int width = 0, int height = 0,
00306                 const vector<bool> &endianness = vector<bool>())
00307         throw(PixelFormat::UnsupportedWordTypeException,
00308               PixelFormat::InconsistencyException, invalid_argument);
00309 
00310 
00311 
00326       void queryPixelMap(double x, double y, long double *pixel,
00327                          int horizontalRepeat = 0, int verticalRepeat = 0) const
00328       {
00329         // Sclae to image size and align with integer coordinats
00330         x = x * interestWidth  - 0.5;
00331         y = y * interestHeight - 0.5;
00332 
00333         // Determine indices of upper left pixel of relevant 2x2 pixel
00334         // box within tiled image compound.
00335         long xi = static_cast<long>(floor(x));
00336         long yi = static_cast<long>(floor(y));
00337 
00338         // Fetch all four colors in the target 2x2 pixel array
00339         int n = numberOfChannels;
00340         Array<long double> c0(n), c1(n), c2(n), c3(n);
00341         getPixel(xi,   yi,   c0.get(), horizontalRepeat, verticalRepeat);
00342         getPixel(xi+1, yi,   c1.get(), horizontalRepeat, verticalRepeat);
00343         getPixel(xi,   yi+1, c2.get(), horizontalRepeat, verticalRepeat);
00344         getPixel(xi+1, yi+1, c3.get(), horizontalRepeat, verticalRepeat);
00345 
00346         // Get the fractional parts (intra pixel positions)
00347         long double xf1 = x - xi;
00348         long double yf1 = y - yi;
00349         long double xf0 = 1 - xf1;
00350         long double yf0 = 1 - yf1;
00351 
00352         // The weight w0 is determined as the area of intersection
00353         // between the real pixel p0 = (xi, yi) and the virtual pixel p
00354         // = (x, y).
00355         long double w0 = xf0 * yf0;
00356         long double w1 = xf1 * yf0;
00357         long double w2 = xf0 * yf1;
00358         long double w3 = xf1 * yf1;
00359 
00360         // Produce the weighted mean color
00361         for(int i=0; i<n; ++i)
00362           pixel[i] = w0 * c0[i] + w1 * c1[i] + w2 * c2[i] + w3 * c3[i];
00363       }
00364 
00365 
00375       void getPixel(long x, long y, long double *pixel,
00376                     int horizontalRepeat = 0, int verticalRepeat = 0) const
00377       {
00378         // Clamp when the number of repetitions is finite
00379         if(0 < horizontalRepeat) Math::clamp<long>(x, 0, interestWidth  * horizontalRepeat - 1);
00380         if(0 < verticalRepeat)   Math::clamp<long>(y, 0, interestHeight * verticalRepeat   - 1);
00381 
00382         // Produce propper image coordinates
00383         x = Math::modulo<long>(x, interestWidth);
00384         y = Math::modulo<long>(y, interestHeight);
00385 
00386         // Adjust for direction of growth
00387         if(rightToLeft) x = interestWidth-1  - x;
00388         if(topToBottom) y = interestHeight-1 - y;
00389         if(verticalStrips) swap(x, y);
00390 
00391         // Determine bit offset of pixel within buffer
00392         long bitOffset = principalBitOffset + x * bitsPerPixel + y * bitsPerStrip;
00393 cerr << "ImageData::getPixel: bit offset: " << bitOffset << endl;
00394 
00395         // Split into word-in-buffer and bit-in-word offsets
00396         long wordOffset;
00397         bitOffset = Math::modulo<long>(bitOffset, bitsPerWord, wordOffset);
00398 
00399         decodePixelSequence(buffer + wordOffset * bytesPerWord, bitOffset, 1, pixel);
00400       }
00401 
00402 
00403     private:
00404 
00426       void decodePixelSequence(const char *data, int wordBitOffest, long n, long double *pixels) const;
00427 
00428 
00453       void unpackPixelSequence(const char *data, int wordBitOffest, long n, long double *pixels) const;
00454 
00460       template<typename T> inline void
00461       unpackPixelSequenceDirectInteger(const char *data, long n,
00462                                        long double *pixels) const;
00463 
00469       template<typename T> inline void
00470       unpackPixelSequenceDirectFloat(const char *data, long n,
00471                                      long double *pixels) const;
00472 
00480       PixelFormat::MaxInt readIntegerWord(const char *data) const
00481       {
00482         if(bytePermutation.empty()) switch(wordType)
00483         {
00484         case PixelFormat::std_char:      return *reinterpret_cast<const unsigned char       *>(data);
00485         case PixelFormat::std_short:     return *reinterpret_cast<const unsigned short      *>(data);
00486         case PixelFormat::std_int:       return *reinterpret_cast<const unsigned int        *>(data);
00487         case PixelFormat::std_long:      return *reinterpret_cast<const unsigned long       *>(data);
00488         case PixelFormat::std_max_int:   return *reinterpret_cast<const PixelFormat::MaxInt *>(data);
00489         default: return 0; // Never
00490         }
00491 
00492         // Handle any kind of alien endianness
00493         switch(wordType)
00494         {
00495         case PixelFormat::std_char:      return readWithBytePermutation< unsigned char       >(data, bytePermutation);
00496         case PixelFormat::std_short:     return readWithBytePermutation< unsigned short      >(data, bytePermutation);
00497         case PixelFormat::std_int:       return readWithBytePermutation< unsigned int        >(data, bytePermutation);
00498         case PixelFormat::std_long:      return readWithBytePermutation< unsigned long       >(data, bytePermutation);
00499         case PixelFormat::std_max_int:   return readWithBytePermutation< PixelFormat::MaxInt >(data, bytePermutation);
00500         default: return 0; // Never
00501         }
00502       }
00503 
00504       char *buffer; 
00505       bool rightToLeft;
00506       bool topToBottom;
00507       bool verticalStrips;
00508       int interestWidth;  
00509       int interestHeight; 
00510 
00511 
00512 
00513       // Quatities derived from the pixel and buffer format specifications
00514 
00515       PixelFormat::FormatType pixelFormatType;
00516       PixelFormat::WordType wordType;
00517 
00518       int bytesPerWord;
00519       int bitsPerWord;
00520 
00528       vector<int> bytePermutation;
00529 
00530       bool mostSignificantBitsFirst;
00531 
00532       int numberOfChannels;
00533 
00534 
00535       struct MemoryField
00536       {
00537         int channelIndex; 
00538         int bitWidth;
00539         PixelFormat::MaxInt bitMask;
00540         long double min; 
00541         long double max; 
00542 
00543         MemoryField(int channelIndex = -1, int bitWidth = 0):
00544           channelIndex(channelIndex), bitWidth(bitWidth),
00545           // Special trick to support shifts by N bits where N is the number of bits in PixelFormat::MaxInt.
00546           bitMask((static_cast<PixelFormat::MaxInt>(1)<<bitWidth-1<<1)-1),
00547           min(0), max(1) {}
00548       };
00549 
00555       vector<MemoryField> memoryFields;
00556 
00557 
00561       long bitsPerPixel;
00562 
00566       long bitsPerStrip;
00567 
00579       long principalBitOffset;
00580     };
00581   }
00582 }
00583 
00584 #endif // ARCHON_UTILITIES_IMAGE_DATA_H

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