Fawkes API
Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * imagediff.cpp - check images if they are different 00004 * 00005 * Generated: Tue Jun 06 10:22:49 2006 00006 * Copyright 2005-2007 Tim Niemueller [www.niemueller.de] 00007 * 00008 ****************************************************************************/ 00009 00010 /* This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. A runtime exception applies to 00014 * this software (see LICENSE.GPL_WRE file mentioned below for details). 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU Library General Public License for more details. 00020 * 00021 * Read the full text in the LICENSE.GPL_WRE file in the doc directory. 00022 */ 00023 00024 #include <fvutils/statistical/imagediff.h> 00025 #include <fvutils/color/yuv.h> 00026 00027 #include <cstdlib> 00028 00029 namespace firevision { 00030 #if 0 /* just to make Emacs auto-indent happy */ 00031 } 00032 #endif 00033 00034 /** @class ImageDiff <fvutils/statistical/imagediff.h> 00035 * Image difference checker. 00036 * @author Tim Niemueller 00037 */ 00038 00039 /** Constructor. 00040 * @param scanline_model scanlinemodel to use, if null all pixels 00041 * are compared. 00042 */ 00043 ImageDiff::ImageDiff(ScanlineModel *scanline_model) 00044 { 00045 this->scanline_model = scanline_model; 00046 } 00047 00048 00049 /** Constructor. 00050 * Use this constructor to compare all pixels. 00051 */ 00052 ImageDiff::ImageDiff() 00053 { 00054 scanline_model = NULL; 00055 } 00056 00057 00058 /** Destructor. */ 00059 ImageDiff::~ImageDiff() 00060 { 00061 } 00062 00063 00064 /** Set first buffer. 00065 * @param yuv422planar_buffer buffer 00066 * @param width image width in pixels 00067 * @param height image height in pixels 00068 */ 00069 void 00070 ImageDiff::setBufferA(unsigned char *yuv422planar_buffer, 00071 unsigned int width, unsigned int height) 00072 { 00073 buffer_a = yuv422planar_buffer; 00074 width_a = width; 00075 height_a = height; 00076 } 00077 00078 00079 /** Set second buffer. 00080 * @param yuv422planar_buffer buffer 00081 * @param width image width in pixels 00082 * @param height image height in pixels 00083 */ 00084 void 00085 ImageDiff::setBufferB(unsigned char *yuv422planar_buffer, 00086 unsigned int width, unsigned int height) 00087 { 00088 buffer_b = yuv422planar_buffer; 00089 width_b = width; 00090 height_b = height; 00091 } 00092 00093 00094 /** Check if images are different. 00095 * This method will compare the two images. If any pixel marked by 00096 * the scanline or any pixel at all if no scanline model is given 00097 * differ the images are considered to be different. The same applies 00098 * if any buffer is unset or the widths or heights are not the same. 00099 * @return true if images are different, false otherwise 00100 */ 00101 bool 00102 ImageDiff::different() 00103 { 00104 if ( (buffer_a == NULL) && (buffer_b == NULL) ) return false; 00105 if ( (buffer_a == NULL) && (buffer_b != NULL) ) return true; 00106 if ( (buffer_a != NULL) && (buffer_b == NULL) ) return true; 00107 if ( (width_a != width_b) || (height_a != height_b) ) return true; 00108 00109 if ( scanline_model != NULL ) { 00110 // use the supplied scanline model 00111 00112 unsigned int x, y; 00113 unsigned char y_a, u_a, v_a, y_b, u_b, v_b; 00114 00115 scanline_model->reset(); 00116 while (! scanline_model->finished() ) { 00117 x = (*scanline_model)->x; 00118 y = (*scanline_model)->y; 00119 00120 YUV422_PLANAR_YUV(buffer_a, width_a, height_a, x, y, y_a, u_a, v_a); 00121 YUV422_PLANAR_YUV(buffer_b, width_b, height_b, x, y, y_b, u_b, v_b); 00122 00123 if ( (y_a != y_b) || (u_a != u_b) || (v_a != v_b) ) { 00124 return true; 00125 } 00126 } 00127 } else { 00128 // no scanline model, check every single pixel 00129 00130 unsigned char *ypa = buffer_a; 00131 unsigned char *ypb = buffer_b; 00132 00133 for ( unsigned int i = 0; i < (width_a * height_a); ++i) { 00134 if ( *ypa != *ypb ) { 00135 return true; 00136 } 00137 ++ypa; 00138 ++ypb; 00139 } 00140 } 00141 00142 return false; 00143 } 00144 00145 00146 /** Number of differing pixels. 00147 * Executes the same routine as different(). But instead of just saying that 00148 * the images are different will tell how many pixels differ. 00149 * @return number of different pixels 00150 */ 00151 unsigned int 00152 ImageDiff::numDifferingPixels() 00153 { 00154 if ( (buffer_a == NULL) && (buffer_b == NULL) ) return 0; 00155 if ( (buffer_a == NULL) && (buffer_b != NULL) ) return (width_b * height_b); 00156 if ( (buffer_a != NULL) && (buffer_b == NULL) ) return (width_a * height_a); 00157 if ( (width_a != width_b) || (height_a != height_b) ) { 00158 return abs(width_a - width_b) * abs(height_a - height_b); 00159 } 00160 00161 unsigned int num = 0; 00162 if ( scanline_model != NULL ) { 00163 // use the supplied scanline model 00164 00165 unsigned int x, y; 00166 unsigned char y_a, u_a, v_a, y_b, u_b, v_b; 00167 00168 scanline_model->reset(); 00169 while (! scanline_model->finished() ) { 00170 x = (*scanline_model)->x; 00171 y = (*scanline_model)->y; 00172 00173 YUV422_PLANAR_YUV(buffer_a, width_a, height_a, x, y, y_a, u_a, v_a); 00174 YUV422_PLANAR_YUV(buffer_b, width_b, height_b, x, y, y_b, u_b, v_b); 00175 00176 if ( (y_a != y_b) || (u_a != u_b) || (v_a != v_b) ) { 00177 ++num; 00178 } 00179 } 00180 } else { 00181 // no scanline model, check every single pixel 00182 00183 unsigned char *ypa = buffer_a; 00184 unsigned char *ypb = buffer_b; 00185 00186 for ( unsigned int i = 0; i < (width_a * height_a); ++i) { 00187 if ( *ypa++ != *ypb++ ) ++num; 00188 } 00189 } 00190 return num; 00191 } 00192 00193 } // end namespace firevision