W analizie kodu najważniejsze jest dobre zrozumienie wszystkich $\pm\frac{1}{2}$, $\pm 1$, Floor, Ceiling, Round.
Kod:
public struct ColorInterpolator
{
private ColorFloat m_numerator;
private double m_denumerator;
public void Collect(ColorFloat a_ray_color, double a_filter_weight)
{
m_numerator += a_ray_color * a_filter_weight;
m_denumerator += a_filter_weight;
}
public ColorFloat Color
{
get
{
if (m_denumerator == 0)
return ColorFloat.Black;
return m_numerator / m_denumerator;
}
}
}
public abstract class Resampler
{
public Filter Filter = new BoxFilter();
internal Film Film;
public static Resampler Create(ResamplerType a_type)
{
if (a_type == ResamplerType.Exact)
return new ExactResampler();
else if (a_type == ResamplerType.LocalGrid)
return new LocalGridResampler();
else if (a_type == ResamplerType.Resizer)
return new ResizerResampler();
else
throw new NotImplementedException();
}
public Rectangle GetAffectedRect(Rectangle a_src_rect)
{
int border = (int)Math.Ceiling(Filter.Ray) + 2;
a_src_rect.Inflate(border, border);
a_src_rect.Intersect(new Rectangle(0, 0, Film.Width, Film.Height));
return a_src_rect;
}
public void Resample(Rectangle a_rect, ColorArrayBase a_dest)
{
for (int y = a_rect.Top; y < a_rect.Bottom; y++)
{
for (int x = a_rect.Left; x < a_rect.Right; x++)
{
a_dest.SetColor(x, y, ResamplePixel(x, y));
}
}
}
public abstract void RenderStart(RenderStartPhase a_phase);
protected abstract ColorFloat ResamplePixel(int a_x, int a_y);
public abstract void SetRayColor(Vector2 a_pixel, ColorFloat a_color);
}
public class ExactResampler : InterpolateResampler
{
public override void SetRayColor(Vector2 a_pixel, ColorFloat a_color)
{
int start_x = (int)Math.Floor(a_pixel.X - Filter.Ray);
int end_x = (int)Math.Ceiling(a_pixel.X + Filter.Ray) - 1;
int start_y = (int)Math.Floor(a_pixel.Y - Filter.Ray);
int end_y = (int)Math.Ceiling(a_pixel.Y + Filter.Ray) - 1;
for (int y = start_y; y <= end_y; y++)
{
int cy = m_overlay_corrector.CorrectY(y);
double wy = Filter.Evaluate((y + 0.5) - a_pixel.Y);
for (int x = start_x; x <= end_x; x++)
{
int cx = m_overlay_corrector.CorrectX(x);
double wx = Filter.Evaluate((x + 0.5) - a_pixel.X);
m_rays[cx, cy].Collect(a_color, wy * wx);
}
}
Debug.Assert(Filter.Evaluate(
a_pixel.X - (start_x + 0.5 - 1)).IsAlmostEquals(0));
Debug.Assert(Filter.Evaluate(
a_pixel.X - (end_x + 0.5 + 1)).IsAlmostEquals(0));
Debug.Assert(Filter.Evaluate(
a_pixel.Y - (start_y + 0.5 - 1)).IsAlmostEquals(0));
Debug.Assert(Filter.Evaluate(
a_pixel.Y - (end_y + 0.5 + 1)).IsAlmostEquals(0));
}
}
Brak komentarzy:
Prześlij komentarz