| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 | using System.Diagnostics;using System.Drawing;namespace PaintDotNet{    public sealed class StitchSurfaceBoxBaseRenderer : StitchSurfaceBoxRenderer    {        private StitchSurface source;        private RenderDelegate renderDelegate;        public StitchSurface Source        {            set            {                this.source = value;                Flush();            }        }        private void Flush()        {            this.renderDelegate = null;        }        protected override void OnVisibleChanged()        {            Invalidate();        }        private void ChooseRenderDelegate()        {            if (SourceSize.Width > DestinationSize.Width)            {                // zoom out                this.renderDelegate = new RenderDelegate(RenderZoomOutRotatedGridMultisampling);            }            else if (SourceSize == DestinationSize)            {                // zoom 100%                this.renderDelegate = new RenderDelegate(RenderOneToOne);            }            else if (SourceSize.Width < DestinationSize.Width)            {                // zoom in                this.renderDelegate = new RenderDelegate(RenderZoomInNearestNeighbor);            }        }        public override void OnDestinationSizeChanged()        {            ChooseRenderDelegate();            this.OwnerList.InvalidateLookups();            base.OnDestinationSizeChanged();        }        public override void OnSourceSizeChanged()        {            ChooseRenderDelegate();            this.OwnerList.InvalidateLookups();            base.OnSourceSizeChanged();        }        public static void RenderOneToOne(StitchSurface dst, StitchSurface source, Point offset)        {            unsafe            {                if (source == null) return;                Rectangle srcRect = new Rectangle(offset, dst.Size);                srcRect.Intersect(source.Bounds);                for (int dstRow = 0; dstRow < srcRect.Height; ++dstRow)                {                    ColorBgrB* dstRowPtr = dst.GetRowAddressUnchecked(dstRow);                    ColorBgrB* srcRowPtr = source.GetPointAddressUnchecked(offset.X, dstRow + offset.Y);                    //source.stitchBounds;                    int dstCol = offset.X;                    int dstColEnd = offset.X + srcRect.Width;                    int checkerY = dstRow + offset.Y;                    while (dstCol < dstColEnd)                    {                        int b;// = srcRowPtr->B;                        int g;// = srcRowPtr->G;                        int r;// = srcRowPtr->R;                        int a = 255;// srcRowPtr->A;                        if (!source.stitchBounds.Contains(new Point(dstCol, checkerY)))// a = 0;                        {                            r = source.stitchBackColor.R;// 0;// p1->R;//                            g = source.stitchBackColor.G;// 0;// p1->G;//                            b = source.stitchBackColor.B;// 0;// p1->B;//                        }                        else                        {                            b = srcRowPtr->B;                            g = srcRowPtr->G;                            r = srcRowPtr->R;                        }                        // Blend it over the checkerboard background                        int v = (((dstCol ^ checkerY) & 8) << 3) + 191;                        a = a + (a >> 7);                        int vmia = v * (256 - a);                        r = ((r * a) + vmia) >> 8;                        g = ((g * a) + vmia) >> 8;                        b = ((b * a) + vmia) >> 8;                        dstRowPtr->setBGR((byte)b, (byte)g, (byte)r);                        ++dstRowPtr;                        ++srcRowPtr;                        ++dstCol;                    }                }            }        }        private void RenderOneToOne(StitchSurface dst, Point offset)        {            RenderOneToOne(dst, this.source, offset);        }        private void RenderZoomInNearestNeighbor(StitchSurface dst, Point offset)        {            unsafe            {                if (this.source == null) return;                int[] d2SLookupY = OwnerList.Dst2SrcLookupY;                int[] d2SLookupX = OwnerList.Dst2SrcLookupX;                for (int dstRow = 0; dstRow < dst.Height; ++dstRow)                {                    int nnY = dstRow + offset.Y;                    int srcY = d2SLookupY[nnY];                    ColorBgrB* dstPtr = dst.GetRowAddressUnchecked(dstRow);                    ColorBgrB* srcRow = this.source.GetRowAddressUnchecked(srcY);                    //source.stitchBounds;                    for (int dstCol = 0; dstCol < dst.Width; ++dstCol)                    {                        int nnX = dstCol + offset.X;                        int srcX = d2SLookupX[nnX];                        ColorBgrB src = *(srcRow + srcX);                        int b;// = src.B;                        int g;// = src.G;                        int r;// = src.R;                        int a = 255;// src.A;                        if (!source.stitchBounds.Contains(new Point(srcX, srcY)))// a = 0;                        {                            r = source.stitchBackColor.R;// 0;// p1->R;//                            g = source.stitchBackColor.G;// 0;// p1->G;//                            b = source.stitchBackColor.B;// 0;// p1->B;//                        }                        else                        {                            b = src.B;                            g = src.G;                            r = src.R;                        }                        // Blend it over the checkerboard background                        int v = (((dstCol + offset.X) ^ (dstRow + offset.Y)) & 8) * 8 + 191;                        a = a + (a >> 7);                        int vmia = v * (256 - a);                        r = ((r * a) + vmia) >> 8;                        g = ((g * a) + vmia) >> 8;                        b = ((b * a) + vmia) >> 8;                        dstPtr->setBGR((byte)b, (byte)g, (byte)r);                        ++dstPtr;                    }                }            }        }        public static void RenderZoomOutRotatedGridMultisampling(StitchSurface dst, StitchSurface source, Point offset, Size destinationSize)        {            unsafe            {                if (source == null) return;                /*                OpenCvSharp.Mat temp1 = new OpenCvSharp.Mat(dst.mat.Size(), OpenCvSharp.MatType.CV_8UC4);                                OpenCvSharp.Cv2.CvtColor(dst.mat, temp1, OpenCvSharp.ColorConversionCodes.BGR2BGRA);                                dst.mat = temp1;                                dst.Stride = temp1.Width * 4;                                dst.scan0.VoidStar = (void*)temp1.Data;                                OpenCvSharp.Mat temp2 = new OpenCvSharp.Mat(source.mat.Size(), OpenCvSharp.MatType.CV_8UC4);                                OpenCvSharp.Cv2.CvtColor(source.mat, temp2, OpenCvSharp.ColorConversionCodes.BGR2BGRA);                                source.mat = temp2;                                source.Stride = temp2.Width * 4;                                source.scan0.VoidStar = (void*)temp2.Data;                */                //if (source.mat != null)                //{                //    OpenCvSharp.Cv2.ImShow("dst", source.mat);                //    OpenCvSharp.Cv2.WaitKey();                //}                //OpenCvSharp.Cv2.ImShow("dst", dst.mat);                //if (dst.mat != null)                //OpenCvSharp.Cv2.CvtColor(dst.mat, dst.mat, OpenCvSharp.ColorConversionCodes.BGR2BGRA);                //OpenCvSharp.Cv2.ImShow("src", source.mat);                //OpenCvSharp.Cv2.WaitKey();                const int fpShift = 12;                const int fpFactor = (1 << fpShift);                Size sourceSize = source.Size;                long fDstLeftLong = ((long)offset.X * fpFactor * (long)sourceSize.Width) / (long)destinationSize.Width;                long fDstTopLong = ((long)offset.Y * fpFactor * (long)sourceSize.Height) / (long)destinationSize.Height;                long fDstRightLong = ((long)(offset.X + dst.Width) * fpFactor * (long)sourceSize.Width) / (long)destinationSize.Width;                long fDstBottomLong = ((long)(offset.Y + dst.Height) * fpFactor * (long)sourceSize.Height) / (long)destinationSize.Height;                int fDstLeft = (int)fDstLeftLong;                int fDstTop = (int)fDstTopLong;                int fDstRight = (int)fDstRightLong;                int fDstBottom = (int)fDstBottomLong;                int dx = (fDstRight - fDstLeft) / dst.Width;                int dy = (fDstBottom - fDstTop) / dst.Height;                //int dstSum = 0;                for (int dstRow = 0, fDstY = fDstTop;                    dstRow < dst.Height && fDstY < fDstBottom;                    ++dstRow, fDstY += dy)                {                    int srcY1 = fDstY >> fpShift;                            // y                    int srcY2 = (fDstY + (dy >> 2)) >> fpShift;              // y + 0.25                    int srcY3 = (fDstY + (dy >> 1)) >> fpShift;              // y + 0.50                    int srcY4 = (fDstY + (dy >> 1) + (dy >> 2)) >> fpShift;  // y + 0.75#if DEBUG                    Debug.Assert(source.IsRowVisible(srcY1));                    Debug.Assert(source.IsRowVisible(srcY2));                    Debug.Assert(source.IsRowVisible(srcY3));                    Debug.Assert(source.IsRowVisible(srcY4));                    Debug.Assert(dst.IsRowVisible(dstRow));#endif                    ColorBgrB* src1 = source.GetRowAddressUnchecked(srcY1);                    ColorBgrB* src2 = source.GetRowAddressUnchecked(srcY2);                    ColorBgrB* src3 = source.GetRowAddressUnchecked(srcY3);                    ColorBgrB* src4 = source.GetRowAddressUnchecked(srcY4);                    ColorBgrB* dstPtr = dst.GetRowAddressUnchecked(dstRow);                    int checkerY = dstRow + offset.Y;                    int checkerX = offset.X;                    int maxCheckerX = checkerX + dst.Width;                    for (int fDstX = fDstLeft;                         checkerX < maxCheckerX && fDstX < fDstRight;                         ++checkerX, fDstX += dx)                    {                        int srcX1 = (fDstX + (dx >> 2)) >> fpShift;             // x + 0.25// fDstX >> fpShift;                           //                        int srcX2 = (fDstX + (dx >> 1) + (dx >> 2)) >> fpShift; // x + 0.75                        int srcX3 = fDstX >> fpShift;                           // x                        int srcX4 = (fDstX + (dx >> 1)) >> fpShift;             // x + 0.50#if DEBUG                        Debug.Assert(source.IsColumnVisible(srcX1));                        Debug.Assert(source.IsColumnVisible(srcX2));                        Debug.Assert(source.IsColumnVisible(srcX3));                        Debug.Assert(source.IsColumnVisible(srcX4));#endif                        ColorBgrB* p1 = src1 + srcX1;                        ColorBgrB* p2 = src2 + srcX2;                        ColorBgrB* p3 = src3 + srcX3;                        ColorBgrB* p4 = src4 + srcX4;                        // / 4;//                        int r;// = (2 + p1->R + p2->R + p3->R + p4->R) >> 2;// p1->R;//                        int g;// = (2 + p1->G + p2->G + p3->G + p4->G) >> 2;// p1->G;//                        int b;// = (2 + p1->B + p2->B + p3->B + p4->B) >> 2;// p1->B;//                        int a = 255;// (2 + p1->A + p2->A + p3->A + p4->A) >> 2;                        if (!source.stitchBounds.Contains(new Point(srcX3, srcY1)))// a = 0;                        {                            r = source.stitchBackColor.R;// 0;// p1->R;//                            g = source.stitchBackColor.G;// 0;// p1->G;//                            b = source.stitchBackColor.B;// 0;// p1->B;//                        }                        else                        {                            r = (2 + p1->R + p2->R + p3->R + p4->R) >> 2;// p1->R;//                            g = (2 + p1->G + p2->G + p3->G + p4->G) >> 2;// p1->G;//                            b = (2 + p1->B + p2->B + p3->B + p4->B) >> 2;// p1->B;//                        }                        int apopacity = a;                        //                        //source.stitchBounds;                        // Blend it over the checkerboard background                        int v = ((checkerX ^ checkerY) & 8) * 8 + 191;                        a = a + (a >> 7);                        int vmia = v * (256 - a);                        r = ((r * a) + vmia) >> 8;                        g = ((g * a) + vmia) >> 8;                        b = ((b * a) + vmia) >> 8;                        dstPtr->setBGR((byte)b, (byte)g, (byte)r);                        //dstPtr->setBGR((byte)240, (byte)240, (byte)240);                        ++dstPtr;                        //++dstSum;                    }                }                //System.Console.WriteLine("dstSum:" + dstSum);            }        }        private void RenderZoomOutRotatedGridMultisampling(StitchSurface dst, Point offset)        {            RenderZoomOutRotatedGridMultisampling(dst, this.source, offset, this.DestinationSize);        }        public override void Render(StitchSurface dst, Point offset)        {            if (this.renderDelegate == null)            {                ChooseRenderDelegate();            }            this.renderDelegate(dst, offset);        }        public StitchSurfaceBoxBaseRenderer(StitchSurfaceBoxRendererList ownerList)            : base(ownerList)        {            ChooseRenderDelegate();        }    }}
 |