CodeVis.com SourceForge.net Logo

CVImageRGBFloat.cpp

Go to the documentation of this file.
00001 // CVImageRGBFloat - floating point RGB image class
00002 // Written by Michael Ellison
00003 //-------------------------------------------------------------------------
00004 //                      CodeVis's Free License
00005 //                         www.codevis.com
00006 //
00007 // Copyright (c) 2003 by Michael Ellison (mike@codevis.com)
00008 // All rights reserved.
00009 //
00010 // You may use this software in source and/or binary form, with or without
00011 // modification, for commercial or non-commercial purposes, provided that 
00012 // you comply with the following conditions:
00013 //
00014 // * Redistributions of source code must retain the above copyright notice,
00015 //   this list of conditions and the following disclaimer. 
00016 //
00017 // * Redistributions of modified source must be clearly marked as modified,
00018 //   and due notice must be placed in the modified source indicating the
00019 //   type of modification(s) and the name(s) of the person(s) performing
00020 //   said modification(s).
00021 //
00022 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
00023 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
00024 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00025 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
00026 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
00027 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 
00028 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
00029 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
00030 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
00031 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
00032 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033 //
00034 //---------------------------------------------------------------------------
00035 // Modifications:
00036 //
00037 //---------------------------------------------------------------------------
00038 //
00052 
00053 #include <memory.h>
00054 #include "CVUtil.h"
00055 #include "CVFile.h"
00056 #include "CVUtil.h"
00057 #include "CVImageRGBFloat.h"
00058 
00059 //---------------------------------------------------------------------------
00060 // constructor - Note that if we're on a big endian machine, we use the
00061 // '8' type of custom P?M file.  If we're on a little-endian machine,
00062 // we use '7'.
00063 //---------------------------------------------------------------------------
00064 CVImageRGBFloat::CVImageRGBFloat()
00065 :CVImage()
00066 {
00067 }
00068 //---------------------------------------------------------------------------
00069 CVImageRGBFloat::~CVImageRGBFloat()
00070 {
00071    // Parent calls destroy
00072 }
00073 
00074 //---------------------------------------------------------------------------
00075 // GetNumChannels
00076 //    Retrieves the number channels per pixel
00077 //---------------------------------------------------------------------------
00078 int CVImageRGBFloat::GetNumChannels() const
00079 {
00080    return 3;
00081 }
00082 
00083 //---------------------------------------------------------------------------
00084 // GetBytesPerPixel
00085 //    Retrieves the number of bytes per pixel.
00086 //---------------------------------------------------------------------------
00087 int CVImageRGBFloat::GetBytesPerPixel() const
00088 {
00089    return 12;
00090 }
00091 
00092 //--------------------------------------------------------------------------
00093 // GetImageType
00094 //    Retrieves the type of image - see CVIMAGE_TYPE enum in header
00095 //---------------------------------------------------------------------------
00096 CVImage::CVIMAGE_TYPE CVImageRGBFloat::GetImageType() const
00097 {
00098    return CVIMAGE_RGBFLOAT;
00099 }
00100 
00101 //---------------------------------------------------------------------------
00102 // GetPNMExtension() retrieves the default file extension for PNM
00103 // file saving. (e.g. ".pgm" for greyscale)
00104 //
00105 // \return const char* - ASCIIZ default file extension, 
00106 //                       including preceeding '.'
00107 // \sa Load(), Save()
00108 //---------------------------------------------------------------------------
00109 const char *CVImageRGBFloat::GetPNMExtension() const
00110 {
00111    return ".pxm";
00112 }
00113 
00114 //---------------------------------------------------------------------------
00115 // GetPNMMagicVal() retrieves the magic value for a pnm file
00116 // matching the current image format.
00117 //---------------------------------------------------------------------------
00118 char CVImageRGBFloat::GetPNMMagicVal() const
00119 {
00120    // 8 is big-endian floating point, 7 is little-endian.
00121    return CVImage::IsBigEndianMachine()?'8':'7';
00122 }
00123 
00124 //---------------------------------------------------------------------------
00125 // GetMaxPixelValue() retrieves the maximum value of any pixel in
00126 // the image.  
00127 //
00128 // In multichannel images (e.g. RGB triplets), it will
00129 // return the maximum value on any of the channels.
00130 //
00131 // All child classes should implement this.
00132 // \param maxValue - reference to max pixel value, set on return.
00133 // \return CVRES result code
00134 // \sa GetPixel(), SetPixel(), CVImage::GetMaxPixel()
00135 //---------------------------------------------------------------------------
00136 CVRES CVImageRGBFloat::GetMaxPixelValue(float& maxValue) const
00137 {
00138    return GetMaxPixel(maxValue);   
00139 }
00140 
00141 //---------------------------------------------------------------------------
00142 // GetPixel() retrieves the red, green, and blue values for a specified
00143 // pixel as floating points.
00144 //
00145 // This is for convenience and prototyping - for high-speed image
00146 // processing you'll need to work more directly with the image
00147 // buffer.
00148 //
00149 //
00150 // \param x - x position within the image of the pixel
00151 // \param y - y position within the image of the pixel
00152 // \param r - receives the red value of the pixel
00153 // \param g - receives the green value of the pixel
00154 // \param b - receives the blue value of the pixel
00155 //
00156 // \return CVRES result code.  CVRES_SUCCESS on success.
00157 // \sa SetPixel()
00158 //---------------------------------------------------------------------------
00159 CVRES CVImageRGBFloat::GetPixel(  int      x,
00160                                   int      y,
00161                                   float&   r,
00162                                   float&   g,
00163                                   float&   b) const
00164 {
00165    CVRES result = CVRES_SUCCESS;
00166    
00167    CVAssert(fData != 0, "Image must be created first!");
00168    if (fData == 0)
00169    {
00170       return CVRES_IMAGE_EMPTY_ERR;
00171    }
00172 
00173    // Bounds check coordinates
00174    CVAssert(( (x >= 0) || (x < fWidth)), "X position is out of bounds!");
00175    CVAssert(( (y >= 0) || (y < fHeight)), "Y position is out of bounds!");
00176 
00177    if ( (x < 0) || (x >= fWidth))
00178    {
00179       return CVRES_IMAGE_OUT_OF_RANGE;
00180    }
00181 
00182    if ( (y < 0) || (y >= fHeight))
00183    {
00184       return CVRES_IMAGE_OUT_OF_RANGE;
00185    }
00186       
00187    // Offset of pixel on x axis in image data
00188    int lineOffset = (this->XOffsetAbs() + x) * 3;
00189 
00190    // Absolute length of line in fData in floats ( >= fWidth * GetBytesPerPixel())
00191    int lineLength = this->AbsWidth() * 3;
00192    
00193    // current position of start of buffer in source
00194    float* curPtr = (float*)fData + lineOffset + 
00195                            ((YOffsetAbs() + y) * lineLength);
00196 
00197    // pull out pixels
00198    r = curPtr[0];
00199    g = curPtr[1];
00200    b = curPtr[2];
00201          
00202    return result;
00203 }
00204 //---------------------------------------------------------------------------
00205 // SetPixel() sets the red, green, and blue pixel values
00206 // for a pixel
00207 //
00208 // This is for convenience and prototyping - for high-speed image
00209 // processing you'll need to work more directly with the image
00210 // buffer.
00211 //
00214 //
00215 // Intensity values above 255 will be truncated to 255. Values
00216 // below 0 will be set to 0.
00217 //
00218 // \param x - x position within the image of the pixel
00219 // \param y - y position within the image of the pixel
00220 // \param r - receives the red value of the pixel
00221 // \param g - receives the green value of the pixel
00222 // \param b - receives the blue value of the pixel
00223 //
00224 // \return CVRES result code.  CVRES_SUCCESS on success.
00225 // \sa GetPixel()
00226 //---------------------------------------------------------------------------
00227 CVRES CVImageRGBFloat::SetPixel( int      x,
00228                                  int      y,
00229                                  float    r,
00230                                  float    g,
00231                                  float    b)
00232 {
00233    CVRES result = CVRES_SUCCESS;
00234    
00235    CVAssert(fData != 0, "Image must be created first!");
00236    if (fData == 0)
00237    {
00238       return CVRES_IMAGE_EMPTY_ERR;
00239    }
00240 
00241    // Bounds check coordinates
00242    CVAssert(( (x >= 0) || (x < fWidth)), "X position is out of bounds!");
00243    CVAssert(( (y >= 0) || (y < fHeight)), "Y position is out of bounds!");
00244 
00245    if ( (x < 0) || (x >= fWidth))
00246    {
00247       return CVRES_IMAGE_OUT_OF_RANGE;
00248    }
00249 
00250    if ( (y < 0) || (y >= fHeight))
00251    {
00252       return CVRES_IMAGE_OUT_OF_RANGE;
00253    }
00254    
00255    // Offset of pixel on x axis in image data
00256    int lineOffset = (this->XOffsetAbs() + x) * 3;
00257 
00258    // Absolute length of line in fData in floats ( >= fWidth * GetBytesPerPixel())
00259    int lineLength = this->AbsWidth() * 3;
00260    
00261    // current position of start of buffer in source
00262    float* curPtr = (float*)fData + lineOffset + 
00263                            ((YOffsetAbs() + y) * lineLength);
00264      
00265    // Store
00266    curPtr[0] = r;
00267    curPtr[1] = g;
00268    curPtr[2] = b;
00269          
00270    return result;
00271 }
00272 
00273 
00274 #ifdef WIN32
00275 //---------------------------------------------------------------------------
00276 // SetFromWin32Bmp()
00277 //    Sets the image from a bitmap buffer
00278 //    We do a full copy of the data for this, since we may flip it and
00279 //    swap red with blue to get it into RGB order rather than Window's BGR.
00280 //    Padding will be removed as well.
00281 //
00282 //    Only supports 24-bit RGB bitmaps.
00283 //
00284 //---------------------------------------------------------------------------
00285 CVRES CVImageRGBFloat::SetFromWin32Bmp(   const BITMAPINFOHEADER* bmih, 
00286                                        const unsigned char*    data)
00287 {    
00288    // Parent does sanity checks (only called from CreateFromWin32Bmp)
00289    CVRES result = CVRES_SUCCESS;
00290 
00291    // Negative height means top down. 
00292    // Flipped is set if bottom-up image (default for win32)
00293    bool flipped = bmih->biHeight >= 0;
00294 
00295    // Create an image of the same size 
00296    // Make sure to use a positive height based on flipped var
00297    // Note: this adds our reference count
00298    this->Create(  bmih->biWidth, 
00299                   flipped?(bmih->biHeight):-(bmih->biHeight), 
00300                   false);
00301       
00302    // Set our starting position in the source image and step pos
00303    float*          dstPos   = (float*)fData;
00304    unsigned char*  srcPos   = 0;
00305 
00306    int srcStep    = -((int)bmih->biSizeImage / fHeight);    
00307 
00308    if (flipped)
00309    {
00310       // Set to point to bottom row in image so we can flip it
00311       srcPos  = (unsigned char*)data + (int)bmih->biSizeImage + srcStep;
00312    }
00313    else
00314    {
00315       // Start at top if not flipped
00316       srcPos  = (unsigned char*)data;     
00317    }
00318 
00319    // Copy row by row from source image to destination image
00320 
00321    // May want to optimize this one a bit.
00322    // We're just flipping the red and blue channels while flipping from 
00323    // bottom to top.  For windows-only development where we work with
00324    // bitmaps, this is an unnecessary step. However, I like keeping all 
00325    // my images in a neutral RGB 24-bit unpadded format for simplicity, 
00326    // so unless it becomes a bottleneck, it makes it simpler.
00327 
00328 
00329    // profiling - time it.
00330    // CVStartTime();
00331          
00332    int y;
00333    for (y = 0; y < fHeight; y++)
00334    {     
00335       unsigned char* srcLine = srcPos;
00336       {              
00337          int x;
00338          for (x = 0; x < fWidth; x++)
00339          {
00340             *dstPos = (float)(*(srcLine+2)); dstPos++;
00341             *dstPos = (float)(*(srcLine+1)); dstPos++;
00342             *dstPos = (float)(*(srcLine)  ); dstPos++;
00343             srcLine +=3;
00344          }
00345       }        
00346       srcPos += srcStep;
00347    }        
00348    
00349    // end profiling - print time
00350    //CVEndTime();
00351 
00352    return result;
00353 }
00354 #endif // WIN32
00355 

Generated on Mon Mar 1 13:27:11 2004 for VidCapture Library by doxygen 1.3.3
CodeVis VidCapture 0.2 Copyright © 2003-2004 by Michael Ellison.