public void Render(IBitmapSrc source, AffinePlan[] affinePlans) { using (VxsTemp.Borrow(out var v1, out var v2)) { BuildOrgImgRectVxs(source.Width, source.Height, v1); AffineMat destRectTransform; if (affinePlans == null) { destRectTransform = AffineMat.Iden; _reuseableAffine.SetElements(destRectTransform); } else { destRectTransform = new AffineMat(); destRectTransform.BuildFromAffinePlans(affinePlans); _reuseableAffine.SetElements(destRectTransform.CreateInvert()); } //TODO: review reusable span generator an interpolator *** //We invert it because it is the transform to make the image go to the same position as the polygon. LBB [2/24/2004] _spanInterpolator.Transformer = _reuseableAffine; _currentImgSpanGen.BackgroundColor = Drawing.Color.Transparent; _currentImgSpanGen.SetInterpolator(_spanInterpolator); _currentImgSpanGen.SetSrcBitmap(source); TransformToVxs(ref destRectTransform, v1, v2); Render(v2, _currentImgSpanGen); _currentImgSpanGen.ReleaseSrcBitmap(); } }
public void Render(IBitmapSrc source, AffinePlan[] affinePlans) { VectorToolBox.GetFreeVxs(out var v1, out var v2); //BuildImageBoundsPath(source.Width, source.Height, affinePlans, v1); BuildOrgImgRectVxs(source.Width, source.Height, v1); //Affine destRectTransform = Affine.NewMatix(affinePlans); var destRectTransform = new AffineMat(); destRectTransform.BuildFromAffinePlans(affinePlans); //TODO: review reusable span generator an interpolator *** var spanInterpolator = new SpanInterpolatorLinear(); // We invert it because it is the transform to make the image go to the same position as the polygon. LBB [2/24/2004] _reuseableAffine.SetElements(destRectTransform.CreateInvert()); spanInterpolator.Transformer = _reuseableAffine;// var imgSpanGen = new ImgSpanGenRGBA_BilinearClip( source, Drawing.Color.Transparent, spanInterpolator); TransformToVxs(ref destRectTransform, v1, v2); Render(v2, imgSpanGen); // VectorToolBox.ReleaseVxs(ref v1, ref v2); }
public void Render(IBitmapSrc source, double destX, double destY, double angleRadians, double inScaleX, double inScaleY) { { // exit early if the dest and source bounds don't touch. // TODO: <BUG> make this do rotation and scalling RectInt sourceBounds = source.GetBounds(); RectInt destBounds = _destBitmapBlender.GetBounds(); sourceBounds.Offset((int)destX, (int)destY); if (!RectInt.DoIntersect(sourceBounds, destBounds)) { if (inScaleX != 1 || inScaleY != 1 || angleRadians != 0) { throw new NotImplementedException(); } return; } } double scaleX = inScaleX; double scaleY = inScaleY; ICoordTransformer graphicsTransform = this.CurrentTransformMatrix; if (!graphicsTransform.IsIdentity) { if (scaleX != 1 || scaleY != 1 || angleRadians != 0) { throw new NotImplementedException(); } graphicsTransform.Transform(ref destX, ref destY); } #if false // this is an optomization that eliminates the drawing of images that have their alpha set to all 0 (happens with generated images like explosions). MaxAlphaFrameProperty maxAlphaFrameProperty = MaxAlphaFrameProperty::GetMaxAlphaFrameProperty(source); if ((maxAlphaFrameProperty.GetMaxAlpha() * color.A_Byte) / 256 <= ALPHA_CHANNEL_BITS_DIVISOR) { m_OutFinalBlitBounds.SetRect(0, 0, 0, 0); } #endif bool isScale = (scaleX != 1 || scaleY != 1); bool isRotated = true; if (Math.Abs(angleRadians) < (0.1 * MathHelper.Tau / 360)) { isRotated = false; angleRadians = 0; } //bool IsMipped = false; //double ox, oy; //source.GetOriginOffset(out ox, out oy); bool canUseMipMaps = isScale; if (scaleX > 0.5 || scaleY > 0.5) { canUseMipMaps = false; } bool renderRequriesSourceSampling = isScale || isRotated || destX != (int)destX || destY != (int)destY; using (VxsTemp.Borrow(out var v1, out var imgBoundsPath)) { // this is the fast drawing path if (renderRequriesSourceSampling) { // if the scalling is small enough the results can be improved by using mip maps //if(CanUseMipMaps) //{ // CMipMapFrameProperty* pMipMapFrameProperty = CMipMapFrameProperty::GetMipMapFrameProperty(source); // double OldScaleX = scaleX; // double OldScaleY = scaleY; // const CFrameInterface* pMippedFrame = pMipMapFrameProperty.GetMipMapFrame(ref scaleX, ref scaleY); // if(pMippedFrame != source) // { // IsMipped = true; // source = pMippedFrame; // sourceOriginOffsetX *= (OldScaleX / scaleX); // sourceOriginOffsetY *= (OldScaleY / scaleY); // } // HotspotOffsetX *= (inScaleX / scaleX); // HotspotOffsetY *= (inScaleY / scaleY); //} //Affine destRectTransform = BuildImageBoundsPath(source.Width, source.Height, // destX, destY, ox, oy, scaleX, scaleY, angleRadians, imgBoundsPath); //1. BuildOrgImgRectVxs(source.Width, source.Height, imgBoundsPath); //2. Affine destRectTransform = CreateAffine(destX, destY, _ox, _oy, scaleX, scaleY, angleRadians); //TODO: review reusable span generator an interpolator *** // We invert it because it is the transform to make the image go to the same position as the polygon. LBB [2/24/2004] _spanInterpolator.Transformer = destRectTransform.CreateInvert(); _currentImgSpanGen.BackgroundColor = Drawing.Color.Black; _currentImgSpanGen.SetInterpolator(_spanInterpolator); _currentImgSpanGen.SetSrcBitmap(source); destRectTransform.TransformToVxs(imgBoundsPath, v1); Render(v1, _currentImgSpanGen); _currentImgSpanGen.ReleaseSrcBitmap(); // this is some debug you can enable to visualize the dest bounding box //LineFloat(BoundingRect.left, BoundingRect.top, BoundingRect.right, BoundingRect.top, WHITE); //LineFloat(BoundingRect.right, BoundingRect.top, BoundingRect.right, BoundingRect.bottom, WHITE); //LineFloat(BoundingRect.right, BoundingRect.bottom, BoundingRect.left, BoundingRect.bottom, WHITE); //LineFloat(BoundingRect.left, BoundingRect.bottom, BoundingRect.left, BoundingRect.top, WHITE); } else // TODO: this can be even faster if we do not use an intermediat buffer { //Affine destRectTransform = BuildImageBoundsPath(source.Width, source.Height, destX, destY, imgBoundsPath); BuildOrgImgRectVxs(source.Width, source.Height, imgBoundsPath); // var destRectTransform = new AffineMat(); destRectTransform.Translate(destX, destY); //TODO: review reusable span generator an interpolator *** // We invert it because it is the transform to make the image go to the same position as the polygon. LBB [2/24/2004] _reuseableAffine.SetElements(destRectTransform.CreateInvert()); _spanInterpolator.Transformer = _reuseableAffine; ImgSpanGen imgSpanGen = null; switch (source.BitDepth) { case 32: if (_imgSpanGenCustom != null) { //use custom span gen _imgSpanGenCustom.SetInterpolator(_spanInterpolator); _imgSpanGenCustom.SetSrcBitmap(source); imgSpanGen = _imgSpanGenCustom; } else { _imgSpanGenNNStepXBy1.SetInterpolator(_spanInterpolator); _imgSpanGenNNStepXBy1.SetSrcBitmap(source); imgSpanGen = _imgSpanGenNNStepXBy1; } break; //case 24: // imgSpanGen = new ImgSpanGenRGB_NNStepXby1(source, interpolator); // break; //case 8: // imgSpanGen = new ImgSpanGenGray_NNStepXby1(source, interpolator); // break; default: throw new NotImplementedException(); } TransformToVxs(ref destRectTransform, imgBoundsPath, v1); Render(v1, imgSpanGen); unchecked { _destImageChanged++; }; } } }