Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi [GR32] How to add intensity? (https://www.delphipraxis.net/146557-%5Bgr32%5D-how-add-intensity.html)

WojTec 22. Jan 2010 11:27


[GR32] How to add intensity?
 
I have simple procedure to add color filter to bitmap:

Delphi-Quellcode:
Row.R := (Color.R * Row.R) div 255;
// Repeat for G and B
How to add Intensity parameter (0=original color, 100=as above)?
Or maybe is better method to colorize filter?

Medium 22. Jan 2010 13:25

Re: [GR32] How to add intensity?
 
I haven't really understood what you do with this particular filter, but it looks like you're looking for simple linear interpolation, where you can shift beween two values freely.

Delphi-Quellcode:
function Lerp(a, b: Byte; t: Double): Byte;
var
  tmp: Double;
begin
  tmp := t*a + (1-t)*b;
  if tmp<0 then result := 0 else
  if tmp>255 then result := 255 else
  result := Round(tmp);
end;

procedure YourFilter(Percent: Integer);
begin
  Row.R := Lerp(Color.R, (Color.R*Row.R) div 255, Percent/100);
  //...
end;

WojTec 22. Jan 2010 15:04

Re: [GR32] How to add intensity?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Something similar (Lerp() coloring too much - up to solid color). I mean like this:

http://i46.tinypic.com/2077v9w.png

:)

jfheins 22. Jan 2010 15:43

Re: [GR32] How to add intensity?
 
I would do something like this:

1. You have the "target color" (full brightness and saturation) and the amount you want to blend (between 0 and 1)

2. For each Pixel do:
2.1: multiply the target color with the brightness of the image pixel
2.2: mix the image pixel and the result from 2.1 together, according to the amount.

:arrow: (1-x) * image_pixel + x * (color * image_pixel_brightness)

The Brigness of a pixel is calculated by adding up all the components and dividung the result by 3. However, there is an advanced formula that weights the colors differently.

fkerber 22. Jan 2010 16:02

Re: [GR32] How to add intensity?
 
Hi!

@WojTec:
Could you please attach the image instead of including it in the posting?
This would decrease loading times and the thread is still useful, even if the image has gone on the other server.

Thanks in advance.

Bye,
Frederic

Medium 22. Jan 2010 16:40

Re: [GR32] How to add intensity?
 
Zitat:

Zitat von WojTec
Something similar (Lerp() coloring too much - up to solid color).

:gruebel: Lerp() can be used for just this. Use the original color of a pixel as first parameter, and the color of that pixel as if the effect was applied fully as second. Pass any value between 0 and 1 as third parameter, and get a linear interpolation between the original and the fully affected color. What exactly is your problem? You might also want to provide some more of your actual code alongside, and possibly some sample output too, helping to describe what the difference between the desired and the achieved effect is.

WojTec 22. Jan 2010 16:59

Re: [GR32] How to add intensity?
 
@jfheins, I'm doing something wrong :(:

Delphi-Quellcode:
var
  Row: PBGRAQuad;
  Color: TBGRAQuad;
  I, J: Integer;
  B: Byte;
  C: TColor;
begin
  Color := ColorToTriple24(AColor);
  Row := PBGRAQuad(@ASource.Bits[0]);

  for I := 0 to ASource.Height - 1 do
  begin
    for J := 0 to ASource.Width - 1 do
    begin
      B := (Row.R + Row.G + Row.B) div 3;
      C := TColor(Round((1 - (APercent / 100)) * RGB(Row.R, Row.G, Row.B) + (APercent / 100) * (RGB(Color.R, Color.G, Color.B) * B)));

      Row.R := GetRValue(C);
      Row.G := GetGValue(C);
      Row.B := GetBValue(C);

      Inc(Row);
    end;
  end;
end;
@fkerber, Ok, I'll remmeber.

WojTec 22. Jan 2010 17:07

Re: [GR32] How to add intensity?
 
@Medium, when Color is for example clYellow and 3rd parameter is 1, any pixel of output is = Color. This is wrong - should be as is on example image above.

fkerber 22. Jan 2010 17:49

Re: [GR32] How to add intensity?
 
Hi!

Zitat:

Zitat von WojTec
@fkerber, Ok, I'll remmeber.

Thanks!
You could also do so in the above posting. It's possible by editing the posting (To do this, click on the button "edit" in the upper right corner).


Bye, Frederic

Medium 22. Jan 2010 19:03

Re: [GR32] How to add intensity?
 
Zitat:

Zitat von WojTec
@Medium, when Color is for example clYellow and 3rd parameter is 1, any pixel of output is = Color. This is wrong - should be as is on example image above.

Oops, I switched the "t" and "(1-t)". Just exchange these, and you're good to go.

Regarding the code you posted: You cannot simply multiply with whole combined RGB-values. You must handle each color channel separately.

WojTec 22. Jan 2010 19:19

Re: [GR32] How to add intensity?
 
@Medium, after exchanges this values, 0% is solid color output.

When intensity is 100% image should be 100% in Color tone, when 50% - in 50% Color tone and 50% original colors (look image).

