2

Image オブジェクトを反転したい。現在、私のコードは次のようになっています。

    private Image Invert(Image img)
    {
        var bmpPicture = new Bitmap(img.Width, img.Height);
        var iaPicture = new ImageAttributes();
        var cmPicture = new ColorMatrix { Matrix00 = -1, Matrix11 = -1, Matrix22 = -1 };
        iaPicture.SetColorMatrix(cmPicture);
        var gfxPicture = Graphics.FromImage(img);
        var rctPicture = new Rectangle(0, 0, img.Width, img.Height);
        gfxPicture.DrawImage(img, rctPicture, 0, 0, img.Width, img.Height, GraphicsUnit.Pixel, iaPicture);
        return bmpPicture;
    }

ただし、これを実行して で表示するとPictureBox、結果は黒い画像になります。これは、Windows 8 リリース プレビューの Visual Studio 2012 で実行しています。これを行うためのより良い方法があれば、私に知らせてください。ありがとう。

4

7 に答える 7

11

これを試してください:http://mariusbancila.ro/blog/2009/11/13/using-colormatrix-for-creating-negative-image/

public Bitmap Transform(Bitmap source)
{
    //create a blank bitmap the same size as original
    Bitmap newBitmap = new Bitmap(source.Width, source.Height);

    //get a graphics object from the new image
    Graphics g = Graphics.FromImage(newBitmap);

    // create the negative color matrix
    ColorMatrix colorMatrix = new ColorMatrix(new float[][]
    {
        new float[] {-1, 0, 0, 0, 0},
        new float[] {0, -1, 0, 0, 0},
        new float[] {0, 0, -1, 0, 0},
        new float[] {0, 0, 0, 1, 0},
        new float[] {1, 1, 1, 0, 1}
    }); 

    // create some image attributes
    ImageAttributes attributes = new ImageAttributes();

    attributes.SetColorMatrix(colorMatrix);

    g.DrawImage(source, new Rectangle(0, 0, source.Width, source.Height),
                0, 0, source.Width, source.Height, GraphicsUnit.Pixel, attributes);

    //dispose the Graphics object
    g.Dispose();

    return newBitmap;
}
于 2012-08-02T16:09:55.653 に答える
3

ピクセル操作に ColorMatrix を使用するための高速な代替手段:

