繁体   English   中英

如何旋转图片框图像中的色相?

[英]How do I rotate hue in a picturebox image?

首先,我要花4个小时探讨这个问题的各种变化。 大多数答案参考MSDN上的教程,这些教程涉及获取颜色块并绘制具有不同色调的新矩形。 这与我要执行的操作完全不同。 我想在图片框中拍摄图像,然后旋转整个图像的色相(从1到359度之间的任何位置)。

这个问题完美地展示了我想做的事情: 使用C#旋转Hue 不幸的是,答案参考的是C / C ++,而不是C#。 这是第一个,我没有代码可发布,因为没有什么事情可以完成我想要完成的工作。 谢谢。

编辑:我只是在使用一些我认为未成功的代码,结果是我的结果只是隐藏的,正在进行一些色相更改,而且很快,只是不正确。 到目前为止,这是我所拥有的:

    private void ColorRotation_Click(object sender, EventArgs e)
    {

        if (pictureBoxMain.Image != null)
        {
            Bitmap image = new Bitmap(pictureBoxMain.Image);
            ImageAttributes imageAttributes = new ImageAttributes();
            int width = image.Width;
            int height = image.Height;
            float degrees = 60f;
            double r = degrees * System.Math.PI / 180; // degrees to radians 

            float[][] colorMatrixElements = { 
            new float[] {(float)System.Math.Cos(r),  (float)System.Math.Sin(r),  0,  0, 0},
            new float[] {(float)-System.Math.Sin(r),  (float)-System.Math.Cos(r),  0,  0, 0},
            new float[] {0,  0,  2,  0, 0},
            new float[] {0,  0,  0,  1, 0},
            new float[] {0, 0, 0, 0, 1}};

            ColorMatrix colorMatrix = new ColorMatrix(colorMatrixElements);

            imageAttributes.SetColorMatrix(
               colorMatrix,
               ColorMatrixFlag.Default,
               ColorAdjustType.Bitmap);

            Graphics myGraphics = CreateGraphics();

            Rectangle myRectangle = new Rectangle();
            pictureBoxMain.Image = image; 
            myRectangle.Width = pictureBoxMain.Width; 
            myRectangle.Height = pictureBoxMain.Height; 
            myGraphics.DrawImage(pictureBoxMain.Image, myRectangle, 30, 50, myRectangle.Width, myRectangle.Height, GraphicsUnit.Pixel, imageAttributes); 
            pictureBoxMain.Refresh(); 
            }        
    }

这里有两个问题:

  1. 我以为“浮动度= 60f;” 会给我60度的旋转角度,结果我得到大约180度的旋转角度。 如何纠正这个问题,以便获得正确的色相旋转量? 我期望60度并获得180度是一个巨大的错误。

  2. 结果不会作为新图像添加到pictureBox中。 它在窗体上被绘制为矩形。 我找不到“ myGraphics.DrawImage()”的重载(我尝试了全部30个),该重载接受pictureBox以及所需的“ G​​raphicsUnit.Pixel”和“ imageAttributes”。 如何更新此代码,以便对图片框中的图像进行更改而不是在表单上绘制? 也许myGraphics.DrawImage()不是答案。

非常感谢

基于此处提供的RGB转换方案,此代码将对HueRotatePictureBox控件中的图像执行HueRotateAngleSelector.Value度的色相旋转:

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Windows.Forms;
...

