ImageResizer  3.4.0
 All Classes Namespaces Functions Variables Enumerations Enumerator Properties Events
Public Member Functions | Static Public Member Functions | Public Attributes | List of all members
ImageResizer.Plugins.RedEye.AdaptiveCircleFill Class Reference

Adaptive thresholding flood fill optimized for round objects. More...

Collaboration diagram for ImageResizer.Plugins.RedEye.AdaptiveCircleFill:
Collaboration graph
[legend]

Public Member Functions

 AdaptiveCircleFill (UnmanagedImage red, System.Drawing.Point startAt, PointF origin, float maxRadius)
 
void FirstPass ()
 
void SecondPass ()
 
unsafe void SetPixel (UnmanagedImage target, int x, int y, byte[] color)
 
unsafe void MarkFilledPixels (UnmanagedImage target, int xoffset, int yoffset, byte[] color)
 
UnmanagedImage GetBlurredMask ()
 
unsafe void CorrectRedEye (UnmanagedImage image, int ox, int oy)
 Using the fill array calculated in passes 1 and 2, apply red-eye correction to the specified image. More...
 

Static Public Member Functions

static void MarkEye (UnmanagedImage image, Point start, int maxEyeRadius, float maxPointSearchDistance=0)
 

Public Attributes

UnmanagedImage red
 An 8-bit image with a redness algorithm applied. More...
 
System.Drawing.Point StartAt
 The pixel at which to begin filling More...
 
byte MinValue = 80
 The absolute minimum brightness to include. Should probably be set to 3/8ths the maximum pixel brightness. More...
 
byte MaxValue = 255
 The maximum brightness expected. Used to provide a range for threshold expectations More...
 
PointF Origin
 The user-specified origin - used to adjust local thresholding. More...
 
double OriginStartOffset
 The distance between origin and startat More...
 
float MaxRadius
 The maximum radius around StartAt in which to fill More...
 
long SumX = 0
 Sum of the X values of all filled pixels. More...
 
long SumY = 0
 Sum of the Y values of all filled pixels More...
 
long SumV = 0
 Sum of the values of all filled pixels More...
 
long FilledCount = 0
 The number of filled pixels. More...
 
PointF WeightedCenter
 Set after the first pass, once we know the appropriate center More...
 
float FilledRadius
 Set after the first pass, once we know the farthest outlying point. More...
 
byte FillAverage
 The average value of the filled area More...
 
bool[,] filledArray
 An array matching the bitmap data, marking which pixels are considered filled. More...
 

Detailed Description

Adaptive thresholding flood fill optimized for round objects.

Definition at line 15 of file AdaptiveCircleFill.cs.

Constructor & Destructor Documentation

ImageResizer.Plugins.RedEye.AdaptiveCircleFill.AdaptiveCircleFill ( UnmanagedImage  red,
System.Drawing.Point  startAt,
PointF  origin,
float  maxRadius 
)
inline

Parameters
redA grayscale image filtered using a redness algorithm
startAtThe maximum brightness point, the place to start filling
originThe origin of the search, usually the click
maxRadiusThe maximum distance from 'startAt' to consider filling

Definition at line 24 of file AdaptiveCircleFill.cs.

24  {
25  this.red = red;
26  this.StartAt = startAt;
27  MaxValue = red.Collect8bppPixelValues(new List<AForge.IntPoint>(new AForge.IntPoint[] { new AForge.IntPoint(startAt.X, startAt.Y) }))[0];
28  //Set the min threshold to 4/10ths the starting point's value
29  MinValue = (byte)Math.Round(0.4 * (double)MaxValue);
30  MinValue = Math.Max((byte)50, MinValue);
31  //Apply some arbitrary values...
32 
33 
34  this.Origin = origin;
35  this.MaxRadius = maxRadius;
36 
37  OriginStartOffset = Math.Sqrt((origin.X - StartAt.X) * (origin.X - StartAt.X) + (origin.Y - StartAt.Y) * (origin.Y - StartAt.Y));
38  }
UnmanagedImage red
An 8-bit image with a redness algorithm applied.
System.Drawing.Point StartAt
The pixel at which to begin filling
byte MinValue
The absolute minimum brightness to include. Should probably be set to 3/8ths the maximum pixel bright...
byte MaxValue
The maximum brightness expected. Used to provide a range for threshold expectations ...
double OriginStartOffset
The distance between origin and startat