public static void BitmapInvertColors(Bitmap bitmapImage)
{
    var bitmapRead   = bitmapImage.LockBits(new Rectangle(0, 0, bitmapImage.Width, bitmapImage.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppPArgb);
    var bitmapLength = bitmapRead.Stride * bitmapRead.Height;
    var bitmapBGRA   = new byte[bitmapLength];
    Marshal.Copy(bitmapRead.Scan0, bitmapBGRA, 0, bitmapLength);
    bitmapImage.UnlockBits(bitmapRead);

    for (int i = 0; i < bitmapLength; i += 4)
    {
        bitmapBGRA[i]     = (byte)(255 - bitmapBGRA[i]);
        bitmapBGRA[i + 1] = (byte)(255 - bitmapBGRA[i + 1]);
        bitmapBGRA[i + 2] = (byte)(255 - bitmapBGRA[i + 2]);
        //        [i + 3] = ALPHA.
    }

    var bitmapWrite = bitmapImage.LockBits(new Rectangle(0, 0, bitmapImage.Width, bitmapImage.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppPArgb);
    Marshal.Copy(bitmapBGRA, 0, bitmapWrite.Scan0, bitmapLength);
    bitmapImage.UnlockBits(bitmapWrite);
}
于 2014-06-23T23:41:59.767 に答える
1

Dan's Answer の VB バージョン。それは魅力のように機能します!!

 Public Function Transform(source As Bitmap) As Bitmap
    'create a blank bitmap the same size as original
    Dim newBitmap As New Bitmap(source.Width, source.Height)

    'get a graphics object from the new image
    Dim g As Graphics = Graphics.FromImage(newBitmap)

    ' create the negative color matrix
    Dim colorMatrix As New ColorMatrix(New Single()() {New Single() {-1, 0, 0, 0, 0}, New Single() {0, -1, 0, 0, 0}, New Single() {0, 0, -1, 0, 0}, New Single() {0, 0, 0, 1, 0}, New Single() {1, 1, 1, 0, 1}})

    ' create some image attributes
    Dim attributes As New ImageAttributes()

    attributes.SetColorMatrix(colorMatrix)

    g.DrawImage(source, New Rectangle(0, 0, source.Width, source.Height), 0, 0, source.Width, source.Height, _
        GraphicsUnit.Pixel, attributes)

    'dispose the Graphics object
    g.Dispose()

    Return newBitmap
End Function
于 2015-10-19T23:41:55.720 に答える
0

反転するということは、ネガを作るということですか?はいの場合、スニペットは次のとおりです。

public void ApplyInvert()
{
    byte A, R, G, B;
    Color pixelColor;

    for (int y = 0; y < bitmapImage.Height; y++)
    {
        for (int x = 0; x < bitmapImage.Width; x++)
        {
            pixelColor = bitmapImage.GetPixel(x, y);
            A = pixelColor.A;
            R = (byte)(255 - pixelColor.R);
            G = (byte)(255 - pixelColor.G);
            B = (byte)(255 - pixelColor.B);
            bitmapImage.SetPixel(x, y, Color.FromArgb((int)A, (int)R, (int)G, (int)B));
        }
    }

}

から: http://www.smokycogs.com/blog/image-processing-in-c-sharp-inverting-an-image/

問題とカラー マトリックスについて詳しく知りたい場合は、次のリンクに進んでください。

于 2012-08-02T14:42:13.183 に答える
0

「SIMD サポート ベクター」を使用して、ポインターよりも高速なコードを作成しました。System.Numerics 名前空間の下にあります。しかし、これらのクラスを使用する前に、NuGet から System.Numerics の更新を取得する必要があります。System.Numerics.Anyways を検索してください画像を反転するクラス

public class VBitmap : IDisposable
{        

    public short Width { get; private set; }
    public short Height { get; private set; }
    public int Stride { get; private set; }
    public int PixelLenght { get; private set; }
    public byte BytesperPixel { get; private set; }
    public PixelFormat PixelFormat { get; private set; }
    public byte[] Pixels { get; private set; }

    public VBitmap(string path)
    {
        using (Bitmap bmp = new Bitmap(path))
        {
            BitmapData bmpdata = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, bmp.PixelFormat);
            Width = checked((short)bmp.Width);
            Height = checked((short)bmp.Height);
            Stride = bmpdata.Stride;
            PixelLenght = Stride * Height;
            BytesperPixel = checked((byte)(Stride / Width));
            PixelLenght = (PixelLenght % 16) != 0 ? PixelLenght + (PixelLenght % 16) : PixelLenght;
            PixelFormat = bmp.PixelFormat;
            Pixels = new byte[PixelLenght];

            Marshal.Copy(bmpdata.Scan0, Pixels, 0, PixelLenght);
            bmp.UnlockBits(bmpdata);
        }
    }
    ~VBitmap()
    {
        Dispose();
    }

    public void InvertPixels()
    {
        byte[] resultarray = Pixels;
        unsafe
        {
            fixed (byte* result_ptr = resultarray)
            {
                for (int i = 0; i < PixelLenght; i += 16)
                    (~new Vector<byte>(Pixels, i)).CopyTo(resultarray, i);
            }
        }
    }

    public void InvertPixels(string name)
    {
        byte[] resultarray = Pixels;
        unsafe
        {
            fixed (byte* result_ptr = resultarray)
            {
                for (int i = 0; i < PixelLenght; i += 16)
                    (~new Vector<byte>(Pixels, i)).CopyTo(resultarray, i);
                SaveImage(name);
            }
        }
    }

    public unsafe void SaveImage(string name)
    {
        fixed (byte* p_ptr = Pixels)
        {
            using (Bitmap resultbmp = new Bitmap(Width, Height, Stride, PixelFormat, (IntPtr)p_ptr))
            {
                resultbmp.Save(name, ImageFormat.Jpeg);
            }
        }
    }

    public void Dispose()
    {
        Width = 0;
        Height = 0;
        Stride = 0;
        PixelLenght = 0;
        BytesperPixel = 0;
        Pixels = null;
        GC.Collect();
    }
}

Usage.Note: ベクトルから最高のパフォーマンスを得るには、リリース モードでコードを実行する必要があります。

static void Main(string[] args)
        {
            new VBitmap("testp.png").InvertPixels("qq.jpg");//Inverts the given bitmap and saves it.   
        }
于 2017-06-09T23:04:36.020 に答える
0

Matrix33またはを設定していませんMatrix44。私の理解では、それMatrix33はアルファ成分になるので、画像全体を透明にしているのではないかと思います.

設定してみてくださいMatrix33 = 1

于 2012-08-02T14:44:23.900 に答える
-1
var gfxPicture = Graphics.FromImage(img); 

==>

var gfxPicture = Graphics.FromImage(bmpPicture); 

DrawImage はイメージを歪める可能性があります。GetPixel は遅いです。WPF イメージング API を試してください。

于 2012-08-02T14:51:28.357 に答える