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
00032
00033
00034
00035
00036
00037
00038
00039
00040 LossyScaler::LossyScaler()
00041 {
00042 orig_width = orig_height = 0;
00043 scal_width = scal_height = 0;
00044 orig_buffer = NULL;
00045 scal_buffer = NULL;
00046
00047 scale_factor = 1.f;
00048 }
00049
00050
00051
00052 LossyScaler::~LossyScaler()
00053 {
00054 }
00055
00056
00057 void
00058 LossyScaler::set_scale_factor(float factor)
00059 {
00060 if ( (factor <= 0) || (factor > 1) ) {
00061 scale_factor = 1.f;
00062 } else {
00063 scale_factor = factor;
00064 }
00065
00066 if (orig_width != 0) {
00067 scal_width = (unsigned int) ceil(orig_width * scale_factor);
00068 scal_width += (scal_width % 2);
00069 }
00070 if (orig_height != 0) {
00071 scal_height = (unsigned int) ceil(orig_height * scale_factor);
00072 scal_height += (scal_width % 2);
00073 }
00074 }
00075
00076
00077 void
00078 LossyScaler::set_original_dimensions(unsigned int width,
00079 unsigned int height)
00080 {
00081 orig_width = width;
00082 orig_height = height;
00083 }
00084
00085
00086 void
00087 LossyScaler::set_scaled_dimensions(unsigned int width,
00088 unsigned int height)
00089 {
00090 scal_width = width;
00091 scal_height = height;
00092
00093 float scale_factor_width = 1.0;
00094 float scale_factor_height = 1.0;
00095
00096 if (orig_width != 0) {
00097 scale_factor_width = scal_width / float(orig_width);
00098 }
00099 if (orig_height != 0) {
00100 scale_factor_height = scal_height / float(orig_height);
00101 }
00102
00103 scale_factor = (scale_factor_width < scale_factor_height) ? scale_factor_width : scale_factor_height;
00104
00105 scal_width = (unsigned int) floor(orig_width * scale_factor);
00106 scal_height = (unsigned int) floor(orig_height * scale_factor);
00107
00108 scal_width += (scal_width % 2);
00109 scal_height += (scal_height % 2);
00110 }
00111
00112
00113 void
00114 LossyScaler::set_original_buffer(unsigned char *buffer)
00115 {
00116 orig_buffer = buffer;
00117 }
00118
00119
00120 void
00121 LossyScaler::set_scaled_buffer(unsigned char *buffer)
00122 {
00123 scal_buffer = buffer;
00124 }
00125
00126
00127 unsigned int
00128 LossyScaler::needed_scaled_width()
00129 {
00130 return scal_width;
00131 }
00132
00133
00134 unsigned int
00135 LossyScaler::needed_scaled_height()
00136 {
00137 return scal_height;
00138 }
00139
00140
00141 float
00142 LossyScaler::get_scale_factor()
00143 {
00144 return scale_factor;
00145 }
00146
00147 void
00148 LossyScaler::scale()
00149 {
00150 if ( orig_width == 0 ) return;
00151 if ( orig_height == 0 ) return;
00152 if ( scal_width == 0 ) return;
00153 if ( scal_height == 0 ) return;
00154 if ( orig_buffer == NULL ) return;
00155 if ( scal_buffer == NULL ) return;
00156 if ( scal_width < needed_scaled_width() ) return;
00157 if ( scal_height < needed_scaled_height() ) return;
00158
00159 float skip = 1 / scale_factor;
00160 unsigned char *oyp = orig_buffer;
00161 unsigned char *oup = YUV422_PLANAR_U_PLANE( orig_buffer, orig_width, orig_height );
00162 unsigned char *ovp = YUV422_PLANAR_V_PLANE( orig_buffer, orig_width, orig_height );
00163
00164 unsigned char *syp = scal_buffer;
00165 unsigned char *sup = YUV422_PLANAR_U_PLANE( scal_buffer, scal_width, scal_height );
00166 unsigned char *svp = YUV422_PLANAR_V_PLANE( scal_buffer, scal_width, scal_height );
00167
00168 memset( syp, 0, scal_width * scal_height );
00169 memset( sup, 128, scal_width * scal_height );
00170
00171 float oh_float = 0.0;
00172 float ow_float = 0.0;
00173
00174 unsigned int oh_pixel;
00175 unsigned int ow_pixel;
00176 unsigned int ow_pixel_next;
00177
00178 for (unsigned int h = 0; h < scal_height; ++h) {
00179 oh_pixel = (unsigned int) rint(oh_float);
00180 ow_float = 0.0;
00181
00182 if (oh_pixel >= orig_height) {
00183 oh_pixel = orig_height - 1;
00184 }
00185 for (unsigned int w = 0; w < scal_width; w += 2) {
00186 ow_pixel = (unsigned int) rint(ow_float);
00187 ow_pixel_next = (unsigned int) rint( ow_float + skip);
00188
00189 if (ow_pixel >= orig_width) {
00190 ow_pixel = orig_width - 1;
00191 }
00192
00193 if (ow_pixel_next >= orig_width) {
00194 ow_pixel_next = orig_width - 1;
00195 }
00196
00197 syp[ h * scal_width + w ] = oyp[ oh_pixel * orig_width + ow_pixel ];
00198 syp[ h * scal_width + w + 1 ] = oyp[ oh_pixel * orig_width + ow_pixel_next ];
00199 sup[ (h * scal_width + w) / 2 ] = (oup[ (oh_pixel * orig_width + ow_pixel) / 2 ] + oup[ (oh_pixel * orig_width + ow_pixel_next) / 2 ]) / 2;
00200 svp[ (h * scal_width + w) / 2 ] = (ovp[ (oh_pixel * orig_width + ow_pixel) / 2 ] + ovp[ (oh_pixel * orig_width + ow_pixel_next) / 2 ]) / 2;
00201
00202 ow_float += 2 * skip;
00203 }
00204 oh_float += skip;
00205 }
00206 }