Fawkes API
Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * lossy.cpp - lossy scaler 00004 * 00005 * Generated: Tue May 16 14:59:30 2006 (Automatica 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 00025 #include <fvutils/scalers/lossy.h> 00026 #include <fvutils/color/yuv.h> 00027 00028 #include <cmath> 00029 #include <cstring> 00030 00031 namespace firevision { 00032 #if 0 /* just to make Emacs auto-indent happy */ 00033 } 00034 #endif 00035 00036 /** @class LossyScaler <fvutils/scalers/lossy.h> 00037 * Lossy image scaler. 00038 * This scaler just takes the required pixels from the image and throws away 00039 * the rest. No enhancement of the image is done. 00040 * This is only suitable for downscaling. The scale factor must be between 00041 * 0 and 1. 00042 */ 00043 00044 /** Constructor. */ 00045 LossyScaler::LossyScaler() 00046 { 00047 orig_width = orig_height = 0; 00048 scal_width = scal_height = 0; 00049 orig_buffer = NULL; 00050 scal_buffer = NULL; 00051 00052 scale_factor = 1.f; 00053 } 00054 00055 00056 /** Destructor. */ 00057 LossyScaler::~LossyScaler() 00058 { 00059 } 00060 00061 00062 void 00063 LossyScaler::set_scale_factor(float factor) 00064 { 00065 if ( (factor <= 0) || (factor > 1) ) { 00066 scale_factor = 1.f; 00067 } else { 00068 scale_factor = factor; 00069 } 00070 00071 if (orig_width != 0) { 00072 scal_width = (unsigned int) ceil(orig_width * scale_factor); 00073 scal_width += (scal_width % 2); 00074 } 00075 if (orig_height != 0) { 00076 scal_height = (unsigned int) ceil(orig_height * scale_factor); 00077 scal_height += (scal_width % 2); 00078 } 00079 } 00080 00081 00082 void 00083 LossyScaler::set_original_dimensions(unsigned int width, 00084 unsigned int height) 00085 { 00086 orig_width = width; 00087 orig_height = height; 00088 } 00089 00090 00091 void 00092 LossyScaler::set_scaled_dimensions(unsigned int width, 00093 unsigned int height) 00094 { 00095 scal_width = width; 00096 scal_height = height; 00097 00098 float scale_factor_width = 1.0; 00099 float scale_factor_height = 1.0; 00100 00101 if (orig_width != 0) { 00102 scale_factor_width = scal_width / float(orig_width); 00103 } 00104 if (orig_height != 0) { 00105 scale_factor_height = scal_height / float(orig_height); 00106 } 00107 00108 scale_factor = (scale_factor_width < scale_factor_height) ? scale_factor_width : scale_factor_height; 00109 00110 scal_width = (unsigned int) floor(orig_width * scale_factor); 00111 scal_height = (unsigned int) floor(orig_height * scale_factor); 00112 00113 scal_width += (scal_width % 2); 00114 scal_height += (scal_height % 2); 00115 } 00116 00117 00118 void 00119 LossyScaler::set_original_buffer(unsigned char *buffer) 00120 { 00121 orig_buffer = buffer; 00122 } 00123 00124 00125 void 00126 LossyScaler::set_scaled_buffer(unsigned char *buffer) 00127 { 00128 scal_buffer = buffer; 00129 } 00130 00131 00132 unsigned int 00133 LossyScaler::needed_scaled_width() 00134 { 00135 return scal_width; 00136 } 00137 00138 00139 unsigned int 00140 LossyScaler::needed_scaled_height() 00141 { 00142 return scal_height; 00143 } 00144 00145 00146 float 00147 LossyScaler::get_scale_factor() 00148 { 00149 return scale_factor; 00150 } 00151 00152 void 00153 LossyScaler::scale() 00154 { 00155 if ( orig_width == 0 ) return; 00156 if ( orig_height == 0 ) return; 00157 if ( scal_width == 0 ) return; 00158 if ( scal_height == 0 ) return; 00159 if ( orig_buffer == NULL ) return; 00160 if ( scal_buffer == NULL ) return; 00161 if ( scal_width < needed_scaled_width() ) return; 00162 if ( scal_height < needed_scaled_height() ) return; 00163 00164 float skip = 1 / scale_factor; 00165 unsigned char *oyp = orig_buffer; 00166 unsigned char *oup = YUV422_PLANAR_U_PLANE( orig_buffer, orig_width, orig_height ); 00167 unsigned char *ovp = YUV422_PLANAR_V_PLANE( orig_buffer, orig_width, orig_height ); 00168 00169 unsigned char *syp = scal_buffer; 00170 unsigned char *sup = YUV422_PLANAR_U_PLANE( scal_buffer, scal_width, scal_height ); 00171 unsigned char *svp = YUV422_PLANAR_V_PLANE( scal_buffer, scal_width, scal_height ); 00172 00173 memset( syp, 0, scal_width * scal_height ); 00174 memset( sup, 128, scal_width * scal_height ); 00175 00176 float oh_float = 0.0; 00177 float ow_float = 0.0; 00178 00179 unsigned int oh_pixel; 00180 unsigned int ow_pixel; 00181 unsigned int ow_pixel_next; 00182 00183 for (unsigned int h = 0; h < scal_height; ++h) { 00184 oh_pixel = (unsigned int) rint(oh_float); 00185 ow_float = 0.0; 00186 00187 if (oh_pixel >= orig_height) { 00188 oh_pixel = orig_height - 1; 00189 } 00190 for (unsigned int w = 0; w < scal_width; w += 2) { 00191 ow_pixel = (unsigned int) rint(ow_float); 00192 ow_pixel_next = (unsigned int) rint( ow_float + skip); 00193 00194 if (ow_pixel >= orig_width) { 00195 ow_pixel = orig_width - 1; 00196 } 00197 00198 if (ow_pixel_next >= orig_width) { 00199 ow_pixel_next = orig_width - 1; 00200 } 00201 00202 syp[ h * scal_width + w ] = oyp[ oh_pixel * orig_width + ow_pixel ]; 00203 syp[ h * scal_width + w + 1 ] = oyp[ oh_pixel * orig_width + ow_pixel_next ]; 00204 sup[ (h * scal_width + w) / 2 ] = (oup[ (oh_pixel * orig_width + ow_pixel) / 2 ] + oup[ (oh_pixel * orig_width + ow_pixel_next) / 2 ]) / 2; 00205 svp[ (h * scal_width + w) / 2 ] = (ovp[ (oh_pixel * orig_width + ow_pixel) / 2 ] + ovp[ (oh_pixel * orig_width + ow_pixel_next) / 2 ]) / 2; 00206 00207 ow_float += 2 * skip; 00208 } 00209 oh_float += skip; 00210 } 00211 } 00212 00213 } // end namespace firevision