public Affine(Affine copyFrom) { sx = copyFrom.sx; shy = copyFrom.shy; shx = copyFrom.shx; sy = copyFrom.sy; tx = copyFrom.tx; ty = copyFrom.ty; }
// From affine public Perspective(Affine a) { sx = (a.sx); shy = (a.shy); w0 = (0); shx = (a.shx); sy = (a.sy); w1 = (0); tx = (a.tx); ty = (a.ty); w2 = (1); }
// Multiply inverse of "m" by "this" and assign the result to "this" public Perspective premultiply_inv(Affine m) { Perspective t = new Perspective(m); t.invert(); Set(t.multiply(this)); return this; }
//------------------------------------------------------------------------ public Perspective trans_perspectivemultiply_inv(Affine m) { Affine t = m; t.Invert(); return multiply(t); }
//------------------------------------------------------------------------ public Perspective premultiply(Affine b) { Perspective a = new Perspective(this); sx = a.sx * b.sx + a.shx * b.shy; shx = a.sx * b.shx + a.shx * b.sy; tx = a.sx * b.tx + a.shx * b.ty + a.tx; shy = a.shy * b.sx + a.sy * b.shy; sy = a.shy * b.shx + a.sy * b.sy; ty = a.shy * b.tx + a.sy * b.ty + a.ty; w0 = a.w0 * b.sx + a.w1 * b.shy; w1 = a.w0 * b.shx + a.w1 * b.sy; w2 = a.w0 * b.tx + a.w1 * b.ty + a.w2; return this; }
//------------------------------------------------------------------------ public Perspective multiply(Affine a) { Perspective b = new Perspective(this); sx = a.sx * b.sx + a.shx * b.shy + a.tx * b.w0; shx = a.sx * b.shx + a.shx * b.sy + a.tx * b.w1; tx = a.sx * b.tx + a.shx * b.ty + a.tx * b.w2; shy = a.shy * b.sx + a.sy * b.shy + a.ty * b.w0; sy = a.shy * b.shx + a.sy * b.sy + a.ty * b.w1; ty = a.shy * b.tx + a.sy * b.ty + a.ty * b.w2; return this; }
//--------------------------------------------------------- Operations public Perspective from_affine(Affine a) { sx = a.sx; shy = a.shy; w0 = 0; shx = a.shx; sy = a.sy; w1 = 0; tx = a.tx; ty = a.ty; w2 = 1; return this; }
public void SetTransform(Affine value) { m_AffineTransformStack.Pop(); m_AffineTransformStack.Push(value); }
// Identity matrix public static Affine NewIdentity() { Affine newAffine = new Affine(); newAffine.Identity(); return newAffine; }
public void Scaling(out double x, out double y) { double x1 = 0.0; double y1 = 0.0; double x2 = 1.0; double y2 = 1.0; Affine t = new Affine(this); t *= NewRotation(-Rotation()); t.Transform(ref x1, ref y1); t.Transform(ref x2, ref y2); x = x2 - x1; y = y2 - y1; }
// Check to see if two matrices are equal public bool IsEqual(Affine m, double epsilon) { return is_equal_eps(sx, m.sx, epsilon) && is_equal_eps(shy, m.shy, epsilon) && is_equal_eps(shx, m.shx, epsilon) && is_equal_eps(sy, m.sy, epsilon) && is_equal_eps(tx, m.tx, epsilon) && is_equal_eps(ty, m.ty, epsilon); }
// Multiply the matrix by another one and return // the result in a separete matrix. public static Affine operator *(Affine a, Affine b) { Affine temp = new Affine(a); temp.Multiply(b); return temp; }
// Multiply matrix to another one void Multiply(Affine m) { double t0 = sx * m.sx + shy * m.shx; double t2 = shx * m.sx + sy * m.shx; double t4 = tx * m.sx + ty * m.shx + m.tx; shy = sx * m.shy + shy * m.sy; sy = shx * m.shy + sy * m.sy; ty = tx * m.shy + ty * m.sy + m.ty; sx = t0; shx = t2; tx = t4; }
void DrawImage(IImage sourceImage, double DestX, double DestY, double HotspotOffsetX, double HotspotOffsetY, double ScaleX, double ScaleY, double AngleRad, RGBA_Bytes Color32, ref RectangleD pFinalBlitBounds, bool doDrawing, bool oneMinusSourceAlphaOne) { Affine destRectTransform = Affine.NewIdentity(); if (HotspotOffsetX != 0.0f || HotspotOffsetY != 0.0f) { destRectTransform *= Affine.NewTranslation(-HotspotOffsetX, -HotspotOffsetY); } if (ScaleX != 1 || ScaleY != 1) { destRectTransform *= Affine.NewScaling(ScaleX, ScaleY); } if (AngleRad != 0) { destRectTransform *= Affine.NewRotation(AngleRad); } if (DestX != 0 || DestY != 0) { destRectTransform *= Affine.NewTranslation(DestX, DestY); } int SourceBufferWidth = (int)sourceImage.Width(); int SourceBufferHeight = (int)sourceImage.Height(); RectPath.Clear(); RectPath.MoveTo(0, 0); RectPath.LineTo(SourceBufferWidth, 0); RectPath.LineTo(SourceBufferWidth, SourceBufferHeight); RectPath.LineTo(0, SourceBufferHeight); RectPath.ClosePolygon(); // Calculate the bounds. LBB [10/5/2004] const int ERROR_ADD = 0; double BoundXDouble, BoundYDouble; BoundXDouble = 0; BoundYDouble = 0; destRectTransform.Transform(ref BoundXDouble, ref BoundYDouble); double BoundX = (double)BoundXDouble; double BoundY = (double)BoundYDouble; pFinalBlitBounds.Left = Math.Floor(BoundX - ERROR_ADD); pFinalBlitBounds.Right = Math.Ceiling(BoundX + ERROR_ADD); pFinalBlitBounds.Top = Math.Floor(BoundY - ERROR_ADD); pFinalBlitBounds.Bottom = Math.Ceiling(BoundY + ERROR_ADD); BoundXDouble = SourceBufferWidth; BoundYDouble = 0; destRectTransform.Transform(ref BoundXDouble, ref BoundYDouble); BoundX = (double)BoundXDouble; BoundY = (double)BoundYDouble; pFinalBlitBounds.Left = Math.Min((long)Math.Floor(BoundX - ERROR_ADD), pFinalBlitBounds.Left); pFinalBlitBounds.Right = Math.Max((long)Math.Ceiling(BoundX + ERROR_ADD), pFinalBlitBounds.Right); pFinalBlitBounds.Top = Math.Min((long)Math.Floor(BoundY - ERROR_ADD), pFinalBlitBounds.Top); pFinalBlitBounds.Bottom = Math.Max((long)Math.Ceiling(BoundY + ERROR_ADD), pFinalBlitBounds.Bottom); BoundXDouble = SourceBufferWidth; BoundYDouble = SourceBufferHeight; destRectTransform.Transform(ref BoundXDouble, ref BoundYDouble); BoundX = (double)BoundXDouble; BoundY = (double)BoundYDouble; pFinalBlitBounds.Left = Math.Min((long)Math.Floor(BoundX - ERROR_ADD), pFinalBlitBounds.Left); pFinalBlitBounds.Right = Math.Max((long)Math.Ceiling(BoundX + ERROR_ADD), pFinalBlitBounds.Right); pFinalBlitBounds.Top = Math.Min((long)Math.Floor(BoundY - ERROR_ADD), pFinalBlitBounds.Top); pFinalBlitBounds.Bottom = Math.Max((long)Math.Ceiling(BoundY + ERROR_ADD), pFinalBlitBounds.Bottom); BoundXDouble = 0; BoundYDouble = SourceBufferHeight; destRectTransform.Transform(ref BoundXDouble, ref BoundYDouble); BoundX = (double)BoundXDouble; BoundY = (double)BoundYDouble; pFinalBlitBounds.Left = Math.Min((long)Math.Floor(BoundX - ERROR_ADD), pFinalBlitBounds.Left); pFinalBlitBounds.Right = Math.Max((long)Math.Ceiling(BoundX + ERROR_ADD), pFinalBlitBounds.Right); pFinalBlitBounds.Top = Math.Min((long)Math.Floor(BoundY - ERROR_ADD), pFinalBlitBounds.Top); pFinalBlitBounds.Bottom = Math.Max((long)Math.Ceiling(BoundY + ERROR_ADD), pFinalBlitBounds.Bottom); if (!doDrawing) { return; } if (m_DestImage.OriginOffset.x != 0 || m_DestImage.OriginOffset.y != 0) { destRectTransform *= Affine.NewTranslation(-m_DestImage.OriginOffset.x, -m_DestImage.OriginOffset.y); } Affine sourceRectTransform = new Affine(destRectTransform); // We invert it because it is the transform to make the image go to the same position as the polygon. LBB [2/24/2004] sourceRectTransform.Invert(); span_allocator spanAllocator = new span_allocator(); span_interpolator_linear interpolator = new span_interpolator_linear(sourceRectTransform); ImageBuffer sourceImageWithBlender = (ImageBuffer)sourceImage;// new ImageBuffer(sourceImage, new BlenderBGRA()); span_image_filter_rgba_bilinear_clip spanImageFilter; ImageBufferAccessorClip source = new ImageBufferAccessorClip(sourceImageWithBlender, RGBA_Doubles.rgba_pre(0, 0, 0, 0).GetAsRGBA_Bytes()); spanImageFilter = new span_image_filter_rgba_bilinear_clip(source, RGBA_Doubles.rgba_pre(0, 0, 0, 0), interpolator); rasterizer_scanline_aa rasterizer = new rasterizer_scanline_aa(); rasterizer.SetVectorClipBox(0, 0, m_DestImage.Width(), m_DestImage.Height()); scanline_packed_8 scanlineCache = new scanline_packed_8(); //scanline_unpacked_8 scanlineCache = new scanline_unpacked_8(); conv_transform transfromedRect = new conv_transform(RectPath, destRectTransform); rasterizer.add_path(transfromedRect); #if false bool HighQualityFilter = (BlitXParams.m_OptionalFlags & CBlitXParams::BlitHighQualityFilter) != 0 && (BlitXParams.m_OptionalFlags & CBlitXParams::RenderOneMinusScrAlpha_One) == 0; if (HighQualityFilter) {