Medium 22. Jan 2010 19:22

Re: [GR32] How to add intensity?
 
If this is not what you get after the change, please post the whole part of your source. Otherwise we won't come far here. I won't ask for it a third time, since the code you provided had little to do with the Lerp() function, and as such can't relate to the problem. (It should work as well if you handled each channel separately, as already said.)

WojTec 23. Jan 2010 11:01

Re: [GR32] How to add intensity?
 
Liste der Anhänge anzeigen (Anzahl: 2)
Ok, let's start from begining. What I need: I want to add color filter to image with intensity parameter. Output should be like on image from post #3. My current code:

Delphi-Quellcode:
Row.R := (Color.R * Row.R) div 255;
Row.G := (Color.G * Row.G) div 255;
Row.B := (Color.B * Row.B) div 255;
Example output from my code:

(see 1.png, left part - 0%)

Now output with @Medium proposition:

Delphi-Quellcode:
function Lerp(a, b: Byte; t: Double): Byte;
var
  tmp: Double;
begin
  tmp := t*a + (1-t)*b;
  if tmp<0 then result := 0 else
  if tmp>255 then result := 255 else
  result := Round(tmp);
end;

Row.R := Lerp(Color.R, (Color.R * Row.R) div 255, APercent / 100);
Row.G := Lerp(Color.G, (Color.G * Row.G) div 255, APercent / 100);
Row.B := Lerp(Color.B, (Color.B * Row.B) div 255, APercent / 100);
(see 1.png)

And @jfheins (or maybe I don't understand your formula and coded wrong?):

Delphi-Quellcode:
B := (Row.R + Row.G + Row.B) div 3;
Row.R := IntToByte(Round((1 - (APercent / 100)) * Row.R + (APercent / 100) * (Color.R * B)));
Row.G := IntToByte(Round((1 - (APercent / 100)) * Row.G + (APercent / 100) * (Color.G * B)));
Row.B := IntToByte(Round((1 - (APercent / 100)) * Row.B + (APercent / 100) * (Color.B * B)));
(see 2.png)

Medium 23. Jan 2010 15:27

Re: [GR32] How to add intensity?
 
As I already said, change the line
tmp := t*a + (1-t)*b;
to
tmp := (1-t)*a + t*b;

Another thing is, that it's not clear to me, which variable holds the original color. Color or Row? If it's Row, then change
Row.R := Lerp(Color.R, (Color.R * Row.R) div 255, APercent / 100);
to
Row.R := Lerp(Row.R, (Color.R * Row.R) div 255, APercent / 100);

And yet another thing unclear to me is, if your initial formula does create the desired effect or not. If it isn't, then my code of course cannot function! It isn't really clear what your problem was: Just the ability to apply it at different percentages, or this AND the formula.
Edit: Scrub the last part, the formula itself looks fine. The two changes above should do well if I interpret the output correctly.

WojTec 23. Jan 2010 17:28

Re: [GR32] How to add intensity?
 
Liste der Anhänge anzeigen (Anzahl: 1)
This is procedure:

Delphi-Quellcode:
var
  Bits: PColor32Entry;
  Color: TColor32Entry;
  I, J: Integer;
  Percent: Single;
begin
  Color.ARGB := Color32(AColor);
  Percent := APercent / 100;
  Bits := @ASource.Bits[0];

  for I := 0 to ASource.Height - 1 do
  begin
    for J := 0 to ASource.Width - 1 do
    begin
      Bits.R := Lerp(Bits.R, (Color.R * Bits.R) div 255, Percent);
      Bits.G := Lerp(Bits.G, (Color.G * Bits.G) div 255, Percent);
      Bits.B := Lerp(Bits.B, (Color.B * Bits.B) div 255, Percent);

      Inc(Bits);
    end;
  end;

  ASource.Changed;
end;
After your latest suggestion percenta parameter work fine :D

But my formula don't makes filter I want... My EN is too poor to explain better what I want :( But I'll try: you have glass with specific color, when you look by this glass you see image in this glass color tone. When you use more thin glass (percent parameter has less value) in same color, you see more origanl image colors, but image you see stay in this glass color tone. Are you understand? I want to obtain filter like this glass. In graphics software you can see this filter, for example in PSP (Effects->Photo effects->Film and filters).

"Row" I used with TBitpam.ScanLine() and forgot change name ;)

Medium 23. Jan 2010 18:22

Re: [GR32] How to add intensity?
 
Aha! You basically want a color tint. The 100% formula for this is:

Brightness := (original.R + original.G + original.B)/(3*255) // normalized to 0..1
NewColor := RGB(tint.R*Brightness, tint.G*Brightness, tint.B*Brightness)

That is what jfheins already wrote, I suppose your implementation had rounding issues or did not normalize brightness (I'm too lazy to verfy this now :)).

This should do the trick:
Delphi-Quellcode:
var
  Bits: PColor32Entry;
  Color: TColor32Entry;
  I, J: Integer;
  Percent: Single;
  Brightness: Single;
begin
  Color.ARGB := Color32(AColor);
  Percent := APercent / 100;
  Bits := @ASource.Bits[0];

  for I := 0 to ASource.Height - 1 do
  begin
    for J := 0 to ASource.Width - 1 do
    begin
      Brightness := (Bits.R+Bits.G+Bits.B)/765;
      Bits.R := Lerp(Bits.R, Round(Brightness * Color.R), Percent);
      Bits.G := Lerp(Bits.G, Round(Brightness * Color.G), Percent);
      Bits.B := Lerp(Bits.B, Round(Brightness * Color.B), Percent);

      Inc(Bits);
    end;
  end;

  ASource.Changed;
end;
As a refinement, you could calculate the brightness weighted according to the suggestion by the JPEG commité, that accounts for green being percieved brightest, followed by red and blue darkest at equal values.
The line
Brightness := (Bits.R+Bits.G+Bits.B)/765;
would then look like
Brightness := (0.299*Bits.R + 0.587*Bits.G + 0.114*Bits.B)/765;

It's a few operations more, but might improve the result notably.

WojTec 25. Jan 2010 11:55

Re: [GR32] How to add intensity?
 
Wow, thanks! It working! Man, lets teach me graphic processing :D How you learn it? I want too! Could you suggest some good sources?
Output is a bit darker than input, but can it correct with next filters ;)

Zitat:

Zitat von Medium
suggestion by the JPEG commité

Brightness := (0.299*Bits.R + 0.587*Bits.G + 0.114*Bits.B)/765;

I thought this is NTSC suggestion?
Also uotput is very dark with this brightness version.
I used it early to remove colors and output is always lighter than classic Sum(RGB)/3. So why here is darker?

Medium 25. Jan 2010 13:25

Re: [GR32] How to add intensity?
 
Zitat:

Zitat von WojTec
How you learn it?

This might sound old, but I learned by doing. I have a general interest in graphics, so my spare time projects often are somehow related. And every time I hit a wall, I fire up good ole oncle google and find something eventually -> *pow* knowledge enhanced :)
I couldn't even recommend any general sources or books, since all I do is basically self-taught by doing, fiddeling around and reading stuff on the internet. It certainly wasn't a matter of days or weeks though ;)

Zitat:

I thought this is NTSC suggestion?
Also uotput is very dark with this brightness version.
I used it early to remove colors and output is always lighter than classic Sum(RGB)/3. So why here is darker?
Could be that this originated with NTSC. I encountered it first when I had to deal with the details of JPEG :angel2:. That the "flat" (sum/3) approach appears darker is understandable. Why the weighted formula also results in a darker image might be cause by that you probably have R and B switched. Bitmap data in memory is usually stored in BGR order, not RGB. Thus simply switching R with B in your TColor32Entry record will probably correct this.

WojTec 25. Jan 2010 13:58

Re: [GR32] How to add intensity?
 
Delphi-Quellcode:
property Bits: PColor32Array read FBits;

TColor32Array = array [0..0] of TColor32;

TColor32Entry = packed record
  case Integer of
    0: (B, G, R, A: Byte);
    1: (ARGB: TColor32);
    2: (Planes: array[0..3] of Byte);
    3: (Components: array[TColor32Component] of Byte);
end;

function Color32(WinColor: TColor): TColor32; overload;
{$IFDEF WIN_COLOR_FIX}
var
  I: Longword;
{$ENDIF}
begin
{$IFDEF CLX}
  WinColor := ColorToRGB(WinColor);
{$ELSE}
  if WinColor < 0 then WinColor := GetSysColor(WinColor and $000000FF);
{$ENDIF}
 
{$IFDEF WIN_COLOR_FIX}
  Result := $FF000000;
  I := (WinColor and $00FF0000) shr 16;
  if I <> 0 then Result := Result or TColor32(Integer(I) - 1);
  I := WinColor and $0000FF00;
  if I <> 0 then Result := Result or TColor32(Integer(I) - $00000100);
  I := WinColor and $000000FF;
  if I <> 0 then Result := Result or TColor32(Integer(I) - 1) shl 16;
{$ELSE}
  asm
        MOV   EAX,WinColor
        BSWAP EAX
        MOV   AL,$FF
        ROR   EAX,8
        MOV   Result,EAX
  end;
{$ENDIF}
end;
There are not my symbols, there are in GR32. I'm using this record in all filters and look to be correct :)

Medium 25. Jan 2010 14:14

Re: [GR32] How to add intensity?
 
Mh, then there is no obvious reason for this darkening. You could use your reference output and compare a white-tinted image (= implicit conversion to grayscales) of just a pure red, green and blue area to derive the weights they used, to make your output similar to it. That is, if you approve of the reference :)

WojTec 12. Jun 2010 19:02

AW: [GR32] How to add intensity?
 
Hello again. I have yet another question in this topic. How to add option "preserve luminosity" to our tint procedure? Currently working very well, but I want to apply tint as creative filter - now my tint working as in PS or PSP but with unchecked "preserve luminosity". Please help :)


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:50 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