如何使用Windows CopyMemory函数复制TBitmap内存

时间:2011-12-02 23:48:28

标签: delphi pointers image-processing

我有1个位图对象:1024px和高度:768 px

我想将此位图对象剪切为左右两部分,但我不想在画布中使用DrawBitmap方法,因为此方法可以使用更多的CPU然后使用CopyMemory。

我不想使用这个方法(leftImg.Canvas.DrawBitmap(MainBmp,RectF(0,0,MainBmp.Width div 2,bmp.Height),     RectF(0,0,leftImg.Width,leftImg.Height),1,True); )

MainBmp := TBitmap.Create(1024, 768);

leftImg := TBitmap.Create(MainBmp.Width div 2, MainBmp.Height);
rightImg := TBitmap.Create(MainBmp.Width div 2, MainBmp.Height);

leftBits := PAlphaColorArray(leftImg.Scanline[0]);

CopyMemory(@leftBits[0], @MainBmp.StartLine[0], (MainBmp.Width div 2) * bmp.Height);

如果我这样做,他可以复制但不会留下位图的一部分:(他从上到下复制了一半。

这幅画正是我想做的。

enter image description here

在剪切过程之后,我需要这样做而不使用任何循环(如while或for)

enter image description here

由于

3 个答案:

答案 0 :(得分:4)

没有办法!正如您所发现的那样,图像数据是逐行存储在存储器中的(因此扫描线)。你想要的只有在逐列的情况下才有可能。没有任何循环,这是不可能的。

答案 1 :(得分:2)

正如您所注意到的,扫描线是从左到右的一行像素。图像中每个垂直高度像素都有一条扫描线。

您的1024px x 768px图像有768条扫描线。从扫描线复制前半部分数据会产生图像的上半部分。

您不必浏览每个像素,您可以跳过,因为所有内容都已编入索引。

但是,既然你想要两半,那么你就不会因为经历整个事情而浪费任何工作。在迭代数据时,同时复制左右两部分。因此,对于第一条扫描线,将前半部分像素复制到左侧图像,将其余像素复制到右侧图像,转到下一行,然后重复。

这应该比DrawBitmap少两倍。

此外,不是加载图像,显示它,然后将其拆分,而是在加载图像时将其拆分。

你仍然需要一个循环,除非你想写所有东西768次。

从技术上讲,你可以旋转图像并按照你想要的方式进行操作,但旋转它也需要循环,你必须在完成后将其旋转回来。

答案 2 :(得分:2)

使用TCanvas.CopyRect()方法将一个TCanvas的部分复制到另一个TCanvas。它允许两个位图具有不同的像素格式。操作系统将在内部为您处理差异:

MainBmp := TBitmap.Create(1024, 768); 

leftImg := TBitmap.Create(MainBmp.Width div 2, MainBmp.Height); 
rightImg := TBitmap.Create(MainBmp.Width div 2, MainBmp.Height); 

leftImg.Canvas.CopyRect(
  Rect(0, 0, leftImg.Width, leftImg.Height),
  MainBmp.Canvas,
  Rect(0, 0, leftImg.Width, leftImg.Height)
);

rightImg.Canvas.CopyRect(
  Rect(0, 0, rightImg.Width, rightImg.Height),
  MainBmp.Canvas,
  Rect(leftBmp.Width, 0, rightImg.Width, rightImg.Height)
);