Frage

Wie kann ich den Farbton eines Bildes mithilfe von GDI+ drehen? ImageAttributes (und vermutlich ColorMatrix)?

Beachten Sie, dass ich den Farbton drehen und nicht das Bild tönen möchte.

BEARBEITEN:Mit dem Drehen des Farbtons meine ich, dass jede Farbe im Bild in eine andere Farbe verschoben werden sollte, anstatt das gesamte Bild in einen Farbton einer Farbe zu verwandeln.

Zum Beispiel,

Original:http://www.codeguru.com/img/legacy/gdi/Tinter03.jpg

Gedreht: http://www.codeguru.com/img/legacy/gdi/Tinter15.jpg oder http://www.codeguru.com/img/legacy/gdi/Tinter17.jpg

War es hilfreich?

Lösung 2

Ich landete Portierung QColorMatrix C # und mit seiner RotateHue Methode.

Andere Tipps

Ich warf zusammen diese für diese Frage (ZIP-Datei mit Projekt c # an der Unterseite der verlinkten Post). Es verwendet nicht ImageAttributes oder ColorMatrix, aber es dreht sich um den Farbton wie Sie beschrieben haben:

//rotate hue for a pixel
private Color CalculateHueChange(Color oldColor, float hue)
{
    HLSRGB color = new HLSRGB(
        Convert.ToByte(oldColor.R),
        Convert.ToByte(oldColor.G),
        Convert.ToByte(oldColor.B));

    float startHue = color.Hue;
    color.Hue = startHue + hue;
    return color.Color;
}

Haben Sie gesehen diesem Artikel auf Codeproject?

Von einem zugegebenermaßen kurzen Blick auf der Seite sieht es aus wie 4D Mathematik. Sie können einen ähnlichen Ansatz verfolgen zu contstructing Matrizen wie für 2D- oder 3D-Mathematik.

Nehmen Sie eine Reihe von Quelle „Punkte“ - in diesem Fall werden Sie 4 müssen - und die entsprechenden Ziel „Punkte“ und eine Matrix erzeugen. Dies kann dann zu jedem „Punkt“ angewandt werden.

diese in 2D zu tun (aus dem Gedächtnis, so konnte ich einen kompletten Heuler in diesen gemacht habe):

Quellpunkte (1, 0) und (0, 1). Die Ziele sind (0, -1) und (1,0). Die Matrix Sie brauchen, ist:

(0, -1, 0)
(1,  0, 0)
(0,  0, 1)

Wenn die zusätzlichen Informationen für den „w“ Wert der Koordinate.

Erweitern Sie diese bis zu {R, G, B, A, w} und Sie werden eine Matrix haben. Nehmen Sie 4 Farben Rot (1, 0, 0, 0, w), Grün (0, 1, 0, 0, w), Blau (0, 0, 1, 0, w) und Transparent (0, 0, 0, 1, w). Trainieren Sie, welche Farben die in der Umgebung in das neue System und bauen Sie Ihre Matrix wie folgt:

  

(R 1 , G 1 , B 1 A 1 , 0)
  (R 2 , G 2 , B 2 A 2 , 0)
  (R 3 , G 3 , B 3 A 3 , 0)
  (R 4 , G 4 , B 4 A 4 , 0)
  (0, 0, 0, 0, 1)

Hinweis: Die Reihenfolge Sie tun Sie mulitplication (Vektor * Matrix oder eine Matrix * Vektor) wird geprüft, ob die transformierten Punkte gehen vertikal oder horizontal in diese Matrix als Matrixmultiplikation nichtkommutative ist. Ich gehe davon aus Vektor * Matrix.

Dies ist eine alte Frage, aber Lösungen geschrieben sind viel komplizierter als die einfache Antwort, die ich gefunden.

Ganz einfach:

  • keine externe Abhängigkeit
  • keine komplizierte Berechnung (keine Bezifferung einen Drehwinkel aus, keine etwas Cosinus Formel Anwendung)
  • tatsächlich tut, eine Drehung von Farben!

Neuformulierung des Problems: Was brauchen wir

I vorbereitet Icons rot gefärbt. Einige Bereiche sind transparent, einige sind mehr oder weniger gesättigt, aber sie haben alle roten Farbton. Ich glaube, es entspricht Ihren sehr gut Anwendungsfall. Die Bilder können auch andere Farben haben, werden sie nur gedreht werden.

Wie die Tönung darstellen bewerben? Die einfachste Antwort ist: a. Color liefern

Arbeiten an einer Lösung

ColorMatrix eine lineare Transformation.

Natürlich, wenn Farbe rot ist, sollte die Transformation Identität sein. Wenn Farbe grün ist, sollte die Transformation rote Karte zu grün, grün zu blau, blau bis rot.

Ein Colormatrix, das tut dies:

0 1 0 0 0
0 0 1 0 0
1 0 0 0 0
0 0 0 1 0
0 0 0 0 1

Mathematische Lösung

Der "Aha" Trick besteht darin, zu erkennen, dass die tatsächliche Form der Matrix

R G B 0 0
B R G 0 0
G B R 0 0
0 0 0 1 0
0 0 0 0 1

, wobei R, G und B ist einfach die Komponente der Abtönfarbe!

Beispielcode

Ich habe Beispiel-Code auf https://code.msdn.microsoft.com / Colormatrix-Bild-Filter-f6ed20ae .

ich es eingestellt und das ist eigentlich in meinem Projekt verwenden:

static class IconTinter
{
    internal static Bitmap TintedIcon(Image sourceImage, Color tintingColor)
    {
        // Following https://code.msdn.microsoft.com/ColorMatrix-Image-Filters-f6ed20ae
        Bitmap bmp32BppDest = new Bitmap(sourceImage.Width, sourceImage.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);

        float cr = tintingColor.R / 255.0f;
        float cg = tintingColor.G / 255.0f;
        float cb = tintingColor.B / 255.0f;

        // See [Rotate Hue using ImageAttributes in C#](http://stackoverflow.com/a/26573948/1429390)
        ColorMatrix colorMatrix = new ColorMatrix(
            new float[][]
                       {new float[] { cr,  cg,  cb,  0,  0}, 
                        new float[] { cb,  cr,  cg,  0,  0}, 
                        new float[] { cg,  cb,  cr,  0,  0}, 
                        new float[] {  0,   0,   0,  1,  0}, 
                        new float[] {  0,   0,   0,  0,  1}
                       }
                       );

        using (Graphics graphics = Graphics.FromImage(bmp32BppDest))
        {
            ImageAttributes bmpAttributes = new ImageAttributes();
            bmpAttributes.SetColorMatrix(colorMatrix);

            graphics.DrawImage(sourceImage,
                new Rectangle(0, 0, sourceImage.Width, sourceImage.Height),
                0, 0,
                sourceImage.Width, sourceImage.Height,
                GraphicsUnit.Pixel, bmpAttributes);

        }

        return bmp32BppDest;
    }
}

Hope, das hilft.

Begrenzung

  • Beachten Sie, dass die Transformation sättigen kann, wenn man zu helle Farben verwenden. Um keine Sättigung zu gewährleisten, tt ist ausreichend, dass R + G + B <= 1.
  • Sie können die Transformation normalisieren, indem man cr, cg, cb von Cr + cg + cb aber den Fall behandeln, in denen Tönungsfarbe schwarz ist, oder Sie werden durch Null teilen.

Der folgende Code erstellt a ColorMatrix zum Anwenden einer Farbtonverschiebung.

Die Erkenntnis, die ich hatte, war, dass bei einer 60°-Verschiebung im Farbtonraum:

  • rot -> grün
  • grün -> blau
  • blau -> rot

ist eigentlich eine 45°-Verschiebung im RGB-Raum:

enter image description here

Sie können also einen Bruchteil einer 120°-Verschiebung in einen Bruchteil einer 90°-Verschiebung umwandeln.

Der HueShift Parameter muss ein Wert zwischen sein -1..1.

Um beispielsweise eine 60°-Verschiebung anzuwenden:

  • rot zu gelb wechseln,
  • wechselt von gelb nach grün
  • wechselt von Grün zu Cyan
  • Cyan in Blau ändern
  • Blau in Magenta ändern
  • Magenta in Rot ändern

Du rufst an:

var cm = GetHueShiftColorMatrix(60/360); //a value between 0..1

Implementierung:

function GetHueShiftColorMatrix(HueShift: Real): TColorMatrix;
var
    theta: Real;
    c, s: Real;
const
    wedge = 120/360;
begin
    if HueShift > 1 then
        HueShift := 0
    else if HueShift < -1 then
        HueShift := 0
    else if Hueshift < 0 then
        HueShift := 1-HueShift;

    if (HueShift >= 0) and (HueShift <= wedge) then
    begin
        //Red..Green
        theta := HueShift / wedge*(pi/2);
        c := cos(theta);
        s := sin(theta);

        cm[0, 0] :=  c; cm[0, 1] :=  0; cm[0, 2] :=  s; cm[0, 3] :=  0; cm[0, 4] := 0;
        cm[1, 0] :=  s; cm[1, 1] :=  c; cm[1, 2] :=  0; cm[1, 3] :=  0; cm[1, 4] := 0;
        cm[2, 0] :=  0; cm[2, 1] :=  s; cm[2, 2] :=  c; cm[2, 3] :=  0; cm[2, 4] := 0;
        cm[3, 0] :=  0; cm[3, 1] :=  0; cm[3, 2] :=  0; cm[3, 3] :=  1; cm[3, 4] := 0;
        cm[4, 0] :=  0; cm[4, 1] :=  0; cm[4, 2] :=  0; cm[4, 3] :=  0; cm[4, 4] := 1;
    end
    else if (HueShift >= wedge) and (HueShift <= (2*wedge)) then
    begin
        //Green..Blue
        theta := (HueShift-wedge) / wedge*(pi/2);
        c := cos(theta);
        s := sin(theta);

        cm[0, 0] :=  0; cm[0, 1] :=  s; cm[0, 2] :=  c; cm[0, 3] :=  0; cm[0, 4] := 0;
        cm[1, 0] :=  c; cm[1, 1] :=  0; cm[1, 2] :=  s; cm[1, 3] :=  0; cm[1, 4] := 0;
        cm[2, 0] :=  s; cm[2, 1] :=  c; cm[2, 2] :=  0; cm[2, 3] :=  0; cm[2, 4] := 0;
        cm[3, 0] :=  0; cm[3, 1] :=  0; cm[3, 2] :=  0; cm[3, 3] :=  1; cm[3, 4] := 0;
        cm[4, 0] :=  0; cm[4, 1] :=  0; cm[4, 2] :=  0; cm[4, 3] :=  0; cm[4, 4] := 1;
    end
    else
    begin
        //Blue..Red
        theta := (HueShift-2*wedge) / wedge*(pi/2);
        c := cos(theta);
        s := sin(theta);

        cm[0, 0] :=  s; cm[0, 1] :=  c; cm[0, 2] :=  0; cm[0, 3] :=  0; cm[0, 4] := 0;
        cm[1, 0] :=  0; cm[1, 1] :=  s; cm[1, 2] :=  c; cm[1, 3] :=  0; cm[1, 4] := 0;
        cm[2, 0] :=  c; cm[2, 1] :=  0; cm[2, 2] :=  s; cm[2, 3] :=  0; cm[2, 4] := 0;
        cm[3, 0] :=  0; cm[3, 1] :=  0; cm[3, 2] :=  0; cm[3, 3] :=  1; cm[3, 4] := 0;
        cm[4, 0] :=  0; cm[4, 1] :=  0; cm[4, 2] :=  0; cm[4, 3] :=  0; cm[4, 4] := 1;
    end;

    Result := cm;
end;

Notiz:Jeder Code wird öffentlich zugänglich gemacht.Keine Quellenangabe erforderlich.

Ich nehme an, dass www.aforgenet.com helfen könnte

Ich baue eine Methode, die @IanBoid Code in C # implementieren.

    public void setHueRotate(Bitmap bmpElement, float value) {

        const float wedge = 120f / 360;

        var hueDegree = -value % 1;
        if (hueDegree < 0) hueDegree += 1;

        var matrix = new float[5][];

        if (hueDegree <= wedge)
        {
            //Red..Green
            var theta = hueDegree / wedge * (Math.PI / 2);
            var c = (float)Math.Cos(theta);
            var s = (float)Math.Sin(theta);

            matrix[0] = new float[] { c, 0, s, 0, 0 };
            matrix[1] = new float[] { s, c, 0, 0, 0 };
            matrix[2] = new float[] { 0, s, c, 0, 0 };
            matrix[3] = new float[] { 0, 0, 0, 1, 0 };
            matrix[4] = new float[] { 0, 0, 0, 0, 1 };

        } else if (hueDegree <= wedge * 2)
        {
            //Green..Blue
            var theta = (hueDegree - wedge) / wedge * (Math.PI / 2);
            var c = (float) Math.Cos(theta);
            var s = (float) Math.Sin(theta);

            matrix[0] = new float[] {0, s, c, 0, 0};
            matrix[1] = new float[] {c, 0, s, 0, 0};
            matrix[2] = new float[] {s, c, 0, 0, 0};
            matrix[3] = new float[] {0, 0, 0, 1, 0};
            matrix[4] = new float[] {0, 0, 0, 0, 1};

        }
        else
        {
            //Blue..Red
            var theta = (hueDegree - 2 * wedge) / wedge * (Math.PI / 2);
            var c = (float)Math.Cos(theta);
            var s = (float)Math.Sin(theta);

            matrix[0] = new float[] {s, c, 0, 0, 0};
            matrix[1] = new float[] {0, s, c, 0, 0};
            matrix[2] = new float[] {c, 0, s, 0, 0};
            matrix[3] = new float[] {0, 0, 0, 1, 0};
            matrix[4] = new float[] {0, 0, 0, 0, 1};
        }

        Bitmap originalImage = bmpElement;

        var imageAttributes = new ImageAttributes();
        imageAttributes.ClearColorMatrix();
        imageAttributes.SetColorMatrix(new ColorMatrix(matrix), ColorMatrixFlag.Default, ColorAdjustType.Bitmap);

        grpElement.DrawImage(
            originalImage, elementArea,
            0, 0, originalImage.Width, originalImage.Height,
            GraphicsUnit.Pixel, imageAttributes
            );
    }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top