JWS C Library
C language utility library
imgblock_util.c
Go to the documentation of this file.
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