src/wavelet2D.c

Go to the documentation of this file.
00001 /*
00002    libit - Library for basic source and channel coding functions
00003    Copyright (C) 2005-2005 Vivien Chappelier, Herve Jegou
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public
00016    License along with this library; if not, write to the Free
00017    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00018 */
00019 
00020 /*
00021   Separable 2D wavelet transform using lifting.
00022   Copyright (C) 2005 Vivien Chappelier, Herve Jegou
00023 */
00024 
00025 #include <it/types.h>
00026 #include <it/wavelet.h>
00027 #include <it/wavelet2D.h>
00028 #include <it/io.h>
00029 
00030 /* This computes the wavelet decomposition using the lifting implementation.
00031    It uses a buffer of exactly twice the size of the image. As the memory 
00032    layout may look a bit complex, these comments address
00033    how one stage of the decomposition is done. 
00034 
00035    1. The image (or low-pass band of the previous level) to decompose is
00036    initially in the upper half of the buffer, in other terms, at the end.
00037 
00038    2. First the horizontal (H) decomposition is done which results in a low and
00039    high band. The low band is stored at the very beginning of the buffer and
00040    has half the number of coefficients of the initial image. The high band is
00041    stored just behind and has the same number of coefficients. The initial 
00042    image is not needed anymore and can now be discarded (overwritten).
00043 
00044    3. The second decomposition is a vertical (V) decomposition on the horizontal
00045    high band. It computes the horizontal high vertical low (high_low) and
00046    horizontal high vertical high (high_high) bands which both have one quarter
00047    the number of coefficients of the original image and are stored at the 
00048    beginning of the second half of the buffer (overwritting partially the
00049    original image). The horizontal high band is discarded.
00050 
00051    4. The final decomposition is a vertical decomposition too, but on the
00052    horizontal low band. The low_low and low_high bands resulting from the
00053    decomposition are stored in the second quarter of the buffer, overwritting
00054    the old horizontal high band. The second and third eighth of the buffer can
00055    now be seen as a new buffer of quarter the size of the initial one,
00056    containing the low pass image to process in its upper half.
00057 
00058    The decomposition can therefore be reiterated. After all levels are
00059    processed, all subbands appear in the initial buffer at a small offset from
00060    the beggining. They are read back, put in a nice matrix and given to the
00061    user.
00062 
00063    The following drawing explains how one stage of the decomposition is done.
00064    For clarity the buffer has been split in 8 slots. What is called a 'page'
00065    in the code corresponds to the length of 4 of those slots.
00066 
00067 buffer:
00068      step 1      step 2      step 3         step 4
00069 
00070   0: empty       low         low            empty       
00071   1: empty       low         low            empty       } seen as the buffer
00072   2: empty       high        empty          low_low     } for the next stage
00073   3: empty   H   high    V   empty      V   low_high      
00074   4: image    => empty    => high_low    => high_low     
00075   5: image       empty       high_high      high_high     
00076   6: image       empty       empty          empty       
00077   7: image       empty       empty          empty       
00078 */
00079 
00080 /*
00081   X[0] = X[0] + alpha * (X[-1] + X[1]); odd
00082   X[0] = X[0] + beta  * (X[-1] + X[1]);  even
00083   X[0] = X[0] + gamma * (X[-1] + X[1]); odd
00084   X[0] = X[0] + delta * (X[-1] + X[1]);  even
00085   X[0] = -scale * X[0];                 odd
00086   X[0] = X[0] / scale;                   even
00087 */
00088 #define reset_pointers()                        \
00089 do {            \
00090   pixels = buffer + page;     \
00091   low = buffer;         \
00092   high = buffer + (page >> 1);      \
00093   low_low =   buffer + (page >> 1) + 0 * (page >> 2); \
00094   low_high =  buffer + (page >> 1) + 1 * (page >> 2); \
00095   high_low =  buffer + (page >> 1) + 2 * (page >> 2); \
00096   high_high = buffer + (page >> 1) + 3 * (page >> 2); \
00097 } while(0)
00098 
00099 #define increment_pointers()      \
00100 do {            \
00101   pixels+=2;          \
00102   low++;          \
00103   high++;         \
00104   high_low++;         \
00105   high_high++;          \
00106   low_high++;         \
00107   low_low++;          \
00108 } while(0)
00109 
00110 #define adjust_pointers(odd)      \
00111 do {            \
00112   pixels+=odd;          \
00113   if(odd == 1) low++;       \
00114   if(odd == -1) high--;       \
00115 } while(0)
00116 
00117 
00118 #define hlifting(dest, source, constant, alt_source_pre, alt_source, alt_source_post, w, h, odd)  \
00119 do {                  \
00120   reset_pointers();             \
00121   for(y = 0; y < (h); y++) {            \
00122     (dest) = (source) + (constant) * (alt_source_pre);      \
00123     increment_pointers();           \
00124                   \
00125     for(x = 1; x < (w)-1; x++) {          \
00126       (dest) = (source) + (constant) * (alt_source);      \
00127       increment_pointers();           \
00128     }                 \
00129                       \
00130     (dest) = (source) + (constant) * (alt_source_post);     \
00131     increment_pointers();           \
00132     adjust_pointers(odd);           \
00133   }                 \
00134 } while(0)
00135 
00136 #define hlifting(dest, source, constant, alt_source_pre, alt_source, alt_source_post, w, h, odd)  \
00137 do {                  \
00138   reset_pointers();             \
00139   for(y = 0; y < (h); y++) {            \
00140     (dest) = (source) + (constant) * (alt_source_pre);      \
00141     increment_pointers();           \
00142                   \
00143     for(x = 1; x < (w)-1; x++) {          \
00144       (dest) = (source) + (constant) * (alt_source);      \
00145       increment_pointers();           \
00146     }                 \
00147                       \
00148     (dest) = (source) + (constant) * (alt_source_post);     \
00149     increment_pointers();           \
00150     adjust_pointers(odd);           \
00151   }                 \
00152 } while(0)
00153 
00154 #define vlifting(dest, source, constant, alt_source_pre, alt_source, alt_source_post, line, w, h) \
00155 do {                  \
00156   reset_pointers();             \
00157   for(x = 0; x < w; x ++) {           \
00158     (dest) = (source) + (constant) * (alt_source_pre);      \
00159     increment_pointers();           \
00160   }                 \
00161   (line) += p;                \
00162   for(y = 1; y < h-1; y ++) {           \
00163     for(x = 0; x < w; x ++) {           \
00164       (dest) = (source) + (constant) * (alt_source);      \
00165       increment_pointers();           \
00166     }                 \
00167     (line) += p;              \
00168   }                 \
00169   for(x = 0; x < w; x ++) {           \
00170     (dest) = (source) + (constant) * (alt_source_post);     \
00171     increment_pointers();           \
00172   }                 \
00173 } while(0)
00174 
00175 #define scale(dest, scale, count)   \
00176 do {            \
00177   reset_pointers();       \
00178   for(x = 0; x < (count); x++) {    \
00179     (dest)[0] *= (scale);     \
00180     increment_pointers();     \
00181   }           \
00182 } while(0)
00183 
00184 #define shift_up(x, l) ((x + ~(-1 << l)) >> l)
00185 #define round_up(x, l) (shift_up(x, l) << l)
00186 
00187 /* compute the next level decomposition using the lifting method. */
00188 static int __wavelet2D_split (it_wavelet2D_t * wavelet)
00189 {
00190   int  i, x, y, w, h, p;
00191   int  width;
00192   int  height;
00193   int  level;
00194   int  levels;
00195   double *buffer;
00196   double *pixels;
00197   double *low, *high, *low_high, *low_low, *high_low, *high_high;
00198   int  page;
00199   int  count;
00200   double const *step;
00201   double scale;
00202 
00203   assert (wavelet);
00204 
00205   if (wavelet->level == wavelet->levels)
00206     return (-IT_EINVAL);
00207 
00208   width = wavelet->width;
00209   height = wavelet->height;
00210   level = wavelet->level;
00211   levels = wavelet->levels;
00212   buffer = wavelet->buffer;
00213   count = wavelet->lifting->count / 2;
00214   step = wavelet->lifting->step;
00215   scale = wavelet->lifting->scale;
00216 
00217   w = shift_up (width, level);
00218   h = shift_up (height, level);
00219   page = (round_up (width, levels) * round_up (height, levels)) >> level;
00220 
00221   /* horizontal filtering */
00222 
00223   /* stage 1 : odd samples lifting */
00224   if (w & 1) {
00225     hlifting (high[0], pixels[1], step[0],
00226         pixels[0] + pixels[2],
00227         pixels[0] + pixels[2], pixels[0] + pixels[2], w / 2, h, 1);
00228   }
00229   else {
00230     hlifting (high[0], pixels[1], step[0],
00231         pixels[0] + pixels[2],
00232         pixels[0] + pixels[2], pixels[0] + pixels[0], w / 2, h, 0);
00233   }
00234 
00235   /* stage 2 : even samples lifting */
00236   if (w & 1) {
00237     hlifting (low[0], pixels[0], step[1],
00238         high[0] + high[0],
00239         high[-1] + high[0], high[-1] + high[-1], w / 2 + 1, h, -1);
00240   }
00241   else {
00242     hlifting (low[0], pixels[0], step[1],
00243         high[0] + high[0],
00244         high[-1] + high[0], high[-1] + high[0], w / 2, h, 0);
00245   }
00246 
00247   reset_pointers ();
00248 
00249   for (i = 1; i < count; i++) {
00250     /* stage 3 : odd samples lifting */
00251     if (w & 1) {
00252       hlifting (high[0], high[0], step[2 * i],
00253     low[0] + low[1],
00254     low[0] + low[1], low[0] + low[1], w / 2, h, 1);
00255     }
00256     else {
00257       hlifting (high[0], high[0], step[2 * i],
00258     low[0] + low[1],
00259     low[0] + low[1], low[0] + low[0], w / 2, h, 0);
00260     }
00261 
00262     /* stage 4 : even samples lifting */
00263     if (w & 1) {
00264       hlifting (low[0], low[0], step[2 * i + 1],
00265     high[0] + high[0],
00266     high[-1] + high[0], high[-1] + high[-1], w / 2 + 1, h, -1);
00267     }
00268     else {
00269       hlifting (low[0], low[0], step[2 * i + 1],
00270     high[0] + high[0],
00271     high[-1] + high[0], high[-1] + high[0], w / 2, h, 0);
00272     }
00273   }
00274 
00275   scale (low, scale, ((w + 1) / 2) * h);
00276   scale (high, 1.0 / scale, (w / 2) * h);
00277 
00278   /* vertical filtering (on horizontal high band) */
00279   p = w / 2;
00280   /* stage 1 : odd samples lifting */
00281   if (h & 1) {
00282     vlifting (high_high[0], high[p], step[0],
00283         high[0] + high[2 * p],
00284         high[0] + high[2 * p],
00285         high[0] + high[2 * p], high, w / 2, h / 2);
00286   }
00287   else {
00288     vlifting (high_high[0], high[p], step[0],
00289         high[0] + high[2 * p],
00290         high[0] + high[2 * p], high[0] + high[0], high, w / 2, h / 2);
00291   }
00292 
00293   /* stage 2 : even samples lifting */
00294   if (h & 1) {
00295     vlifting (high_low[0], high[0], step[1],
00296         high_high[0] + high_high[0],
00297         high_high[-p] + high_high[0],
00298         high_high[-p] + high_high[-p], high, w / 2, h / 2 + 1);
00299   }
00300   else {
00301     vlifting (high_low[0], high[0], step[1],
00302         high_high[0] + high_high[0],
00303         high_high[-p] + high_high[0],
00304         high_high[-p] + high_high[0], high, w / 2, h / 2);
00305   }
00306 
00307   for (i = 1; i < count; i++) {
00308     /* stage 3 : odd samples lifting */
00309     if (h & 1) {
00310       vlifting (high_high[0], high_high[0], step[2 * i],
00311     high_low[0] + high_low[p],
00312     high_low[0] + high_low[p],
00313     high_low[0] + high_low[p], high, w / 2, h / 2);
00314     }
00315     else {
00316       vlifting (high_high[0], high_high[0], step[2 * i],
00317     high_low[0] + high_low[p],
00318     high_low[0] + high_low[p],
00319     high_low[0] + high_low[0], high, w / 2, h / 2);
00320     }
00321 
00322     /* stage 4 : even samples lifting */
00323     if (h & 1) {
00324       vlifting (high_low[0], high_low[0], step[2 * i + 1],
00325     high_high[0] + high_high[0],
00326     high_high[-p] + high_high[0],
00327     high_high[-p] + high_high[-p], high, w / 2, h / 2 + 1);
00328     }
00329     else {
00330       vlifting (high_low[0], high_low[0], step[2 * i + 1],
00331     high_high[0] + high_high[0],
00332     high_high[-p] + high_high[0],
00333     high_high[-p] + high_high[0], high, w / 2, h / 2);
00334     }
00335   }
00336   scale (high_low, scale, p * (h + 1) / 2);
00337   scale (high_high, 1.0 / scale, p * (h + 1) / 2);
00338 
00339   /* vertical filtering (on horizontal low band) */
00340   p = (w + 1) / 2;
00341   /* stage 1 : odd samples lifting */
00342   if (h & 1) {
00343     vlifting (low_high[0], low[p], step[0],
00344         low[0] + low[2 * p],
00345         low[0] + low[2 * p],
00346         low[0] + low[2 * p], low, (w + 1) / 2, h / 2);
00347   }
00348   else {
00349     vlifting (low_high[0], low[p], step[0],
00350         low[0] + low[2 * p],
00351         low[0] + low[2 * p], low[0] + low[0], low, (w + 1) / 2, h / 2);
00352   }
00353 
00354   /* stage 2 : even samples lifting */
00355   if (h & 1) {
00356     vlifting (low_low[0], low[0], step[1],
00357         low_high[0] + low_high[0],
00358         low_high[-p] + low_high[0],
00359         low_high[-p] + low_high[-p], low, (w + 1) / 2, h / 2 + 1);
00360   }
00361   else {
00362     vlifting (low_low[0], low[0], step[1],
00363         low_high[0] + low_high[0],
00364         low_high[-p] + low_high[0],
00365         low_high[-p] + low_high[0], low, (w + 1) / 2, h / 2);
00366   }
00367 
00368   for (i = 1; i < count; i++) {
00369     /* stage 3 : odd samples lifting */
00370     if (h & 1) {
00371       vlifting (low_high[0], low_high[0], step[2 * i],
00372     low_low[0] + low_low[p],
00373     low_low[0] + low_low[p],
00374     low_low[0] + low_low[p], low, (w + 1) / 2, h / 2);
00375     }
00376     else {
00377       vlifting (low_high[0], low_high[0], step[2 * i],
00378     low_low[0] + low_low[p],
00379     low_low[0] + low_low[p],
00380     low_low[0] + low_low[0], low, (w + 1) / 2, h / 2);
00381     }
00382 
00383     /* stage 4 : even samples lifting */
00384     if (h & 1) {
00385       vlifting (low_low[0], low_low[0], step[2 * i + 1],
00386     low_high[0] + low_high[0],
00387     low_high[-p] + low_high[0],
00388     low_high[-p] + low_high[-p], low, (w + 1) / 2, h / 2 + 1);
00389     }
00390     else {
00391       vlifting (low_low[0], low_low[0], step[2 * i + 1],
00392     low_high[0] + low_high[0],
00393     low_high[-p] + low_high[0],
00394     low_high[-p] + low_high[0], low, (w + 1) / 2, h / 2);
00395     }
00396   }
00397 
00398   scale (low_low, scale, p * (h + 1) / 2);
00399   scale (low_high, 1.0 / scale, p * (h + 1) / 2);
00400 
00401   wavelet->level++;
00402 
00403   return (0);
00404 }
00405 
00406 /* reconstruct the previous level of decomposition
00407    by inverting the lifting steps. */
00408 static int __wavelet2D_merge (it_wavelet2D_t * wavelet)
00409 {
00410   int  i, x, y, w, h, p;
00411   int  width;
00412   int  height;
00413   int  level;
00414   int  levels;
00415   double *pixels;
00416   double *buffer;
00417   double *low, *high, *low_high, *low_low, *high_low, *high_high;
00418   int  page;
00419   int  count;
00420   double const *step;
00421   double scale;
00422 
00423   assert (wavelet);
00424 
00425   if (wavelet->level == 0)
00426     return (-IT_EINVAL);
00427 
00428   wavelet->level--;
00429 
00430   width = wavelet->width;
00431   height = wavelet->height;
00432   level = wavelet->level;
00433   levels = wavelet->levels;
00434   buffer = wavelet->buffer;
00435   count = wavelet->lifting->count / 2;
00436   step = wavelet->lifting->step;
00437   scale = wavelet->lifting->scale;
00438 
00439   w = shift_up (width, level);
00440   h = shift_up (height, level);
00441   page = (round_up (width, levels) * round_up (height, levels)) >> level;
00442 
00443   /* vertical filtering (on horizontal low band) */
00444   p = (w + 1) / 2;
00445 
00446   scale (low_low, 1.0 / scale, p * (h + 1) / 2);
00447   scale (low_high, scale, p * (h + 1) / 2);
00448 
00449   for (i = 1; i < count; i++) {
00450     /* stage 4 : even samples lifting */
00451     if (h & 1) {
00452       vlifting (low_low[0], low_low[0], -step[2 * i + 1],
00453     low_high[0] + low_high[0],
00454     low_high[-p] + low_high[0],
00455     low_high[-p] + low_high[-p], low, (w + 1) / 2, h / 2 + 1);
00456     }
00457     else {
00458       vlifting (low_low[0], low_low[0], -step[2 * i + 1],
00459     low_high[0] + low_high[0],
00460     low_high[-p] + low_high[0],
00461     low_high[-p] + low_high[0], low, (w + 1) / 2, h / 2);
00462     }
00463 
00464     /* stage 3 : odd samples lifting */
00465     if (h & 1) {
00466       vlifting (low_high[0], low_high[0], -step[2 * i],
00467     low_low[0] + low_low[p],
00468     low_low[0] + low_low[p],
00469     low_low[0] + low_low[p], low, (w + 1) / 2, h / 2);
00470     }
00471     else {
00472       vlifting (low_high[0], low_high[0], -step[2 * i],
00473     low_low[0] + low_low[p],
00474     low_low[0] + low_low[p],
00475     low_low[0] + low_low[0], low, (w + 1) / 2, h / 2);
00476     }
00477   }
00478 
00479   /* stage 2 : even samples lifting */
00480   if (h & 1) {
00481     vlifting (low[0], low_low[0], -step[1],
00482         low_high[0] + low_high[0],
00483         low_high[-p] + low_high[0],
00484         low_high[-p] + low_high[-p], low, (w + 1) / 2, h / 2 + 1);
00485   }
00486   else {
00487     vlifting (low[0], low_low[0], -step[1],
00488         low_high[0] + low_high[0],
00489         low_high[-p] + low_high[0],
00490         low_high[-p] + low_high[0], low, (w + 1) / 2, h / 2);
00491   }
00492 
00493   /* stage 1 : odd samples lifting */
00494   if (h & 1) {
00495     vlifting (low[p], low_high[0], -step[0],
00496         low[0] + low[2 * p],
00497         low[0] + low[2 * p],
00498         low[0] + low[2 * p], low, (w + 1) / 2, h / 2);
00499   }
00500   else {
00501     vlifting (low[p], low_high[0], -step[0],
00502         low[0] + low[2 * p],
00503         low[0] + low[2 * p], low[0] + low[0], low, (w + 1) / 2, h / 2);
00504   }
00505 
00506   /* vertical filtering (on horizontal high band) */
00507   p = w / 2;
00508 
00509   scale (high_low, 1.0 / scale, p * (h + 1) / 2);
00510   scale (high_high, scale, p * (h + 1) / 2);
00511 
00512   for (i = 1; i < count; i++) {
00513     /* stage 4 : even samples lifting */
00514     if (h & 1) {
00515       vlifting (high_low[0], high_low[0], -step[2 * i + 1],
00516     high_high[0] + high_high[0],
00517     high_high[-p] + high_high[0],
00518     high_high[-p] + high_high[-p], high, w / 2, h / 2 + 1);
00519     }
00520     else {
00521       vlifting (high_low[0], high_low[0], -step[2 * i + 1],
00522     high_high[0] + high_high[0],
00523     high_high[-p] + high_high[0],
00524     high_high[-p] + high_high[0], high, w / 2, h / 2);
00525     }
00526 
00527     /* stage 3 : odd samples lifting */
00528     if (h & 1) {
00529       vlifting (high_high[0], high_high[0], -step[2 * i],
00530     high_low[0] + high_low[p],
00531     high_low[0] + high_low[p],
00532     high_low[0] + high_low[p], high, w / 2, h / 2);
00533     }
00534     else {
00535       vlifting (high_high[0], high_high[0], -step[2 * i],
00536     high_low[0] + high_low[p],
00537     high_low[0] + high_low[p],
00538     high_low[0] + high_low[0], high, w / 2, h / 2);
00539     }
00540   }
00541 
00542   /* stage 2 : even samples lifting */
00543   if (h & 1) {
00544     vlifting (high[0], high_low[0], -step[1],
00545         high_high[0] + high_high[0],
00546         high_high[-p] + high_high[0],
00547         high_high[-p] + high_high[-p], high, w / 2, h / 2 + 1);
00548   }
00549   else {
00550     vlifting (high[0], high_low[0], -step[1],
00551         high_high[0] + high_high[0],
00552         high_high[-p] + high_high[0],
00553         high_high[-p] + high_high[0], high, w / 2, h / 2);
00554   }
00555 
00556   /* stage 1 : odd samples lifting */
00557   if (h & 1) {
00558     vlifting (high[p], high_high[0], -step[0],
00559         high[0] + high[2 * p],
00560         high[0] + high[2 * p],
00561         high[0] + high[2 * p], high, w / 2, h / 2);
00562   }
00563   else {
00564     vlifting (high[p], high_high[0], -step[0],
00565         high[0] + high[2 * p],
00566         high[0] + high[2 * p], high[0] + high[0], high, w / 2, h / 2);
00567   }
00568 
00569   /* horizontal filtering */
00570   scale (low, 1.0 / scale, ((w + 1) / 2) * h);
00571   scale (high, scale, (w / 2) * h);
00572 
00573   for (i = 1; i < count; i++) {
00574     /* stage 4 : even samples lifting */
00575     if (w & 1) {
00576       hlifting (low[0], low[0], -step[2 * i + 1],
00577     high[0] + high[0],
00578     high[-1] + high[0], high[-1] + high[-1], w / 2 + 1, h, -1);
00579     }
00580     else {
00581       hlifting (low[0], low[0], -step[2 * i + 1],
00582     high[0] + high[0],
00583     high[-1] + high[0], high[-1] + high[0], w / 2, h, 0);
00584     }
00585 
00586     /* stage 3 : odd samples lifting */
00587     if (w & 1) {
00588       hlifting (high[0], high[0], -step[2 * i],
00589     low[0] + low[1],
00590     low[0] + low[1], low[0] + low[1], w / 2, h, 1);
00591     }
00592     else {
00593       hlifting (high[0], high[0], -step[2 * i],
00594     low[0] + low[1],
00595     low[0] + low[1], low[0] + low[0], w / 2, h, 0);
00596     }
00597   }
00598 
00599   /* stage 2 : even samples lifting */
00600   if (w & 1) {
00601     hlifting (pixels[0], low[0], -step[1],
00602         high[0] + high[0],
00603         high[-1] + high[0], high[-1] + high[-1], w / 2 + 1, h, -1);
00604   }
00605   else {
00606     hlifting (pixels[0], low[0], -step[1],
00607         high[0] + high[0],
00608         high[-1] + high[0], high[-1] + high[0], w / 2, h, 0);
00609   }
00610 
00611   /* stage 1 : odd samples lifting */
00612   if (w & 1) {
00613     hlifting (pixels[1], high[0], -step[0],
00614         pixels[0] + pixels[2],
00615         pixels[0] + pixels[2], pixels[0] + pixels[2], w / 2, h, 1);
00616   }
00617   else {
00618     hlifting (pixels[1], high[0], -step[0],
00619         pixels[0] + pixels[2],
00620         pixels[0] + pixels[2], pixels[0] + pixels[0], w / 2, h, 0);
00621   }
00622 
00623   return (0);
00624 }
00625 
00626 /* arrange the transformed coefficients in an image */
00627 /* where the top left corner contains the lowest band.  */
00628 static int __wavelet_flatten (it_wavelet2D_t * it_this, mat image)
00629 {
00630   int  x, y, wf, hf, wc, hc, ps;
00631   int  width, height, level, page;
00632   int  levels;
00633   double *band;
00634   double *buffer = it_this->buffer;
00635 
00636   width = it_this->width;
00637   height = it_this->height;
00638   levels = it_this->levels;
00639   page = round_up (width, levels) * round_up (height, levels);
00640   buffer = it_this->buffer + page;
00641   ps = width;
00642 
00643   if (width != mat_width (image))
00644     return (-IT_EINVAL);
00645   if (height != mat_height (image))
00646     return (-IT_EINVAL);
00647 
00648   hc = height;
00649   wc = width;
00650 
00651   for (level = 0; level < levels; level++) {
00652     page = (round_up (width, levels) * round_up (height, levels)) >> level;
00653     buffer = (it_this->buffer) + (page >> 1);
00654 
00655     ps = (ps + 1) / 2;    /* upper rounded */
00656     hf = hc / 2;
00657     hc = (hc + 1) / 2;
00658     wf = wc / 2;
00659     wc = (wc + 1) / 2;
00660 
00661     band = buffer + 2 * (page >> 2);  /* HL */
00662     for (y = 0; y < hc; y++)
00663       for (x = 0; x < wf; x++)
00664   image[y][x + wc] = band[y * wf + x];
00665 
00666     band = buffer + 1 * (page >> 2);  /* LH */
00667     for (y = 0; y < hf; y++)
00668       for (x = 0; x < wc; x++)
00669   image[y + hc][x] = band[y * wc + x];
00670 
00671     band = buffer + 3 * (page >> 2);  /* HH */
00672     for (y = 0; y < hf; y++)
00673       for (x = 0; x < wf; x++)
00674   image[y + hc][x + wc] = band[y * wf + x];
00675   }
00676 
00677   band = buffer;    /* LL */
00678   for (y = 0; y < hc; y++)
00679     for (x = 0; x < wc; x++)
00680       image[y][x] = band[y * wc + x];
00681 
00682   return (0);
00683 }
00684 
00685 /* read the transformed coefficients from an image */
00686 /* where the top left corner contains the lowest band.  */
00687 static int __wavelet_unflatten (it_wavelet2D_t * it_this, mat image)
00688 {
00689   int  x, y, wf, hf, wc, hc, ps;
00690   int  width, height, level, page;
00691   int  levels;
00692   double *band;
00693   double *buffer = it_this->buffer;
00694 
00695   width = it_this->width;
00696   height = it_this->height;
00697   levels = it_this->levels;
00698   page = round_up (width, levels) * round_up (height, levels);
00699   buffer = it_this->buffer + page;
00700   ps = width;
00701 
00702   if (width != mat_width (image))
00703     return (-IT_EINVAL);
00704   if (height != mat_height (image))
00705     return (-IT_EINVAL);
00706 
00707   /* we are given a fully decomposed image */
00708   it_this->level = levels;
00709   hc = height;
00710   wc = width;
00711 
00712   for (level = 0; level < levels; level++) {
00713     page = (round_up (width, levels) * round_up (height, levels)) >> level;
00714     buffer = (it_this->buffer) + (page >> 1);
00715 
00716     ps = (ps + 1) / 2;    /* upper rounded */
00717     hf = hc / 2;
00718     hc = (hc + 1) / 2;
00719     wf = wc / 2;
00720     wc = (wc + 1) / 2;
00721 
00722     band = buffer + 2 * (page >> 2);  /* HL */
00723     for (y = 0; y < hc; y++)
00724       for (x = 0; x < wf; x++)
00725   band[y * wf + x] = image[y][x + wc];
00726 
00727     band = buffer + 1 * (page >> 2);  /* LH */
00728     for (y = 0; y < hf; y++)
00729       for (x = 0; x < wc; x++)
00730   band[y * wc + x] = image[y + hc][x];
00731 
00732     band = buffer + 3 * (page >> 2);  /* HH */
00733     for (y = 0; y < hf; y++)
00734       for (x = 0; x < wf; x++)
00735   band[y * wf + x] = image[y + hc][x + wc];
00736   }
00737 
00738   band = buffer;    /* LL */
00739   for (y = 0; y < hc; y++)
00740     for (x = 0; x < wc; x++)
00741       band[y * wc + x] = image[y][x];
00742 
00743   return (0);
00744 }
00745 
00746 /* compute the wavelet transform of the image */
00747 static Mat __it_wavelet2D_transform (it_transform2D_t * transform,
00748              Mat __image)
00749 {
00750   it_wavelet2D_t *wavelet = IT_WAVELET2D (transform);
00751   int  x, y;
00752   int  width, height;
00753   int  page;
00754   int  levels;
00755   double *buffer;
00756   mat  flat;
00757   mat  image = (mat) __image;
00758   int  free_on_exit = 0;
00759 
00760   assert (image);
00761 
00762   /* check the input is actually a mat */
00763   assert (Vec_header (image[0]).element_size == sizeof (double));
00764 
00765   width = mat_width (image);
00766   height = mat_height (image);
00767 
00768   if (!wavelet->width || !wavelet->height) {
00769     it_transform2D_set_size (wavelet, width, height);
00770     free_on_exit = 1;
00771   }
00772 
00773   flat = mat_new (height, width);
00774   levels = wavelet->levels;
00775   page = round_up (width, levels) * round_up (height, levels);
00776   buffer = wavelet->buffer + page;
00777 
00778   for (y = 0; y < height; y++)
00779     for (x = 0; x < width; x++)
00780       buffer[y * width + x] = image[y][x];
00781 
00782   while (wavelet->level < levels)
00783     __wavelet2D_split (wavelet);
00784 
00785   __wavelet_flatten (IT_WAVELET2D (transform), flat);
00786 
00787   if (free_on_exit)
00788     it_transform2D_clear_size (wavelet);
00789 
00790   return ((Mat) flat);
00791 }
00792 
00793 /* compute the inverse wavelet transform of the coefficients */
00794 static Mat __it_wavelet2D_itransform (it_transform2D_t * transform,
00795               Mat __flat)
00796 {
00797   it_wavelet2D_t *wavelet = IT_WAVELET2D (transform);
00798   int  width, height;
00799   int  x, y;
00800   int  page;
00801   int  levels;
00802   double *buffer;
00803   mat  image;
00804   mat  flat = (mat) __flat;
00805   int  free_on_exit = 0;
00806 
00807   assert (flat);
00808 
00809   /* check the input is actually a vec */
00810   assert (Vec_header (flat[0]).element_size == sizeof (double));
00811 
00812   width = mat_width (flat);
00813   height = mat_height (flat);
00814 
00815   if (!wavelet->width || !wavelet->height) {
00816     it_transform2D_set_size (wavelet, width, height);
00817     free_on_exit = 1;
00818   }
00819 
00820   image = mat_new (height, width);
00821   levels = wavelet->levels;
00822   page = round_up (width, levels) * round_up (height, levels);
00823   buffer = wavelet->buffer + page;
00824 
00825   __wavelet_unflatten (IT_WAVELET2D (transform), flat);
00826 
00827   while (wavelet->level)
00828     __wavelet2D_merge (wavelet);
00829 
00830   for (y = 0; y < height; y++)
00831     for (x = 0; x < width; x++)
00832       image[y][x] = buffer[y * width + x];
00833 
00834   if (free_on_exit)
00835     it_transform2D_clear_size (wavelet);
00836 
00837   return ((Mat) image);
00838 }
00839 
00840 static int __it_wavelet2D_copy (it_wavelet2D_t * it_this,
00841         it_wavelet2D_t * source)
00842 {
00843   assert (it_this->levels == source->levels);
00844 
00845   if (source->width && source->height) {
00846     it_transform2D_set_size (it_this, source->width, source->height);
00847     vec_copy (it_this->buffer, source->buffer);
00848   }
00849 
00850   return (0);
00851 }
00852 
00853 static void __wavelet2D_get_output_size (it_transform2D_t * transform,
00854            idx_t * width, idx_t * height)
00855 {
00856   /* this transform is critically sampled */
00857 }
00858 
00859 static void __wavelet2D_set_size (it_transform2D_t * transform,
00860           idx_t width, idx_t height)
00861 {
00862   it_wavelet2D_t *wavelet = IT_WAVELET2D (transform);
00863   int  levels = wavelet->levels;
00864 
00865   if (wavelet->width && wavelet->height)
00866     vec_delete (wavelet->buffer);
00867 
00868   if (width && height)
00869     wavelet->buffer =
00870       vec_new (2 * round_up (width, levels) * round_up (height, levels));
00871 
00872   wavelet->width = width;
00873   wavelet->height = height;
00874 }
00875 
00876 static void __wavelet2D_get_size (it_transform2D_t * transform,
00877           idx_t * width, idx_t * height)
00878 {
00879   it_wavelet2D_t *wavelet = IT_WAVELET2D (transform);
00880 
00881   *width = wavelet->width;
00882   *height = wavelet->height;
00883 }
00884 
00885 static void __wavelet2D_destructor (it_object_t * it_this)
00886 {
00887   it_wavelet2D_t *wavelet = IT_WAVELET2D (it_this);
00888 
00889   if (wavelet->width && wavelet->height)
00890     vec_delete (wavelet->buffer);
00891 
00892   /* call the parent destructor */
00893   wavelet->it_overloaded (destructor) (it_this);
00894 }
00895 
00896 it_instanciate (it_wavelet2D_t)
00897 {
00898   it_new_args_start ();
00899   it_construct (it_transform2D_t);
00900   it_set_magic (it_this, it_wavelet2D_t);
00901 
00902   /* overload the virtual destructor */
00903   it_overload (it_this, it_object_t, destructor, __wavelet2D_destructor);
00904 
00905   IT_TRANSFORM2D (it_this)->transform = __it_wavelet2D_transform;
00906   IT_TRANSFORM2D (it_this)->itransform = __it_wavelet2D_itransform;
00907   IT_TRANSFORM2D (it_this)->get_output_size = __wavelet2D_get_output_size;
00908   IT_TRANSFORM2D (it_this)->set_size = __wavelet2D_set_size;
00909   IT_TRANSFORM2D (it_this)->get_size = __wavelet2D_get_size;
00910 
00911   it_this->copy = __it_wavelet2D_copy;
00912 
00913   it_this->level = 0;
00914   it_this->lifting = it_new_args_next (it_wavelet_lifting_t *);
00915   it_this->levels = it_new_args_next (int);
00916   it_this->width = 0;
00917   it_this->height = 0;
00918 
00919   it_new_args_stop ();
00920 
00921   return (it_this);
00922 }
00923 
00924 /*--------------------------------------------------------------------*/
00925 mat *it_wavelet2D_split (mat wav, int nb_levels)
00926 {
00927   int  mid_row, mid_col, nb_row, nb_col, l;
00928   mat *subbands;
00929 
00930   assert (wav);
00931 
00932   nb_row = mat_height (wav);
00933   nb_col = mat_width (wav);
00934   mid_row = (nb_row + 1) / 2;
00935   mid_col = (nb_col + 1) / 2;
00936 
00937   subbands = (mat *) malloc (sizeof (mat) * (3 * nb_levels + 1));
00938 
00939   for (l = nb_levels; l > 0; l--) {
00940     subbands[l * 3 - 2] =
00941       mat_get_submatrix (wav, 0, mid_col, mid_row - 1, nb_col - 1);
00942     subbands[l * 3 - 1] =
00943       mat_get_submatrix (wav, mid_row, 0, nb_row - 1, mid_col - 1);
00944     subbands[l * 3] =
00945       mat_get_submatrix (wav, mid_row, mid_col, nb_row - 1, nb_col - 1);
00946 
00947     nb_row = mid_row;
00948     nb_col = mid_col;
00949     mid_row = (nb_row + 1) / 2;
00950     mid_col = (nb_col + 1) / 2;
00951   }
00952 
00953   subbands[0] = mat_get_submatrix (wav, 0, 0, nb_row -1 , nb_col -1);
00954   return subbands;
00955 }
00956 
00957 mat it_wavelet2D_merge (mat * subbands, int nb_levels)
00958 {
00959   int  mid_row, mid_col, nb_row, nb_col, l;
00960   mat  wav;
00961 
00962   assert (subbands);
00963 
00964   wav = mat_new (mat_height (subbands[nb_levels * 3])
00965     + mat_height (subbands[nb_levels * 3 - 2]),
00966     mat_width (subbands[nb_levels * 3])
00967     + mat_width (subbands[nb_levels * 3 - 1]));
00968 
00969   nb_row = mat_height (wav);
00970   nb_col = mat_width (wav);
00971   mid_row = (nb_row + 1) / 2;
00972   mid_col = (nb_col + 1) / 2;
00973 
00974   for (l = nb_levels; l > 0; l--) {
00975     mat_set_submatrix (wav, subbands[l * 3 - 2], 0, mid_col);
00976     mat_set_submatrix (wav, subbands[l * 3 - 1], mid_row, 0);
00977     mat_set_submatrix (wav, subbands[l * 3], mid_row, mid_col);
00978 
00979     nb_row = mid_row;
00980     nb_col = mid_col;
00981     mid_row = (nb_row + 1) / 2;
00982     mid_col = (nb_col + 1) / 2;
00983   }
00984 
00985   mat_set_submatrix (wav, subbands[0], 0, 0);
00986   return wav;
00987 }
00988 
00989 mat it_dwt2D (mat m, it_wavelet_lifting_t const *lifting, int levels)
00990 {
00991   it_wavelet2D_t *wavelet;
00992   mat  t;
00993 
00994   wavelet = it_wavelet2D_new (lifting, levels);
00995 
00996   t = (mat) it_transform2D (wavelet, m);
00997 
00998   it_delete (wavelet);
00999 
01000   return (t);
01001 }
01002 
01003 mat it_idwt2D (mat t, it_wavelet_lifting_t const *lifting, int levels)
01004 {
01005   it_wavelet2D_t *wavelet;
01006   mat  m;
01007 
01008   wavelet = it_wavelet2D_new (lifting, levels);
01009 
01010   m = (mat) it_itransform2D (wavelet, t);
01011 
01012   it_delete (wavelet);
01013 
01014   return (m);
01015 }

Hosted by
Copyright (C) 2005-2006 Hervé Jégou
Vivien Chappelier
Francois Cayre
libit logo courtesy of Jonathan Delhumeau