编程语言
首页 > 编程语言> > c#-使用安全代码将频道从一个图像复制到另一个

c#-使用安全代码将频道从一个图像复制到另一个

作者:互联网

我试图使用System.Runtime.InteropServices.Marshal.Copy重构此不安全的代码,以将单个ARGB通道从一个图像复制到另一个图像,如本例中MSDN所示,但我完全迷失了.

谁能指导我完成我的工作?

public enum ChannelARGB
{
    Blue = 0,
    Green = 1,
    Red = 2,
    Alpha = 3
}

public static void transferOneARGBChannelFromOneBitmapToAnother(
    Bitmap source,
    Bitmap dest,
    ChannelARGB sourceChannel,
    ChannelARGB destChannel )
{
    if ( source.Size!=dest.Size )
        throw new ArgumentException();
    Rectangle r = new Rectangle( Point.Empty, source.Size );
    BitmapData bdSrc = source.LockBits( r, 
                                        ImageLockMode.ReadOnly, 
                                        PixelFormat.Format32bppArgb );
    BitmapData bdDst = dest.LockBits( r, 
                                      ImageLockMode.ReadWrite,
                                      PixelFormat.Format32bppArgb );
    unsafe
    {
        byte* bpSrc = (byte*)bdSrc.Scan0.ToPointer();
        byte* bpDst = (byte*)bdDst.Scan0.ToPointer();
        bpSrc += (int)sourceChannel;
        bpDst += (int)destChannel;
        for ( int i = r.Height * r.Width; i > 0; i-- )
        {
            *bpDst = *bpSrc;
            bpSrc += 4;
            bpDst += 4;
        }
    }
    source.UnlockBits( bdSrc );
    dest.UnlockBits( bdDst );
}

编辑

为了尝试通过@Ben Voigt walk,尽管到目前为止我已经提出了这个建议.不幸的是,我现在收到以下错误:

Attempted to read or write protected memory. This is often an
indication that other memory is corrupt.

    private static void TransferOneArgbChannelFromOneBitmapToAnother(
                                         Bitmap source,
                                         Bitmap destination, 
                                         ChannelARGB sourceChannel, 
                                         ChannelARGB destinationChannel)
    {
        if (source.Size != destination.Size)
        {
            throw new ArgumentException();
        }

        Rectangle rectangle = new Rectangle(Point.Empty, source.Size);

        // Lockbits the source.
        BitmapData bitmapDataSource = source.LockBits(rectangle,
                                                  ImageLockMode.ReadWrite,
                                                  PixelFormat.Format32bppArgb);

        // Declare an array to hold the bytes of the bitmap.
        int bytes = bitmapDataSource.Stride * bitmapDataSource.Height;

        // Allocate a buffer for the source image
        byte[] sourceRgbValues = new byte[bytes];

        // Get the address of the first line.
        IntPtr ptrSource = bitmapDataSource.Scan0;

        // Copy the RGB values into the array.
        System.Runtime.InteropServices.Marshal.Copy(ptrSource, 
                                                    sourceRgbValues, 
                                                    0, 
                                                    bytes);

        // Unlockbits the source.
        source.UnlockBits(bitmapDataSource);

        // Lockbits the destination.
        BitmapData bitmapDataDestination = destination.LockBits(rectangle,
                                                  ImageLockMode.ReadWrite,
                                                  PixelFormat.Format32bppArgb);

        // Allocate a buffer for image
        byte[] destinationRgbValues = new byte[bytes];

        IntPtr ptrDestination = bitmapDataDestination.Scan0;

        // Copy the RGB values into the array.
        System.Runtime.InteropServices.Marshal.Copy(ptrDestination,
                                                    destinationRgbValues, 
                                                    0, 
                                                    bytes);

        ptrSource += (int)sourceChannel;
        ptrDestination += (int)destinationChannel;

        for (int i = rectangle.Height * rectangle.Width; i > 0; i--)
        {
            destinationRgbValues[i] = sourceRgbValues[i];
            ptrSource += 4;
            ptrDestination += 4;
        }

        // Copy the RGB values back to the bitmap
        // ******This is where I am getting the exception*******.
        System.Runtime.InteropServices.Marshal.Copy(destinationRgbValues, 
                                                    0, 
                                                    ptrDestination, 
                                                    bytes);

        // Unlock bits the destination.
        destination.UnlockBits(bitmapDataDestination);
    }

谁能看到我做错了吗?老实说,这有点让我烦恼.我想我应该买一些书.

解决方法:

> LockBits源.
>元帅.将源BitmapData复制到byte []缓冲区.
>解锁源.
> LockBits目的地.
>元帅.将目标BitmapData复制到byte []缓冲区.
>遍历并将该通道从源字节[]复制到目标字节[](请注意,对索引而不是对指针使用算术运算)
>元帅.将目标字节[]复制回BitmapData.
>解锁目标.

不过,我不确定这是什么意思.使用Marshal.Copy的代码与使用unsafe关键字的代码一样危险,并且应该需要类似的代码安全权限.

可能更有效的方法是使用ImageAttributes.SetColorMatrix从目标图像中删除所需的通道,从源图像中删除所有其他通道,然后进行融合.参见示例ColorMatrix

或者使用DirectX(或OpenGL)和仅传输一个通道的着色器.

标签:gdi-2,c
来源: https://codeday.me/bug/20191201/2079271.html