Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

ImageUtil.c

Go to the documentation of this file.
00001 /* ---------------------------------------------------------------------------
00002     Phission : 
00003         Realtime Vision Processing System
00004     
00005     Copyright (C) 2003-2006 Philip D.S. Thoren (pthoren@cs.uml.edu)
00006     University of Massachusetts at Lowell,
00007     Laboratory for Artificial Intelligence and Robotics
00008     
00009     This file is part of Phission.
00010 
00011     Phission is free software; you can redistribute it and/or modify
00012     it under the terms of the GNU Lesser General Public License as published by
00013     the Free Software Foundation; either version 2 of the License, or
00014     (at your option) any later version.
00015 
00016     Phission is distributed in the hope that it will be useful,
00017     but WITHOUT ANY WARRANTY; without even the implied warranty of
00018     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019     GNU Lesser General Public License for more details.
00020 
00021     You should have received a copy of the GNU Lesser General Public License
00022     along with Phission; if not, write to the Free Software
00023     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00024 
00025  ---------------------------------------------------------------------------*/
00026 #ifdef HAVE_CONFIG_H
00027     #include <phissionconfig.h>
00028 #endif
00029 
00030 #include <phStandard.h>
00031 
00032 #include <string.h> /* memcpy */
00033 #include <math.h> /* round, floor */
00034 #include <phMath.h>
00035 
00036 #include <ImageDefinitions.h>
00037 #include <ImageUtil.h>
00038 
00039 #include <phError.h>
00040 #include <phMemory.h>
00041 #include <phPrint.h>
00042 
00043 #ifdef __cplusplus
00044 extern "C" 
00045 {
00046 #endif /* __cplusplus */
00047 
00048 #define NO_ALLOC 1
00049 #define BI_FIXED_POINT() 1
00050 #define BI_USE_INDEX_TABLE() 1
00051    
00052 /* ---------------------------------------------------------------------- */
00053 /* Formula from : 
00054  *  http://www.engineering.uiowa.edu/~gec/248_s00_students/blake_carlson/hw2/adiphw2.html
00055  * Original Source @ (new code way different from sourced code):
00056  *  http://www.engineering.uiowa.edu/~gec/248_s00_students/blake_carlson/hw2/src/prob1/imscale.cc
00057  *
00058  *   F(p',q') = ( F(p,q)     * R(-a)     * R(b)          ) +
00059  *              ( F(p,q+1)   * R(-a)     * R(-(1-b))    ) +
00060  *              ( F(p+1,q)   * R(1-a)    * R(b)          ) +
00061  *              ( F(p+1,q+1) * R(1-a)    * R(-(1-b))     )
00062  *
00063  *          ( x + 1   -1 <= x <  0
00064  *   R(x) = <
00065  *          ( 1 - x    0 <= x <= 1
00066  */
00067 /* ---------------------------------------------------------------------- */
00068     
00069 /* ---------------------------------------------------------------------- */
00070 /* From: 
00071  *  http://www.engineering.uiowa.edu/~gec/248_s00_students/li_zhang/hw2/bilinearInterp.m
00072  *
00073  * function valuef = bilinearInterp(a,b,p,q,F)
00074  *   [M,N]=size(F);
00075  *
00076  *   if q+1 <= N & p+1<=M 
00077  *      valuef = (1-a)*((1-b)*double(F(p,q)) + b*double(F(p,q+1)))...
00078  *                  + a*((1-b)*double(F(p+1,q)) + b*double(F(p+1,q+1)));
00079  *   elseif p+1<=M %only interp along p direction
00080  *      valuef = (1-a) * double(F(p,q)) + a * double(F(p+1,q));
00081  *   elseif q+1 <= N %only interp along q direction
00082  *      valuef = (1-b) * double(F(p,q)) + b * double(F(p,q+1));
00083  *   else
00084  *      valuef = double(F(p,q));
00085  *   end
00086  *   %value = round(valuef);
00087  */
00088 /* ---------------------------------------------------------------------- */
00089     
00090 /* ---------------------------------------------------------------------- */
00091 /* From "Practical Algorithms for Image Analysis; Description, 
00092  * Examples, and Code" by Micheal Seul, Lawrence O'Gorman and 
00093  * Michael J. Sammon.
00094  *
00095  * The following found on page 45.
00096  * ----------------------------------------------------------------------
00097  * Nearest Neighbor Interpolation:
00098  *
00099  * O strategy: assign gray value of closest pixel
00100  * O expression: 
00101  *      Output[x',y'] = Input( (int)(y + 0.5), (int)(x + 0.5) 
00102  * 
00103  * ----------------------------------------------------------------------
00104  * Bilinear Interpolation:
00105  * 
00106  * o strategy: select weighted sumn of 4 nearest pixels in Input
00107  *  (a) weights proportional to distance
00108  * ...
00109  * o expression: 
00110  *  (a) : Output(x',y') = a       * b      * Input(   y,   x ) +
00111  *                        (1 - a) * b      * Input(   y, x+1 ) +
00112  *                        a       * (1 - b)* Input( y+1, x   ) +
00113  *                        (1 - a) * (1 - b)* Input( y+1, x+1 )
00114  * ----------------------------------------------------------------------
00115  */
00116 /* ---------------------------------------------------------------------- */
00117 /* round off the width to 4 decimal places */
00118 /*    const float w_scale = (floor(100 * ((float)nw / (float)w)) / 100);*/
00119 /*    const float h_scale = (floor(100 * ((float)nh / (float)h)) / 100);*/
00120 /* ---------------------------------------------------------------------- */
00121 /* ---------------------------------------------------------------------- */
00122 /* Bilinear Types: */
00123 /* ---------------------------------------------------------------------- */
00124 typedef struct ph_x_table_t 
00125 {
00126     float       b1;
00127     float       b2;
00128 
00129     float       f_x;
00130     uint32_t    i_x;
00131     
00132     uint32_t elements;
00133     uint32_t size;
00134 
00135 } ph_bilinear_ph_x_table_type;
00136 
00137 /* ---------------------------------------------------------------------- */
00138 typedef struct ph_y_table_t 
00139 {
00140     float      a1;
00141     float      a2;
00142 
00143     float      f_y;
00144     uint32_t   i_y;
00145 
00146     uint32_t   pixel_offset_y;
00147     uint32_t   scale_offset_y;
00148 
00149     uint32_t elements;
00150     uint32_t size;
00151 
00152 } ph_bilinear_ph_y_table_type;
00153 
00154 /* ---------------------------------------------------------------------- */
00155 typedef struct ph_bilinear_pix_array_t
00156 {
00157     uint32_t v[4];
00158     
00159 } ph_bilinear_pix_array_type;
00160 
00161 /* ---------------------------------------------------------------------- */
00162 typedef struct ph_bilinear_pixel_t
00163 {
00164     uint32_t one;
00165     uint32_t two;
00166     uint32_t three;
00167     uint32_t four;
00168     
00169 } ph_bilinear_pixel_type;
00170 /* ---------------------------------------------------------------------- */
00171 typedef union bilinear_pixel_u 
00172 {
00173     ph_bilinear_pix_array_type array;
00174     ph_bilinear_pixel_type       pix;
00175 
00176 } bilinear_pixel_union;
00177 
00178 /* ---------------------------------------------------------------------- */
00179 struct ph_bilinear_table_t
00180 {
00181     uint32_t in_w;
00182     uint32_t in_h;
00183     uint32_t in_d;
00184     uint32_t out_w;
00185     uint32_t out_h;
00186 
00187     uint32_t max_nw;
00188     uint32_t max_nh;
00189 
00190     float w_scale;
00191     float h_scale;
00192     
00193     float wK;
00194     float hK;
00195     float K;
00196 
00197     ph_bilinear_ph_x_table_type *x_table;
00198     ph_bilinear_ph_y_table_type *y_table;    
00199 
00200     bilinear_pixel_union *in_pixels;
00201 };
00202 
00203 /* ---------------------------------------------------------------------- */
00204 void ph_bilinear_table_free(struct ph_bilinear_table_t **table)
00205 {
00206     phFUNCTION("ph_bilinear_table_free")
00207 
00208     if (table == NULL) return;
00209 
00210     if (*table == NULL) return;
00211     
00212     phFree((*table)->x_table);
00213     phFree((*table)->y_table);
00214     phFree((*table)->in_pixels);
00215     phFree(*table);
00216 
00217     return;
00218 }
00219 
00220 /* ---------------------------------------------------------------------- */
00221 static int ph_calculate_bilinear_table( const uint32_t w,
00222                                         const uint32_t h,
00223                                         const uint32_t d,
00224                                         const uint32_t nw,
00225                                         const uint32_t nh,
00226                                         struct ph_bilinear_table_t **table)
00227 {
00228     phFUNCTION("ph_calculate_bilinear_table")
00229 
00230     uint32_t i = 0;
00231     uint32_t j = 0;
00232     uint32_t index = 0;
00233     
00234     int32_t calc_table = 0;
00235     
00236     if (table == NULL) goto error;
00237     
00238     if (*table == NULL)
00239     {
00240         (*table) = (struct ph_bilinear_table_t *)
00241                      phCalloc(1,sizeof(struct ph_bilinear_table_t));
00242         phCHECK_NULLPTR(*table,"calloc","*table alloc failed");
00243         
00244         calc_table = 1;
00245     }
00246   
00247     /* Allocate the table mapping */
00248     if ((*table)->in_pixels == NULL)
00249     {
00250         (*table)->in_pixels = (bilinear_pixel_union *)
00251                          phCalloc(nw*nh,sizeof(bilinear_pixel_union));
00252         phCHECK_NULLPTR((*table)->in_pixels,"phCalloc",
00253                       "(*table)->in_pixels alloc failed");
00254         
00255         calc_table = 1;
00256     }
00257     /* Reallocate the memory if the target/out dimensions have 
00258      * changed in size */
00259     else if (((*table)->out_w != nw) ||
00260              ((*table)->out_h != nh))
00261     {
00262         (*table)->in_pixels = (bilinear_pixel_union *)
00263                          phRealloc((*table)->in_pixels,
00264                                  nw*nh*sizeof(bilinear_pixel_union));
00265         phCHECK_NULLPTR((*table)->in_pixels,"phRealloc",
00266                       "(*table)->in_pixels alloc failed");
00267         
00268         calc_table = 1;
00269     }
00270     
00271     /* Allocate the ... */
00272     /* X TABLE */
00273     if ((*table)->x_table == NULL)
00274     {
00275         (*table)->x_table = (ph_bilinear_ph_x_table_type *)
00276                                 phCalloc(nw,sizeof(ph_bilinear_ph_x_table_type));
00277         phCHECK_NULLPTR((*table)->x_table,"calloc",
00278                       "*table->x_table alloc failed");
00279     
00280         calc_table = 1;
00281     }
00282     /* Reallocate memory if it's required */
00283     else if (nw > (*table)->max_nw)
00284     {
00285         (*table)->x_table = (ph_bilinear_ph_x_table_type *)
00286                                 phRealloc((*table)->x_table,
00287                                         nw * sizeof(ph_bilinear_ph_x_table_type));
00288         phCHECK_NULLPTR((*table)->x_table,"phRealloc",
00289                       "*table->x_table phRealloc failed");
00290 
00291         (*table)->max_nw = nw;
00292         
00293         calc_table = 1;
00294     }
00295              /* Check out width */
00296     else if ((nw != (*table)->out_w) || 
00297              /* Check in width */
00298              (w != (*table)->in_w))
00299     {
00300         calc_table = 1;
00301     }
00302     
00303     /* Allocate the ... */
00304     /* Y TABLE */
00305     if ((*table)->y_table == NULL)
00306     {
00307         (*table)->y_table = (ph_bilinear_ph_y_table_type *)phCalloc(nh,sizeof(ph_bilinear_ph_y_table_type));
00308         phCHECK_NULLPTR((*table)->y_table,"calloc","*table->y_table alloc failed");
00309     
00310         calc_table = 1;
00311     }
00312     /* allocate more memory if it's required */
00313     else if (nh > (*table)->max_nh)
00314     {
00315         (*table)->y_table = (ph_bilinear_ph_y_table_type *)
00316                                 phRealloc((*table)->y_table,
00317                                         nh * sizeof(ph_bilinear_ph_y_table_type));
00318         phCHECK_NULLPTR((*table)->y_table,"phRealloc","*table->y_table phRealloc failed");
00319 
00320         (*table)->max_nh = nh;
00321         
00322         calc_table = 1;
00323     }
00324              /* Check out height */
00325     else if ((nh != (*table)->out_h) || 
00326              /* Check in height */
00327              (h != (*table)->in_h))
00328     {
00329         calc_table = 1;
00330     }    
00331 
00332     /* Check in depth */
00333     /* if the depth has been changed, the in->out table needs to
00334      * be recalculated */
00335     if ((*table)->in_d != d) calc_table = 1;
00336    
00337     /* Recalculate the table if any of the parameters have
00338      * changed in any way */
00339     if (calc_table)
00340     {
00341         const uint32_t ZERO = (0);
00342         const uint32_t ONE  = (1*d);    
00343         const uint32_t ZEROY = 0;
00344         const uint32_t ONEY  = w*d;
00345     
00346         const uint32_t bound_x = w - 1;
00347         const uint32_t bound_y = h - 1;
00348         
00349         uint32_t pixel_offset = 0;
00350         ph_bilinear_ph_x_table_type *x_table = (*table)->x_table;
00351         ph_bilinear_ph_y_table_type *y_table = (*table)->y_table;
00352         
00353         (*table)->in_d = d;
00354         
00355         /* Recalc the X table */
00356         (*table)->in_w = w;
00357         (*table)->out_w = nw;
00358         
00359         (*table)->h_scale = (float)((float)nh / (float)h);
00360         (*table)->hK      = (float)(1.0 / (*table)->h_scale);
00361         (*table)->w_scale = (float)((float)nw / (float)(*table)->in_w);
00362         (*table)->wK      = (float)(1.0 / (*table)->w_scale);
00363         (*table)->K = ((*table)->wK < (*table)->hK) ? (*table)->wK : (*table)->hK;
00364         
00365         /* Calculate the x variables and store them in the table */
00366         for(i=0; i < nw; i++) {
00367             x_table[i].f_x = ((float)i * (*table)->wK);
00368             x_table[i].i_x = (uint32_t)round(x_table[i].f_x);
00369             x_table[i].b1 = (float)(x_table[i].f_x - floor(x_table[i].f_x));
00370             x_table[i].b2 = (float)(1.0 - x_table[i].b1);
00371         }
00372 
00373         /* Recalc the Y table */
00374         (*table)->in_h = h;
00375         (*table)->out_h = nh;
00376         (*table)->h_scale = (float)((float)nh / (float)h);
00377         (*table)->hK      = (float)(1.0 / (*table)->h_scale);
00378         
00379         /* Calculate the y variables and store them in the table */
00380         for( j=0; j < nh; j++) {
00381             y_table[j].f_y = (float)j * (*table)->hK;
00382             y_table[j].i_y = (uint32_t)round(y_table[j].f_y);
00383             y_table[j].a1  = (float)(y_table[j].f_y - floor(y_table[j].f_y));
00384             y_table[j].a2  = (float)(1.0 - y_table[j].a1);
00385             
00386             y_table[j].scale_offset_y = (j*nw*d);
00387             y_table[j].pixel_offset_y = w * y_table[j].i_y * d;
00388         }
00389 
00390         /* Calculate the mapping of the indecies from input -> output */
00391         for( j=0; j < nh; j++) {
00392             for(i=0; i < nw; i++) {
00393                 pixel_offset = x_table[i].i_x * d /* pixel offset x */+ y_table[j].pixel_offset_y;
00394             
00395                 /* This index doesn't require depth multiplication */
00396                 index = (j * nw) + i;
00397                 
00398                 /* Get the pixel intensities here and avoid bounds problems
00399                  * near the borders of the image */
00400                 (*table)->in_pixels[index].pix.one = 
00401                                 pixel_offset + ZERO + ZEROY;
00402                 
00403                 (*table)->in_pixels[index].pix.two = 
00404                                 ((x_table[i].i_x < bound_x) ? 
00405                                     pixel_offset + ONE  + ZEROY : 
00406                                     pixel_offset);
00407                 
00408                 (*table)->in_pixels[index].pix.three = 
00409                                 ((y_table[j].i_y < bound_y) ? 
00410                                     pixel_offset + ZERO + ONEY : 
00411                                     pixel_offset);
00412 
00413                 (*table)->in_pixels[index].pix.four = 
00414                                 (((x_table[i].i_x < bound_x) && 
00415                                   (y_table[j].i_y < bound_y)) ? 
00416                                     pixel_offset + ONE  + ONEY : 
00417                                     pixel_offset );
00418             }
00419         }
00420     }
00421     
00422     return phSUCCESS;
00423 error:
00424     return phFAIL;
00425 }
00426 
00427 /* ---------------------------------------------------------------------- */
00428 /* Use bilinear interpolation to resample the image */
00429 /* ph_bilinear_scale : this scales an image using bilinear scaling.
00430  *
00431  * image - the input image
00432  * w,h,d - input image width x height x depth
00433  * nw,nh - new width x new height of the output image
00434  * scaled_image - new scaled version of input image, 
00435  *                has same depth as input image
00436  *                                                                        */
00437 /* ---------------------------------------------------------------------- */
00438 /* If *pscaled_image is NULL, memory is allocated.
00439  * Else *pscaled_image must be allocated already */
00440 /* ---------------------------------------------------------------------- */
00441 int ph_bilinear_scale( const uint8_t *image,
00442                        const uint32_t w,  /* input width */
00443                        const uint32_t h,  /* input height */
00444                        const uint32_t f,  /* input format */
00445                        const uint32_t nw, /* new width */
00446                        const uint32_t nh, /* new height */
00447                        struct ph_bilinear_table_t **table,
00448                        uint8_t **pscaled_image )
00449 {
00450     phFUNCTION("ph_bilinear_scale")
00451     
00452     const uint32_t fi = phImageFormatToIndex(f);
00453     const uint32_t d  = phImageDepth[fi];
00454 
00455     /* used to generate the table locally is the user passed NULL */
00456     uint32_t                    free_table  = 0;
00457     struct ph_bilinear_table_t  *local_table= NULL;
00458 
00459     /* Declare a few variable that will be used in both
00460      * resampling routines. */
00461     uint32_t                    out_row     = 0;
00462     uint32_t                    out_pixel   = 0;
00463     ph_bilinear_ph_x_table_type *x_table    = NULL;
00464     ph_bilinear_ph_y_table_type *y_table    = NULL;
00465     bilinear_pixel_union        *in_pixels  = NULL;
00466     ph_bilinear_pixel_type      pi;
00467     uint32_t                    pixel_val   = 0;
00468     float                       a1, a2, b1, b2;
00469     
00470 #if BI_FIXED_POINT()
00471     int32_t pix1, pix2, pix3, pix4;
00472 #else
00473     float pix1, pix2, pix3, pix4;
00474 #endif
00475 
00476     uint32_t i = 0;
00477     uint32_t j = 0;
00478     uint32_t k = 0;
00479     
00480     int return_val = 0;
00481 
00482     uint8_t *scaled_image = NULL;
00483     
00484     if (pscaled_image == NULL)
00485     {
00486         goto error;
00487     }
00488     if (image == NULL)
00489     {
00490         goto error;
00491     }
00492 
00493     scaled_image = *pscaled_image;
00494     
00495     /* allocate the scaled image data */
00496     if (scaled_image == NULL) {
00497         *pscaled_image = scaled_image = phCalloc(w*h*d,sizeof(uint8_t));
00498         phCHECK_NULLPTR(scaled_image,"calloc","calloc failed.");
00499     }
00500     
00501     if (((w == nw) && (h == nh)) || ((nh <= 0) || (nw <= 0))) {
00502         DEBUG_PRINT("Returning");
00503         phMemcpy(scaled_image,image,w*h*d*sizeof(uint8_t));
00504         return NO_ALLOC;
00505     }
00506 
00507     if (table == NULL)
00508     {
00509         free_table = 1;
00510         table = &local_table;
00511     }
00512    
00513     /* Create the data index mapping from input indecies->>output  */
00514     rc = ph_calculate_bilinear_table(w,h,d,nw,nh,table);
00515     phCHECK_RC(rc,NULL,"ph_calculate_bilinear_table");
00516     
00517     x_table = (*table)->x_table;
00518     y_table = (*table)->y_table;
00519     in_pixels = (*table)->in_pixels;
00520 
00521     for( j=0; j < nh; j++) {
00522         out_row = (j * nw);
00523             
00524         a2 = y_table[j].a2;
00525         a1 = y_table[j].a1;
00526         
00527         for(i=0; i < nw; i++) {
00528             out_pixel = (out_row + i) * d;
00529 
00530             b2 = x_table[i].b2;
00531             b1 = x_table[i].b1;
00532             
00533             pi = in_pixels[(j * nw) + i].pix;
00534  
00535             /* Get the pixel intensities here and avoid bounds problems
00536              * near the borders of the image */
00537             for (k = 0; k < d; k++ )
00538             {
00539 #if BI_FIXED_POINT()
00540                 pix1 = (uint32_t) image[pi.one + k];
00541                 pix2 = (uint32_t) image[pi.two + k];
00542                 pix3 = (uint32_t) image[pi.three + k];
00543                 pix4 = (uint32_t) image[pi.four + k];
00544 #else /* BI_FIXED_POINT() */
00545                 pix1 = (float) image[pi.one + k];
00546                 pix2 = (float) image[pi.two + k];
00547                 pix3 = (float) image[pi.three + k];
00548                 pix4 = (float) image[pi.four + k];
00549 #endif
00550                 /* Round by casting, "round" is too slow */
00551                 pixel_val = (uint32_t)(
00552                        a2 * ((b2 * pix1/*pixel1*/) + 
00553                              (b1 * pix2/*pixel2*/) ) +  
00554                        a1 * ((b2 * pix3/*pixel3*/) + 
00555                              (b1 * pix4/*pixel4*/) ));
00556                        
00557                 scaled_image[out_pixel + k] = (uint8_t) phMIN(pixel_val,255);
00558             }
00559         }
00560     }
00561 
00562     DEBUG_PRINT("Returning\n");
00563     
00564     if (free_table) {
00565         ph_bilinear_table_free(table);
00566         table = NULL;
00567     }
00568     
00569     return return_val;
00570 error:
00571     if (free_table) {
00572         ph_bilinear_table_free(table);
00573         table = NULL;
00574     }
00575     
00576     return phFAIL;
00577 }
00578     
00579 /* ---------------------------------------------------------------------- */
00580 /* Nearest Neighbor */
00581 /* ---------------------------------------------------------------------- */
00582 struct ph_nearest_neighbor_table_t
00583 {
00584     uint32_t total_pixels;
00585     
00586     uint32_t in_h;
00587     uint32_t in_w;
00588     uint32_t in_d;
00589     uint32_t out_h;
00590     uint32_t out_w;
00591     
00592     uint32_t *in_pixels;
00593 };
00594 
00595 /* ---------------------------------------------------------------------- */
00596 void ph_nearest_neighbor_table_free(struct ph_nearest_neighbor_table_t **table)
00597 {
00598     phFUNCTION("ph_nearest_neighbor_table_free")
00599     
00600     if (table == NULL) return;
00601 
00602     if (*table == NULL) return;
00603 
00604     phFree((*table)->in_pixels);
00605     phFree(*table);
00606 
00607     return;
00608 }
00609 
00610 /* ---------------------------------------------------------------------- */
00611 static int ph_calculate_nn_table( const uint32_t w,  /* input width */
00612                                   const uint32_t h,  /* input height */
00613                                   const uint32_t d,  /* input depth */
00614                                   const uint32_t nw, /* new width */
00615                                   const uint32_t nh, /* new height */
00616                                   struct ph_nearest_neighbor_table_t **table )
00617 {
00618     phFUNCTION("ph_calculate_nn_table")
00619 
00620     uint32_t calc_table = 0;
00621 
00622     if (table == NULL) goto error;
00623 
00624     /* allocate a new table if this one hasn't been allocated */
00625     if (*table == NULL)
00626     {
00627         (*table) = (struct ph_nearest_neighbor_table_t *)
00628                         phCalloc(1,sizeof(struct ph_nearest_neighbor_table_t));
00629         phCHECK_NULLPTR(*table,"calloc","*table alloc failed");
00630     }
00631 
00632     if ((*table)->in_pixels == NULL)
00633     {
00634         (*table)->in_pixels = (uint32_t *)phCalloc(nw*nh,sizeof(uint32_t));
00635         phCHECK_NULLPTR((*table)->in_pixels, "calloc","in_pixels alloc failed");
00636         calc_table = 1;
00637     }
00638     else if (((*table)->out_w != nw) || 
00639              ((*table)->out_h != nh))
00640     {
00641         (*table)->in_pixels = (uint32_t *)phRealloc((*table)->in_pixels,
00642                                                   nw*nh*sizeof(uint32_t));
00643         phCHECK_NULLPTR((*table)->in_pixels, "phRealloc","pixel phRealloc failed");
00644         calc_table = 1;
00645     }
00646     
00647     if (((*table)->in_w != w) ||
00648         ((*table)->in_h != h) ||
00649         ((*table)->in_d != d))
00650     {
00651         calc_table = 1;
00652     }
00653 
00654     if (calc_table)
00655     {
00656         const uint32_t w_minus_one = w - 1;
00657         const uint32_t h_minus_one = h - 1;
00658         
00659         const float xscale_down = (float)w / (float)((nw == 0) ? 1 : nw);
00660         const float yscale_down = (float)h / (float)((nh == 0) ? 1 : nh);
00661         
00662         uint32_t i = 0;
00663         uint32_t j = 0;
00664         
00665         uint32_t x = 0;
00666         uint32_t y = 0;
00667         uint32_t i_row = 0;
00668         
00669         uint32_t *in_pixels_ptr = (*table)->in_pixels;
00670        
00671         for (i = 0; i < nh; i++)
00672         {
00673             y = (uint32_t)(((float)(i) * yscale_down));
00674             if (y >= h) y = h_minus_one;
00675             
00676             i_row = y * w;
00677         
00678             for (j = 0; j < nw; j++)
00679             {
00680                 x = (uint32_t)(((float)(j) * xscale_down));
00681                 if (x >= w) x = w_minus_one;
00682                 
00683                 *in_pixels_ptr = ((i_row + x) * d);
00684                 in_pixels_ptr++;
00685             }
00686         }
00687     }
00688     else
00689     {
00690         return phSUCCESS;
00691     }
00692 
00693     (*table)->in_w = w;
00694     (*table)->in_h = h;
00695     (*table)->in_d = d;
00696     (*table)->out_w = nw;
00697     (*table)->out_h = nh;
00698     
00699     return phSUCCESS;
00700 error:
00701     return phFAIL;
00702 
00703 }
00704 
00705 /* ---------------------------------------------------------------------- */
00706 int ph_nearest_neighbor_scale( const uint8_t *image,
00707                                const uint32_t w,  /* input width */
00708                                const uint32_t h,  /* input height */
00709                                const uint32_t f,  /* input format */
00710                                const uint32_t nw, /* new width */
00711                                const uint32_t nh, /* new height */
00712                                struct ph_nearest_neighbor_table_t **table,
00713                                uint8_t **pscaled_image )
00714 {
00715     phFUNCTION("ph_nearest_neighbor_scale")
00716     
00717     const uint32_t fi = phImageFormatToIndex(f);
00718     const uint32_t d = phImageDepth[fi];
00719 
00720     uint32_t id = 0;
00721     uint32_t i = 0;
00722     uint32_t j = 0;
00723     
00724     uint32_t *pixel_index_ptr = NULL;
00725     const uint8_t *imgptr = NULL;
00726     uint8_t *scaled_image = NULL;
00727    
00728     uint32_t free_table = 0;
00729     struct ph_nearest_neighbor_table_t *local_table = NULL;
00730    
00731     if (pscaled_image == NULL)
00732     {
00733         goto error;
00734     }
00735     if (image == NULL)
00736     {
00737         goto error;
00738     }
00739     
00740     scaled_image = *pscaled_image;
00741     
00742     /* allocate the scaled image data */
00743     if (scaled_image == NULL) {
00744         *pscaled_image = scaled_image = phCalloc(w*h*d,sizeof(uint8_t));
00745         phCHECK_NULLPTR(scaled_image,"calloc","calloc failed.");
00746     }
00747     
00748     if (((w == nw) && (h == nh)) || ((nh <= 0) || (nw <= 0))) {
00749         DEBUG_PRINT("Returning");
00750         phMemcpy(scaled_image,image,w*h*d*sizeof(uint8_t));
00751         return NO_ALLOC;
00752     }
00753 
00754     if (table == NULL)
00755     {
00756         free_table = 1;
00757         table = &local_table;
00758     }
00759 
00760     /* Save all the pixel mappings to a table */
00761     rc = ph_calculate_nn_table(w,h,d,nw,nh,table);
00762     phCHECK_RC(rc,NULL,"ph_calculate_nn_table");
00763 
00764     pixel_index_ptr = (*table)->in_pixels;
00765     
00766     for (i = 0; i < nh; i++) {
00767         for (j = 0; j < nw; j++) {
00768             imgptr = &(image[*pixel_index_ptr]);
00769 
00770             for (id = 0; id < d; id++) {
00771                 *scaled_image = *imgptr;
00772                 
00773                 scaled_image++;
00774                 imgptr++;
00775             }
00776                
00777             pixel_index_ptr++;
00778         }
00779     }
00780 
00781     if (free_table)
00782     {
00783         ph_nearest_neighbor_table_free(table);
00784         table = NULL;
00785     }
00786      
00787     return phSUCCESS;
00788 error:
00789     
00790     if (free_table)
00791     {
00792         ph_nearest_neighbor_table_free(table);
00793         table = NULL;
00794     }
00795 
00796     return phFAIL;
00797 }
00798 
00799 /* ------------------------------------------------------------------------ */
00800 int ph_image_crop(const uint8_t     *imgptr,
00801                   const uint32_t    in_w,  /* input width */
00802                   const uint32_t    in_h,  /* input height */
00803                   const uint32_t    in_f,  /* input format */
00804                   uint32_t          x1,
00805                   uint32_t          y1,
00806                   uint32_t          x2,
00807                   uint32_t          y2,
00808                   uint8_t           **pcropped_image,
00809                   uint32_t          *ps,
00810                   uint32_t          *pw,
00811                   uint32_t          *ph )
00812 {
00813     phFUNCTION("ph_image_crop")
00814 
00815     uint32_t h = 0;
00816 
00817     uint32_t in_d           = 0;
00818     uint32_t row_stride     = 0;
00819 
00820     uint32_t crop_width     = 0;
00821     uint32_t crop_height    = 0;
00822     uint32_t crop_format    = 0;
00823     uint32_t crop_row_stride= 0;
00824     
00825     uint8_t  *crop_buffer   = NULL;
00826     uint32_t crop_buffersize= 0;
00827     uint32_t crop_imgsize   = 0;
00828     uint8_t  *crop_imgptr   = NULL;
00829 
00830     int copy_whole = 0;
00831 
00832     if ((pcropped_image == NULL) || (imgptr == NULL))
00833     {
00834         goto error;
00835     }
00836     
00837     if (in_w > 0)
00838     {
00839         if (x1 >= in_w) x1 = in_w-1;
00840         if (x2 >= in_w) x2 = in_w-1;
00841     }
00842     if (in_h > 0)
00843     {
00844         if (y1 >= in_h) y1 = in_h-1;
00845         if (y2 >= in_h) y2 = in_h-1;
00846     }
00847     if (x1 > x2)    x1 = x2;
00848     if (y1 > y2)    y1 = y2;
00849     if (x2 < x1)    x2 = x1;
00850     if (y2 < y1)    y2 = y1;
00851 
00852     in_d        = phImageFormatToDepth(in_f);
00853     row_stride  = in_w * in_d;
00854 
00855     crop_width      = (x2 - x1) + 1; /* x is indexed from 0, w is 1 more */
00856     crop_height     = (y2 - y1) + 1; /* y is indexed from 0, h is 1 more */
00857     
00858     /* crop the entire width of the input image? */
00859     if (crop_width == in_w)
00860     {
00861         /* Crop entire height of the input image? i.e. 100% of the image */
00862         if (crop_height == in_h)
00863             copy_whole = 1;
00864         /* .. Just copy a few rows of the image */
00865         else 
00866             copy_whole = 2;
00867     }
00868     crop_imgsize    = phIMAGE_SIZE(crop_width, crop_height, in_f);
00869     crop_buffer     = *pcropped_image;
00870     if (ps != NULL) 
00871         crop_buffersize = *ps;
00872 
00873     /* resize the buffer or allocate it with a Dynamic ALLOC */
00874     phDALLOC_RESIZE( crop_buffer, crop_buffersize, crop_imgsize, uint8_t);
00875 
00876     /* if the crop size is the same as the size of the input image */
00877     if (copy_whole == 1)
00878     {
00879         phMemcpy(crop_buffer,imgptr,crop_buffersize);
00880     }
00881     /* The x coordinates are the entire width of the image, so we can copy
00882      * y2-y1 rows all at once */
00883     else if (copy_whole == 2)
00884     {
00885         imgptr      += (y1 * in_w) * in_d;
00886         phMemcpy(crop_buffer,imgptr,crop_buffersize);
00887     }
00888     /* otherwise we're copying a piece of the image */
00889     else
00890     {
00891         imgptr      += (x1 + (y1 * in_w)) * in_d;
00892 
00893         crop_row_stride   = crop_width * in_d;
00894         crop_imgptr       = crop_buffer;
00895 
00896         for (h = y1; 
00897              h < y2; 
00898              h++, imgptr += row_stride, crop_imgptr += crop_row_stride )
00899         {
00900             phMemcpy(crop_imgptr,imgptr,crop_row_stride);
00901         }
00902     }
00903     
00904     if (pw != NULL) *pw = crop_width;
00905     if (ph != NULL) *ph = crop_height;
00906     if (ps != NULL) *ps = crop_buffersize;
00907     
00908     *pcropped_image = crop_buffer;
00909     
00910     return phSUCCESS;
00911 error:
00912 
00913     return phFAIL;
00914 }
00915 
00916 /* ---------------------------------------------------------------------- */
00917 #ifdef __cplusplus
00918 }; /* extern "C" */
00919 #endif /* __cplusplus */
00920 




Copyright (C) 2002 - 2007 Philip D.S. Thoren ( pthoren@users.sourceforge.net )
University Of Massachusetts at Lowell
Robotics Lab
SourceForge.net Logo

Generated on Sat Jun 16 02:44:02 2007 for phission by  doxygen 1.4.4