0

The following code is for 2D Wavelet Decomposition:

wfb2dec.cpp

#include "global.h"
#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>

void MatConCat(imgpel **, imgpel **, imgpel **, imgpel **, imgpel **, int, int);
void BorderWrap(imgpel **, imgpel **, int, int, int, int);
void Conv2D(imgpel **, imgpel **, double *, char *, int, int, int, int);
void VSubSample(imgpel **, imgpel **, int, int);
void HSubSample(imgpel **, imgpel **, int, int);

int wfb2dec(double *h, double *g, int m, int n, imgpel **frameI_dwt, int lvl)
{
    // h is the Low Pass analysis filter;
    int len_h0 = (int)h[0]; //sizeof(h) / sizeof(double);
    int ext_h0 = (int)floor(len_h0 / 2);

    double *h0 = (double *) malloc(len_h0 * sizeof(double));
    memcpy(h0, &h[1], len_h0 * sizeof(double));

    // h1 is the High Pass analysis filter; (needs to be derived from g);
    int len_h1 = (int)g[0];
    int c = (int)floor((len_h1 + 1) / 2);

    if ((len_h1 % 2) == 0)
        c += 1;
    int ext_h1 = len_h1 - c + 1;

    double *h1 = (double *) malloc(len_h1 * sizeof(double));
    memcpy(h1, g + 1, len_h1 * sizeof(double));
    //h1 = g;
    analysis_hpf(h1, h1, len_h1, c);

    imgpel **x = frameI_dwt;
    //Wavelet Decomposition:-
    for (int i = 0; i < lvl; i++)
    {
        int m1 = (int)(m / pow(2,i));
        int n1 = (int)(n / pow(2,i));

        //Row-wise filtering:-
        imgpel **x_L = (imgpel **) malloc((m1*n1) * sizeof(imgpel));
        imgpel **x_H = (imgpel **) malloc((m1*n1) * sizeof(imgpel));
        imgpel **x_Ls = (imgpel **)malloc((m1*n1/2) * sizeof(imgpel));
        imgpel **x_Hs = (imgpel **)malloc((m1*n1/2) * sizeof(imgpel));

        x_L = rowfiltering(x, h0, ext_h0, len_h0, m1, n1);
        VSubSample(x_L, x_Ls, m1, n1);

        x_H = rowfiltering(x, h1, ext_h1, len_h1, m1, n1);
        VSubSample(x_H, x_Hs, m1, n1);

        free(x_L); free(x_H);

        //Column-wise filtering:-
        imgpel **x_LL = (imgpel **) malloc((m1*n1 / 2) * sizeof(imgpel));
        imgpel **x_LH = (imgpel **) malloc((m1*n1 / 2) * sizeof(imgpel));
        imgpel **x_HL = (imgpel **) malloc((m1*n1 / 2) * sizeof(imgpel));
        imgpel **x_HH = (imgpel **) malloc((m1*n1 / 2) * sizeof(imgpel));

        imgpel **x_LLs = (imgpel **)malloc((m1*n1 / 4) * sizeof(imgpel));
        imgpel **x_LHs = (imgpel **)malloc((m1*n1 / 4) * sizeof(imgpel));
        imgpel **x_HLs = (imgpel **)malloc((m1*n1 / 4) * sizeof(imgpel));
        imgpel **x_HHs = (imgpel **)malloc((m1*n1 / 4) * sizeof(imgpel));

        imgpel **x_L_tr = (imgpel **)malloc((m1*n1 / 2) * sizeof(imgpel));
        cvTranspose(x_Ls, x_L_tr);
        free(x_Ls);

        imgpel **x_H_tr = (imgpel **)malloc((m1*n1 / 2) * sizeof(imgpel));
        cvTranspose(x_Hs, x_H_tr);
        free(x_Hs);

        x_LL = rowfiltering(x_L_tr, h0, ext_h0, len_h0, m1, n1/2);
        HSubSample(x_LL, x_LLs, m1, n1 / 2);
        x_LH = rowfiltering(x_L_tr, h1, ext_h1, len_h1, m1, n1/2);
        HSubSample(x_LH, x_LHs, m1, n1 / 2);
        x_HL = rowfiltering(x_H_tr, h0, ext_h0, len_h0, m1, n1/2);
        HSubSample(x_HL, x_HLs, m1, n1 / 2);
        x_HH = rowfiltering(x_H_tr, h1, ext_h1, len_h1, m1, n1/2);
        HSubSample(x_HH, x_HHs, m1, n1 / 2);
        free(x_L_tr); free(x_H_tr);
        free(x_LL); free(x_LH); free(x_HL); free(x_HH);

        MatConCat(x_LLs, x_LHs, x_HLs, x_HHs, x, m1, n1);

        x = (imgpel **) realloc(x, (m1 / 2) * (n1 / 2) * sizeof(imgpel));
        x = x_LLs;

        free(x_LLs); free(x_LHs); free(x_HLs); free(x_HHs);


    }

    return 1;
}

