void Arc3DModel::GenerateGradientSmoothingMask(int subsampleFactor, QImage &OriginalTexture, CharImage &mask)
{
    CharImage gray(OriginalTexture);
    CharImage grad;
    grad.resize(gray.w,gray.h);
    int w=gray.w,h=gray.h;
    for(int x=1;x<w-1;++x)
        for(int y=1;y<h-1;++y)
        {
            int dx=abs(int(gray.Val(x,y))-int(gray.Val(x-1,y))) + abs(int(gray.Val(x,y))-int(gray.Val(x+1,y)));
            int dy=abs(int(gray.Val(x,y))-int(gray.Val(x,y-1))) + abs(int(gray.Val(x,y))-int(gray.Val(x,y+1)));
            grad.Val(x,y)=min(255,16*dx+dy);
        }

        // create subsampled mask
        int ws=gray.w/subsampleFactor, hs=gray.h/subsampleFactor;
        mask.resize(ws,hs);

        for(int x=0;x<ws;++x)
            for(int y=0;y<hs;++y)
            {
                unsigned char maxGrad=0;
                for(int si=0;si<subsampleFactor;++si)
                    for(int sj=0;sj<subsampleFactor;++sj)
                        maxGrad = max(maxGrad, grad.Val(x*subsampleFactor+sj,y*subsampleFactor+si));

                mask.Val(x,y) = maxGrad;
            }

            CharImage mask2;
            mask2.resize(ws, hs);

            // average filter (11 x 11)
            int avg;
            int wsize = 5;
            for (int y = wsize; y < hs-wsize; y++)
                for (int x = wsize; x < ws-wsize; x++)
                {
                    avg = 0;
                    for (int yy = y - wsize; yy <= y + wsize; yy++)
                        for (int xx = x - wsize; xx <= x + wsize; xx++)
                            avg += mask.Val(xx, yy);

                    mask2.Val(x, y) = min(255, avg / ((2 * wsize + 1)* (2 * wsize +1)));
                }

                mask.convertToQImage().save("tmp_testmask.jpg","jpg");
                mask2.convertToQImage().save("tmp_testmaskSmooth.jpg","jpg");

                // erosion filter (7 x 7)
                int minimum;
                wsize = 3;
                for (int y = wsize; y < hs-wsize; y++)
                    for (int x = wsize; x < ws-wsize; x++)
                    {
                        minimum = mask2.Val(x, y);
                        for (int yy = y - wsize; yy <= y + wsize; yy++)
                            for (int xx = x - wsize; xx <= x + wsize; xx++)
                                if (mask2.Val(xx, yy) < minimum)
                                    minimum = mask2.Val(xx, yy);

                        mask.Val(x, y) = minimum;
                    }

                    grad.convertToQImage().save("tmp_test.jpg","jpg");
                    mask.convertToQImage().save("tmp_testmaskeroded.jpg","jpg");
}