JWS C Library
C language utility library
|
00001 /* 00002 * This work is licensed under a Creative Commons 00003 * Attribution-Noncommercial-Share Alike 3.0 United States License. 00004 * 00005 * http://creativecommons.org/licenses/by-nc-sa/3.0/us/ 00006 * 00007 * You are free: 00008 * 00009 * to Share - to copy, distribute, display, and perform the work 00010 * to Remix - to make derivative works 00011 * 00012 * Under the following conditions: 00013 * 00014 * Attribution. You must attribute the work in the manner specified by the 00015 * author or licensor (but not in any way that suggests that they endorse you 00016 * or your use of the work). 00017 * 00018 * Noncommercial. You may not use this work for commercial purposes. 00019 * 00020 * Share Alike. If you alter, transform, or build upon this work, you may 00021 * distribute the resulting work only under the same or similar license to 00022 * this one. 00023 * 00024 * For any reuse or distribution, you must make clear to others the license 00025 * terms of this work. The best way to do this is by including this header. 00026 * 00027 * Any of the above conditions can be waived if you get permission from the 00028 * copyright holder. 00029 * 00030 * Apart from the remix rights granted under this license, nothing in this 00031 * license impairs or restricts the author's moral rights. 00032 */ 00033 00034 00046 #include <jwsc/config.h> 00047 00048 #include <stdlib.h> 00049 #include <inttypes.h> 00050 #include <math.h> 00051 #include <assert.h> 00052 00053 #include "jwsc/base/error.h" 00054 #include "jwsc/matblock/matblock.h" 00055 #include "jwsc/filter/3d.h" 00056 #include "jwsc/imgblock/imgblock.h" 00057 00058 00088 Error* down_sample_imgblock_f 00089 ( 00090 Imgblock_f** img_out, 00091 const Imgblock_f* img_in, 00092 float img_factor, 00093 float row_factor, 00094 float col_factor 00095 ) 00096 { 00097 int64_t num_in_imgs, num_in_rows, num_in_cols; 00098 int64_t num_out_imgs, num_out_rows, num_out_cols; 00099 int64_t num_h_imgs, num_h_rows, num_h_cols; 00100 int64_t in_img, in_row, in_col; 00101 int64_t out_img, out_row, out_col; 00102 int64_t h_img, h_row, h_col; 00103 int64_t h_img_center; 00104 int64_t h_row_center; 00105 int64_t h_col_center; 00106 int64_t i, j, k; 00107 00108 float img_delta_sum, col_delta_sum, row_delta_sum; 00109 float r_sum, g_sum, b_sum; 00110 float img_delta; 00111 float row_delta; 00112 float col_delta; 00113 float img_sigma; 00114 float row_sigma; 00115 float col_sigma; 00116 float weight; 00117 float weight_sum; 00118 00119 Imgblock_f* img = NULL; 00120 Matblock_f* h = NULL; 00121 00122 /* Test if the factors are in (0, 1]. */ 00123 if (0 >= img_factor || img_factor > 1.0 || 00124 0 >= row_factor || row_factor > 1.0 || 00125 0 >= col_factor || col_factor > 1.0) 00126 { 00127 if (*img_out != img_in) 00128 { 00129 free_imgblock_f(*img_out); 00130 *img_out = NULL; 00131 } 00132 return JWSC_EARG("Down sampling factors must be in (0, 1]"); 00133 } 00134 00135 num_in_imgs = img_in->num_imgs; 00136 num_in_rows = img_in->num_rows; 00137 num_in_cols = img_in->num_cols; 00138 00139 num_out_imgs = ceil(img_factor*num_in_imgs); 00140 num_out_rows = ceil(row_factor*num_in_rows); 00141 num_out_cols = ceil(col_factor*num_in_cols); 00142 00143 if (num_in_imgs == num_out_imgs && 00144 num_in_rows == num_out_rows && 00145 num_in_cols == num_out_cols) 00146 return NULL; 00147 00148 img_delta = 1.0 / img_factor; 00149 row_delta = 1.0 / row_factor; 00150 col_delta = 1.0 / col_factor; 00151 00152 img_sigma = 0.35 * img_delta; 00153 row_sigma = 0.35 * row_delta; 00154 col_sigma = 0.35 * col_delta; 00155 00156 assert(create_auto_3d_gaussian_filter_f(&h, img_sigma, row_sigma, 00157 col_sigma) == NULL); 00158 num_h_imgs = h->num_mats; 00159 num_h_rows = h->num_rows; 00160 num_h_cols = h->num_cols; 00161 00162 img = (*img_out == img_in) ? NULL : *img_out; 00163 create_imgblock_f(&img, num_out_imgs, num_out_rows, num_out_cols); 00164 00165 h_img_center = num_h_imgs / 2; 00166 h_row_center = num_h_rows / 2; 00167 h_col_center = num_h_cols / 2; 00168 00169 img_delta_sum = 0.5*img_delta; 00170 in_img = ceil(img_delta_sum) - 1; 00171 for (out_img = 0; out_img < num_out_imgs; out_img++) 00172 { 00173 row_delta_sum = 0.5*row_delta; 00174 in_row = ceil(row_delta_sum) - 1; 00175 for (out_row = 0; out_row < num_out_rows; out_row++) 00176 { 00177 col_delta_sum = 0.5*col_delta; 00178 in_col = ceil(col_delta_sum) - 1; 00179 for (out_col = 0; out_col < num_out_cols; out_col++) 00180 { 00181 r_sum = 0; 00182 g_sum = 0; 00183 b_sum = 0; 00184 weight_sum = 0; 00185 00186 i = -1; 00187 j = -1; 00188 k = -1; 00189 00190 for (h_img = 0; h_img < num_h_imgs; h_img++) 00191 { 00192 for (h_row = 0; h_row < num_h_rows; h_row++) 00193 { 00194 for (h_col = 0; h_col < num_h_cols; h_col++) 00195 { 00196 i = in_img + (h_img - h_img_center); 00197 if (i < 0) 00198 { 00199 i = 0; 00200 } 00201 else if (i >= num_in_imgs) 00202 { 00203 i = num_in_imgs - 1; 00204 } 00205 00206 j = in_row + (h_row - h_row_center); 00207 if (j < 0) 00208 { 00209 j = 0; 00210 } 00211 else if (j >= num_in_rows) 00212 { 00213 j = num_in_rows - 1; 00214 } 00215 00216 k = in_col + (h_col - h_col_center); 00217 if (k < 0) 00218 { 00219 k = 0; 00220 } 00221 else if (k >= num_in_cols) 00222 { 00223 k = num_in_cols - 1; 00224 } 00225 00226 weight = h->elts[ h_img ][ h_row ][ h_col ]; 00227 00228 r_sum += img_in->pxls[ i ][ j ][ k ].r * weight; 00229 g_sum += img_in->pxls[ i ][ j ][ k ].g * weight; 00230 b_sum += img_in->pxls[ i ][ j ][ k ].b * weight; 00231 00232 weight_sum += weight; 00233 } 00234 } 00235 } 00236 00237 if (weight_sum > 0) 00238 { 00239 r_sum /= weight_sum; 00240 g_sum /= weight_sum; 00241 b_sum /= weight_sum; 00242 00243 img->pxls[ out_img ][ out_row ][ out_col ].r = r_sum; 00244 img->pxls[ out_img ][ out_row ][ out_col ].g = g_sum; 00245 img->pxls[ out_img ][ out_row ][ out_col ].b = b_sum; 00246 } 00247 else 00248 { 00249 img->pxls[ out_img ][ out_row ][ out_col ].r = 00250 img_in->pxls[ i ][ j ][ k ].r; 00251 img->pxls[ out_img ][ out_row ][ out_col ].g = 00252 img_in->pxls[ i ][ j ][ k ].g; 00253 img->pxls[ out_img ][ out_row ][ out_col ].b = 00254 img_in->pxls[ i ][ j ][ k ].b; 00255 } 00256 00257 col_delta_sum += col_delta; 00258 in_col = floor(col_delta_sum); 00259 if (in_col >= num_in_cols) 00260 in_col = num_in_cols - 1; 00261 } 00262 00263 row_delta_sum += row_delta; 00264 in_row = floor(row_delta_sum); 00265 if (in_row >= num_in_rows) 00266 in_row = num_in_rows - 1; 00267 } 00268 00269 img_delta_sum += img_delta; 00270 in_img = floor(img_delta_sum); 00271 if (in_img >= num_in_imgs) 00272 in_img = num_in_imgs - 1; 00273 } 00274 00275 if (*img_out == img_in) 00276 { 00277 copy_imgblock_f(img_out, img); 00278 free_imgblock_f(img); 00279 } 00280 else 00281 { 00282 *img_out = img; 00283 } 00284 00285 free_matblock_f(h); 00286 00287 return NULL; 00288 } 00289