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