private void HueRotateButton_Click(object sender, EventArgs e)
{
    // Get the cosine and sine of the selected hue rotation angle
    var radians = Math.PI * (double)HueRotateAngleSelector.Value / 180.0;
    var cos = Math.Cos(radians);
    var sin = Math.Sin(radians);

    // Calculate the elements of the RGB transformation matrix
    var a00 = 0.213 + cos * 0.787 - sin * 0.213;
    var a01 = 0.213 - cos * 0.213 + sin * 0.143;
    var a02 = 0.213 - cos * 0.213 - sin * 0.787;
    var a10 = 0.715 - cos * 0.715 - sin * 0.715;
    var a11 = 0.715 + cos * 0.285 + sin * 0.140;
    var a12 = 0.715 - cos * 0.715 + sin * 0.715;
    var a20 = 0.072 - cos * 0.072 + sin * 0.928;
    var a21 = 0.072 - cos * 0.072 - sin * 0.283;
    var a22 = 0.072 + cos * 0.928 + sin * 0.072;

    // Get the current image from the picture box control, ...
    var bitmap = (Bitmap)HueRotatePictureBox.Image;
    var width = bitmap.Width;
    var height = bitmap.Height;

    // ... and open it for modification
    var bitmapData = bitmap.LockBits(
        new Rectangle(0, 0, width, height),
        ImageLockMode.ReadWrite,
        PixelFormat.Format32bppArgb);

    var scan0 = bitmapData.Scan0;
    var stride = bitmapData.Stride;

    // Copy the image pixels to a local byte array
    var length = height * stride;
    var bytes = new byte[length];
    Marshal.Copy(scan0, bytes, 0, length);

    // Loop over all pixels in the image
    for (var y = 0; y < height; y++)
    {
        var offset = stride * y;
        for (var x = 0; x < width; x++, offset += 4)
        {
            // Get the original RGB components for the individual pixel
            // (the alpha component should not be changed and is therefore ignored)
            double b = bytes[offset];
            double g = bytes[offset + 1];
            double r = bytes[offset + 2];

            // Apply the hue rotation transform
            var rr = Math.Max(0.0, Math.Min(255.0, r * a00 + g * a10 + b * a20));
            var gr = Math.Max(0.0, Math.Min(255.0, r * a01 + g * a11 + b * a21));
            var br = Math.Max(0.0, Math.Min(255.0, r * a02 + g * a12 + b * a22));

            // Update the RGB components
            bytes[offset] = (byte)br;
            bytes[offset + 1] = (byte)gr;
            bytes[offset + 2] = (byte)rr;
        }
    }

    // Bitmap editing is finished, transfer the updated byte array to the image pixels 
    // and "lock" the image again
    Marshal.Copy(bytes, 0, scan0, length);
    bitmap.UnlockBits(bitmapData);

    // Update the image in the picture box
    HueRotatePictureBox.Image = bitmap;
}

上面的代码将拍摄如下图像:

在此处输入图片说明

180度的色相旋转会将其转换为:

在此处输入图片说明

注意! 上面的代码始终在图片框控件中获取当前图像并应用色相旋转。 因此,如果两次应用180°色相旋转您将返回到原始图像。 如果您希望始终对原始图像应用色相旋转,则应更新var bitmap =定义以始终从单独的位置选择原始图像。

UPDATE
改用GraphicsImageAttributesColorMatrix方法,可以将按钮事件处理程序编写如下:

private void HueRotateButton_Click(object sender, EventArgs e)
{
    // Get the cosine and sine of the selected hue rotation angle
    var radians = Math.PI * (double)HueRotateAngleSelector.Value / 180.0;
    var cos = (float)Math.Cos(radians);
    var sin = (float)Math.Sin(radians);

    // Create an image attributes object from a hue rotation color matrix
    var colorMatrix =
        new ColorMatrix(
            new[]
                {
                    new[] { 0.213f + cos * 0.787f - sin * 0.213f, 0.213f - cos * 0.213f + sin * 0.143f, 0.213f - cos * 0.213f - sin * 0.787f, 0f, 0f }, 
                    new[] { 0.715f - cos * 0.715f - sin * 0.715f, 0.715f + cos * 0.285f + sin * 0.140f, 0.715f - cos * 0.715f + sin * 0.715f, 0f, 0f },
                    new[] { 0.072f - cos * 0.072f + sin * 0.928f, 0.072f - cos * 0.072f - sin * 0.283f, 0.072f + cos * 0.928f + sin * 0.072f, 0f, 0f }, 
                    new[] { 0f, 0f, 0f, 1f, 0f }, 
                    new[] { 0f, 0f, 0f, 0f, 1f }
                });
    var imageAttributes = new ImageAttributes();
    imageAttributes.SetColorMatrix(colorMatrix);

    // Get the current image from the picture box control
    var bitmap = (Bitmap)HueRotatePictureBox.Image;
    var width = bitmap.Width;
    var height = bitmap.Height;

    // Get a graphics object of the bitmap and draw the hue rotation
    // transformed image on the bitmap area
    var graphics = Graphics.FromImage(bitmap);
    graphics.DrawImage(
        bitmap,
        new Rectangle(0, 0, width, height),
        0,
        0,
        width,
        height,
        GraphicsUnit.Pixel,
        imageAttributes);

    // Update the image in the picutre box
    HueRotatePictureBox.Image = bitmap;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM