Example #1
0
int d_idwt(double coeffs_a[], int coeffs_a_len, double coeffs_d[], int coeffs_d_len, Wavelet* wavelet, double output[],
		 int output_len, int mode, int correct_size)
{
	int input_len;
	
	if(coeffs_a != NULL && coeffs_d != NULL){
		if(correct_size){
			if( (coeffs_a_len > coeffs_d_len ? coeffs_a_len - coeffs_d_len : coeffs_d_len-coeffs_a_len) > 1) 
			{ 	
//				goto errorIDWT;
                                exit(0);
			}
			input_len = coeffs_a_len>coeffs_d_len? coeffs_d_len : coeffs_a_len; // min
		} else {
			if(coeffs_a_len != coeffs_d_len) {
//				goto errorIDWT;
                                exit(0);
			}
			input_len = coeffs_a_len;
		}
	} else if(coeffs_a != NULL){
		input_len  = coeffs_a_len;
	} else if (coeffs_d != NULL){
		input_len = coeffs_d_len;
	} else {
//		goto errorIDWT;
                exit(0);
	}
	
	int supposed_len = idwt_buffer_length(input_len, wavelet->rec_len, mode);
		
	if(output_len != supposed_len) {
		goto errorIDWT;
	}
	memset(output, 0, output_len * sizeof(double));

	if(coeffs_a){
		if(upsampling_convolution_valid_sf(coeffs_a, input_len, wavelet->synthesisLow->coeff, wavelet->rec_len, output, output_len, mode) < 0) {
			goto errorIDWT;
		}
	}
	// +=
	if(coeffs_d){
		if(upsampling_convolution_valid_sf(coeffs_d, input_len, wavelet->synthesisHigh->coeff, wavelet->rec_len, output, output_len, mode) < 0) {
			goto errorIDWT;
		}
	}	
	
	return 0;

errorIDWT:
//	cout << "Invalid input size for output array. This is  " <<
//	    	    "unrecoverable and should not have happened " << endl;
    exit(0);

}
Example #2
0
File: wt.c Project: booherbg/pywt
// IDWT reconstruction from aproximation and detail coeffs
//
// If fix_size_diff is 1 then coeffs arrays can differ by one in length (this
// is useful in multilevel decompositions and reconstructions of odd-length signals)
// Requires zoer-filled output buffer
int double_idwt(double coeffs_a[], index_t coeffs_a_len,
                 double coeffs_d[], index_t coeffs_d_len,
                 Wavelet* wavelet,
                 double output[], index_t output_len,
                 MODE mode, int fix_size_diff){

    int input_len;
    
    // If one of coeffs array is NULL then the reconstruction will be performed
    // using the other one

    if(coeffs_a != NULL && coeffs_d != NULL){

        if(fix_size_diff){
            if( (coeffs_a_len > coeffs_d_len ? coeffs_a_len - coeffs_d_len
                                             : coeffs_d_len-coeffs_a_len) > 1){ // abs(a-b)
                goto error;
            }

            input_len = coeffs_a_len>coeffs_d_len ? coeffs_d_len
                                                  : coeffs_a_len; // min
        } else {
            if(coeffs_a_len != coeffs_d_len)
                goto error;

            input_len = coeffs_a_len;
        }

    } else if(coeffs_a != NULL){
        input_len  = coeffs_a_len;

    } else if (coeffs_d != NULL){
        input_len = coeffs_d_len;

    } else {
        goto error;
    }
    
    // check output size
    if(output_len != idwt_buffer_length(input_len, wavelet->rec_len, mode))
        goto error;

    // // set output to zero (this can be ommited if output array is already cleared)
    // memset(output, 0, output_len * sizeof(double));

    // reconstruct approximation coeffs with lowpass reconstruction filter
    if(coeffs_a){
        if(double_upsampling_convolution_valid_sf(coeffs_a, input_len, wavelet->rec_lo_double,
                                wavelet->rec_len, output, output_len, mode) < 0){
            goto error;
        }
    }
    // and add reconstruction of details coeffs performed with highpass reconstruction filter
    if(coeffs_d){
        if(double_upsampling_convolution_valid_sf(coeffs_d, input_len, wavelet->rec_hi_double,
                                wavelet->rec_len, output, output_len, mode) < 0){
            goto error;
        }
    }

    return 0;

    error:
        return -1;
}
Example #3
0
int $DTYPE$_upsampling_convolution_valid_sf_periodization(const $DTYPE$* input, const_index_t N,
                                    const $DTYPE$* filter, const_index_t F,
                                    $DTYPE$* output, const_index_t O)
{

    $DTYPE$ *ptr_out = output;
    $DTYPE$ *filter_even, *filter_odd;
    $DTYPE$ *periodization_buf = NULL;
    $DTYPE$ *periodization_buf_rear = NULL;
    $DTYPE$ *ptr_base;
    $DTYPE$ sum_even, sum_odd;
    index_t i, j, k, N_p = 0;
    index_t F_2 = F/2;

    if(F%2) return -3; // Filter must have even-length.

    ///////////////////////////////////////////////////////////////////////////
    // Handle special situation when input coeff data is shorter than half of
    // the filter's length. The coeff array has to be extended periodically.
    // This can be only valid for PERIODIZATION_MODE

    if(N < F_2)
    // =======
    {
        // Input data for periodization mode has to be periodically extended

        // New length for temporary input
        N_p = F_2-1 +N;

        // periodization_buf will hold periodically copied input coeffs values
        periodization_buf = wtcalloc(N_p, sizeof($DTYPE$));

        if(periodization_buf == NULL)
            return -1;

        // Copy input data to it's place in the periodization_buf
        // -> [0 0 0 i1 i2 i3 0 0 0]
        k = (F_2-1)/2;
        for(i=k; i < k+N; ++i)
            periodization_buf[i] = input[(i-k)%N];

        //if(N%2)
        //    periodization_buf[i++] = input[N-1];

        // [0 0 0 i1 i2 i3 0 0 0]
        //  points here ^^
        periodization_buf_rear = periodization_buf+i-1;

        // copy cyclically () to right
        // [0 0 0 i1 i2 i3 i1 i2 ...]
        j = i-k;
        for(; i < N_p; ++i)
            periodization_buf[i] = periodization_buf[i-j];

        // copy cyclically () to left
        // [... i2 i3 i1 i2 i3 i1 i2 i3]
        j = 0;
        for(i=k-1; i >= 0; --i){
            periodization_buf[i] = periodization_buf_rear[j];
            --j;
        }

        // Now perform the valid convolution
        if(F_2%2){
            $DTYPE$_upsampling_convolution_valid_sf(periodization_buf, N_p, filter, F, output, O, MODE_ZEROPAD);

        // The F_2%2==0 case needs special result fix (oh my, another one..)
        } else {

            // Cheap result fix for short inputs
            // Memory allocation for temporary output is done.
            // Computed temporary result is copied to output*

            ptr_out = wtcalloc(idwt_buffer_length(N, F, MODE_PERIODIZATION), sizeof($DTYPE$));
            if(ptr_out == NULL){
                wtfree(periodization_buf);
                return -1;
            }

            // Convolve here as for (F_2%2) branch above
            $DTYPE$_upsampling_convolution_valid_sf(periodization_buf, N_p, filter, F, ptr_out, O, MODE_ZEROPAD);

            // rewrite result to output
            for(i=2*N-1; i > 0; --i){
                output[i] += ptr_out[i-1];
            }
            // and the first element
            output[0] += ptr_out[2*N-1];
            wtfree(ptr_out);
            // and voil`a!, ugh
        }

    } else {
    // Otherwise (N >= F_2)

        // Allocate memory for even and odd elements of the filter
        filter_even = wtmalloc(F_2 * sizeof($DTYPE$));
        filter_odd = wtmalloc(F_2 * sizeof($DTYPE$));

        if(filter_odd == NULL || filter_odd == NULL){
            if(filter_odd == NULL) wtfree(filter_odd);
            if(filter_even == NULL) wtfree(filter_even);
            return -1;
        }

        // split filter to even and odd values
        for(i = 0; i < F_2; ++i){
            filter_even[i] = filter[i << 1];
            filter_odd[i] = filter[(i << 1) + 1];
        }

        ///////////////////////////////////////////////////////////////////////////
        // This part is quite complicated and has some wild checking to get results
        // similar to those from Matlab(TM) Wavelet Toolbox

        k = F_2-1;

        // Check if extending is really needed
        N_p = F_2-1 + (index_t) ceil(k/2.); /*split filter len correct. +  extra samples*/

        // ok, if is then do:
        // 1. Allocate buffers for front and rear parts of extended input
        // 2. Copy periodically appriopriate elements from input to the buffers
        // 3. Convolve front buffer, input and rear buffer with even and odd
        //    elements of the filter (this results in upsampling)
        // 4. Free memory

        if(N_p > 0){
        // =======

            // Allocate memory only for the front and rear extension parts, not the
            // whole input
            periodization_buf = wtcalloc(N_p, sizeof($DTYPE$));
            periodization_buf_rear = wtcalloc(N_p, sizeof($DTYPE$));

            // Memory checking
            if(periodization_buf == NULL || periodization_buf_rear == NULL){
                if(periodization_buf == NULL) wtfree(periodization_buf);
                if(periodization_buf_rear == NULL) wtfree(periodization_buf_rear);
                wtfree(filter_odd);
                wtfree(filter_even);
                return -1;
            }

            // Fill buffers with appriopriate elements
            memcpy(periodization_buf + N_p - k, input, k * sizeof($DTYPE$));        // copy from beginning of input to end of buffer
            for(i = 1; i <= (N_p - k); ++i)                                        // kopiowanie 'cykliczne' od końca input
                periodization_buf[(N_p - k) - i] = input[N - (i%N)];

            memcpy(periodization_buf_rear, input + N - k, k * sizeof($DTYPE$));    // copy from end of input to begginning of buffer
            for(i = 0; i < (N_p - k); ++i)                                        // kopiowanie 'cykliczne' od początku input
                periodization_buf_rear[k + i] = input[i%N];

            ///////////////////////////////////////////////////////////////////
            // Convolve filters with the (front) periodization_buf and compute
            // the first part of output

            ptr_base = periodization_buf + F_2 - 1;

            if(k%2 == 1){
                sum_odd = 0;

                for(j = 0; j < F_2; ++j)
                    sum_odd += filter_odd[j] * ptr_base[-j];
                *(ptr_out++) += sum_odd;

                --k;
                if(k)
                    $DTYPE$_upsampling_convolution_valid_sf(periodization_buf + 1, N_p-1, filter, F, ptr_out, O-1, MODE_ZEROPAD);

                ptr_out += k; // k0 - 1 // really move backward by 1

            } else if(k){
                $DTYPE$_upsampling_convolution_valid_sf(periodization_buf, N_p, filter, F, ptr_out, O, MODE_ZEROPAD);
                ptr_out += k;
            }
        }

        ///////////////////////////////////////////////////////////////////////////
        // Perform _valid_ convolution (only when all filter_even and filter_odd elements
        // are in range of input data).
        //
        // This part is simple, no extra hacks, just two convolutions in one loop

        ptr_base = ($DTYPE$*)input + F_2 - 1;
        for(i = 0; i < N-(F_2-1); ++i){    // sliding over signal from left to right

            sum_even = 0;
            sum_odd = 0;

            for(j = 0; j < F_2; ++j){
                sum_even += filter_even[j] * ptr_base[i-j];
                sum_odd += filter_odd[j] * ptr_base[i-j];
            }

            *(ptr_out++) += sum_even;
            *(ptr_out++) += sum_odd;
        }
        //
        ///////////////////////////////////////////////////////////////////////////

        if(N_p > 0){
        // =======

            k = F_2-1;
            if(k%2 == 1){
                if(F/2 <= N_p - 1){ // k > 1 ?
                    $DTYPE$_upsampling_convolution_valid_sf(periodization_buf_rear , N_p-1, filter, F, ptr_out, O-1, MODE_ZEROPAD);
                }

                ptr_out += k; // move forward anyway -> see lower

                if(F_2%2 == 0){ // remaining one element
                    ptr_base = periodization_buf_rear + N_p - 1;

                    sum_even = 0;
                    for(j = 0; j < F_2; ++j){
                        sum_even += filter_even[j] * ptr_base[-j];
                    }
                    *(--ptr_out) += sum_even; // move backward first
                }
            } else {
                if(k){
                    $DTYPE$_upsampling_convolution_valid_sf(periodization_buf_rear, N_p, filter, F, ptr_out, O, MODE_ZEROPAD);
                }
            }
        }
        if(periodization_buf != NULL) wtfree(periodization_buf);
        if(periodization_buf_rear != NULL) wtfree(periodization_buf_rear);

        wtfree(filter_even);
        wtfree(filter_odd);

    }
    return 0;
}
int upsampling_convolution_valid_sf(const DTYPE* input, const int N, const double* filter, const int F, double* output, const int O, const int mode){
	double *ptr_out = output;
	double *filter_even, *filter_odd;
	DTYPE *periodization_buf = NULL, *periodization_buf_rear = NULL;
	DTYPE *ptr_base;
	double sum_even, sum_odd;
	int i, j, k, N_p = 0;
	int F_2 = F/2;	// F/2

	if(F%2) return -3;

	if(F_2 > N){
		if(mode == MODE_PERIODIZATION){
			N_p = F_2-1 +N;
			periodization_buf = (double*) wtcalloc(N_p, sizeof(DTYPE));
			k = (F_2-1)/2;

			for(i=k; i < k+N; ++i)
				periodization_buf[i] = input[(i-k)%N];
			//if(N%2)
			//	periodization_buf[i++] = input[N-1];
			periodization_buf_rear = periodization_buf+i-1;

			j = i-k;
			for(; i < N_p; ++i)
				periodization_buf[i] = periodization_buf[i-j];

			j = 0;
			for(i=k-1; i >= 0; --i){
				periodization_buf[i] = periodization_buf_rear[j];
				--j;
			}
			
			if(F_2%2==0){
				// cheap result fix
				ptr_out = (double*) wtcalloc(idwt_buffer_length(N, F, MODE_PERIODIZATION), sizeof(double));
				if(ptr_out == NULL)
					return -3;

				upsampling_convolution_valid_sf(periodization_buf, N_p, filter, F, ptr_out, O, MODE_ZEROPAD);

				for(i=2*N-1; i > 0; --i){
					output[i] += ptr_out[i-1];
				}
				output[0] += ptr_out[2*N-1];
				wtfree(ptr_out);
			} else {
				upsampling_convolution_valid_sf(periodization_buf, N_p, filter, F, output, O, MODE_ZEROPAD);
			}
			return 0;
		} else {
			return -2;	// invalid lengths
		}
	}

	// allocate memory for even and odd elements of filter
	filter_even = (double*) malloc(F_2 * sizeof(double));
	filter_odd = (double*) malloc(F_2 * sizeof(double));

	if(filter_odd == NULL || filter_odd == NULL){
		return -1;
	}

	// copy values
	for(i = 0; i < F_2; ++i){
		filter_even[i] = filter[i << 1];
		filter_odd[i] = filter[(i << 1) + 1];
	}

	///////////////////////////////////////////////////////////////////////////
	// MODE_PERIODIZATION 
	// this part is quite complicated

		if(mode == MODE_PERIODIZATION){

			k = F_2-1;

			N_p = F_2-1 + (int) ceil(k/2.); /*split filter len correct. +  extra samples*/
			
			if(N_p > 0){
				periodization_buf = (double*) calloc(N_p, sizeof(double));
				periodization_buf_rear = (double*) calloc(N_p, sizeof(double));
			
				if(k <= N){
					memcpy(periodization_buf + N_p - k, input, k * sizeof(double));		// copy from beginning of input to end of buffer
					for(i = 1; i <= (N_p - k); ++i)										// kopiowanie 'cykliczne' od koñca input 
						periodization_buf[(N_p - k) - i] = input[N - (i%N)];
					memcpy(periodization_buf_rear, input + N - k, k * sizeof(double));	// copy from end of input to begginning of buffer
					for(i = 0; i < (N_p - k); ++i)										// kopiowanie 'cykliczne' od pocz¹tku input
						periodization_buf_rear[k + i] = input[i%N];
				} else {
					//printf("see %d line in %s!!\n", __LINE__, __FILE__);
					// TODO: is this ever called? if yes check for errors
					for(i = 0; i < k; ++i)
						periodization_buf[(N_p - k) + i] = input[i % N];
					for(i = 1; i < (N_p - k); ++i)
						periodization_buf[(N_p - k) - i] = input[N - (i%N)];

					//for(i = 0; i < N_p; ++i)
					//	printf("%f ", periodization_buf[i]);
					//printf("--\n");
					//for(i = 0; i < N_p; ++i)
					//	printf("%f ", periodization_buf_rear[i]);
					//printf("\n");
				}

				ptr_base = periodization_buf + F_2 - 1;
				if(k%2 == 1){
					sum_odd = 0;
					for(j = 0; j < F_2; ++j)
						sum_odd += filter_odd[j] * ptr_base[-j];
					*(ptr_out++) += sum_odd;
					--k;
					if(k)
						upsampling_convolution_valid_sf(periodization_buf + 1, N_p-1, filter, F, ptr_out, O-1, MODE_ZEROPAD);
					ptr_out += k; // k0 - 1 // really move backward by 1
				} else if(k){
					upsampling_convolution_valid_sf(periodization_buf, N_p, filter, F, ptr_out, O, MODE_ZEROPAD);
					ptr_out += k;
				}
			}
		}
	// MODE_PERIODIZATION
	///////////////////////////////////////////////////////////////////////////

	///////////////////////////////////////////////////////////////////////////
	// perform _valid_ convolution (only when all filter_even and filter_odd elements are in range of input data)
	// this part is quite simple, no extra hacks
		ptr_base = (DTYPE*)input + F_2 - 1;
		for(i = 0; i < N-(F_2-1); ++i){	// sliding over signal from left to right
			
			sum_even = 0;
			sum_odd = 0;
			// iterate filters elements
			for(j = 0; j < F_2; ++j){
				sum_even += filter_even[j] * ptr_base[i-j];
				sum_odd += filter_odd[j] * ptr_base[i-j];
			}

			*(ptr_out++) += sum_even; 
			*(ptr_out++) += sum_odd;
		}
	//
	///////////////////////////////////////////////////////////////////////////

	///////////////////////////////////////////////////////////////////////////
	// MODE_PERIODIZATION
		if(mode == MODE_PERIODIZATION){
			if(N_p>0){
				k = F_2-1;
				if(k%2 == 1){
					if(F/2 <= N_p - 1) // k > 1 ?
						upsampling_convolution_valid_sf(periodization_buf_rear , N_p-1, filter, F, ptr_out, O-1, MODE_ZEROPAD);
					ptr_out += k; // move forward anyway -> see lower

					if(F_2%2 == 0){ // remaining one element
						ptr_base = periodization_buf_rear + N_p - 1;
						sum_even = 0;
						for(j = 0; j < F_2; ++j)
							sum_even += filter_even[j] * ptr_base[-j];
						*(--ptr_out) += sum_even; // move backward first
					}
				} else {
					if(k)
						upsampling_convolution_valid_sf(periodization_buf_rear, N_p, filter, F, ptr_out, O, MODE_ZEROPAD);
				}
			}
			if(periodization_buf != NULL) wtfree(periodization_buf);
			if(periodization_buf_rear != NULL) wtfree(periodization_buf_rear);
		}
	// MODE_PERIODIZATION
	///////////////////////////////////////////////////////////////////////////

	wtfree(filter_even);
	wtfree(filter_odd);
	return 0;
}