Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi Color mixer (https://www.delphipraxis.net/165379-color-mixer.html)

WojTec 27. Dez 2011 13:53

Color mixer
 
I'm trying implement this tool:

Code:
http://www.design-lib.com/color_tool_mixer.php
I already have this:

Delphi-Quellcode:
type
  TColorArray = array of TColor;

function GetColors(const C1, C2: TColor; Steps: Byte): TColorArray;

function Blend(Color1, Color2: TColor; A: Byte): TColor; // by R. M. Klever
var
  c1, c2: LongInt;
  r, g, b, v1, v2: byte;
begin
  A:= Round(2.55 * A);
  c1 := ColorToRGB(Color1);
  c2 := ColorToRGB(Color2);
  v1:= Byte(c1);
  v2:= Byte(c2);
  r:= A * (v1 - v2) shr 8 + v2;
  v1:= Byte(c1 shr 8);
  v2:= Byte(c2 shr 8);
  g:= A * (v1 - v2) shr 8 + v2;
  v1:= Byte(c1 shr 16);
  v2:= Byte(c2 shr 16);
  b:= A * (v1 - v2) shr 8 + v2;
  Result := (b shl 16) + (g shl 8) + r;
end;

var
  V, T: Byte;
begin
  SetLength(Result, 0);

  V := 100 div (Steps + 1);
  T := 0;

  while T < 100 do
  begin
    Inc(T, V);

    SetLength(Result, Length(Result) + 1);
    Result[High(Result)] := Blend(C1, C2, T);
  end;
end;
I don't know, don't want to working as expected, F1 :sad:

WojTec 27. Dez 2011 16:08

Re: Color mixer
 
Delphi-Quellcode:
var
  V, T: Byte;
begin
  SetLength(Result, 0);

  V := 100 div (EnsureRange(ASteps, 1, 64) + 1);
  T := V;

  while (T < 100) and (100 - T >= V) do
  begin
    SetLength(Result, Length(Result) + 1);
    Result[High(Result)] := BlendColors(AColor1, AColor2, T);

    Inc(T, V);
  end;
end;
F1 :(

jaenicke 27. Dez 2011 16:29

AW: Color mixer
 
Unfortunately you forgot to tell us what does happen instead of what should have happened.

And I do not know where you use this function and how you use this function.

WojTec 27. Dez 2011 18:24

Re: Color mixer
 
Did you saw link above? So, generaly thera are 2 colors on input and on output I want to array with n colors between input colors - it mean not full gradient, but just n colors.

jaenicke 27. Dez 2011 18:50

AW: Color mixer
 
I understood what you want to do but I have no idea what your problem is. Does the code result in a wrong display? Or do you have a problem when you try to use the code? At the moment I am not at home, I will continue there...

WojTec 27. Dez 2011 20:37

Re: Color mixer
 
  1. It returns different colors than above script.
  2. When steps > 15 then returns more colors than I want (in other words for steps 1-15 array has 1-15 colors, for more steps array hase more colors than should contain, eg for 16 it contains 19 colors or for 64 --> 99).

Maybe my idea is good but imprecise?

freeway 27. Dez 2011 21:19

AW: Color mixer
 
for 100 div (64 + 1) = 1 so you get 100 steps also 100 div (16 +1) = 5 you get 20 steps

Delphi-Quellcode:
 
var V,T : single;
    S : byte;

  V := 100 / (Steps + 1);
  T := 0;

  while T < 100 do
  begin
    T := T + V;    //add real
    S := trunc(T); //get byte
    SetLength(Result, Length(Result) + 1);
    Result[High(Result)] := Blend(C1, C2, S);
  end;
end;

Aphton 28. Dez 2011 05:12

AW: Color mixer
 
Liste der Anhänge anzeigen (Anzahl: 1)
Delphi-Quellcode:
uses Math;
(...)
function GetColors(const C1, C2: TColor; Steps: Byte): TColorArray;

function Blend(const Color1, Color2: TColor; const A: Byte): TColor; // by Aphton
var
  dA : Single;
  c1  : Array[0..3] of Byte Absolute Color1;
  c2  : Array[0..3] of Byte Absolute Color2;
  rs : Array[0..3] of Byte Absolute Result;
begin
  dA   := A/100;
  rs[0] := Round(c1[0] + (c2[0] - c1[0]) * dA);
  rs[1] := Round(c1[1] + (c2[1] - c1[1]) * dA);
  rs[2] := Round(c1[2] + (c2[2] - c1[2]) * dA);  
  rs[3] := 0;
end;

var
  i: Integer;
  V, T: Byte;
begin
  if Steps < 3 then Exit;

  SetLength(Result, Steps);
  dec(Steps);

  Result[0] := C1;
  Result[Steps] := C2;

  V := 100 div Steps;
  T := 0;

  for i := 1 to Steps - 1 do
  begin
    inc(T, V);
    Result[i] := Blend(C1, C2, Min(T, 100));
  end;
end;
10 Steps on color_tool_mixer.php = 12 with GetColors() (including Color1 and Color2)
Results in...

Furtbichler 28. Dez 2011 07:41

AW: Color mixer
 
Die Sache mit dem
Delphi-Quellcode:
V := 100 div Steps;
ist unglücklich und führt zu ungenauen Ergebnissen.

Wieso nicht einfach eine Mischroutine schreiben, die einen Float-Wert als Mischungsverhältnis akzeptiert (also einfach die von Aphton leicht umschreiben).

Delphi-Quellcode:
function Blend(const Color1, Color2: TColor; const MixRatio: Double): TColor; // by Aphton
var
   c1 : Array[0..3] of Byte Absolute Color1;
   c2 : Array[0..3] of Byte Absolute Color2;
   rs : Array[0..3] of Byte Absolute Result;
begin
   rs[0] := Round(c1[0] + (c2[0] - c1[0]) * MixRatio);
   rs[1] := Round(c1[1] + (c2[1] - c1[1]) * MixRatio);
   rs[2] := Round(c1[2] + (c2[2] - c1[2]) * MixRatio);
   rs[3] := 0;
end;
...

Delta := 1/Steps;
MixRatio := 0;
For i:=0 To Steps-1 do begin
  ColorArray[i] := MixColors(Color1, color2, MixRatio);
  MixRatio := MixRatio + Delta
End;
Wer komplett auf Floatingpointarithmetik verzichten will, kann es so probieren
Delphi-Quellcode:
function Blend(const Color1, Color2: TColor; const MixColor1, MixColor2 : Integer): TColor; // by Aphton
// Mische zwei Farben im Verhältnis MixColor1:MixColor2
var
   c1 : Array[0..3] of Byte Absolute Color1;
   c2 : Array[0..3] of Byte Absolute Color2;
   rs : Array[0..3] of Byte Absolute Result;
   MixColors : Integer;

begin
   MixColors := MixColor1 + MixColor2;
   rs[0] := Min(255, (c1[0]*MixColor1 + c2[0]*MixColor2) div MixColors);
   rs[1] := Min(255, (c1[0]*MixColor1 + c2[0]*MixColor2) div MixColors);
   rs[2] := Min(255, (c1[0]*MixColor1 + c2[0]*MixColor2) div MixColors);
   rs[3] := 0;
end;

...
For i:=1 To Steps-1 do
  ColorArray[i] := MixColors(Color1, color2, i, Steps - i - 1);
Die Integer-Variante könnte marginal andere Ergebnisse liefern (sofern sie denn funktioniert).

Aphton 28. Dez 2011 07:59

AW: Color mixer
 
Ja stimmt, so ist es eig. besser.
Ich habs ja auch nur schnell hingeschrieben, nicht groß überlegt, sry xD

WojTec 28. Dez 2011 15:34

Re: Color mixer
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hi, thanks!

Float point version working, but: first element in result is first input color, then steps-1 are real steps. Why?

Second int version is making black-white gradient, why?

Iwo Asnet 28. Dez 2011 15:49

AW: Color mixer
 
There is a small error in the float-version: If you want 3 steps, you need a delta of 0.5 (0->0.5->1.0), so Delta should be 1/(Steps-1);

Delphi-Quellcode:
Delta := 1/ (Steps-1);
MixRatio := 0;
For i:=0 To Steps-1 do begin
  ColorArray[i] := MixColors(Color1, color2, MixRatio);
  MixRatio := MixRatio + Delta
End;
For question #2 I leave it up to you to find the error yourself (I found it in 5 secs).

WojTec 28. Dez 2011 16:01

Re: Color mixer
 
Thanks, I tried it too, but I forgot about ( and ) :-D

And what about BW gradient from int version?

Furtbichler 28. Dez 2011 18:27

AW: Re: Color mixer
 
Zitat:

Zitat von WojTec (Beitrag 1143502)
And what about BW gradient from int version?

I also...
Zitat:

leave it up to you to find the error yourself.
Hint: It's a copy & paste error in the Blend-Function

WojTec 19. Apr 2012 19:48

Re: Color mixer
 
Liste der Anhänge anzeigen (Anzahl: 1)
Guys, how to do something similar, but with color wheel, mean not only 2 colors gradient, but N colors beetwen 2 input colors?

Furtbichler 20. Apr 2012 00:17

AW: Color mixer
 
Are you lazy? Blend Color1->Color2, then Color2->Color3 etc.

WojTec 23. Mai 2012 17:10

Re: Color mixer
 
I don't understand you, what I need to blend with?

Medium 23. Mai 2012 18:11

AW: Color mixer
 
He means that you simply need to string pairwise blended colors together. That's the common way of doing it, and most probably also the by far easiest, especially if you have gradients for two colors already implemented (since it's the same thing, just done a few times in a row).

WojTec 24. Mai 2012 08:37

Re: Color mixer
 
When I'll blend red and magenta (above image) I'll get RGB(255, 0, 127), this color isn't in example output. So, I still don't understand what I need to blend? :(

Medium 24. Mai 2012 09:44

AW: Color mixer
 
Ah! You don't want to blend with multiple preset colors in between, but using a different color model I suppose! The above looks like the blending was done in HSV or HSL space. (Don't know if right- or left-handed hue, but that should be simple enough to try out.) So instead of blending using RGB, just do it in HSV/HSL. That should get you pretty close to the above result.

WojTec 24. Mai 2012 14:25

Re: Color mixer
 
RGB(255, 0, 0) = HSL(0, 100, 50)
RGB(255, 0, 255) = HSL(300, 100, 50)
add H/S/L values and divide by 2
result HSL(300, 200, 100) = RGB(0, 255, 128)
result is similar to color 3 in sample

Is this good way? :cyclops: Ah, I don't think so :(

Medium 24. Mai 2012 15:50

AW: Color mixer
 
Well, there is a multitude of possible ways to tweak this. And since we do not know where your sample came from, if you need to reproduce it exactly and how your original reference actually does it, we can merely try and try and try to get closer to it step by step. With only one sample and no way to see what other border colors should produce, this is as far as it gets - at least if we exclude further utter guesswork.

WojTec 24. Mai 2012 16:03

Re: Color mixer
 
So, gradient haven't to be identical as in sample. I just want to know way to get something similar ;) Could you post some example, please?

Medium 25. Mai 2012 08:38

AW: Re: Color mixer
 
I just saw, that my HSL idea could still work, since you made an error in your example:

RGB(255, 0, 0) = HSL(0, 100, 50)
RGB(255, 0, 255) = HSL(300, 100, 50)
add H/S/L values and divide by 2 you forgot the latter ;)
result HSL(300150, 200100, 10050) = I don't have a converter handy, but I am pretty confident, that this will look a lot more like what you want

