【发布时间】:2014-10-21 19:51:59
【问题描述】:
我对 C++/CLI 中的位图有疑问。简而言之,我必须将位图块加载到 PictureBox,显示它并将其移动到下面几行。我做的步骤是:
1 - 从硬盘加载完整的位图,并获取它的参数(宽度、高度等)。
2 - 创建一个能够完全包含此位图的 PictureBox。
3 - 创建一个位图,我将用作绘图区域,并将其放在 PictureBox 内。
4 - 将初始位图的一个块(前 150 行)复制到我的绘图区域并显示它。
5 - 将此块移动到下面几行。 (这是我的问题)。
当我移动图像时,出现错误:图像似乎向左移动,而右侧是图像的左侧部分。我上传了图片:
这是移动之前的图像块,一切正常。 http://i58.tinypic.com/2duf48x.png
这是移动后的图像,如您所见,它似乎向左移动。 http://i61.tinypic.com/jz9ond.png
我用来“移动”图像的方法是:
1 - LockBits 并获得 anIntPtr,我将其转换为 unsigned char*。 2 - 使用 memcpy(或 memmove)移动块。
这里是代码,这些是类构造函数(Windows 窗体构造函数)和我用来显示和移动块的方法:
MyForm(){
InitializeComponent();
//Get a test srcIm and it's parameters.
srcIm = gcnew Bitmap("./img/zhbackground.bmp");
iWidth = srcIm->Width;
iHeigth = srcIm->Height;
pxF = srcIm->PixelFormat;
Bpp = Image::GetPixelFormatSize(pxF) / 8;
//Prepare a PictureBox, which will be given as parameter to Windows Form.
pb = gcnew PictureBox();
pb->SizeMode = PictureBoxSizeMode::StretchImage;
pb->Size = Drawing::Size(iWidth, iHeigth);
pb->Location = Drawing::Point(0, 0);
//Create draw area and put it into the PictureBox.
drawArea = gcnew Bitmap(pb->Width, pb->Height, pxF);
pb->Image = drawArea;
this->Controls->Add(this->pb);
}
void test(){
//This is the number of lines of my image chunk.
int nLines = 150;
//First, load the first 150 lines of my image (that's on hard drive).
BitmapData ^srcData = srcIm->LockBits(
Drawing::Rectangle(0, 0, iWidth, iHeigth),
ImageLockMode::ReadOnly,
pxF
);
unsigned char *srcStream = (unsigned char*)srcData->Scan0.ToPointer();
//Prepare the draw area for paint my image chunk.
BitmapData ^dstData = drawArea->LockBits(
Drawing::Rectangle(0, 0, iWidth, iHeigth),
ImageLockMode::ReadWrite,
pxF
);
unsigned char *dAhandler = (unsigned char*)dstData->Scan0.ToPointer();
//Paint the chunk. (My image's 150 first lines)
memcpy(dAhandler, srcStream, iWidth * Bpp * nLines);
//Unlock and refresh to see the image.
drawArea->UnlockBits(dstData);
this->pb->Refresh();
//Wait 1 second...
Threading::Thread::Sleep(1000);
//Unlock draw area to move the image.
dstData = drawArea->LockBits(
Drawing::Rectangle(0, 0, iWidth, iHeigth),
ImageLockMode::ReadWrite,
pxF
);
dAhandler = (unsigned char*)dstData->Scan0.ToPointer();
//First, move the image from the beggining to 150 lines below.
memcpy(&dAhandler[nLines * iWidth * Bpp], dAhandler, iWidth * nLines * Bpp);
//Paint the "hole" with black.
memset(dAhandler, 0, iWidth * Bpp * nLines);
//Unlock and display the image.
drawArea->UnlockBits(dstData);
this->pb->Refresh();
//Unlock the source image (image load from hard drive).
srcIm->UnlockBits(srcData);
}
我测试了很多方法:
1 - 我读到如果你使用 LockBits(),你可以获得的 IntPtr 是像素的字节数组,一个接着一个。这意味着我不会遇到内存中的位图组织等问题。
2 - 我已经测试了 memcpy 和 memmove。
3 - 我已经测试了一个简单的 for 循环。
没有用,我不知道该怎么办。
谢谢,问候。
【问题讨论】: