0

我有一个缩放算法,它似乎可以将图像缩放到正确的大小,但会在图像的右半部分产生伪影(轻微的图像损坏)。由于我没有使用指针的经验,我怀疑我的指针算术可能出错了!

要在 OSX 上运行项目: 1. 从以下位置下载:https ://www.dropbox.com/s/myme1z1mkxjwyjf/artifact.zip?dl=0

  1. 打开在 proj.ios 中找到的 xcodeproj 文件

  2. 所有相关的代码都在 HelloWorldScene.cpp 中

在函数 test() 中,您可以注释掉/取消注释我们希望测试的方法。:

void HelloWorld::test(){
    testCopy(); //In this case the image appears as expected. (a simple copy)
//    testScale(); //In this case there are strange artifacts on the right tip of the arrow.
}

测试副本,是我尝试只复制缓冲区的内容而不做任何不好的事情,如内存损坏、泄漏等......图像出现在屏幕上看起来不错!

void HelloWorld::testCopy(){
std::string infile = _imageName;

Image* img = new Image();
img->initWithImageFile(infile);
auto odata = img->getData();

Image* copy = new Image();

int components = 4;
auto finalDataLen = img->getDataLen();
auto finalData = static_cast<unsigned char*>(malloc(finalDataLen));

for (int i = 0; i<img->getWidth(); i++) {
    for (int j = 0; j<img->getHeight(); j++) {
        unsigned char *pixel = odata + (i + j * img->getWidth()) * components;

        unsigned char *fpixel = finalData + (i + j * img->getWidth()) * components;
        fpixel[0] = pixel[0];
        fpixel[1] = pixel[1];
        fpixel[2] = pixel[2];
        fpixel[3] = pixel[3];
    }
}
copy->initWithRawData(finalData, finalDataLen, img->getWidth(), img->getHeight(), 8);
Texture2D* tk = new Texture2D();
tk->initWithImage(copy);

Sprite* foo = Sprite::createWithTexture(tk);
foo->setPosition(Director::getInstance()->getVisibleSize().width/2,Director::getInstance()->getVisibleSize().height/2);
foo->setScale(0.8);
this->addChild(foo);

delete img;
delete copy;
return;

}

现在注释掉 testCopy(); 并取消注释 testScale(); 在这种情况下,图像会出现,但图像右侧有一些损坏!

void HelloWorld::testScale(){
    std::string infile = _imageName;

    Image* img = new Image();
    img->initWithImageFile(infile);
    Image* scl = new Image();
    scaleImage(img, scl, 0.8);

    Texture2D* tk = new Texture2D(); //Texture is needed as long as the sprite exists, so we aren't deleting it.
    tk->initWithImage(scl);
    Sprite* foo = Sprite::createWithTexture(tk);
    foo->setPosition(Director::getInstance()->getVisibleSize().width/2,Director::getInstance()->getVisibleSize().height/2);
    this->addChild(foo);

    delete img;
    delete scl;

    return;
}

void HelloWorld::scaleImage(Image* original,Image* scaledImage,const float& scale){
    int width = scale*original->getWidth();
    int height = scale*original->getHeight();

    int x=4;

    unsigned char* data = original->getData();

    auto dataLen = width * height * x * sizeof(unsigned char);
    auto data2 = static_cast<unsigned char*>(malloc(dataLen));

    //sprshrink seems to be the problem method.
    sprshrink(data2, width, height, data, original->getWidth(), original->getHeight());
    scaledImage->initWithRawData(data2, dataLen, width, height, 8);
}

