问题  需要帮助,从GetPixel / SetPixel迁移到Lockbits

奥尔格

新成员
已加入
2015年5月31日
留言内容
1
编程经验
Beginner
这是我的GetPixel / SetPixel代码,用于增加图像中的红色和紫色

C#:
[COLOR=#00008b]private[/COLOR][COLOR=#00008b]void[/COLOR][COLOR=#000000] redsAndPurplesToolStripMenuItem_Click([/COLOR][COLOR=#00008b]object[/COLOR][COLOR=#000000] sender, [/COLOR][COLOR=#2b91af]EventArgs[/COLOR][COLOR=#000000] e)[/COLOR]
[COLOR=#000000]{[/COLOR][INDENT][COLOR=#808080]//从图片框获取位图[/COLOR]
[COLOR=#2b91af]Bitmap[/COLOR][COLOR=#000000] bmpMain = ([/COLOR][COLOR=#2b91af]Bitmap[/COLOR][COLOR=#000000])pictureBoxMain.[/COLOR][COLOR=#2b91af]Image[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2b91af]Clone[/COLOR][COLOR=#000000]();[/COLOR]

[COLOR=#808080]// search through each pixel via x, y coordinates, examine and make changes. Dont let values exceed 255 or fall under 0.  [/COLOR]
[COLOR=#00008b]for[/COLOR][COLOR=#000000] ([/COLOR][COLOR=#2b91af]int[/COLOR][COLOR=#000000] y = [/COLOR][COLOR=#800000]0[/COLOR][COLOR=#000000]; y < bmpMain.[/COLOR][COLOR=#2b91af]Height[/COLOR][COLOR=#000000]; y++)[/COLOR]
[COLOR=#00008b]   for[/COLOR][COLOR=#000000] ([/COLOR][COLOR=#2b91af]int[/COLOR][COLOR=#000000] x = [/COLOR][COLOR=#800000]0[/COLOR][COLOR=#000000]; x < bmpMain.[/COLOR][COLOR=#2b91af]Width[/COLOR][COLOR=#000000]; x++)[/COLOR]
[COLOR=#000000]   {[/COLOR]
[COLOR=#000000]        bmpMain[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2b91af]GetPixel[/COLOR][COLOR=#000000](x, y);[/COLOR]
[COLOR=#2b91af]        Color[/COLOR][COLOR=#000000] c = bmpMain.[/COLOR][COLOR=#2b91af]GetPixel[/COLOR][COLOR=#000000](x, y);[/COLOR]
[COLOR=#2b91af]        int[/COLOR][COLOR=#000000] myRed = c.R, myGreen = c.G, myBlue = c.B;[/COLOR]
[COLOR=#000000]        myGreen [/COLOR][COLOR=#000000]-= [/COLOR][COLOR=#800000]128[/COLOR][COLOR=#000000];[/COLOR]
[COLOR=#00008b]        if[/COLOR][COLOR=#000000] (myGreen < [/COLOR][COLOR=#800000]0[/COLOR][COLOR=#000000]) myGreen = [/COLOR][COLOR=#800000]0[/COLOR][COLOR=#000000];[/COLOR][COLOR=#000000] 
         bmpMain.[/COLOR][COLOR=#2b91af]SetPixel[/COLOR][COLOR=#000000](x, y, [/COLOR][COLOR=#2b91af]Color[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2b91af]FromArgb[/COLOR][COLOR=#000000]([/COLOR][COLOR=#800000]255[/COLOR][COLOR=#000000], myRed, myGreen, myBlue));[/COLOR]
[COLOR=#000000]   }[/COLOR]

[COLOR=#808080]//将新的位图分配给图片框[/COLOR]
[COLOR=#000000]pictureBoxMain[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2b91af]Image[/COLOR][COLOR=#000000] = ([/COLOR][COLOR=#2b91af]Bitmap[/COLOR][COLOR=#000000])bmpMain;[/COLOR]

[COLOR=#808080]// Save a copy to the HD for undo / redo.[/COLOR]
[COLOR=#00008b]string[/COLOR][COLOR=#000000] myString = [/COLOR][COLOR=#2b91af]Environment[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2b91af]GetEnvironmentVariable[/COLOR][COLOR=#000000]([/COLOR][COLOR=#800000]"temp"[/COLOR][COLOR=#000000], [/COLOR][COLOR=#2b91af]EnvironmentVariableTarget[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2b91af]Machine[/COLOR][COLOR=#000000]);[/COLOR]
[COLOR=#000000]pictureBoxMain[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2b91af]Image[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2b91af]Save[/COLOR][COLOR=#000000](myString + [/COLOR][COLOR=#800000]"\\ColorAppRedo.png"[/COLOR][COLOR=#000000], [/COLOR][COLOR=#2b91af]System[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2b91af]Drawing[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2b91af]Imaging[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2b91af]ImageFormat[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2b91af]Png[/COLOR][COLOR=#000000])[/COLOR][/INDENT]
[COLOR=#000000]}
[/COLOR]

这是我第一次尝试锁定位:

C#:
[COLOR=#00008b]private[/COLOR][COLOR=#00008b]void[/COLOR][COLOR=#000000] redsAndPurplesToolStripMenuItem_Click([/COLOR][COLOR=#00008b]object[/COLOR][COLOR=#000000] sender, [/COLOR][COLOR=#2b91af]EventArgs[/COLOR][COLOR=#000000] e)[/COLOR]
[COLOR=#000000]{[/COLOR][INDENT][COLOR=#808080]
//从图片框获取位图[/COLOR]
[COLOR=#2b91af]Bitmap[/COLOR][COLOR=#000000] bmpMain = ([/COLOR][COLOR=#2b91af]Bitmap[/COLOR][COLOR=#000000])pictureBoxMain.[/COLOR][COLOR=#2b91af]Image[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2b91af]Clone[/COLOR][COLOR=#000000]();[/COLOR]

[COLOR=#2b91af]Rectangle[/COLOR][COLOR=#000000] rect = [/COLOR][COLOR=#00008b]new[/COLOR][COLOR=#2b91af]Rectangle[/COLOR][COLOR=#000000]([/COLOR][COLOR=#2b91af]Point[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2b91af]Empty[/COLOR][COLOR=#000000], bmpMain.[/COLOR][COLOR=#2b91af]Size[/COLOR][COLOR=#000000]);[/COLOR][COLOR=#000000] 
[/COLOR][COLOR=#2b91af]BitmapData[/COLOR][COLOR=#000000] bmpData = bmpMain.[/COLOR][COLOR=#2b91af]LockBits[/COLOR][COLOR=#000000](rect, [/COLOR][COLOR=#2b91af]ImageLockMode[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2b91af]ReadOnly[/COLOR][COLOR=#000000], bmpMain.[/COLOR][COLOR=#2b91af]PixelFormat[/COLOR][COLOR=#000000]);[/COLOR][COLOR=#000000] 

[/COLOR][COLOR=#808080]// search through each pixel via x, y coordinates, examine and make changes. Dont let values exceed 255 or fall under 0.  [/COLOR]
[COLOR=#00008b]for[/COLOR][COLOR=#000000] ([/COLOR][COLOR=#2b91af]int[/COLOR][COLOR=#000000] y = [/COLOR][COLOR=#800000]0[/COLOR][COLOR=#000000]; y < bmpMain.[/COLOR][COLOR=#2b91af]Height[/COLOR][COLOR=#000000]; y++)[/COLOR]
[COLOR=#00008b]   for[/COLOR][COLOR=#000000] ([/COLOR][COLOR=#2b91af]int[/COLOR][COLOR=#000000] x = [/COLOR][COLOR=#800000]0[/COLOR][COLOR=#000000]; x < bmpMain.[/COLOR][COLOR=#2b91af]Width[/COLOR][COLOR=#000000]; x++)[/COLOR]
[COLOR=#000000]   {[/COLOR]
[COLOR=#000000]       bmpMain[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2b91af]GetPixel[/COLOR][COLOR=#000000](x, y);[/COLOR]
[COLOR=#2b91af]       Color[/COLOR][COLOR=#000000] c = [/COLOR][COLOR=#00008b]new[/COLOR][COLOR=#2b91af]Color[/COLOR][COLOR=#000000]();[/COLOR][COLOR=#000000] 
        [/COLOR][COLOR=#2b91af]int[/COLOR][COLOR=#000000] myRed = c.R, myGreen = c.G, myBlue = c.B;[/COLOR]
[COLOR=#000000]       myGreen [/COLOR][COLOR=#000000]-= [/COLOR][COLOR=#800000]128[/COLOR][COLOR=#000000];[/COLOR]
[COLOR=#00008b]       if[/COLOR][COLOR=#000000] (myGreen < [/COLOR][COLOR=#800000]0[/COLOR][COLOR=#000000]) myGreen = [/COLOR][COLOR=#800000]0[/COLOR][COLOR=#000000];[/COLOR][COLOR=#000000] 
        bmpMain.[/COLOR][COLOR=#2b91af]SetPixel[/COLOR][COLOR=#000000](x, y, [/COLOR][COLOR=#2b91af]Color[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2b91af]FromArgb[/COLOR][COLOR=#000000]([/COLOR][COLOR=#800000]255[/COLOR][COLOR=#000000], myRed, myGreen, myBlue));[/COLOR]
[COLOR=#000000]   }[/COLOR]
[COLOR=#000000]
bmpMain[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2b91af]UnlockBits[/COLOR][COLOR=#000000](bmpData);
[/COLOR][COLOR=#808080]
//将新的位图分配给图片框
[/COLOR][COLOR=#000000]pictureBoxMain[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2b91af]Image[/COLOR][COLOR=#000000] = ([/COLOR][COLOR=#2b91af]Bitmap[/COLOR][COLOR=#000000])bmpMain;[/COLOR]

[COLOR=#808080]// Save a copy to the HD for undo / redo.[/COLOR]
[COLOR=#00008b]string[/COLOR][COLOR=#000000] myString = [/COLOR][COLOR=#2b91af]Environment[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2b91af]GetEnvironmentVariable[/COLOR][COLOR=#000000]([/COLOR][COLOR=#800000]"temp"[/COLOR][COLOR=#000000], [/COLOR][COLOR=#2b91af]EnvironmentVariableTarget[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2b91af]Machine[/COLOR][COLOR=#000000]);[/COLOR]
[COLOR=#000000]pictureBoxMain[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2b91af]Image[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2b91af]Save[/COLOR][COLOR=#000000](myString + [/COLOR][COLOR=#800000]"\\ColorAppRedo.png"[/COLOR][COLOR=#000000], [/COLOR][COLOR=#2b91af]System[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2b91af]Drawing[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2b91af]Imaging[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2b91af]ImageFormat[/COLOR][COLOR=#000000].[/COLOR][COLOR=#2b91af]Png[/COLOR][COLOR=#000000]);[/COLOR][/INDENT]
[COLOR=#000000]} [/COLOR]

问题是在嵌套循环中,我不了解如何将GetPixel / SetPixel代码转换为Lockbits代码。我已经阅读了教程,我需要一个例子。将嵌套循环代码从GetPixel / SetPixel转换为Lockbits的正确方法是什么?非常感谢你
 

SumantraChoudry

新成员
已加入
2015年8月27日
留言内容
1
编程经验
5-10
尝试中的问题之一是您使用了ImageLockMode.ReadOnly,它不允许您修改像素数据。
另一个问题是在位图数据中正确使用Scan0指针。这是在24位BGR情况下使用指针的代码:
//从图片框获取位图
位图bmpMain =(Bitmap)pictureBoxMain.Image.Clone();

Rectangle rect =新Rectangle(Point.Empty,bmpMain.Size);
BitmapData bmpData = bmpMain.LockBits(rect,ImageLockMode.ReadWrite,bmpMain.PixelFormat);

不安全的
{
如果(bmpData.PixelFormat == PixelFormat.Format24bppRgb)
{
for (int y = 0; y <bmpData.Height; y ++)
{
字节* pByte =(字节*)bmpData.Scan0.ToPointer(); //从第一个像素开始
pByte + = y * bmpData.Stride; //转到正确的扫描线

for (int x = 0; x < bmpData.Width; x++)
{
int myBlue = *pByte;
//使用Blue组件执行某些操作
* pByte =(字节)myBlue;
pByte++;

int myGreen = * pByte;
myGreen -= 128;
if (myGreen < 0) myGreen = 0;
* pByte =(字节)myGreen;
pByte++;

int myRed = *pByte;
//使用Red组件执行某些操作
* pByte =(字节)myRed;
pByte++;
}
}
}
}
bmpMain.UnlockBits(bmpData);

//将新的位图分配给图片框
pictureBoxMain.Image =(位图)bmpMain;

请注意,与使用GetPixel和SetPixel相比,直接使用LockBits和BitmapData处理像素具有速度优势,但是需要付出一定的代价:
1)像素定位算法变得复杂。我上面粘贴的代码示例针对的是PixelFormat.Format24bppRgb的特定情况。如果您的图像是任何其他像素格式,则计算将有所不同。如果要处理所有可能的位图格式,请准备好一个漫长的项目。
2)要获得速度优势,必须使用不安全的指针。在大多数情况下,C#使您免受此类不安全代码的影响,甚至允许您使用System.Runtime.InteropServices.Marshal.Copy()处理像素。但是,如果这样做,代码将失去速度优势的重要部分。
除非您精通指针和不安全的代码,否则如果处理速度对您来说是主要问题,那么最好使用优化的图像处理库(例如Leadtools)。
 
最佳 底部