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
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #ifndef ENVISION_ENV_C_MATH_OPS_C_DEFINED
00039 #define ENVISION_ENV_C_MATH_OPS_C_DEFINED
00040
00041 #include "Envision/env_c_math_ops.h"
00042
00043 #include "Envision/env_log.h"
00044 #include "Envision/env_types.h"
00045
00046
00047 void env_c_lowpass_5_x_dec_x_fewbits_optim(const intg32* src,
00048 const env_size_t w,
00049 const env_size_t h,
00050 intg32* dst,
00051 const env_size_t w2)
00052 {
00053 ENV_ASSERT(w2 == w/2);
00054
00055 if (w == 2 || w == 3)
00056 for (env_size_t j = 0; j < h; ++j)
00057 {
00058
00059 *dst++ = (src[0] * 3 + src[1] * 2) / 5;
00060 src += w;
00061 }
00062 else
00063
00064
00065
00066
00067 for (env_size_t j = 0; j < h; ++j)
00068 {
00069 const intg32* src2 = src;
00070
00071 *dst++ = (src2[0] * 2 + src2[1]) / 3;
00072
00073
00074
00075
00076 for (env_size_t i = 0; i < w-3; i += 2)
00077 {
00078 *dst++ = (src2[1] + src2[3] + src2[2] * 2) >> 2;
00079 src2 += 2;
00080 }
00081
00082 src += w;
00083 }
00084 }
00085
00086
00087 void env_c_lowpass_5_y_dec_y_fewbits_optim(const intg32* src,
00088 const env_size_t w,
00089 const env_size_t h,
00090 intg32* dst,
00091 const env_size_t h2)
00092 {
00093 ENV_ASSERT(h2 == h/2);
00094
00095
00096 const env_size_t w2 = w + w, w3 = w2 + w;
00097
00098 if (h == 2 || h == 3)
00099 {
00100
00101 for (env_size_t i = 0; i < w; ++i)
00102 {
00103 *dst++ = (src[0] * 3 + src[w] * 2) / 5;
00104 src++;
00105 }
00106 src -= w;
00107 }
00108 else
00109 {
00110
00111 for (env_size_t k = 0; k < w; ++k)
00112 {
00113 *dst++ = (src[ 0] * 2 + src[ w]) / 3;
00114 src++;
00115 }
00116 src -= w;
00117
00118
00119
00120
00121 for (env_size_t i = 0; i < h-3; i += 2)
00122 {
00123 for (env_size_t k = 0; k < w; ++k)
00124 {
00125 *dst++ = (src[ w] + src[w3] + src[w2] * 2) >> 2;
00126 src++;
00127 }
00128 src += w;
00129 }
00130 }
00131 }
00132
00133
00134 void env_c_lowpass_9_x_fewbits_optim(const intg32* src,
00135 const env_size_t w,
00136 const env_size_t h,
00137 intg32* dst)
00138 {
00139 ENV_ASSERT(w >= 9);
00140
00141
00142 for (env_size_t j = 0; j < h; ++j)
00143 {
00144
00145 *dst++ =
00146 (src[0] * 72 +
00147 src[1] * 56 +
00148 src[2] * 28 +
00149 src[3] * 8
00150 ) / 164;
00151 *dst++ =
00152 ((src[0] + src[2]) * 56 +
00153 src[1] * 72 +
00154 src[3] * 28 +
00155 src[4] * 8
00156 ) / 220;
00157 *dst++ =
00158 ((src[0] + src[4]) * 28 +
00159 (src[1] + src[3]) * 56 +
00160 src[2] * 72 +
00161 src[5] * 8
00162 ) / 248;
00163
00164
00165 for (env_size_t i = 0; i < w - 6; ++i)
00166 {
00167 *dst++ =
00168 ((src[0] + src[6]) * 8 +
00169 (src[1] + src[5]) * 28 +
00170 (src[2] + src[4]) * 56 +
00171 src[3] * 72
00172 ) >> 8;
00173 ++src;
00174 }
00175
00176
00177 *dst++ =
00178 (src[0] * 8 +
00179 (src[1] + src[5]) * 28 +
00180 (src[2] + src[4]) * 56 +
00181 src[3] * 72
00182 ) / 248;
00183 ++src;
00184 *dst++ =
00185 (src[0] * 8 +
00186 src[1] * 28 +
00187 (src[2] + src[4]) * 56 +
00188 src[3] * 72
00189 ) / 220;
00190 ++src;
00191 *dst++ =
00192 (src[0] * 8 +
00193 src[1] * 28 +
00194 src[2] * 56 +
00195 src[3] * 72
00196 ) / 164;
00197 src += 4;
00198 }
00199 }
00200
00201
00202 void env_c_lowpass_9_y_fewbits_optim(const intg32* src,
00203 const env_size_t w,
00204 const env_size_t h,
00205 intg32* dst)
00206 {
00207 ENV_ASSERT(h >= 9);
00208
00209
00210 const env_size_t w2 = w + w, w3 = w2 + w, w4 = w3 + w, w5 = w4 + w, w6 = w5 + w;
00211
00212
00213 for (env_size_t i = 0; i < w; ++i)
00214 {
00215 *dst++ =
00216 (src[ 0] * 72 +
00217 src[ w] * 56 +
00218 src[w2] * 28 +
00219 src[w3] * 8
00220 ) / 164;
00221 ++src;
00222 }
00223 src -= w;
00224 for (env_size_t i = 0; i < w; ++i)
00225 {
00226 *dst++ =
00227 ((src[ 0] + src[w2]) * 56 +
00228 src[ w] * 72 +
00229 src[w3] * 28 +
00230 src[w4] * 8
00231 ) / 220;
00232 ++src;
00233 }
00234 src -= w;
00235 for (env_size_t i = 0; i < w; ++i)
00236 {
00237 *dst++ =
00238 ((src[ 0] + src[w4]) * 28 +
00239 (src[ w] + src[w3]) * 56 +
00240 src[w2] * 72 +
00241 src[w5] * 8
00242 ) / 248;
00243 ++src;
00244 }
00245 src -= w;
00246
00247 for (env_size_t j = 0; j < h - 6; j ++)
00248 for (env_size_t i = 0; i < w; ++i)
00249 {
00250 *dst++ =
00251 ((src[ 0] + src[w6]) * 8 +
00252 (src[ w] + src[w5]) * 28 +
00253 (src[w2] + src[w4]) * 56 +
00254 src[w3] * 72
00255 ) >> 8;
00256 ++src;
00257 }
00258
00259 for (env_size_t i = 0; i < w; ++i)
00260 {
00261 *dst++ =
00262 (src[ 0] * 8 +
00263 (src[ w] + src[w5]) * 28 +
00264 (src[w2] + src[w4]) * 56 +
00265 src[w3] * 72
00266 ) / 248;
00267 ++src;
00268 }
00269 for (env_size_t i = 0; i < w; ++i)
00270 {
00271 *dst++ =
00272 (src[ 0] * 8 +
00273 src[ w] * 28 +
00274 (src[w2] + src[w4]) * 56 +
00275 src[w3] * 72
00276 ) / 220;
00277 ++src;
00278 }
00279 for (env_size_t i = 0; i < w; ++i)
00280 {
00281 *dst++ =
00282 (src[ 0] * 8 +
00283 src[ w] * 28 +
00284 src[w2] * 56 +
00285 src[w3] * 72
00286 ) / 164;
00287 ++src;
00288 }
00289 }
00290
00291
00292 void env_c_get_min_max(const intg32* src, const env_size_t sz,
00293 intg32* xmini, intg32* xmaxi)
00294 {
00295 ENV_ASSERT(sz > 0);
00296 *xmini = *xmaxi = src[0];
00297 for (env_size_t i = 0; i < sz; ++i)
00298 {
00299 if (src[i] < *xmini) *xmini = src[i];
00300 else if (src[i] > *xmaxi) *xmaxi = src[i];
00301 }
00302 }
00303
00304
00305 void env_c_inplace_rectify(intg32* dst, const env_size_t sz)
00306 {
00307 for (env_size_t i = 0; i < sz; ++i)
00308 if (dst[i] < 0) dst[i] = 0;
00309 }
00310
00311
00312 void env_c_inplace_normalize(intg32* const dst, const env_size_t sz,
00313 const intg32 nmin, const intg32 nmax,
00314 intg32* const actualmin_p,
00315 intg32* const actualmax_p,
00316 const intg32 rangeThresh)
00317 {
00318 ENV_ASSERT(sz > 0);
00319 ENV_ASSERT(nmax >= nmin);
00320
00321 intg32 mi, ma;
00322 env_c_get_min_max(dst, sz, &mi, &ma);
00323 const intg32 old_scale = ma - mi;
00324 if (old_scale == 0 || old_scale < rangeThresh)
00325 { for (env_size_t i = 0; i < sz; ++i) dst[i] = 0; return; }
00326 const intg32 new_scale = nmax - nmin;
00327
00328 if (new_scale == 0)
00329 { for (env_size_t i = 0; i < sz; ++i) dst[i] = nmin; return; }
00330
00331
00332 intg32 actualmin, actualmax;
00333
00334 if (old_scale == new_scale)
00335 {
00336 const intg32 add = nmin - mi;
00337 if (add != 0)
00338 for (env_size_t i = 0; i < sz; ++i)
00339 dst[i] += add;
00340
00341 actualmin = nmin;
00342 actualmax = nmax;
00343 }
00344 #if defined(ENV_INTG64_TYPE)
00345 else
00346 {
00347 for (env_size_t i = 0; i < sz; ++i)
00348 dst[i] = nmin + ((((intg64)(dst[i] - mi)) * new_scale)
00349 / old_scale);
00350
00351 actualmin = nmin;
00352 actualmax = nmin + ((((intg64)(old_scale)) * new_scale)
00353 / old_scale);
00354 }
00355 #else
00356 else if (old_scale > new_scale)
00357 {
00358
00359
00360
00361
00362
00363
00364 const intg32 nscale_max = INTG32_MAX / old_scale;
00365
00366 intg32 new_scale_reduced = new_scale;
00367 intg32 old_scale_reduced = old_scale;
00368
00369 while (new_scale_reduced > nscale_max)
00370 {
00371 new_scale_reduced /= 2;
00372 old_scale_reduced /= 2;
00373 }
00374
00375 ENV_ASSERT(new_scale_reduced >= 1);
00376 ENV_ASSERT(old_scale_reduced >= 1);
00377
00378 for (env_size_t i = 0; i < sz; ++i)
00379 dst[i] = nmin
00380 + (((dst[i] - mi) * new_scale_reduced)
00381 / (old_scale_reduced+1));
00382
00383 actualmin = nmin;
00384 actualmax = nmin + ((old_scale * new_scale_reduced)
00385 / (old_scale_reduced+1));
00386 }
00387 else
00388 {
00389 const intg32 mul = new_scale / old_scale;
00390 for (env_size_t i = 0; i < sz; ++i)
00391 dst[i] = nmin + ((dst[i] - mi) * mul);
00392
00393 actualmin = nmin;
00394 actualmax = nmin + (old_scale * mul);
00395 }
00396 #endif // !defined(ENV_INTG64_TYPE)
00397
00398
00399
00400
00401 if (actualmin_p)
00402 *actualmin_p = actualmin;
00403 if (actualmax_p)
00404 *actualmax_p = actualmax;
00405
00406 }
00407
00408
00409 void env_c_luminance_from_byte(const struct env_rgb_pixel* const src,
00410 const env_size_t sz,
00411 const env_size_t nbits,
00412 intg32* const dst)
00413 {
00414 if (nbits > 8)
00415 for (env_size_t i = 0; i < sz; ++i)
00416 dst[i] = ((src[i].p[0] + src[i].p[1] + src[i].p[2]) / 3) << (nbits - 8);
00417 else if (nbits < 8)
00418 for (env_size_t i = 0; i < sz; ++i)
00419 dst[i] = ((src[i].p[0] + src[i].p[1] + src[i].p[2]) / 3) >> (8 - nbits);
00420 else
00421 for (env_size_t i = 0; i < sz; ++i)
00422 dst[i] = (src[i].p[0] + src[i].p[1] + src[i].p[2]) / 3;
00423 }
00424
00425
00426 void env_c_image_div_scalar(const intg32* const a,
00427 const env_size_t sz,
00428 intg32 val,
00429 intg32* const dst)
00430 {
00431 for (env_size_t i = 0; i < sz; ++i)
00432 dst[i] = a[i] / val;
00433 }
00434
00435
00436 void env_c_image_div_scalar_accum(const intg32* const a,
00437 const env_size_t sz,
00438 intg32 val,
00439 intg32* const dst)
00440 {
00441 for (env_size_t i = 0; i < sz; ++i)
00442 dst[i] += a[i] / val;
00443 }
00444
00445
00446 void env_c_image_minus_image(const intg32* const a,
00447 const intg32* const b,
00448 const env_size_t sz,
00449 intg32* const dst)
00450 {
00451 for (env_size_t i = 0; i < sz; ++i)
00452 dst[i] = a[i] - b[i];
00453 }
00454
00455
00456
00457
00458
00459
00460
00461
00462 #endif // ENVISION_ENV_C_MATH_OPS_C_DEFINED