//Why does this method produce artifcats ?
void HelloWorld::sprshrink(unsigned char *dest, int dwidth, int dheight, unsigned char *src, int swidth, int sheight){
    int x, y;
    int i, ii;
    float red, green, blue, alpha;
    float xfrag, yfrag, xfrag2, yfrag2;
    float xt, yt, dx, dy;
    int xi, yi;


    dx = ((float)swidth)/dwidth;
    dy = ((float)sheight)/dheight;

    for(yt= 0, y=0;y<dheight;y++, yt += dy)
    {
        yfrag = (float) ceil(yt) - yt;
        if(yfrag == 0)
            yfrag = 1;
        yfrag2 = yt+dy - (float) floor(yt + dy);
        if(yfrag2 == 0 && dy != 1.0f)
            yfrag2 = 1;

        for(xt = 0, x=0;x<dwidth;x++, xt+= dx)
        {
            xi = (int) xt;
            yi = (int) yt;
            xfrag = (float) ceil(xt) - xt;
            if(xfrag == 0)
                xfrag = 1;
            xfrag2 = xt+dx - (float) floor(xt+dx);
            if(xfrag2 == 0 && dx != 1.0f)
                xfrag2 = 1;
            red = xfrag * yfrag * src[(yi*swidth+xi)*4];
            green =  xfrag * yfrag * src[(yi*swidth+xi)*4+1];
            blue =   xfrag * yfrag * src[(yi*swidth+xi)*4+2];
            alpha =  xfrag * yfrag * src[(yi*swidth+xi)*4+3];

            for(i=0; xi + i + 1 < xt+dx-1; i++)
            {
                red += yfrag * src[(yi*swidth+xi+i+1)*4];
                green += yfrag * src[(yi*swidth+xi+i+1)*4+1];
                blue += yfrag * src[(yi*swidth+xi+i+1)*4+2];
                alpha += yfrag * src[(yi*swidth+xi+i+1)*4+3];
            }

            red += xfrag2 * yfrag * src[(yi*swidth+xi+i+1)*4];
            green += xfrag2 * yfrag * src[(yi*swidth+xi+i+1)*4+1];
            blue += xfrag2 * yfrag * src[(yi*swidth+xi+i+1)*4+2];
            alpha += xfrag2 * yfrag * src[(yi*swidth+xi+i+1)*4+3];
            for(i=0; yi+i+1 < yt +dy-1 && yi + i+1 < sheight;i++)
            {
                red += xfrag * src[((yi+i+1)*swidth+xi)*4];
                green += xfrag * src[((yi+i+1)*swidth+xi)*4+1];
                blue += xfrag * src[((yi+i+1)*swidth+xi)*4+2];
                alpha += xfrag * src[((yi+i+1)*swidth+xi)*4+3];

                for (ii = 0; xi + ii + 1 < xt + dx - 1 && xi + ii + 1 < swidth; ii++)
                {
                    red += src[((yi+i+1)*swidth+xi+ii+1)*4];
                    green += src[((yi+i+1)*swidth+xi+ii+1)*4+1];
                    blue += src[((yi+i+1)*swidth+xi+ii+1)*4+2];
                    alpha += src[((yi+i+1)*swidth+xi+ii+1)*4+3];
                }

                red += xfrag2 * src[((yi+i+1)*swidth+xi+ii+1)*4];
                green += xfrag2 * src[((yi+i+1)*swidth+xi+ii+1)*4+1];
                blue += xfrag2 * src[((yi+i+1)*swidth+xi+ii+1)*4+2];
                alpha += xfrag2 * src[((yi+i+1)*swidth+xi+ii+1)*4+3];
            }

            if (yi + i + 1 < sheight)
            {
                red += xfrag * yfrag2 * src[((yi + i + 1)*swidth + xi) * 4];
                green += xfrag * yfrag2 * src[((yi + i + 1)*swidth + xi) * 4 + 1];
                blue += xfrag * yfrag2 * src[((yi + i + 1)*swidth + xi) * 4 + 2];
                alpha += xfrag * yfrag2 * src[((yi + i + 1)*swidth + xi) * 4 + 3];

                for (ii = 0; xi + ii + 1 < xt + dx - 1 && xi + ii + 1 < swidth; ii++)
                {
                    red += yfrag2 * src[((yi + i + 1)*swidth + xi + ii + 1) * 4];
                    green += yfrag2 * src[((yi + i + 1)*swidth + xi + ii + 1) * 4 + 1];
                    blue += yfrag2 * src[((yi + i + 1)*swidth + xi + ii + 1) * 4 + 2];
                    alpha += yfrag2 * src[((yi + i + 1)*swidth + xi + ii + 1) * 4 + 3];
                }
            }

            if (yi + i + 1 < sheight && x + xi + 1 < swidth)
            {
                red += xfrag2 * yfrag2 * src[((yi + i + 1)*swidth + xi + ii + 1) * 4];
                green += xfrag2 * yfrag2 * src[((yi + i + 1)*swidth + xi + ii + 1) * 4 + 1];
                blue += xfrag2 * yfrag2 * src[((yi + i + 1)*swidth + xi + ii + 1) * 4 + 2];
                alpha += xfrag2 * yfrag2 * src[((yi + i + 1)*swidth + xi + ii + 1) * 4 + 3];
            }
            red /= dx * dy;
            green /= dx * dy;
            blue /= dx * dy;
            alpha /= dx * dy;
            red = clamp(red, 0, 255);
            green = clamp(green, 0, 255);
            blue = clamp(blue, 0, 255);
            alpha = clamp(alpha, 0, 255);

            dest[(y*dwidth+x)*4] = (unsigned char) red;
            dest[(y*dwidth+x)*4+1] = (unsigned char) green;
            dest[(y*dwidth+x)*4+2] = (unsigned char) blue;
            dest[(y*dwidth+x)*4+3] = (unsigned char) alpha;
        }
    }
}

我怀疑我的缩减算法(sprshrink)有效(因为它是别人的!:D),并怀疑我在 testScale() 中使用指针时犯了错误!你怎么看 ?我是否正确分配和使用我的指针?我究竟做错了什么?

图片:

清除:

图片清晰

运行 testScale() 而不是 testCopy() 时的伪影(注释掉 testCopy)。 运行缩放方法后的神器!

4

0 回答 0