Fawkes API Fawkes Development Version

lossy.cpp

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
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends