在IronPython中使用Bitmap.LockBits和Marshal.Copy不按预期更改图像

时间:2010-04-03 13:01:39

标签: interop gdi+ ironpython

我编写了以下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中导致问题的

2 个答案:

答案 0 :(得分:1)

我不懂Python,所以我不知道如何

for i in rgbValues[::3]: 
        i = 255 

应该有效。但如果它实际上将每个第三个字节设置为255,则会出现两个问题:

  1. 通过将红色分量设置为255,您不能将颜色设置为红色,因为它已经具有该值。你必须减少蓝色和绿色组件。
  2. 当格式为24bpp( 使用32bpp时)时,您无法编写尝试一次更改位图所有像素的代码。你必须逐行扫描。

答案 1 :(得分:0)

感谢danbystrom让我去检查这个 - 这是我的for循环语法,当我确定我做对了时,它们都混乱了。应该是正确的语法:

for y in range(bmData.Height):
    for x in range(bmData.Width):
        rgbValues[(bmData.Stride * y) + (3 * x) +2] = 255

D'哦!但它只是表明让其他人质疑你在做什么的好处:)