我有一个缩放算法,可以将图像缩放到正确的大小,但会在图像的右半部分产生伪像(轻微的图像损坏)。由于我没有经验使用指针,我怀疑我可能在我的指针算术上犯了错误!
在OSX上运行项目: 1.从https://www.dropbox.com/s/myme1z1mkxjwyjf/artifact.zip?dl=0
下载打开proj.ios
所有相关的代码都在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()中使用指针时出错了!你怎么看 ?我是否正确分配和使用指针?我做错了什么?
图片:
清除: