C#图像过滤器的Parallel.For需要较长时间 [英] c# image filter parallel.for takes longer time

查看:157
本文介绍了C#图像过滤器的Parallel.For需要较长时间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里的代码有什么办法可以让它更快导致其slowerden单

 公共位图pSetInvert(位图_currentBitmap) 
{
位图TEMP =(位图)_currentBitmap;
位图BMAP =(位图)temp.Clone();
彩色℃;
的Parallel.For(0,bmap.Width,我= GT;
{
锁(BMAP)
{
为(INT J = 0; J< bmap.Height; J ++)
{
C = bmap.GetPixel(I,J);
bmap.SetPixel(I,J,Color.FromArgb(255 - CR,255 - 鸟苷,255 - CB));
}
}
});
回报率(位图)bmap.Clone();
}


解决方案

通过使用锁定你正在你的代码的并行部分连续工作,酷似与同步开销单线程应用程序,它实际上会更慢。



下面是直接访问位图数据的辅助类,你可以同时处理图片



FastImage助手类:

 使用系统; 
使用System.Drawing中;
使用System.Drawing.Imaging;
:使用System.IO;使用System.Runtime.InteropServices
;

命名空间ImageManipulation
{
类FastImage:IDisposable的
{
私人位图_buffer;
私人字节[] _rawData;
私人的GCHandle _rawHandle;
私人诠释_formatSize;
私人诠释_width;
私人诠释_height;

公众诠释宽度
{
{返回_width; }
}

公众诠释身高
{
得到{_height; }
}

公众的byte [] GetRawData()
{
返回_rawData;
}

公共字节这个[INT指数]
{
{返回_rawData [指数] }
集合{_rawData [指数] =值; }
}

众彩这[INT X,INT Y]
{
得到
{
返回与getPixel(X,Y) ;
}

{
与setPixel(X,Y,值);
}
}

公共颜色与getPixel(INT X,int y)对
{
VAR偏移量= Y * _width * _formatSize;
偏差+ = X * _formatSize;
返回Color.FromArgb(_rawData [偏移+ 3],_rawData [偏移+ 2],_rawData [偏移+ 1],_rawData [偏移]);
}

公共无效与setPixel(INT X,INT Y,色值)
{
VAR偏移量= Y * _width * _formatSize;
偏差+ = X * _formatSize;

_rawData [抵销] = value.B;
_rawData [偏移+ 1] = value.G;
_rawData [偏移+ 2] = value.R;
_rawData [偏移+ 3] = value.A;

}

私人FastImage(){}

公共静态FastImage创建(图片来源)
{
变种图像=新FastImage();

变种bmpSource =新位图(源);
变种bmpData = bmpSource.LockBits(新矩形(0,0,source.Width,source.Height),System.Drawing.Imaging.ImageLockMode.ReadWrite,bmpSource.PixelFormat);

image._width = source.Width;
image._height = source.Height;

image._formatSize = 4;
VAR跨距= bmpSource.Width * image._formatSize;
image._rawData =新的字节[步幅* bmpSource.Height]。
image._rawHandle = GCHandle.Alloc(image._rawData,GCHandleType.Pinned);
变种指针= Marshal.UnsafeAddrOfPinnedArrayElement(image._rawData,0);
image._buffer =新位图(bmpSource.Width,bmpSource.Height,步幅,PixelFormat.Format32bppArgb /*bmpSource.PixelFormat*/,指针);
bmpSource.UnlockBits(bmpData);

VAR显卡= Graphics.FromImage(image._buffer);

graphics.DrawImageUnscaledAndClipped(bmpSource,新的Rectangle(0,0,source.Width,source.Height));
graphics.Dispose();

返回图像;
}

公共无效的Dispose()
{
_rawHandle.Free();
_buffer.Dispose();
}

公共无效保存(流流)
{
_buffer.Save(流ImageFormat.Bmp);
}

公共位图ToBitmap()
{
回报率(位图)_buffer.Clone();
}
}
}

和这里使用的代码 FastImage 类:

 公共位图pSetInvert(位图_currentBitmap)
{使用
(VAR BMAP = FastImage.Create(_currentBitmap))
{
的Parallel.For(0,bmap.Width,我= GT;
{
对于(INT J = 0; J< bmap.Height; J ++)
{
变种C = bmap.GetPixel(I,J);
bmap.SetPixel(I,J,颜色.FromArgb(255 - CR,255 - 字幕机,255 - CB));

}
});
返回bmap.ToBitmap();
}
}


here is the code is there any way to make it faster cause its slowerden single

public Bitmap pSetInvert(Bitmap _currentBitmap)
    {
        Bitmap temp = (Bitmap)_currentBitmap;
        Bitmap bmap = (Bitmap)temp.Clone();
        Color c;
        Parallel.For(0, bmap.Width, i =>
        {
            lock (bmap)
            {
                for (int j = 0; j < bmap.Height; j++)
                {
                    c = bmap.GetPixel(i, j);
                    bmap.SetPixel(i, j, Color.FromArgb(255 - c.R, 255 - c.G, 255 - c.B));
                } 
            }
        });
        return (Bitmap)bmap.Clone();
    }

解决方案

By using lock you are making parallel part of your code to work serially, exactly like a single thread application with synchronization overhead so it actually would be slower.

here is a helper class that access bitmap data directly and you can manipulate image in concurrently.

FastImage Helper Class:

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;

namespace ImageManipulation
{
    class FastImage : IDisposable
    {
        private Bitmap _buffer;
        private byte[] _rawData;
        private GCHandle _rawHandle;
        private int _formatSize;
        private int _width;
        private int _height;

        public int Width
        {
            get { return _width; }
        }

        public int Height
        {
            get { return _height; }
        }

        public byte[] GetRawData()
        {
            return _rawData;
        }

        public byte this[int index]
        {
            get { return _rawData[index]; }
            set { _rawData[index] = value; }
        }

        public Color this[int x, int y]
        {
            get
            {
                return GetPixel(x, y);
            }
            set
            {
                SetPixel(x, y, value);
            }
        }

        public Color GetPixel(int x, int y)
        {
            var offset = y*_width*_formatSize;
            offset += x*_formatSize;
            return Color.FromArgb(_rawData[offset + 3], _rawData[offset + 2], _rawData[offset + 1], _rawData[offset]);
        }

        public void SetPixel(int x, int y, Color value)
        {
            var offset = y*_width*_formatSize;
            offset += x*_formatSize;

            _rawData[offset] = value.B;
            _rawData[offset + 1] = value.G;
            _rawData[offset + 2] = value.R;
            _rawData[offset + 3] = value.A;

        }

        private FastImage() { }

        public static FastImage Create(Image source)
        {
            var image = new FastImage();

            var bmpSource = new Bitmap(source);
            var bmpData = bmpSource.LockBits(new Rectangle(0, 0, source.Width, source.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, bmpSource.PixelFormat);

            image._width = source.Width;
            image._height = source.Height;

            image._formatSize = 4;
            var stride = bmpSource.Width * image._formatSize;
            image._rawData = new byte[stride * bmpSource.Height];
            image._rawHandle = GCHandle.Alloc(image._rawData, GCHandleType.Pinned);
            var pointer = Marshal.UnsafeAddrOfPinnedArrayElement(image._rawData, 0);
            image._buffer = new Bitmap(bmpSource.Width, bmpSource.Height, stride, PixelFormat.Format32bppArgb /*bmpSource.PixelFormat*/, pointer);
            bmpSource.UnlockBits(bmpData);

            var graphics = Graphics.FromImage(image._buffer);

            graphics.DrawImageUnscaledAndClipped(bmpSource, new Rectangle(0, 0, source.Width, source.Height));
            graphics.Dispose();

            return image;
        }

        public void Dispose()
        {
            _rawHandle.Free();
            _buffer.Dispose();
        }

        public void Save(Stream stream)
        {
            _buffer.Save(stream, ImageFormat.Bmp);
        }

        public Bitmap ToBitmap()
        {
            return (Bitmap)_buffer.Clone();
        }
    }
}

and here is your code using FastImage class:

 public Bitmap pSetInvert(Bitmap _currentBitmap)
        {
            using (var bmap = FastImage.Create(_currentBitmap))
            {
                Parallel.For(0, bmap.Width, i =>
                {
                    for (int j = 0; j < bmap.Height; j++)
                    {
                        var c = bmap.GetPixel(i, j);
                        bmap.SetPixel(i, j, Color.FromArgb(255 - c.R, 255 - c.G, 255 - c.B));

                    }
                });
                return bmap.ToBitmap();
            }
        }

这篇关于C#图像过滤器的Parallel.For需要较长时间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