BRL-CAD
wavelet.c
Go to the documentation of this file.
1 /* W A V E L E T . C
2  * BRL-CAD
3  *
4  * Copyright (c) 2004-2014 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 
21 /** @addtogroup wavelet */
22 /** @{ */
23 /** @file libbn/wavelet.c
24  *
25  * @brief
26  * This is a standard wavelet library that takes a given data buffer of some data
27  * type and then performs a wavelet transform on that data.
28  *
29  * The transform
30  * operations available are to either decompose or reconstruct a signal into its
31  * corresponding wavelet form based on the haar wavelet.
32  *
33  * Wavelet decompose/reconstruct operations
34  *
35  * - bn_wlt_haar_1d_double_decompose(tbuffer, buffer, dimen, channels, limit)
36  * - bn_wlt_haar_1d_float_decompose (tbuffer, buffer, dimen, channels, limit)
37  * - bn_wlt_haar_1d_char_decompose (tbuffer, buffer, dimen, channels, limit)
38  * - bn_wlt_haar_1d_short_decompose (tbuffer, buffer, dimen, channels, limit)
39  * - bn_wlt_haar_1d_int_decompose (tbuffer, buffer, dimen, channels, limit)
40  * - bn_wlt_haar_1d_long_decompose (tbuffer, buffer, dimen, channels, limit)
41  *
42  * - bn_wlt_haar_1d_double_reconstruct(tbuffer, buffer, dimen, channels, sub_sz, limit)
43  * - bn_wlt_haar_1d_float_reconstruct (tbuffer, buffer, dimen, channels, sub_sz, limit)
44  * - bn_wlt_haar_1d_char_reconstruct (tbuffer, buffer, dimen, channels, sub_sz, limit)
45  * - bn_wlt_haar_1d_short_reconstruct (tbuffer, buffer, dimen, channels, sub_sz, limit)
46  * - bn_wlt_haar_1d_int_reconstruct (tbuffer, buffer, dimen, channels, sub_sz, limit)
47  * - bn_wlt_haar_1d_long_reconstruct (tbuffer, buffer, dimen, channels, sub_sz, limit)
48  *
49  * - bn_wlt_haar_2d_double_decompose(tbuffer, buffer, dimen, channels, limit)
50  * - bn_wlt_haar_2d_float_decompose (tbuffer, buffer, dimen, channels, limit)
51  * - bn_wlt_haar_2d_char_decompose (tbuffer, buffer, dimen, channels, limit)
52  * - bn_wlt_haar_2d_short_decompose (tbuffer, buffer, dimen, channels, limit)
53  * - bn_wlt_haar_2d_int_decompose (tbuffer, buffer, dimen, channels, limit)
54  * - bn_wlt_haar_2d_long_decompose (tbuffer, buffer, dimen, channels, limit)
55  *
56  * - bn_wlt_haar_2d_double_reconstruct(tbuffer, buffer, dimen, channels, sub_sz, limit)
57  * - bn_wlt_haar_2d_float_reconstruct (tbuffer, buffer, dimen, channels, sub_sz, limit)
58  * - bn_wlt_haar_2d_char_reconstruct (tbuffer, buffer, dimen, channels, sub_sz, limit)
59  * - bn_wlt_haar_2d_short_reconstruct (tbuffer, buffer, dimen, channels, sub_sz, limit)
60  * - bn_wlt_haar_2d_int_reconstruct (tbuffer, buffer, dimen, channels, sub_sz, limit)
61  * - bn_wlt_haar_2d_long_reconstruct (tbuffer, buffer, dimen, channels, sub_sz, limit)
62  *
63  * - bn_wlt_haar_2d_double_decompose2(tbuffer, buffer, width, height, channels, limit)
64  * - bn_wlt_haar_2d_float_decompose2 (tbuffer, buffer, width, height, channels, limit)
65  * - bn_wlt_haar_2d_char_decompose2 (tbuffer, buffer, width, height, channels, limit)
66  * - bn_wlt_haar_2d_short_decompose2 (tbuffer, buffer, width, height, channels, limit)
67  * - bn_wlt_haar_2d_int_decompose2 (tbuffer, buffer, width, height, channels, limit)
68  * - bn_wlt_haar_2d_long_decompose2 (tbuffer, buffer, width, height, channels, limit)
69  *
70  * - bn_wlt_haar_2d_double_reconstruct2(tbuffer, buffer, width, height, channels, sub_sz, limit)
71  * - bn_wlt_haar_2d_float_reconstruct2 (tbuffer, buffer, width, height, channels, sub_sz, limit)
72  * - bn_wlt_haar_2d_char_reconstruct2 (tbuffer, buffer, width, height, channels, sub_sz, limit)
73  * - bn_wlt_haar_2d_short_reconstruct2 (tbuffer, buffer, width, height, channels, sub_sz, limit)
74  * - bn_wlt_haar_2d_int_reconstruct2 (tbuffer, buffer, width, height, channels, sub_sz, limit)
75  * - bn_wlt_haar_2d_long_reconstruct2 (tbuffer, buffer, width, height, channels, sub_sz, limit)
76  *
77  *
78  * For greatest accuracy, it is preferable to convert everything to "double"
79  * and decompose/reconstruct with that. However, there are useful
80  * properties to performing the decomposition and/or reconstruction in
81  * various data types (most notably char).
82  *
83  * Rather than define all of these routines explicitly, we define
84  * 2 macros "decompose" and "reconstruct" which embody the structure of
85  * the function (which is common to all of them). We then instantiate
86  * these macros once for each of the data types. It's ugly, but it
87  * assures that a change to the structure of one operation type
88  * (decompose or reconstruct) occurs for all data types.
89  *
90  *
91  *
92  *
93  * bn_wlt_haar_1d_*_decompose(tbuffer, buffer, dimen, channels, limit)
94  * @par Parameters:
95  * - tbuffer a temporary data buffer 1/2 as large as "buffer". See (1) below.
96  * - buffer pointer to the data to be decomposed
97  * - dimen the number of samples in the data buffer
98  * - channels the number of values per sample
99  * - limit the extent of the decomposition
100  *
101  * Perform a Haar wavelet decomposition on the data in buffer "buffer". The
102  * decomposition is done "in place" on the data, hence the values in "buffer"
103  * are not preserved, but rather replaced by their decomposition.
104  * The number of original samples in the buffer (parameter "dimen") and the
105  * decomposition limit ("limit") must both be a power of 2 (e.g. 512, 1024).
106  * The buffer is decomposed into "average" and "detail" halves until the
107  * size of the "average" portion reaches "limit". Simultaneous
108  * decomposition of multi-plane (e.g. pixel) data, can be performed by
109  * indicating the number of planes in the "channels" parameter.
110  *
111  * (1) The process requires a temporary buffer which is 1/2 the size of the
112  * longest span to be decomposed. If the "tbuffer" argument is non-null then
113  * it is a pointer to a temporary buffer. If the pointer is NULL, then a
114  * local temporary buffer will be allocated (and freed).
115  *
116  * @par Examples:
117  @code
118  double dbuffer[512], cbuffer[256];
119  ...
120  bn_wlt_haar_1d_double_decompose(cbuffer, dbuffer, 512, 1, 1);
121  @endcode
122  *
123  * performs complete decomposition on the data in array "dbuffer".
124  *
125  @code
126  double buffer[3][512]; /_* 512 samples, 3 values/sample (e.g. RGB?)*_/
127  double tbuffer[3][256]; /_* the temporary buffer *_/
128  ...
129  bn_wlt_haar_1d_double_decompose(tbuffer, buffer, 512, 3, 1);
130  @endcode
131  *
132  * This will completely decompose the data in buffer. The first sample will
133  * be the average of all the samples. Alternatively:
134  *
135  * bn_wlt_haar_1d_double_decompose(tbuffer, buffer, 512, 3, 64);
136  *
137  * decomposes buffer into a 64-sample "average image" and 3 "detail" sets.
138  *
139  * bn_wlt_haar_1d_*_reconstruct(tbuffer, buffer, dimen, channels, sub_sz, limit)
140  *
141  */
142 /** @} */
143 
144 #include "common.h"
145 
146 #include <stdio.h>
147 #include <string.h>
148 
149 #include "vmath.h"
150 #include "bu/log.h"
151 #include "bu/malloc.h"
152 #include "bn/wavelet.h"
153 
154 /**
155  * This source file uses C-style "templates" where functions specific
156  * to a set of specified data types are automatically
157  * declared/provided via one single macro implementation.
158  */
159 #define decompose_1d(DATATYPE) bn_wlt_haar_1d_ ## DATATYPE ## _decompose
160 
161 
162 /*
163  * DATATYPE *tbuffer; // temporary buffer
164  * DATATYPE *buffer; // data buffer
165  * unsigned long dimen; // # of samples in data buffer
166  * unsigned long channels; // # of data values per sample
167  * unsigned long limit; // extent of decomposition
168  */
169 
170 #define make_wlt_haar_1d_decompose(DATATYPE) \
171  void \
172  decompose_1d(DATATYPE) \
173  ( DATATYPE *tbuffer, DATATYPE *buffer, unsigned long dimen, unsigned long channels, unsigned long limit ) \
174  { \
175  register DATATYPE *detail; \
176  register DATATYPE *avg; \
177  unsigned long img_size; \
178  unsigned long half_size; \
179  int do_free = 0; \
180  unsigned long x, x_tmp, d, i, j_idx; \
181  register fastf_t onehalf = (fastf_t)0.5; \
182  \
183  CK_POW_2( dimen ); \
184  \
185  if ( ! tbuffer ) { \
186  tbuffer = (DATATYPE *)bu_malloc( \
187  (dimen/2) * channels * sizeof( *buffer ), \
188  "1d wavelet buffer"); \
189  do_free = 1; \
190  } \
191  \
192  /* each iteration of this loop decomposes the data into 2 halves: \
193  * the "average image" and the "image detail" \
194  */ \
195  for (img_size = dimen; img_size > limit; img_size = half_size ) { \
196  \
197  half_size = img_size/2; \
198  \
199  detail = tbuffer; \
200  avg = buffer; \
201  \
202  for ( x=0; x < img_size; x += 2 ) { \
203  x_tmp = x*channels; \
204  \
205  for (d=0; d < channels; d++, avg++, detail++) { \
206  i = x_tmp + d; \
207  j_idx = i + channels; \
208  *detail = (buffer[i] - buffer[j_idx]) * onehalf; \
209  *avg = (buffer[i] + buffer[j_idx]) * onehalf; \
210  } \
211  } \
212  \
213  /* "avg" now points to the first element AFTER the "average \
214  * image" section, and hence is the START of the "image \
215  * detail" portion. Convenient, since we now want to copy \
216  * the contents of "tbuffer" (which holds the image detail) into \
217  * place. \
218  */ \
219  memcpy(avg, tbuffer, sizeof(*buffer) * channels * half_size); \
220  } \
221  \
222  if (do_free) \
223  bu_free( (void *)tbuffer, "1d wavelet buffer"); \
224  }
225 
226 
227 #define reconstruct(DATATYPE ) bn_wlt_haar_1d_ ## DATATYPE ## _reconstruct
228 
229 #define make_wlt_haar_1d_reconstruct( DATATYPE ) \
230  void \
231  reconstruct(DATATYPE) \
232  ( DATATYPE *tbuffer, DATATYPE *buffer, unsigned long dimen, unsigned long channels, unsigned long subimage_size, unsigned long limit ) \
233  { \
234  register DATATYPE *detail; \
235  register DATATYPE *avg; \
236  unsigned long img_size; \
237  unsigned long dbl_size; \
238  int do_free = 0; \
239  unsigned long x_tmp, d, x, i, j_idx; \
240  \
241  CK_POW_2( subimage_size ); \
242  CK_POW_2( dimen ); \
243  CK_POW_2( limit ); \
244  \
245  if ( ! (subimage_size < dimen) ) { \
246  bu_log("%s:%d Dimension %lu should be greater than subimage size (%lu)\n", \
247  __FILE__, __LINE__, dimen, subimage_size); \
248  bu_bomb("reconstruct"); \
249  } \
250  \
251  if ( ! (subimage_size < limit) ) { \
252  bu_log("%s:%d Channels limit %lu should be greater than subimage size (%lu)\n", \
253  __FILE__, __LINE__, limit, subimage_size); \
254  bu_bomb("reconstruct"); \
255  } \
256  \
257  if ( ! (limit <= dimen) ) { \
258  bu_log("%s:%d Dimension %lu should be greater than or equal to the channels limit (%lu)\n", \
259  __FILE__, __LINE__, dimen, limit); \
260  bu_bomb("reconstruct"); \
261  } \
262  \
263  \
264  if ( ! tbuffer ) { \
265  tbuffer = ( DATATYPE *)bu_malloc((dimen/2) * channels * sizeof( *buffer ), \
266  "1d wavelet reconstruct tmp buffer"); \
267  do_free = 1; \
268  } \
269  \
270  /* Each iteration of this loop reconstructs an image twice as \
271  * large as the original using a "detail image". \
272  */ \
273  for (img_size=subimage_size; img_size < limit; img_size=dbl_size) { \
274  dbl_size = img_size * 2; \
275  \
276  d = img_size * channels; \
277  detail = &buffer[ d ]; \
278  \
279  /* copy the original or "average" data to temporary buffer */ \
280  avg = tbuffer; \
281  memcpy(avg, buffer, sizeof(*buffer) * d); \
282  \
283  \
284  for (x=0; x < dbl_size; x += 2 ) { \
285  x_tmp = x * channels; \
286  for (d=0; d < channels; d++, avg++, detail++ ) { \
287  i = x_tmp + d; \
288  j_idx = i + channels; \
289  buffer[i] = *avg + *detail; \
290  buffer[j_idx] = *avg - *detail; \
291  } \
292  } \
293  } \
294  \
295  if (do_free) \
296  bu_free( (void *)tbuffer, \
297  "1d wavelet reconstruct tmp buffer"); \
298  }
299 
300 /* Believe it or not, this is where the actual code is generated */
301 
304 
307 
310 
313 
316 
319 
320 
321 #define decompose_2d( DATATYPE ) bn_wlt_haar_2d_ ## DATATYPE ## _decompose
322 
323 #define make_wlt_haar_2d_decompose(DATATYPE) \
324  void \
325  decompose_2d(DATATYPE) \
326  (DATATYPE *tbuffer, DATATYPE *buffer, unsigned long dimen, unsigned long channels, unsigned long limit) \
327  { \
328  register DATATYPE *detail; \
329  register DATATYPE *avg; \
330  unsigned long img_size; \
331  unsigned long half_size; \
332  unsigned long x, y, x_tmp, y_tmp, d, i, j_idx; \
333  register fastf_t onehalf = (fastf_t)0.5; \
334  \
335  CK_POW_2( dimen ); \
336  \
337  if ( ! tbuffer ) { \
338  tbuffer = (DATATYPE *)bu_malloc( \
339  (dimen/2) * channels * sizeof( *buffer ), \
340  "1d wavelet buffer"); \
341  } \
342  \
343  /* each iteration of this loop decomposes the data into 4 quarters: \
344  * the "average image", the horizontal detail, the vertical detail \
345  * and the horizontal-vertical detail \
346  */ \
347  for (img_size = dimen; img_size > limit; img_size = half_size ) { \
348  half_size = img_size/2; \
349  \
350  /* do a horizontal detail decomposition first */ \
351  for (y=0; y < img_size; y++ ) { \
352  y_tmp = y * dimen * channels; \
353  \
354  detail = tbuffer; \
355  avg = &buffer[y_tmp]; \
356  \
357  for (x=0; x < img_size; x += 2 ) { \
358  x_tmp = x*channels + y_tmp; \
359  \
360  for (d=0; d < channels; d++, avg++, detail++) { \
361  i = x_tmp + d; \
362  j_idx = i + channels; \
363  *detail = (buffer[i] - buffer[j_idx]) * onehalf; \
364  *avg = (buffer[i] + buffer[j_idx]) * onehalf; \
365  } \
366  } \
367  /* "avg" now points to the first element AFTER the \
368  * "average image" section, and hence is the START \
369  * of the "image detail" portion. Convenient, since \
370  * we now want to copy the contents of "tbuffer" (which \
371  * holds the image detail) into place. \
372  */ \
373  memcpy(avg, tbuffer, sizeof(*buffer) * channels * half_size); \
374  } \
375  \
376  /* Now do the vertical decomposition */ \
377  for (x=0; x < img_size; x ++ ) { \
378  x_tmp = x*channels; \
379  \
380  detail = tbuffer; \
381  avg = &buffer[x_tmp]; \
382  \
383  for (y=0; y < img_size; y += 2) { \
384  y_tmp =y*dimen*channels + x_tmp; \
385  \
386  for (d=0; d < channels; d++, avg++, detail++) { \
387  i = y_tmp + d; \
388  j_idx = i + dimen*channels; \
389  *detail = (buffer[i] - buffer[j_idx]) * onehalf; \
390  *avg = (buffer[i] + buffer[j_idx]) * onehalf; \
391  } \
392  avg += (dimen-1)*channels; \
393  } \
394  \
395  /* "avg" now points to the element ABOVE the \
396  * last "average image" pixel or the first "detail" \
397  * location in the user buffer. \
398  * \
399  * There is no memcpy for the columns, so we have to \
400  * copy the data back to the user buffer ourselves. \
401  */ \
402  detail = tbuffer; \
403  for (y=half_size; y < img_size; y++) { \
404  for (d=0; d < channels; d++) { \
405  *avg++ = *detail++; \
406  } \
407  avg += (dimen-1)*channels; \
408  } \
409  } \
410  } \
411  }
412 
413 
414 #define reconstruct_2d( DATATYPE ) bn_wlt_haar_2d_ ## DATATYPE ## _reconstruct
415 
416 #define make_wlt_haar_2d_reconstruct(DATATYPE) \
417  void \
418  reconstruct_2d(DATATYPE) \
419  (DATATYPE *tbuf, DATATYPE *buf, unsigned long width, unsigned long channels, unsigned long avg_size, unsigned long limit) \
420  { \
421  register DATATYPE *detail; \
422  register DATATYPE *avg; \
423  unsigned long img_size; \
424  unsigned long dbl_size; \
425  unsigned long x_tmp, d, x, i, j_idx; \
426  unsigned long y, row_len, row_start; \
427  \
428  CK_POW_2( avg_size ); \
429  CK_POW_2( width ); \
430  CK_POW_2( limit ); \
431  \
432  /* XXX check for: \
433  * subimage_size < dimen && subimage_size < limit \
434  * limit <= dimen \
435  */ \
436  \
437  \
438  if ( ! tbuf ) { \
439  tbuf = ( DATATYPE *)bu_malloc((width/2) * channels * sizeof( *buf ), \
440  "1d wavelet reconstruct tmp buffer"); \
441  } \
442  \
443  row_len = width * channels; \
444  \
445  /* Each iteration of this loop reconstructs an image twice as \
446  * large as the original using a "detail image". \
447  */ \
448  \
449  for (img_size = avg_size; img_size < limit; img_size = dbl_size) { \
450  dbl_size = img_size * 2; \
451  \
452  \
453  /* first is a vertical reconstruction */ \
454  for (x=0; x < dbl_size; x++ ) { \
455  /* reconstruct column x */ \
456  \
457  /* copy column of "average" data to tbuf */ \
458  x_tmp = x*channels; \
459  for (y=0; y < img_size; y++) { \
460  i = x_tmp + y*row_len; \
461  j_idx = y * channels; \
462  for (d=0; d < channels; d++) { \
463  tbuf[j_idx++] = buf[i++]; \
464  } \
465  } \
466  avg = tbuf; \
467  detail = &buf[x_tmp + img_size*row_len]; \
468  \
469  /* reconstruct column */ \
470  for (y=0; y < dbl_size; y += 2) { \
471  \
472  i = x_tmp + y*row_len; \
473  j_idx = i + row_len; \
474  \
475  for (d=0; d < channels; d++, avg++, detail++) { \
476  buf[i++] = *avg + *detail; \
477  buf[j_idx++] = *avg - *detail; \
478  } \
479  detail += row_len - channels; \
480  } \
481  } \
482  \
483  /* now a horizontal reconstruction */ \
484  for (y=0; y < dbl_size; y++ ) { \
485  /* reconstruct row y */ \
486  \
487  /* copy "average" row to tbuf and set pointer to \
488  * beginning of "detail" \
489  */ \
490  d = img_size * channels; \
491  row_start = y*row_len; \
492  \
493  \
494  avg = &buf[ row_start ]; \
495  detail = &buf[ row_start + d]; \
496  \
497  memcpy(tbuf, avg, sizeof(*buf) * d); \
498  avg = tbuf; \
499  \
500  /* reconstruct row */ \
501  for (x=0; x < dbl_size; x += 2 ) { \
502  x_tmp = x * channels; \
503  i = row_start + x * channels; \
504  j_idx = i + channels; \
505  \
506  for (d=0; d < channels; d++, avg++, detail++) { \
507  buf[i++] = *avg + *detail; \
508  buf[j_idx++] = *avg - *detail; \
509  } \
510  } \
511  } \
512  } \
513  }
514 
521 
528 
529 
530 #define decompose_2d_2( DATATYPE ) bn_wlt_haar_2d_ ## DATATYPE ## _decompose2
531 
532 #define make_wlt_haar_2d_decompose2(DATATYPE) \
533  void \
534  decompose_2d_2(DATATYPE) \
535  (DATATYPE *tbuffer, DATATYPE *buffer, unsigned long width, unsigned long height, unsigned long channels, unsigned long limit) \
536  { \
537  register DATATYPE *detail; \
538  register DATATYPE *avg; \
539  unsigned long img_wsize; \
540  unsigned long img_hsize; \
541  unsigned long half_wsize; \
542  unsigned long half_hsize; \
543  unsigned long x, y, x_tmp, y_tmp, d, i, j_idx; \
544  register fastf_t onehalf = (fastf_t)0.5; \
545  \
546  CK_POW_2( width ); \
547  CK_POW_2( height ); \
548  \
549  /* create a temp buffer the half the size of the larger dimension \
550  */ \
551  if ( ! tbuffer ) { \
552  tbuffer = (DATATYPE *)bu_malloc( \
553  (((width>height)?width:height)/2) * channels * sizeof( *buffer ), \
554  "1d wavelet buffer"); \
555  } \
556  \
557  /* each iteration of this loop decomposes the data into 4 quarters: \
558  * the "average image", the horizontal detail, the vertical detail \
559  * and the horizontal-vertical detail \
560  */ \
561  for (img_wsize = width, img_hsize = height; (img_wsize > limit) && (img_hsize > limit); img_wsize = half_wsize, img_hsize = half_hsize ) { \
562  half_wsize = img_wsize/2; \
563  half_hsize = img_hsize/2; \
564  \
565  /* do a horizontal detail decomposition first */ \
566  for (y=0; y < img_hsize; y++ ) { \
567  y_tmp = y * width * channels; \
568  \
569  detail = tbuffer; \
570  avg = &buffer[y_tmp]; \
571  \
572  for (x=0; x < img_wsize; x += 2 ) { \
573  x_tmp = x*channels + y_tmp; \
574  \
575  for (d=0; d < channels; d++, avg++, detail++) { \
576  i = x_tmp + d; \
577  j_idx = i + channels; \
578  *detail = (buffer[i] - buffer[j_idx]) * onehalf; \
579  *avg = (buffer[i] + buffer[j_idx]) * onehalf; \
580  } \
581  } \
582  /* "avg" now points to the first element AFTER the \
583  * "average image" section, and hence is the START \
584  * of the "image detail" portion. Convenient, since \
585  * we now want to copy the contents of "tbuffer" (which \
586  * holds the image detail) into place. \
587  */ \
588  memcpy(avg, tbuffer, sizeof(*buffer) * channels * half_wsize); \
589  } \
590  \
591  /* Now do the vertical decomposition */ \
592  for (x=0; x < img_wsize; x ++ ) { \
593  x_tmp = x*channels; \
594  \
595  detail = tbuffer; \
596  avg = &buffer[x_tmp]; \
597  \
598  for (y=0; y < img_hsize; y += 2) { \
599  y_tmp =y*width*channels + x_tmp; \
600  \
601  for (d=0; d < channels; d++, avg++, detail++) { \
602  i = y_tmp + d; \
603  j_idx = i + width*channels; \
604  *detail = (buffer[i] - buffer[j_idx]) * onehalf; \
605  *avg = (buffer[i] + buffer[j_idx]) * onehalf; \
606  } \
607  avg += (width-1)*channels; \
608  } \
609  \
610  /* "avg" now points to the element ABOVE the \
611  * last "average image" pixel or the first "detail" \
612  * location in the user buffer. \
613  * \
614  * There is no memcpy for the columns, so we have to \
615  * copy the data back to the user buffer ourselves. \
616  */ \
617  detail = tbuffer; \
618  for (y=half_hsize; y < img_hsize; y++) { \
619  for (d=0; d < channels; d++) { \
620  *avg++ = *detail++; \
621  } \
622  avg += (width-1)*channels; \
623  } \
624  } \
625  } \
626  }
627 
634 
635 
636 /*
637  * Local Variables:
638  * mode: C
639  * tab-width: 8
640  * indent-tabs-mode: t
641  * c-file-style: "stroustrup"
642  * End:
643  * ex: shiftwidth=4 tabstop=8
644  */
Header file for the BRL-CAD common definitions.
#define make_wlt_haar_1d_reconstruct(DATATYPE)
Definition: wavelet.c:229
#define make_wlt_haar_2d_reconstruct(DATATYPE)
#define make_wlt_haar_1d_decompose(DATATYPE)
Definition: wavelet.c:170
#define make_wlt_haar_2d_decompose(DATATYPE)
#define make_wlt_haar_2d_decompose2(DATATYPE)