WojTec 25. Mai 2012 20:32

Re: Color mixer
 
Oh, you've right, thanks ;)

Ok, I'm trying make blender in HSL space and I did it:

Delphi-Quellcode:
// get both colors HSL values to HSL1 and HSL2

H := Round((MaxHue / 100) * AValue) * (HSL2[0] - HSL1[0]) shr 8 + HSL1[0];
S := Round((MaxSat / 100) * AValue) * (HSL2[1] - HSL1[1]) shr 8 + HSL1[1];
L := Round((MaxLum / 100) * AValue) * (HSL2[2] - HSL1[2]) shr 8 + HSL1[2];

// set result as TColor
This is working. Now 2 questions: this is working in CW mode (as you see on the image posted early), how to make it in CCW? And second one, how to get n colors form this gradient, like in you proposed in RGB mode?

Medium 25. Mai 2012 23:08

AW: Color mixer
 
CW or CCW depends a little on how you draw the color circle. The mathematical positive direction is CCW, which also seems to be the common way to draw it. To make it CW, you can just flip the two colors and reverse the generated gradient :)


The multicolor thingy is something quite different: It's for when you want to blend between two colors, but need to define a specific color that should be reached somewhere in the middle of that gradient. Say like you had red->blue, but now you want yellow in there red->yellow->blue. For this you can just make two gradients: red->yellow, yellow->blue, and draw them connected. For the individual gradient parts, you could use whatever gradient method you want, i.e. in RGB or HSL or any other color space of course.
This may seem blatant, but to avoid any confusion :) (And at first it seemed like you wanted a gradient with multiple color points defined along the gradient.)

