C++ 在c++;

C++ 在c++;,c++,bitmapdata,C++,Bitmapdata,下面是我的程序。我尝试在VisualC++中使用BITMAPATATION类应用灰度过滤器。我在11点收到AccessViolationException,被注释标记。我试过使用CLR:Safe和CLR:pure,但没有用。在c#中,这将通过使用不安全块来解决。有什么建议吗?其他相关问题的解决方案都不起作用 Bitmap^ bmp = gcnew Bitmap(pictureBox1->Image); BitmapData^ data = bmp->LockBits(Rectan

下面是我的程序。我尝试在VisualC++中使用BITMAPATATION类应用灰度过滤器。我在11点收到AccessViolationException,被注释标记。我试过使用CLR:Safe和CLR:pure,但没有用。在c#中,这将通过使用不安全块来解决。有什么建议吗?其他相关问题的解决方案都不起作用

 Bitmap^ bmp = gcnew Bitmap(pictureBox1->Image);

BitmapData^ data = bmp->LockBits(Rectangle(0,0,bmp->Width,bmp->Height), ImageLockMode::ReadWrite, PixelFormat::Format24bppRgb);

        int blue=0, green=0, red=0; 

             System::IntPtr s = data->Scan0; 

            int* P = (int*)(void*)s;

            for (int i =0; i<bmp->Height;i++)

            {

                for (int j = 0; j < bmp->Width*3; j++)

                {

                    blue = (int)P[0];  //access violation exception

                    green =(int )P[1];

                    red = (int)P[2];

                    int avg = (int)((blue + green + red) / 3);

                    P[0] = avg;

                    P[1] = avg;

                    P[2] = avg;                       

                    P +=3;

                }

            }
            bmp->UnlockBits(data);
        pictureBox1->Image = bmp;
Bitmap^bmp=gcnew位图(pictureBox1->Image);
BitmapData^data=bmp->LockBits(矩形(0,0,bmp->宽度,bmp->高度),ImageLockMode::ReadWrite,PixelFormat::Format24bppRgb);
int蓝色=0,绿色=0,红色=0;
系统::IntPtr s=data->Scan0;
int*P=(int*)(void*)s;
for(int i=0;iHeight;i++)
{
对于(int j=0;jWidth*3;j++)
{
blue=(int)P[0];//访问冲突异常
绿色=(int)P[1];
红色=(int)P[2];
平均整数=(整数)(蓝+绿+红)/3;
P[0]=平均值;
P[1]=平均值;
P[2]=平均值;
P+=3;
}
}
bmp->解锁位(数据);
pictureBox1->Image=bmp;

当您应该使用
字节*
时,您使用的是
int*
。每个像素有三个字节,每个通道有一个字节。int(可能)是4个字节,因此
p[0]
返回一个完整的像素加上超过它的字节。这就是为什么会出现访问冲突;您正在超出图像缓冲区的界限

当递增指针时,就是在向其添加
sizeof*p
字节。在这种情况下,
P+=3
将指针
P
增加
12个字节。太多了,你将永远无法用
int*
读取24bpp图像的单个像素(或通道)。您还假设您的步幅为
Width*3
,这可能是正确的,也可能是错误的(位图是4字节对齐的。)

Byte*base=(Byte*)数据->扫描0;
int stride=数据->步幅;
对于(int y=0;yHeight;++y){
字节*src=base+y*步幅;
对于(int x=0;xWidth;++x,src+=3){
//位图是按BGR顺序存储的(尽管在这里并不重要)。
//我假设一个24bpp的位图。
字节b=src[0];
字节g=src[1];
字节r=src[2];
整数平均=(r+g+b)/3;
src[0]=src[1]=src[2]=(字节)平均值;
}
}

P+=3显然不正确,指针偏移了3 x sizeof(int)=12个字节。对24bpp映像使用int*是不正确的,请使用字节*。这是正确的。可能还需要查看Bitmap.LockBits方法,我认为它返回了状态-指针是通过参数返回的(或者这是C#不是C++)?@TonyWilk:
LockBits
返回一个
BitmapData
对象,这就是
data
所在的位置。调用
LockBits
只是没有显示出来(在这里或OP的例子中)。@Ed s。它就像一个符咒。它在没有跨步引用的情况下也能工作。@SSSpecialist:不过,在将指针设置到行的开头时,需要使用跨步。跨距是扫描行的宽度,以字节为单位。图像的逻辑宽度(以字节为单位)不一定是跨距。位图是4字节对齐的,即,如果宽度不是4(字节)的倍数,则填充位图。
Byte* base = (Byte*)data->Scan0;
int stride = data->Stride;

for(int y = 0; y < data->Height; ++y) {
    Byte* src = base + y * stride;
    for(int x = 0; x < data->Width; ++x, src += 3) {
        // bitmaps are stored in BGR order (though not really important here).
        // I'm assuming a 24bpp bitmap.
        Byte b = src[0];
        Byte g = src[1];
        Byte r = src[2];
        int average = (r + g + b) / 3;
        src[0] = src[1] = src[2] = (Byte)average;
    }
}