Member Function Documentation

unsafe void ImageResizer.Plugins.RedEye.AdaptiveCircleFill.CorrectRedEye ( UnmanagedImage  image,
int  ox,
int  oy 
)
inline

Using the fill array calculated in passes 1 and 2, apply red-eye correction to the specified image.

Parameters
image
ox
oy

Definition at line 369 of file AdaptiveCircleFill.cs.

369  {
370  int pixelSize = System.Drawing.Image.GetPixelFormatSize(image.PixelFormat) / 8;
371  if (pixelSize > 4) throw new Exception("Invalid pixel depth");
372  UnmanagedImage mask = GetBlurredMask(); ;
373  try {
374  long scan0 = (long)image.ImageData;
375  long stride = image.Stride;
376  // do the job
377  byte* src;
378  //Establish bounds
379  int top = oy;
380  int bottom = oy + mask.Height;
381  int left = ox;
382  int right = ox + mask.Width;
383 
384  byte* fade;
385  float fadeVal;
386  float gray;
387 
388  //Scan region
389  for (int y = top; y < bottom; y++) {
390  src = (byte*)(scan0 + y * stride + (left * pixelSize));
391  for (int x = left; x < right; x++, src += pixelSize) {
392  if (src[RGB.R] == 0) continue; //Because 0 will crash the formula
393 
394  //Get ptr to mask pixel
395  fade = (byte*)((long)mask.ImageData + (y - top) * mask.Stride + x - left);
396  if (*fade == 0) continue;
397 
398  fadeVal = (float)*fade / 255.0F;
399  //Calculate monochrome alternative
400  gray = (byte)((float)src[RGB.G] * 0.5f + (float)src[RGB.B] * 0.5f);
401 
402  //Apply monochrome alternative using mask
403  src[RGB.R] = (byte)((fadeVal * gray) + (1.0 - fadeVal) * src[RGB.R]);
404  src[RGB.G] = (byte)((fadeVal * gray) + (1.0 - fadeVal) * src[RGB.G]);
405  src[RGB.B] = (byte)((fadeVal * gray) + (1.0 - fadeVal) * src[RGB.B]);
406 
407  }
408  }
409  } finally {
410  if (mask != null) mask.Dispose();
411  }
412  }
static void ImageResizer.Plugins.RedEye.AdaptiveCircleFill.MarkEye ( UnmanagedImage  image,
Point  start,
int  maxEyeRadius,
float  maxPointSearchDistance = 0 
)
inlinestatic

Parameters
image
start
maxEyeRadiusShould be 2-3 percent of max(width/height)
maxPointSearchDistanceIn source pixels, the max distance from 'start' from which to look for the starting point. Good default: roughly 24 display pixels.

Definition at line 47 of file AdaptiveCircleFill.cs.

47  {
48  int maxRadius = maxEyeRadius * 2 + (int)Math.Ceiling(maxPointSearchDistance);
49  //Find subset
50  Rectangle subset = new Rectangle(start.X - maxRadius,start.Y - maxRadius,maxRadius * 2, maxRadius * 2);
51  if (subset.X < 0) { subset.Width += subset.X; subset.X = 0; }
52  if (subset.Y < 0) { subset.Height += subset.Y; subset.Y = 0; }
53  if (subset.Right >= image.Width) subset.Width -= (subset.Right - image.Width + 1);
54  if (subset.Bottom >= image.Height) subset.Height -= (subset.Bottom - image.Height + 1);
55 
56  start.X -= subset.X;
57  start.Y -= subset.Y;
58 
59  //Skip processing if we're slightly out of bounds
60  if (subset.X < 0 || subset.Y < 0 || subset.Width < 0 || subset.Height < 0 || subset.Right >= image.Width || subset.Bottom >= image.Height) return;
61 
62  UnmanagedImage red = null;
63  try{
64  Point startAt = start;
65  using (UnmanagedImage c = new Crop(subset).Apply(image)) {
66  red = new RedEyeFilter(2).Apply(c);
67  if (maxPointSearchDistance > 0) startAt = new ManualSearcher().FindMaxPixel(c,start,maxPointSearchDistance);
68  }
69 
70  var fill = new AdaptiveCircleFill(red, startAt, start, maxEyeRadius * 2);
71  fill.FirstPass();
72  fill.SecondPass();
73  fill.CorrectRedEye(image, subset.X, subset.Y);
74  //fill.MarkFilledPixels(image, subset.X, subset.Y, new byte[] { 0, 255, 0, 0 });
75 
76  //fill.SetPixel(image, startAt.X + subset.X, startAt.Y + subset.Y, new byte[] { 255, 255, 0, 0 });
77  }finally{
78  if (red != null) red.Dispose();
79  }
80  }
UnmanagedImage red
An 8-bit image with a redness algorithm applied.
AdaptiveCircleFill(UnmanagedImage red, System.Drawing.Point startAt, PointF origin, float maxRadius)
Width and height are considered exact values - cropping is used if there is an aspect ratio differenc...

Member Data Documentation

byte ImageResizer.Plugins.RedEye.AdaptiveCircleFill.FillAverage

The average value of the filled area

Definition at line 144 of file AdaptiveCircleFill.cs.

bool [,] ImageResizer.Plugins.RedEye.AdaptiveCircleFill.filledArray

An array matching the bitmap data, marking which pixels are considered filled.

Definition at line 149 of file AdaptiveCircleFill.cs.

long ImageResizer.Plugins.RedEye.AdaptiveCircleFill.FilledCount = 0

The number of filled pixels.

Definition at line 130 of file AdaptiveCircleFill.cs.

float ImageResizer.Plugins.RedEye.AdaptiveCircleFill.FilledRadius

Set after the first pass, once we know the farthest outlying point.

Definition at line 139 of file AdaptiveCircleFill.cs.

float ImageResizer.Plugins.RedEye.AdaptiveCircleFill.MaxRadius

The maximum radius around StartAt in which to fill

Definition at line 113 of file AdaptiveCircleFill.cs.

byte ImageResizer.Plugins.RedEye.AdaptiveCircleFill.MaxValue = 255

The maximum brightness expected. Used to provide a range for threshold expectations

Definition at line 98 of file AdaptiveCircleFill.cs.

byte ImageResizer.Plugins.RedEye.AdaptiveCircleFill.MinValue = 80

The absolute minimum brightness to include. Should probably be set to 3/8ths the maximum pixel brightness.

Definition at line 94 of file AdaptiveCircleFill.cs.

PointF ImageResizer.Plugins.RedEye.AdaptiveCircleFill.Origin

The user-specified origin - used to adjust local thresholding.

Definition at line 104 of file AdaptiveCircleFill.cs.

double ImageResizer.Plugins.RedEye.AdaptiveCircleFill.OriginStartOffset

The distance between origin and startat

Definition at line 108 of file AdaptiveCircleFill.cs.

UnmanagedImage ImageResizer.Plugins.RedEye.AdaptiveCircleFill.red

An 8-bit image with a redness algorithm applied.

Definition at line 85 of file AdaptiveCircleFill.cs.

System.Drawing.Point ImageResizer.Plugins.RedEye.AdaptiveCircleFill.StartAt

The pixel at which to begin filling

Definition at line 90 of file AdaptiveCircleFill.cs.

long ImageResizer.Plugins.RedEye.AdaptiveCircleFill.SumV = 0

Sum of the values of all filled pixels

Definition at line 126 of file AdaptiveCircleFill.cs.

long ImageResizer.Plugins.RedEye.AdaptiveCircleFill.SumX = 0

Sum of the X values of all filled pixels.

Definition at line 118 of file AdaptiveCircleFill.cs.

long ImageResizer.Plugins.RedEye.AdaptiveCircleFill.SumY = 0

Sum of the Y values of all filled pixels

Definition at line 122 of file AdaptiveCircleFill.cs.

PointF ImageResizer.Plugins.RedEye.AdaptiveCircleFill.WeightedCenter

Set after the first pass, once we know the appropriate center

Definition at line 135 of file AdaptiveCircleFill.cs.


The documentation for this class was generated from the following file: