在 IronPython 中使用 Bitmap.LockBits 和 Marshal.Copy 未按预期更改图像
我编写了以下 IronPython 代码:
import clr
clr.AddReference("System.Drawing")
from System import *
from System.Drawing import *
from System.Drawing.Imaging import *
def NoWorko(bitmap):
bmData = bitmap.LockBits(Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb)
total_bytes = (bmData.Stride) * bmData.Height
rgbValues = Array.CreateInstance(Byte, total_bytes)
Runtime.InteropServices.Marshal.Copy(bmData.Scan0, rgbValues, 0, total_bytes)
for i in rgbValues:
i = 255 - i
#The following line doesn't appear to actually copy the bits back
Runtime.InteropServices.Marshal.Copy(rgbValues, 0, bmData.Scan0, total_bytes)
bitmap.UnlockBits(bmData)
originalImage = Bitmap("Test.bmp")
newPic = NoWorko(originalImage)
newPic.Save("New.bmp")
这是我对此 MSDN 代码示例的解释: http://msdn.microsoft.com/en-us/library/5ey6h79d.aspx除了我保存更改后的位图而不是在表单中显示它。
代码运行,但是新保存的位图是原始图像的精确副本,没有发生任何更改的迹象(它应该创建红色色调)。谁能告诉我我的代码有什么问题吗?
我使用的图像只是我在 Paint 中创建的 24bpp 位图(它只是一个大的白色矩形!),使用 IronPython 2.6 并在 Windows 7 (x64) 上使用已安装 .Net Framework 3.5 SP1。
更新
有人指出我在尝试向白色图像添加红色色调时的愚蠢行为 - 所以现在代码只是反转颜色。我已经在许多图像上尝试过此操作,但似乎没有任何效果。
但是,以下(非常相似)C# 程序:
public static void Main(string[] args)
{
Bitmap bitmap = new Bitmap("nTest.jpg");
BitmapData bmData = bitmap.LockBits( new Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
int total_bytes = (bmData.Stride) * bmData.Height;
byte[] rgbValues = new byte[total_bytes];
Marshal.Copy(bmData.Scan0, rgbValues, 0, total_bytes);
for(int i = 0; i < total_bytes; i++)
{
rgbValues[i] = (byte)(255 - rgbValues[i]);
}
Marshal.Copy(rgbValues, 0, bmData.Scan0, total_bytes);
bitmap.UnlockBits(bmData);
bitmap.Save("nNew.jpg");
}
适用于我尝试过的所有图像。
调用有关。
Runtime.InteropServices.Marshal.Copy(rgbValues, 0, bmData.Scan0, bytes)
我不确定,但这似乎与导致问题的 IPY 中的
I have written the following IronPython code:
import clr
clr.AddReference("System.Drawing")
from System import *
from System.Drawing import *
from System.Drawing.Imaging import *
def NoWorko(bitmap):
bmData = bitmap.LockBits(Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb)
total_bytes = (bmData.Stride) * bmData.Height
rgbValues = Array.CreateInstance(Byte, total_bytes)
Runtime.InteropServices.Marshal.Copy(bmData.Scan0, rgbValues, 0, total_bytes)
for i in rgbValues:
i = 255 - i
#The following line doesn't appear to actually copy the bits back
Runtime.InteropServices.Marshal.Copy(rgbValues, 0, bmData.Scan0, total_bytes)
bitmap.UnlockBits(bmData)
originalImage = Bitmap("Test.bmp")
newPic = NoWorko(originalImage)
newPic.Save("New.bmp")
Which is my interpretation of this MSDN code sample: http://msdn.microsoft.com/en-us/library/5ey6h79d.aspx except that I am saving the altered bitmap instead of displaying it in a Form.
The code runs, however the newly saved bitmap is an exact copy of the original image with no sign of any changes having occurred (it's supposed to create a red tint). Could anyone advise what's wrong with my code?
The image I'm using is simply a 24bpp bitmap I created in Paint (it's just a big white rectangle!), using IronPython 2.6 and on Windows 7 (x64) with .Net Framework 3.5 SP1 installed.
Update
My foolishness has been pointed out in trying to add a red tint to a white image - so now the code simply inverts the colours. I've tried this on a number of images, but it just doesn't seem to have any effect.
However, the following (very similar) C# program:
public static void Main(string[] args)
{
Bitmap bitmap = new Bitmap("nTest.jpg");
BitmapData bmData = bitmap.LockBits( new Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
int total_bytes = (bmData.Stride) * bmData.Height;
byte[] rgbValues = new byte[total_bytes];
Marshal.Copy(bmData.Scan0, rgbValues, 0, total_bytes);
for(int i = 0; i < total_bytes; i++)
{
rgbValues[i] = (byte)(255 - rgbValues[i]);
}
Marshal.Copy(rgbValues, 0, bmData.Scan0, total_bytes);
bitmap.UnlockBits(bmData);
bitmap.Save("nNew.jpg");
}
Worked on all the images I've tried.
I'm not sure, but it seems to be something to do with the call to:
Runtime.InteropServices.Marshal.Copy(rgbValues, 0, bmData.Scan0, bytes)
in IPY that is causing the problem.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我不懂Python,所以我不知道
应该如何工作。但如果它实际上将每个第三个字节设置为 255,则会遇到两个问题:
I don't know Python, so I have no idea how
is supposed to work. But provided that it actually sets each third byte to 255 you have two problems:
感谢 danbystrom 让我去检查一下——当我确信我做对了时,我的 for 循环语法完全混淆了。正确的语法应该是:
D'oh!但这只是表明让其他人质疑你在做什么的好处:)
Thanks to danbystrom for making me go and check this - it was my for loop syntax that was all mixed up, when I was certain I'd got it right. The correct syntax should have been:
D'oh! But it just goes to show the benefit of having other people question what you're doing :)