灰度图像转换Turbo C ++

时间:2011-07-03 04:57:01

标签: c++ turbo-c++

我正在尝试将RGB图像转换为灰度图像。 RGB图像为160 * 120 * 4,而我的灰度为160 * 120 * 1。然而,它并没有让我觉得我只是简单的黑色,它需要很长时间。这是我写的wat,请指教。感谢

int i, j, sum;
Image = new unsigned char [ 160 * 120 * 1 ];
for( int j = 0; j < 120; j++ ) {

    for( int i = 0; i < 160; i++ ) {
    sum=0;
        sum += PaintBox1->Canvas->Pixels[ i ][ j ];
        sum += PaintBox1->Canvas->Pixels[ i ][ j ];
        sum += PaintBox1->Canvas->Pixels[ i ][ j ];
        sum += PaintBox1->Canvas->Pixels[ i ][ j ];
        *Image = sum/4;

        PaintBox2->Canvas->Pixels[ i ][ j ] = *Image;
        Image++;
    }
}

2 个答案:

答案 0 :(得分:1)

我可以立即看到代码中的几个问题。最引人注目的是来自最里面的for循环:

sum=0;
sum += PaintBox1->Canvas->Pixels[ i ][ j ];
sum += PaintBox1->Canvas->Pixels[ i ][ j ];
sum += PaintBox1->Canvas->Pixels[ i ][ j ];
sum += PaintBox1->Canvas->Pixels[ i ][ j ];
*Image = sum/4;

在这里,您只需将相同的值添加到sum四次,然后再除以四。这使得这六行等同于

*Image = PaintBox1->Canvas->Pixels[ i ][ j ];

显然,你实际上想要平均每个频道。如果您的RGB图像是作为三维数组实现的,那么这可能类似于:

sum = 0;
sum += PaintBox1->Canvas->Pixels[ i ][ j ][ 0 ];
sum += PaintBox1->Canvas->Pixels[ i ][ j ][ 1 ];
sum += PaintBox1->Canvas->Pixels[ i ][ j ][ 2 ];
sum += PaintBox1->Canvas->Pixels[ i ][ j ][ 3 ];
*Image = sum/4;

但是,从您的代码示例中,看起来您的RGB图像实际上是作为(un)有符号整数的二维数组实现的。在这种情况下,以下代码应该足够(假设整数是您机器上的四个字节):

sum = 0;
unsigned int pixel = PaintBox1->Canvas->Pixels[ i ][ j ];
for(int k = 0; k < 4; ++k)
{
    sum += pixel & 0xFF;
    pixel >>= 1;
}
*Image = sum/4;

我看到的另一个主要问题是你没有保持指向灰度数组开头的指针。您将其初始化为

Image = new unsigned char[ 160 * 120 * 1 ];

这很好。但是每次循环,你都写了

Image++;

相反,你应该保持一个指向数组开头的指针,并有一个临时指针作为迭代器:

// before the for loops
Image = new unsigned char[ 160 * 120 * 1 ];
unsigned char * temp = Image;

// at the end of the inner for loop:
temp++;

所以你只能移动temp指针,而Image保持不变。

答案 1 :(得分:0)

VCL 画布使用TColor保留颜色。但是,内部格式由PixelFormat的{​​{1}}格式定义。通常为Canvaspf32bit ... pf24bit始终为32位无论使用哪种图像TColor,因为转换过程中都会发生很多转换(这就是为什么它这么慢),但是请注意,不同的PixelFormat设置可能会颠倒RGB顺序,从而使{{1} }也颠倒了(渲染为PixelFormat)!!!

例如,如果您使用 VCL s

clYellow,...

则每个像素为32位值。您可以为位图安全地执行此操作,但是我不确定Form / PaintBox画布是否与窗口绑定在一起,我怀疑您的clAqua,...是相似的(很可能是24位),因此您需要稍微更改代码:

Graphics::TBitmap *bmp=new Graphics::TBitmap;
bmp->PixelFormat=pf32bit;

PixelFormat属性是sloooow我将使用VCL位图,而使用其int x,y,xs=160,ys=120; DWORD rgb,bw; Image = new unsigned char [ xs*ys*1 ]; for(y=0;y<ys;y++) for(x=0;x<xs;x++) { rgb = PaintBox1->Canvas->Pixels[x][y]; bw = ( rgb &255) // sum r,g,b +((rgb>> 8)&255) +((rgb>>16)&255); bw/=3; // normalize *Image = bw; // write to your array Image++; bw*=0x00010101; // convert intensity to grayscale RGB color (you can shift and or instead) PaintBox2->Canvas->Pixels[x][y]=TColor(bw); // write back } Image-=xs*ys; 属性,它的速度快约1000倍以上,并且实现了加载/保存功能,因此您可以使用bmp文件容易。有关更多信息,请参见:

还有更多将RGB转换为强度的方法,请参见: