Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi Vignette effect (https://www.delphipraxis.net/154568-vignette-effect.html)

WojTec 15. Sep 2010 17:57


Vignette effect
 
Hello. I want to draw vignette effect, but don't have idea how to do this? For graphics I'm using GR32. Could you help?

mkinzler 15. Sep 2010 18:08

AW: Vintage effect
 
What do you think of "vintage Effect"?

WojTec 15. Sep 2010 18:13

Re: Vignette effect
 
Sorry, I used bad word :cry: I mean vignette. I now corrected.

sx2008 16. Sep 2010 00:56

AW: Vignette effect
 
You could calculate the brightness of every Pixel with a 2-dimensional Gaussian function.
Here is some Pseudocode:
Delphi-Quellcode:
xcenter := Bitmap.Width div 2;
ycenter := Bitmap.Height div 2;
for each Pixel do
begin
  brightness_factor := mygaussian(x - xcenter, y-ycenter)* 0.5{=effect depth} + 0.3{basic brightness};
  Pixel[x,y].red  := Pixel[x,y].red * brightness_factor;
  Pixel[x,y].green := Pixel[x,y].green * brightness_factor;
  Pixel[x,y].blue := Pixel[x,y].blue * brightness_factor;
end;
It it works, you could replace the mygaussian() function with other possibly better functions.

WojTec 16. Sep 2010 09:21

Re: Vignette effect
 
It's clear all, but not how to implement Gaussian function, I don't understand it too much :cry:

Delphi-Quellcode:
function TwoDimensionalGaussian(X, Y: Single): Single;
var
  a, b, c: Single;
begin

end;
I don't know how to "fill" this function. I'm also not sure parameters and result types, Single are correct? :(

sx2008 17. Sep 2010 23:19

AW: Vignette effect
 
I think the following function is faster and easier to understand
than the gaussian function:

Delphi-Quellcode:
function CalcVignetteBrightness(X, Y: Single): Single;
var
  distance : Single;
  inner_radius, outer_radius : Single;
begin
  inner_radius := 50;
  outer_radius := 150;

  // calculate the distance from the origin (center of the image)
  distance := SQRT(SQR(x) + SQR(Y));
 
  if distance <= inner_radius then
    result := 1.0   // Brightness 100%
  else if distance <= outer_radius then
    // decreasing Brightness from 100% downto 0%
    result := (distance - inner_radius) / (outer_radius - inner_radius)
  else
    result := 0.0; // it's dark outside the outer_radius
end;

WojTec 18. Sep 2010 13:09

Re: Vignette effect
 
This is what I have:

Delphi-Quellcode:
function VignetteBrightness(X, Y: Single): Single;
var
  distance: Single;
  inner_radius, outer_radius: Single;
begin
  inner_radius := 50;
  outer_radius := 150;

  // calculate the distance from the origin (center of the image)
  distance := SQRT(SQR(x) + SQR(Y));

  if distance <= inner_radius then
    result := 1.0 // Brightness 100%
  else if distance <= outer_radius then
    // decreasing Brightness from 100% downto 0%
    result := (distance - inner_radius) / (outer_radius - inner_radius)
  else
    result := 0.0; // it's dark outside the outer_radius
end;

procedure Vignette(ASource: TBitmap32);
var
  Bits: PColor32Entry;
  I, J, XCenter, YCenter: Integer;
  Brightness: Single;
begin
  XCenter := ASource.Width div 2;
  YCenter := ASource.Height div 2;

  Bits := @ASource.Bits[0];

  for J := 0 to ASource.Height - 1 do
  begin
    for I := 0 to ASource.Width - 1 do
    begin
      Brightness := VignetteBrightness(I - XCenter, J - YCenter) * 0.5{=effect depth} + 0.3{basic brightness};

      Bits.R := IntToByte(Round(Bits.R + Brightness));
      Bits.G := IntToByte(Round(Bits.G + Brightness));
      Bits.B := IntToByte(Round(Bits.B + Brightness));

      Inc(Bits);
    end;
  end;

  ASource.Changed;
end;
And no effect - image not changed. Why?
I tried change inner_radius, outer_radius, effect depth and basic brightness, bot no effect too :(

sx2008 18. Sep 2010 13:43

AW: Re: Vignette effect
 
Zitat:

Zitat von WojTec (Beitrag 1050420)
And no effect - image not changed. Why?

You must multiply with the brightness factor.
And you have to care about arithmetic overflow.

Delphi-Quellcode:
function ClampByte(value:Integer):Byte;
begin
  if value > 255 then
    result := 255
  (* not neccesary when a pixel is multiplied with a positive value
  else if value < 0
    result := 0
  *)
  else
    result := Byte(value);
end;
...
Bits.R := ClampByte(Round(Bits.R * Brightness));

WojTec 18. Sep 2010 14:30

Re: Vignette effect
 
Ah, of course, that's my mistake :D
Ok, working, but not exactly as should - darker should be near edges, not center as is now ;)

sx2008 18. Sep 2010 15:19

AW: Re: Vignette effect
 
Zitat:

Zitat von WojTec (Beitrag 1050434)
Ok, working, but not exactly as should - darker should be near edges, not center as is now ;)

Hmm ,there is a little bug:
Delphi-Quellcode:
  else if distance <= outer_radius then
    // decreasing Brightness from 100% downto 0%
//    result := (distance - inner_radius) / (outer_radius - inner_radius) // wrong
    result := (outer_radius - distance) / (outer_radius - inner_radius)

WojTec 18. Sep 2010 18:36

Re: Vignette effect
 
You are great! This is much faster than my method: I draw white shape on black or grey (or in other grey scale color) background, apply blur and finally blend with image - effect is powerful, but blur part is very slow if greater radius is used.

Can I ask yet one more question? Your nice brightness function generates circle - is possible to use ellipse in image orientation?

xZise 18. Sep 2010 20:58

AW: Vignette effect
 
You could also apply this on an ellipse. The main idea is, to reduce the brightness depending on the distance to the edge.
So you have the width/height and the location (x, y). Now you must change the inner/outer radius from a absolute to a relative value.

Argh :P at the moment I'm too tired to explain this complete.

Fabian

sx2008 18. Sep 2010 23:28

AW: Vignette effect
 
Delphi-Quellcode:
function CalcVignetteBrightness(X, Y: Single): Single;
var
  distance : Single;
  inner_radius, outer_radius, : Single;
begin
  inner_radius := 50;
  outer_radius := 150;
  x := x * 0.75; // <= try this

  // calculate the distance from the origin (center of the image)
  distance := SQRT(SQR(x) + SQR(Y));

turboPASCAL 19. Sep 2010 06:43

AW: Vignette effect
 
Liste der Anhänge anzeigen (Anzahl: 1)
Mal eine Frage, sollte das Ergebnis nicht so aussehen ? (Image 1)
Bei eurer Methode kommt das dabei heraus. (Image 2)

xZise 19. Sep 2010 10:48

AW: Vignette effect
 
Moin,
hast du sein Bugfix eingebaut:
Zitat:

Zitat von sx2008 (Beitrag 1050439)
Zitat:

Zitat von WojTec (Beitrag 1050434)
Ok, working, but not exactly as should - darker should be near edges, not center as is now ;)

Hmm ,there is a little bug:
Delphi-Quellcode:
  else if distance <= outer_radius then
    // decreasing Brightness from 100% downto 0%
//    result := (distance - inner_radius) / (outer_radius - inner_radius) // wrong
    result := (outer_radius - distance) / (outer_radius - inner_radius)

MfG
Fabian

turboPASCAL 19. Sep 2010 11:45

AW: Vignette effect
 
Wie meinst du denn das ? I don't speak English.

WojTec 19. Sep 2010 12:03

Re: Vignette effect
 
X multiply something is nice, I added support for ellipse based on image oriantation. Thanks guys :)

My current slow methed I told yesterday (based on blured shape) - do you know method fast like the one by @sx2008, but with any shape (rectangle, rounded rectangle, ellipse and any other)?

PS: @sx2008, your algorithm is named?

xZise 20. Sep 2010 13:18

AW: Vignette effect
 
Zitat:

Zitat von turboPASCAL (Beitrag 1050541)
Wie meinst du denn das ? I don't speak English.

Er hat bei der Subtraktion die zwei Werte vertauscht. Die musst du auch vertauchen, damit es passt. Es ist nämlich der Faktor wie hell das Pixel ist. 1 = 100 % = ursprüngliche Helligkeit und 0 = 0 % = komplett dunkel ist der Rückgabewert.
Jetzt gibt es ein Radius der bestimmt, ab wann es nicht mehr dunkler wird. Und es gibt auch einen Radius der bestimmt ab wann es nicht mehr heller wird.

Jetzt nimmt er den Abstand dazwischen, d.h. den Radius (das steht unter den Bruch). Und zusätzlich berechnet er über den Bruch, wie weit der Punkt vom Mittelpunkt entfernt ist (distance) und setzt das in Relation zum äußeren Radius (outer_radius). Umso größer die Distanz zum Mittelpunkt umso kleiner wird der unterschied zum äußeren Radius, somit sinkt der Wert über den Bruch und damit der komplette Bruch.

Meine Theorie ist, dass du die falsche Version genommen hast, zumindest sieht das invertierte so aus.

MfG
Fabian


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:52 Uhr.

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