void analysis_hpf(double *h1, double *g, int len_h1, int c)
{
    for (int i = 0; i < len_h1; i++)
    {
        h1[i] = -1 * g[i] * pow(-1, i - c + 1);
    }
}


imgpel ** rowfiltering(imgpel **x, double *f, int ext, int len, int m1, int n1)
{
    int ext2 = len - ext - 1;

    imgpel **x_Bor;
    int memory_size = get_mem2Dpel(&x_Bor, m1, n1 + ext + ext2);
    //x = [x(:, end-ext1+1:end) x x(:, 1:ext2)];
    BorderWrap(x, x_Bor, m1, n1, ext, ext2);

    //cv::Mat A = cv::Mat(m1, n1, CV_16U, x);
    //cv::Mat Apad = cv::Mat(m1, n1 + ext + ext2, CV_16U, x_Bor);
    //cv::copyMakeBorder(A, Apad, 0, 0, ext, ext2, CV_HAL_BORDER_WRAP);

    //y = conv2(x, f, 'valid');

    //imgpel **y = (imgpel **)malloc(m1*n1 * sizeof(imgpel));
    imgpel **y;
    memory_size = get_mem2Dpel(&y, m1, n1 + ext + ext2);
    Conv2D(x_Bor, y, f, (char *)"valid", m1, n1, ext, len);

    return y;
}

void VSubSample(imgpel **x, imgpel **xs, int m1, int n1)
{
    for (int i = 0; i < m1; i++)
    {
        for (int j = 0; j < n1; j += 2)
        {
            xs[i][j / 2] = x[i][j];
        }
    }
}

void HSubSample(imgpel **x, imgpel **xs, int m1, int n1)
{
    for (int i = 0; i < n1; i++)
    {
        for (int j = 0; j < m1; j += 2)
        {
            xs[j / 2][i] = x[j][i];
        }
    }
}

void MatConCat(imgpel **x_LL, imgpel **x_LH, imgpel **x_HL, imgpel **x_HH, imgpel **x, int m1, int n1)
{
    //memcpy(x, x_LL, (m1*n1 / 4) * sizeof(imgpel));
    for (int i = 0; i < m1/2; i++)
    {
        for (int j = 0; j < n1/2; j++)
        {
            x[i][j] = x_LL[i][j];
        }
    }
    //memcpy(((frameI_dwt + 0) + n1 / 2), x_LH, (m1*n1 / 4) * sizeof(imgpel));
    for (int i = 0; i < m1/2; i++)
    {
        for (int j = (n1/2)+1; i < n1; j++)
        {
            x[i][j] = x_LH[i][j - (n1 / 2) - 1];
        }
    }
    //memcpy(((frameI_dwt + m1 / 2) + 0), x_HL, (m1*n1 / 4) * sizeof(imgpel));
    for (int i = (m1/2)+1; i < m1; i++)
    {
        for (int j = 0; j < n1/2;j++)
        {
            x[i][j] = x_HL[i - (m1 / 2) - 1][j];
        }

    }
    //memcpy(((frameI_dwt + m1 / 2) + n1 / 2), x_HH, (m1*n1 / 4) * sizeof(imgpel));
    for (int i = (m1/2)+1; i < m1; i++)
    {
        for (int j = (n1/2)+1; j < n1; j++)
        {
            x[i][j] = x_HH[i - (m1 / 2) - 1][j - (n1 / 2) - 1];
        }

    }
}

void BorderWrap(imgpel **x, imgpel **x_Bor, int m1, int n1, int ext, int ext2)
{
    for (int i = ext; i > 0; i--)
    {
        for (int j = 0; j < m1; j++)
        {
            x_Bor[j][ext - i] = x[j][n1 - i];
        }
    }

    for (int i = 0; i < ext2; i++)
    {
        for (int j = 0; j < m1; j++)
        {
            x_Bor[j][n1 + i + 1] = x[j][i];
        }
    }

    for (int i = 0; i < n1; i++)
    {
        for (int j = 0; j < m1; j++)
        {
            x_Bor[j][ext + i] = x[j][i];
        }
    }

}

void Conv2D(imgpel **x_Bor, imgpel **y, double *f, char *a, int m1, int n1, int ext, int len)
{
    int ext2 = len - ext - 1;

    for (int i = 0; i < m1; i++)
    {
        for (int j = 0; j < n1; i++)
        {
            y[i][j] = 0;
            //flip filter f for convolution:-
            for (int k = 0; k < len; k++)
            {
                y[i][j] += x_Bor[i][j + k] * f[len - k - 1];
            }
        }
    }

}

The above function is called by encoder.cpp in the main() function. Variables/functions which are not declared in wfb2dec.cpp are in the header global.h.

I run into

Access Violation Reading/Writing Location

exception each time at different locations whenever I run the code. Where could be the problem?

Barmar
  • 741,623
  • 53
  • 500
  • 612
S. Kahu
  • 11
  • 5
  • 1
    thats a good deal of code, but a minimal example probably wouldn't have the pointer error. Sounds like you've gotten messages about specific lines that have failed? Add them here. – erik258 Aug 11 '18 at 00:48
  • 2
    Obviously there's a bug buried somewhere in the code, which corrupts memory. The way to find and fix those bugs is to make it logically impossible for them to happen in the first place. This means safely using C++ containers, iterators, and iterator-based algorithms instead of `malloc`-ing chunks of memory, and relying on your own noggin' to make sure that you allocated the right size and you will not blow past the end of malloced buffer, leaving a wake of destruction behind. Get rid of everything that's written here, and write it from scratch without a single `malloc` or `memcpy` anywhere. – Sam Varshavchik Aug 11 '18 at 00:51
  • To add to what others have mentioned, why are you casting to `char *` here? `Conv2D(x_Bor, y, f, (char *)"valid", m1, n1, ext, len);` -- That cast is highly suspicious. What is the compiler error if you removed that cast? If you get an error, *read it carefully and understand it*. Don't just mask it by casting. If that function attempts to change the data `"valid"` the behavior is undefined. – PaulMcKenzie Aug 11 '18 at 02:51
  • 1
    Visual Studio has a very good debugger. You can certainly use it to figure out where you're stepping over memory. – Retired Ninja Aug 11 '18 at 03:49
  • [This question](https://stackoverflow.com/questions/17416543/access-a-1d-array-as-a-2d-array-in-c) may be helpful. – 1201ProgramAlarm Aug 11 '18 at 03:56
  • even if crash happens randomly, each failure has a concrete reason, which may be found by inspecting memory at the moment of error, so please provide a single case of failure, and what the relevent variables contain. – max630 Aug 11 '18 at 05:40
  • Your best bet is to use memory analysis tools, such as AddressSanitizer, MemorySanitizer, valgrind, and so on. Usually, the bug happens much earlier than the crash. I know that visual studio has similar tools for C++ (safe iterators, IIRC), but it should also have something similar for C. Check https://stackoverflow.com/q/47711390/4955498 – Michael Veksler Aug 11 '18 at 08:30
  • There are errors in your code that are obvious ones. Such as this:`imgpel **x_L = (imgpel **) malloc((m1*n1) * sizeof(imgpel));` then you do this right afterwards: `x_L = rowfiltering(x, h0, ext_h0, len_h0, m1, n1);` -- That is a memory leak. You allocated memory, assigned the pointer returned from `malloc` to `x_L`, and then you immediately leak the memory by assigning `x_L` to the call to `rowfiltering`. – PaulMcKenzie Aug 11 '18 at 12:08
  • I think the OP can take this opportunity to turn this (obvious) C code into C++. A good learning experience of taking this code and rewriting it using `std::vector` and other containers. – PaulMcKenzie Aug 11 '18 at 20:22

0 Answers0