CodeVis.com SourceForge.net Logo

CVImageRGB24.cpp

Go to the documentation of this file.
00001 // CVImageRGB24 - 24-bit 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 //---------------------------------------------------------------------------
00051 
00052 #include <memory.h>
00053 #include "CVUtil.h"
00054 #include "CVFile.h"
00055 #include "CVImageRGB24.h"
00056 #include "CVUtil.h"
00057 
00058 //---------------------------------------------------------------------------
00059 CVImageRGB24::CVImageRGB24()
00060 :CVImage()
00061 {
00062 }
00063 //---------------------------------------------------------------------------
00064 CVImageRGB24::~CVImageRGB24()
00065 {
00066    // Parent calls destroy
00067 }
00068 
00069 //---------------------------------------------------------------------------
00070 // GetNumChannels
00071 //    Retrieves the number channels per pixel
00072 //---------------------------------------------------------------------------
00073 int CVImageRGB24::GetNumChannels() const
00074 {
00075    return 3;
00076 }
00077 
00078 //---------------------------------------------------------------------------
00079 // GetBytesPerPixel
00080 //    Retrieves the number of bytes per pixel.
00081 //---------------------------------------------------------------------------
00082 int CVImageRGB24::GetBytesPerPixel() const
00083 {
00084    return 3;
00085 }
00086 
00087 //--------------------------------------------------------------------------
00088 // GetImageType
00089 //    Retrieves the type of image - see CVIMAGE_TYPE enum in header
00090 //---------------------------------------------------------------------------
00091 CVImage::CVIMAGE_TYPE CVImageRGB24::GetImageType() const
00092 {
00093    return CVIMAGE_RGB24;
00094 }
00095 
00096 //---------------------------------------------------------------------------
00097 // GetPNMExtension() retrieves the default file extension for PNM
00098 // file saving. (e.g. ".pgm" for greyscale)
00099 //
00100 // \return const char* - ASCIIZ default file extension, 
00101 //                       including preceeding '.'
00102 // \sa Load(), Save()
00103 //---------------------------------------------------------------------------
00104 const char *CVImageRGB24::GetPNMExtension() const
00105 {
00106    return ".ppm";
00107 }
00108 
00109 //---------------------------------------------------------------------------
00110 // GetPNMMagicVal() retrieves the magic value for a pnm file
00111 // matching the current image format.
00112 //---------------------------------------------------------------------------
00113 char CVImageRGB24::GetPNMMagicVal() const
00114 {
00115    return '6';
00116 }
00117 
00118 //---------------------------------------------------------------------------
00119 // GetMaxPixelValue() retrieves the maximum value of any pixel in
00120 // the image.  
00121 //
00122 // In multichannel images (e.g. RGB triplets), it will
00123 // return the maximum value on any of the channels.
00124 //
00125 // All child classes should implement this.
00126 // \param maxValue - reference to max pixel value, set on return.
00127 // \return CVRES result code
00128 // \sa GetPixel(), SetPixel(), CVImage::GetMaxPixel()
00129 //---------------------------------------------------------------------------
00130 CVRES CVImageRGB24::GetMaxPixelValue(float& maxValue) const
00131 {
00132    unsigned char maxPixel;   
00133    CVRES result = GetMaxPixel(maxPixel);   
00134    maxValue = (float)maxPixel;
00135    return result;
00136 }
00137 
00138 //---------------------------------------------------------------------------
00139 // GetPixel() retrieves the red, green, and blue values for a specified
00140 // pixel as floating points.
00141 //
00142 // This is for convenience and prototyping - for high-speed image
00143 // processing you'll need to work more directly with the image
00144 // buffer.
00145 //
00146 // Within CVImageRGB24, this returns the red, green, and blue values
00147 // all of which will be between 0-255.
00148 //
00149 // \param x - x position within the image of the pixel
00150 // \param y - y position within the image of the pixel
00151 // \param r - receives the red value of the pixel
00152 // \param g - receives the green value of the pixel
00153 // \param b - receives the blue value of the pixel
00154 //
00155 // \return CVRES result code.  CVRES_SUCCESS on success.
00156 // \sa SetPixel()
00157 //---------------------------------------------------------------------------
00158 CVRES CVImageRGB24::GetPixel( int      x,
00159                               int      y,
00160                               float&   r,
00161                               float&   g,
00162                               float&   b) const
00163 {
00164    CVRES result = CVRES_SUCCESS;
00165    
00166    CVAssert(fData != 0, "Image must be created first!");
00167    if (fData == 0)
00168    {
00169       return CVRES_IMAGE_EMPTY_ERR;
00170    }
00171 
00172    // Bounds check coordinates
00173    CVAssert(( (x >= 0) || (x < fWidth)), "X position is out of bounds!");
00174    CVAssert(( (y >= 0) || (y < fHeight)), "Y position is out of bounds!");
00175 
00176    if ( (x < 0) || (x >= fWidth))
00177    {
00178       return CVRES_IMAGE_OUT_OF_RANGE;
00179    }
00180 
00181    if ( (y < 0) || (y >= fHeight))
00182    {
00183       return CVRES_IMAGE_OUT_OF_RANGE;
00184    }
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 bytes ( >= fWidth * GetBytesPerPixel())
00191    int lineLength = this->AbsWidth() * 3;
00192    
00193    // current position of start of buffer in source
00194    unsigned char* curPtr = fData + lineOffset + 
00195                            ((YOffsetAbs() + y) * lineLength);
00196 
00197    // pull out pixels
00198    r = (float)curPtr[0];
00199    g = (float)curPtr[1];
00200    b = (float)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 //
00212 // Within CVImageRGB24, the values are truncated to be between
00213 // 0 (min) and 255 (max), then set.      
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 CVImageRGB24::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 bytes ( >= fWidth * GetBytesPerPixel())
00259    int lineLength = this->AbsWidth() * 3;
00260    
00261    // current position of start of buffer in source
00262    unsigned char* curPtr = fData + lineOffset + 
00263                            ((YOffsetAbs() + y) * lineLength);
00264    
00265    // Bounds check the pixel values
00266    r = CVMax( 0.0f,   r );
00267    r = CVMin( 255.0f, r );
00268    g = CVMax( 0.0f,   g );
00269    g = CVMin( 255.0f, g );
00270    b = CVMax( 0.0f,   b );
00271    b = CVMin( 255.0f, b );
00272 
00273    // Store
00274    curPtr[0] = (unsigned char)r;
00275    curPtr[1] = (unsigned char)g;
00276    curPtr[2] = (unsigned char)b;
00277          
00278    return result;
00279 }
00280 
00281 #ifdef WIN32
00282 //---------------------------------------------------------------------------
00283 // SetFromWin32Bmp()
00284 //    Sets the image from a bitmap buffer
00285 //    We do a full copy of the data for this, since we may flip it and
00286 //    swap red with blue to get it into RGB order rather than Window's BGR.
00287 //    Padding will be removed as well.
00288 //
00289 //    Only supports 24-bit RGB bitmaps.
00290 //
00291 //---------------------------------------------------------------------------
00292 CVRES CVImageRGB24::SetFromWin32Bmp(   const BITMAPINFOHEADER* bmih, 
00293                                        const unsigned char*    data)
00294 {  
00295    CVAssert(fData == 0, 
00296       "SetFromWin32Bmp requires a clean, uninitialized,"\
00297       " but instantiated image");
00298 
00299    // Parent does sanity checks (only called from CreateFromWin32bmp)  
00300    CVRES result = CVRES_SUCCESS;
00301 
00302    // Negative height means top down. 
00303    // Flipped is set if bottom-up image (default for win32)
00304    bool flipped = bmih->biHeight >= 0;
00305 
00306    // Create an image of the same size 
00307    // Make sure to use a positive height based on flipped var
00308    // Note: this adds our reference
00309    Create(  bmih->biWidth, 
00310                   flipped?(bmih->biHeight):-(bmih->biHeight), 
00311                   false);
00312       
00313    // Set our starting position in the source image and step pos
00314    unsigned char* dstPos   = fData;
00315    unsigned char* srcPos   = 0;
00316 
00317    int srcStep    = -((int)bmih->biSizeImage / fHeight);    
00318 
00319    if (flipped)
00320    {
00321       // Set to point to bottom row in image so we can flip it
00322       srcPos  = (unsigned char*)data + (int)bmih->biSizeImage + srcStep;
00323    }
00324    else
00325    {
00326       // Start at top if not flipped
00327       srcPos  = (unsigned char*)data;     
00328    }
00329 
00330    // Copy row by row from source image to destination image
00331 
00332    // May want to optimize this one a bit.
00333    // We're just flipping the red and blue channels while flipping from 
00334    // bottom to top.  For windows-only development where we work with
00335    // bitmaps, this is an unnecessary step. However, I like keeping all 
00336    // my images in a neutral RGB 24-bit unpadded format for simplicity, 
00337    // so unless it becomes a bottleneck, it makes it simpler.
00338 
00339    // profiling - time it.
00340    // CVStartTime();
00341          
00342    int y;
00343    for (y = 0; y < fHeight; y++)
00344    {     
00345       unsigned char* srcLine = srcPos;
00346       {              
00347          int x;
00348          for (x = 0; x < fWidth; x++)
00349          {
00350             *dstPos = *(srcLine+2); dstPos++;
00351             *dstPos = *(srcLine+1); dstPos++;
00352             *dstPos = *(srcLine);   dstPos++;
00353             srcLine +=3;
00354          }
00355       }        
00356       srcPos += srcStep;
00357    }        
00358    
00359    // end profiling - print time
00360    //CVEndTime();
00361 
00362    return result;
00363 }
00364 #endif // WIN32
00365 

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.