WojTec 26. Mai 2012 19:23

Re: Color mixer
 
Liste der Anhänge anzeigen (Anzahl: 1)
CCW I mean something like in attachement (this is in HSB, but idea is identical) ;)

Ok, but problem is, how to get these gradient points? To draw I can use HSL blend function (above; and for example don't use 100 percents, but let's say 4, 8, ... and get 25 colors instead 100) and all will be ok. But I want to get up to 256 colors between 2 colors on HSL wheel (like 256 colors in RGB on begin of this thread) ;)

Medium 26. Mai 2012 20:26

AW: Color mixer
 
Internal color calculation should always be done in floating point, unless for realtime purposes. Usually channels (regardless of the color model) are considered to range from 0 to 1 (exception: YCC, where chroma is -.5 to .5). Only when performing the actual drawing, the float colors are scaled into the target image's color format. That way you would not have the problem, and also minimize quantization errors across the entire application, that are quite prone to emerge when doing multiple and different processes on the same image.

I do not however understand your issue with the (C)CW gradients. CCW -> blend Color1 to Color2. CW -> blend Color2 to Color1, and reverse the resulting list of colors.

freeway 26. Mai 2012 21:32

AW: Color mixer
 
what you call gradient is the result from HSL wheel reduced to 100

if you add the colors and the result goes over 100 what will you get then ?

100 - actual value = new value

WojTec 16. Aug 2012 17:21

Re: Color mixer
 
I'm trying and nothing :(

For blend in HSL I have this. Please, how to get what I'm talking about :?:

WojTec 17. Aug 2012 13:35

Re: Color mixer
 
Delphi-Quellcode:
var
  RGB: array [0..2] of Byte;
  HSL1, HSL2: array [0..2] of Integer;
  H, S, L: Integer;
begin
  // get values here

  // Max* vars are = 256
  H := Round((MaxHue / ARange) * AValue) * (HSL2[0] - HSL1[0]) shr 8 + HSL1[0];
  S := Round((MaxSat / ARange) * AValue) * (HSL2[1] - HSL1[1]) shr 8 + HSL1[1];
  L := Round((MaxLum / ARange) * AValue) * (HSL2[2] - HSL1[2]) shr 8 + HSL1[2];

  /// set color here
end;

SetLength(A, Round(edtSteps.Value) + 2);
A[0] := Color1;
A[High(A)] := Color2;

N := 255 div (Round(edtSteps.Value) + 1);
X := 0;
Caption := IntToStr(N);
for I := 1 to High(A) - 1 do
begin
  Inc(X, N);
  A[I] := BlendColorsHueCW(Color1, Color2, Byte(X), 255);
end;
F1 :cry:


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:27 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz