lossy.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
00033 }
00034 #endif
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
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
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 }