Exemple #1
0
        private void setVertex()
        {
            float xmin = float.MaxValue;
            float ymin = float.MaxValue;
            float xmax = float.MinValue;
            float ymax = float.MinValue;

            for (int i = 0; i < 4; i++)
            {
                xmax = Math.Max(xmax, vertex[i].X);
                ymax = Math.Max(ymax, vertex[i].Y);
                xmin = Math.Min(xmin, vertex[i].X);
                ymin = Math.Min(ymin, vertex[i].Y);
            }

            rect = new RectInt((int)xmin, (int)ymin, (int)(xmax - xmin), (int)(ymax - ymin));
            AB   = MyVectorHelper.NewFromTwoPoints(vertex[0], vertex[1]);
            BC   = MyVectorHelper.NewFromTwoPoints(vertex[1], vertex[2]);
            CD   = MyVectorHelper.NewFromTwoPoints(vertex[2], vertex[3]);
            DA   = MyVectorHelper.NewFromTwoPoints(vertex[3], vertex[0]);
            // get unit vector
            AB /= AB.Magnitude;
            BC /= BC.Magnitude;
            CD /= CD.Magnitude;
            DA /= DA.Magnitude;
        }
 bool IsOnPlaneABCD(PointF pt) //  including point on border
 {
     return(!MyVectorHelper.IsCCW(pt, _p0, _p1) &&
            !MyVectorHelper.IsCCW(pt, _p1, _p2) &&
            !MyVectorHelper.IsCCW(pt, _p2, _p3) &&
            !MyVectorHelper.IsCCW(pt, _p3, _p0));
 }
        MemBitmap GetTransformedBitmapNoInterpolation()
        {
            var destCB = new MemBitmap(_destBounds.Width, _destBounds.Height);

#if DEBUG
            destCB._dbugNote = "GetTransformedBitmapNoInterpolation()";
#endif
            var    destWriter = new MyBitmapBlender(destCB);
            PointF ptInPlane  = new PointF();

            int    x1, y1;
            double dab, dbc, dcd, dda;

            int    rectWidth  = _destBounds.Width;
            int    rectHeight = _destBounds.Height;
            Vector ab_vec     = _AB;
            Vector bc_vec     = _BC;
            Vector cd_vec     = _CD;
            Vector da_vec     = _DA;
            int    rectLeft   = _destBounds.Left;
            int    rectTop    = _destBounds.Top;



            unsafe
            {
                using (TempMemPtr.FromBmp(_srcBmp, out int *bufferPtr))
                {
                    BufferReader4 reader = new BufferReader4(bufferPtr, _srcBmp.Width, _srcBmp.Height);

                    for (int y = 0; y < rectHeight; ++y)
                    {
                        for (int x = 0; x < rectWidth; ++x)
                        {
                            PointF srcPt = new PointF(x, y);
                            srcPt.Offset(rectLeft, rectTop);
                            if (!IsOnPlaneABCD(srcPt))
                            {
                                continue;
                            }
                            x1 = (int)ptInPlane.X;
                            y1 = (int)ptInPlane.Y;

                            reader.SetStartPixel(x1, y1);
                            destWriter.SetPixel(x, y, reader.Read1());
                            //-------------------------------------
                            dab         = Math.Abs((MyVectorHelper.NewFromTwoPoints(_p0, srcPt)).CrossProduct(ab_vec));
                            dbc         = Math.Abs((MyVectorHelper.NewFromTwoPoints(_p1, srcPt)).CrossProduct(bc_vec));
                            dcd         = Math.Abs((MyVectorHelper.NewFromTwoPoints(_p2, srcPt)).CrossProduct(cd_vec));
                            dda         = Math.Abs((MyVectorHelper.NewFromTwoPoints(_p3, srcPt)).CrossProduct(da_vec));
                            ptInPlane.X = (float)(_srcW * (dda / (dda + dbc)));
                            ptInPlane.Y = (float)(_srcH * (dab / (dab + dcd)));
                        }
                    }
                    return(destCB);
                }
            }
        }
        void UpdateVertices()
        {
            float xmin = float.MaxValue;
            float ymin = float.MaxValue;
            float xmax = float.MinValue;
            float ymax = float.MinValue;

            {
                //update 4 corners
                //--------------------------
                xmin = Math.Min(xmin, _p0.X);
                xmax = Math.Max(xmax, _p0.X);
                ymin = Math.Min(ymin, _p0.Y);
                ymax = Math.Max(ymax, _p0.Y);
                //--------------------------
                xmin = Math.Min(xmin, _p1.X);
                xmax = Math.Max(xmax, _p1.X);
                ymin = Math.Min(ymin, _p1.Y);
                ymax = Math.Max(ymax, _p1.Y);
                //--------------------------
                xmin = Math.Min(xmin, _p2.X);
                xmax = Math.Max(xmax, _p2.X);
                ymin = Math.Min(ymin, _p2.Y);
                ymax = Math.Max(ymax, _p2.Y);
                //--------------------------
                xmin = Math.Min(xmin, _p3.X);
                xmax = Math.Max(xmax, _p3.X);
                ymin = Math.Min(ymin, _p3.Y);
                ymax = Math.Max(ymax, _p3.Y);
            }


            _destBounds = new Drawing.Rectangle((int)xmin, (int)ymin, (int)(xmax - xmin), (int)(ymax - ymin));
            _AB         = MyVectorHelper.NewFromTwoPoints(_p0, _p1);
            _BC         = MyVectorHelper.NewFromTwoPoints(_p1, _p2);
            _CD         = MyVectorHelper.NewFromTwoPoints(_p2, _p3);
            _DA         = MyVectorHelper.NewFromTwoPoints(_p3, _p0);
            //-----------------------------------------------------------------------
            // get unit vector
            _AB /= _AB.Magnitude;
            _BC /= _BC.Magnitude;
            _CD /= _CD.Magnitude;
            _DA /= _DA.Magnitude;
            //-----------------------------------------------------------------------
        }
Exemple #5
0
        private bool IsOnPlaneABCD(PointF pt) //  including point on border
        {
            if (!MyVectorHelper.IsCCW(pt, vertex[0], vertex[1]))
            {
                if (!MyVectorHelper.IsCCW(pt, vertex[1], vertex[2]))
                {
                    if (!MyVectorHelper.IsCCW(pt, vertex[2], vertex[3]))
                    {
                        if (MyVectorHelper.IsCCW(pt, vertex[3], vertex[0]))
                        {
                            return(true);
                        }
                    }
                }
            }

            return(false);
        }
Exemple #6
0
        ActualImage GetTransformedBitmapNoInterpolation()
        {
            var destCB     = new ActualImage(rect.Width, rect.Height, PixelFormat.ARGB32);
            var destWriter = new MyImageReaderWriter();

            destWriter.ReloadImage(destCB);
            PointF ptInPlane = new PointF();
            int    x1, x2, y1, y2;
            double dab, dbc, dcd, dda;
            float  dx1, dx2, dy1, dy2, dx1y1, dx1y2, dx2y1, dx2y2;
            int    rectWidth  = rect.Width;
            int    rectHeight = rect.Height;
            var    ab_vec     = this.AB;
            var    bc_vec     = this.BC;
            var    cd_vec     = this.CD;
            var    da_vec     = this.DA;
            int    rectLeft   = this.rect.Left;
            int    rectTop    = this.rect.Top;

            for (int y = 0; y < rectHeight; ++y)
            {
                for (int x = 0; x < rectWidth; ++x)
                {
                    PointF srcPt = new PointF(x, y);
                    srcPt.Offset(rectLeft, rectTop);
                    if (!IsOnPlaneABCD(srcPt))
                    {
                        continue;
                    }
                    x1 = (int)ptInPlane.X;
                    y1 = (int)ptInPlane.Y;
                    destWriter.SetPixel(x, y, srcCB.GetPixel(x1, y1));
                    //-------------------------------------
                    dab         = Math.Abs((MyVectorHelper.NewFromTwoPoints(vertex[0], srcPt)).CrossProduct(ab_vec));
                    dbc         = Math.Abs((MyVectorHelper.NewFromTwoPoints(vertex[1], srcPt)).CrossProduct(bc_vec));
                    dcd         = Math.Abs((MyVectorHelper.NewFromTwoPoints(vertex[2], srcPt)).CrossProduct(cd_vec));
                    dda         = Math.Abs((MyVectorHelper.NewFromTwoPoints(vertex[3], srcPt)).CrossProduct(da_vec));
                    ptInPlane.X = (float)(srcW * (dda / (dda + dbc)));
                    ptInPlane.Y = (float)(srcH * (dab / (dab + dcd)));
                }
            }
            return(destCB);
        }
Exemple #7
0
        unsafe ActualImage GetTransformedBicubicInterpolation()
        {
            //4 points sampling
            //weight between four point


            PointF ptInPlane = new PointF();
            int    x1, x2, y1, y2;
            double dab, dbc, dcd, dda;
            float  dx1, dx2, dy1, dy2, dx1y1, dx1y2, dx2y1, dx2y2;
            int    rectWidth  = rect.Width;
            int    rectHeight = rect.Height;
            var    ab_vec     = this.AB;
            var    bc_vec     = this.BC;
            var    cd_vec     = this.CD;
            var    da_vec     = this.DA;


            TempMemPtr    bufferPtr = srcCB.GetBufferPtr();
            byte *        buffer    = (byte *)bufferPtr.Ptr;
            int           stride    = srcCB.Stride;
            int           bmpWidth  = srcCB.Width;
            int           bmpHeight = srcCB.Height;
            BufferReader4 reader    = new BufferReader4(buffer, stride, bmpWidth, bmpHeight);

            MyColor[] pixelBuffer = new MyColor[16];
            byte[]    sqPixs      = new byte[16];
            //Bitmap outputbmp = new Bitmap(rectWidth, rectHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
            ////-----------------------------------------------
            //var bmpdata2 = outputbmp.LockBits(new Rectangle(0, 0, rectWidth, rectHeight),
            //    System.Drawing.Imaging.ImageLockMode.ReadWrite, outputbmp.PixelFormat);
            ////-----------------------------------------

            ActualImage         destCB     = new ActualImage(rect.Width, rect.Height, PixelFormat.ARGB32);
            MyImageReaderWriter destWriter = new MyImageReaderWriter();

            destWriter.ReloadImage(destCB);
            //PointF ptInPlane = new PointF();

            //int stride2 = bmpdata2.Stride;
            //byte[] outputBuffer = new byte[stride2 * outputbmp.Height];

            // int targetPixelIndex = 0;
            // int startLine = 0;

            int rectLeft = this.rect.Left;
            int rectTop  = this.rect.Top;

            for (int y = 0; y < rectHeight; ++y)
            {
                for (int x = 0; x < rectWidth; ++x)
                {
                    PointF srcPt = new PointF(x, y);
                    srcPt.Offset(rectLeft, rectTop);
                    if (!IsOnPlaneABCD(srcPt))
                    {
                        continue;
                    }
                    //-------------------------------------
                    dab         = Math.Abs(MyVectorHelper.NewFromTwoPoints(vertex[0], srcPt).CrossProduct(ab_vec));
                    dbc         = Math.Abs(MyVectorHelper.NewFromTwoPoints(vertex[1], srcPt).CrossProduct(bc_vec));
                    dcd         = Math.Abs(MyVectorHelper.NewFromTwoPoints(vertex[2], srcPt).CrossProduct(cd_vec));
                    dda         = Math.Abs(MyVectorHelper.NewFromTwoPoints(vertex[3], srcPt).CrossProduct(da_vec));
                    ptInPlane.X = (float)(srcW * (dda / (dda + dbc)));
                    ptInPlane.Y = (float)(srcH * (dab / (dab + dcd)));
                    x1          = (int)ptInPlane.X;
                    y1          = (int)ptInPlane.Y;
                    if (x1 >= 2 && x1 < srcW - 2 && y1 >= 2 && y1 < srcH - 2)
                    {
                        reader.SetStartPixel(x1, y1);
                        reader.Read16(pixelBuffer);
                        //do interpolate

                        //find src pixel and approximate
                        MyColor color = GetApproximateColor_Bicubic(reader,
                                                                    ptInPlane.X,
                                                                    ptInPlane.Y);
                        //outputBuffer[targetPixelIndex] = (byte)color.b;
                        //outputBuffer[targetPixelIndex + 1] = (byte)color.g;
                        //outputBuffer[targetPixelIndex + 2] = (byte)color.r;
                        //outputBuffer[targetPixelIndex + 3] = (byte)color.a;
                        //targetPixelIndex += 4;

                        destWriter.SetPixel(x, y, new Drawing.Color(color.a, color.b, color.g, color.r)); //TODO:review here blue switch to red channel
                    }
                }
                //newline
                // startLine += stride2;
                //targetPixelIndex = startLine;
            }

            bufferPtr.Release();
            //------------------------
            //System.Runtime.InteropServices.Marshal.Copy(
            //outputBuffer, 0,
            //bmpdata2.Scan0, outputBuffer.Length);
            //outputbmp.UnlockBits(bmpdata2);
            ////outputbmp.Save("d:\\WImageTest\\n_lion_bicubic.png");
            //return outputbmp;
            return(destCB);
        }
Exemple #8
0
        ActualImage GetTransformedBilinearInterpolation()
        {
            //4 points sampling
            //weight between four point
            ActualImage         destCB     = new ActualImage(rect.Width, rect.Height, PixelFormat.ARGB32);
            MyImageReaderWriter destWriter = new MyImageReaderWriter();

            destWriter.ReloadImage(destCB);
            PointF ptInPlane = new PointF();
            int    x1, x2, y1, y2;
            double dab, dbc, dcd, dda;
            float  dx1, dx2, dy1, dy2, dx1y1, dx1y2, dx2y1, dx2y2;
            int    rectWidth  = rect.Width;
            int    rectHeight = rect.Height;
            var    ab_vec     = this.AB;
            var    bc_vec     = this.BC;
            var    cd_vec     = this.CD;
            var    da_vec     = this.DA;
            int    rectLeft   = this.rect.Left;
            int    rectTop    = this.rect.Top;

            for (int y = 0; y < rectHeight; ++y)
            {
                for (int x = 0; x < rectWidth; ++x)
                {
                    PointF srcPt = new PointF(x, y);
                    srcPt.Offset(rectLeft, rectTop);
                    if (!IsOnPlaneABCD(srcPt))
                    {
                        continue;
                    }
                    //-------------------------------------
                    dab         = Math.Abs(MyVectorHelper.NewFromTwoPoints(vertex[0], srcPt).CrossProduct(ab_vec));
                    dbc         = Math.Abs(MyVectorHelper.NewFromTwoPoints(vertex[1], srcPt).CrossProduct(bc_vec));
                    dcd         = Math.Abs(MyVectorHelper.NewFromTwoPoints(vertex[2], srcPt).CrossProduct(cd_vec));
                    dda         = Math.Abs(MyVectorHelper.NewFromTwoPoints(vertex[3], srcPt).CrossProduct(da_vec));
                    ptInPlane.X = (float)(srcW * (dda / (dda + dbc)));
                    ptInPlane.Y = (float)(srcH * (dab / (dab + dcd)));
                    x1          = (int)ptInPlane.X;
                    y1          = (int)ptInPlane.Y;
                    if (x1 >= 0 && x1 < srcW && y1 >= 0 && y1 < srcH)
                    {
                        //bilinear interpolation ***
                        x2  = (x1 == srcW - 1) ? x1 : x1 + 1;
                        y2  = (y1 == srcH - 1) ? y1 : y1 + 1;
                        dx1 = ptInPlane.X - (float)x1;
                        if (dx1 < 0)
                        {
                            dx1 = 0;
                        }
                        dx1 = 1f - dx1;
                        dx2 = 1f - dx1;
                        dy1 = ptInPlane.Y - (float)y1;
                        if (dy1 < 0)
                        {
                            dy1 = 0;
                        }
                        dy1   = 1f - dy1;
                        dy2   = 1f - dy1;
                        dx1y1 = dx1 * dy1;
                        dx1y2 = dx1 * dy2;
                        dx2y1 = dx2 * dy1;
                        dx2y2 = dx2 * dy2;
                        //use 4 points

                        Drawing.Color x1y1Color = srcCB.GetPixel(x1, y1);
                        Drawing.Color x2y1Color = srcCB.GetPixel(x2, y1);
                        Drawing.Color x1y2Color = srcCB.GetPixel(x1, y2);
                        Drawing.Color x2y2Color = srcCB.GetPixel(x2, y2);
                        float         a         = (x1y1Color.alpha * dx1y1) + (x2y1Color.alpha * dx2y1) + (x1y2Color.alpha * dx1y2) + (x2y2Color.alpha * dx2y2);
                        float         b         = (x1y1Color.blue * dx1y1) + (x2y1Color.blue * dx2y1) + (x1y2Color.blue * dx1y2) + (x2y2Color.blue * dx2y2);
                        float         g         = (x1y1Color.green * dx1y1) + (x2y1Color.green * dx2y1) + (x1y2Color.green * dx1y2) + (x2y2Color.green * dx2y2);
                        float         r         = (x1y1Color.red * dx1y1) + (x2y1Color.red * dx2y1) + (x1y2Color.red * dx1y2) + (x2y2Color.red * dx2y2);
                        destWriter.SetPixel(x, y, new Drawing.Color((byte)a, (byte)b, (byte)g, (byte)r));
                        //destCB.SetColorPixel(x, y, new ColorRGBA((byte)b, (byte)g, (byte)r, (byte)a));
                    }
                }
            }
            return(destCB);
        }
        //ActualBitmap GetTransformedBilinearInterpolation()
        //{
        //    //4 points sampling
        //    //weight between four point
        //    ActualBitmap destCB = new ActualBitmap(rect.Width, rect.Height);
        //    MyBitmapBlender destWriter = new MyBitmapBlender(destCB);
        //    PointF ptInPlane = new PointF();
        //    int x1, x2, y1, y2;
        //    double dab, dbc, dcd, dda;
        //    float dx1, dx2, dy1, dy2, dx1y1, dx1y2, dx2y1, dx2y2;
        //    int rectWidth = rect.Width;
        //    int rectHeight = rect.Height;
        //    Vector ab_vec = this.AB;
        //    Vector bc_vec = this.BC;
        //    Vector cd_vec = this.CD;
        //    Vector da_vec = this.DA;
        //    int rectLeft = this.rect.Left;
        //    int rectTop = this.rect.Top;



        //    for (int y = 0; y < rectHeight; ++y)
        //    {
        //        for (int x = 0; x < rectWidth; ++x)
        //        {
        //            PointF srcPt = new PointF(x, y);
        //            srcPt.Offset(rectLeft, rectTop);
        //            if (!IsOnPlaneABCD(srcPt))
        //            {
        //                continue;
        //            }
        //            //-------------------------------------
        //            dab = Math.Abs(MyVectorHelper.NewFromTwoPoints(_p0, srcPt).CrossProduct(ab_vec));
        //            dbc = Math.Abs(MyVectorHelper.NewFromTwoPoints(_p1, srcPt).CrossProduct(bc_vec));
        //            dcd = Math.Abs(MyVectorHelper.NewFromTwoPoints(_p2, srcPt).CrossProduct(cd_vec));
        //            dda = Math.Abs(MyVectorHelper.NewFromTwoPoints(_p3, srcPt).CrossProduct(da_vec));

        //            ptInPlane.X = (float)(srcW * (dda / (dda + dbc)));
        //            ptInPlane.Y = (float)(srcH * (dab / (dab + dcd)));
        //            x1 = (int)ptInPlane.X;
        //            y1 = (int)ptInPlane.Y;

        //            if (x1 >= 0 && x1 < srcW && y1 >= 0 && y1 < srcH)
        //            {
        //                //bilinear interpolation ***
        //                x2 = (x1 == srcW - 1) ? x1 : x1 + 1;
        //                y2 = (y1 == srcH - 1) ? y1 : y1 + 1;
        //                dx1 = ptInPlane.X - x1;
        //                if (dx1 < 0) dx1 = 0;
        //                dx1 = 1f - dx1;
        //                dx2 = 1f - dx1;
        //                dy1 = ptInPlane.Y - y1;
        //                if (dy1 < 0) dy1 = 0;
        //                dy1 = 1f - dy1;
        //                dy2 = 1f - dy1;
        //                dx1y1 = dx1 * dy1;
        //                dx1y2 = dx1 * dy2;
        //                dx2y1 = dx2 * dy1;
        //                dx2y2 = dx2 * dy2;
        //                //use 4 points


        //                Drawing.Color x1y1Color = srcCB.GetPixel(x1, y1);
        //                Drawing.Color x2y1Color = srcCB.GetPixel(x2, y1);
        //                Drawing.Color x1y2Color = srcCB.GetPixel(x1, y2);
        //                Drawing.Color x2y2Color = srcCB.GetPixel(x2, y2);
        //                float a = (x1y1Color.alpha * dx1y1) + (x2y1Color.alpha * dx2y1) + (x1y2Color.alpha * dx1y2) + (x2y2Color.alpha * dx2y2);
        //                float b = (x1y1Color.blue * dx1y1) + (x2y1Color.blue * dx2y1) + (x1y2Color.blue * dx1y2) + (x2y2Color.blue * dx2y2);
        //                float g = (x1y1Color.green * dx1y1) + (x2y1Color.green * dx2y1) + (x1y2Color.green * dx1y2) + (x2y2Color.green * dx2y2);
        //                float r = (x1y1Color.red * dx1y1) + (x2y1Color.red * dx2y1) + (x1y2Color.red * dx1y2) + (x2y2Color.red * dx2y2);
        //                destWriter.SetPixel(x, y, new Drawing.Color((byte)a, (byte)b, (byte)g, (byte)r));
        //            }
        //        }
        //    }
        //    return destCB;
        //}
        unsafe MemBitmap GetTransformedBicubicInterpolation()
        {
            //4 points sampling
            //weight between four point
            PointF ptInPlane = new PointF();
            int    x1, x2, y1, y2;
            double dab, dbc, dcd, dda;
            //float dx1, dx2, dy1, dy2, dx1y1, dx1y2, dx2y1, dx2y2;
            int    destRectWidth  = _destBounds.Width;
            int    dectRectHeight = _destBounds.Height;
            Vector ab_vec         = _AB;
            Vector bc_vec         = _BC;
            Vector cd_vec         = _CD;
            Vector da_vec         = _DA;

            using (TempMemPtr.FromBmp(_srcBmp, out int *bufferPtr))
            {
                BufferReader4 reader = new BufferReader4(bufferPtr, _srcBmp.Width, _srcBmp.Height);

                MemBitmap destCB = new MemBitmap(_destBounds.Width, _destBounds.Height);
#if DEBUG
                destCB._dbugNote = "GetTransformedBicubicInterpolation()";
#endif
                MyBitmapBlender destWriter = new MyBitmapBlender(destCB);
                int             rectLeft   = _destBounds.Left;
                int             rectTop    = _destBounds.Top;

                //***
                PixelFarm.Drawing.Color[] colors = new PixelFarm.Drawing.Color[16];

                int srcW_lim = _srcW - 2;
                int srcH_lim = _srcH - 2;

                for (int y = 0; y < dectRectHeight; ++y)
                {
                    for (int x = 0; x < destRectWidth; ++x)
                    {
                        PointF srcPt = new PointF(x, y);
                        srcPt.Offset(rectLeft, 0);
                        if (!IsOnPlaneABCD(srcPt))
                        {
                            continue;
                        }
                        //-------------------------------------
                        dab         = Math.Abs(MyVectorHelper.NewFromTwoPoints(_p0, srcPt).CrossProduct(ab_vec));
                        dbc         = Math.Abs(MyVectorHelper.NewFromTwoPoints(_p1, srcPt).CrossProduct(bc_vec));
                        dcd         = Math.Abs(MyVectorHelper.NewFromTwoPoints(_p2, srcPt).CrossProduct(cd_vec));
                        dda         = Math.Abs(MyVectorHelper.NewFromTwoPoints(_p3, srcPt).CrossProduct(da_vec));
                        ptInPlane.X = (float)(_srcW * (dda / (dda + dbc)));
                        ptInPlane.Y = (float)(_srcH * (dab / (dab + dcd)));
                        x1          = (int)ptInPlane.X;
                        y1          = (int)ptInPlane.Y;
                        if (x1 >= 2 && x1 < srcW_lim &&
                            y1 >= 2 && y1 < srcH_lim)
                        {
                            reader.SetStartPixel(x1, y1);
                            //reader.Read16(pixelBuffer);
                            //do interpolate
                            //find src pixel and approximate
                            destWriter.SetPixel(x, y,

                                                GetApproximateColor_Bicubic(reader,
                                                                            colors,
                                                                            ptInPlane.X,
                                                                            ptInPlane.Y)); //TODO:review here blue switch to red channel
                        }
                    }
                    //newline
                    // startLine += stride2;
                    //targetPixelIndex = startLine;
                }


                //------------------------
                //System.Runtime.InteropServices.Marshal.Copy(
                //outputBuffer, 0,
                //bmpdata2.Scan0, outputBuffer.Length);
                //outputbmp.UnlockBits(bmpdata2);
                ////outputbmp.Save("n_lion_bicubic.png");
                //return outputbmp;
                return(destCB);
            }
        }
        unsafe MemBitmap GetTransformedBilinearInterpolation()
        {
            //4 points sampling
            //weight between four point
            MemBitmap destCB = new MemBitmap(_destBounds.Width, _destBounds.Height);

#if DEBUG
            destCB._dbugNote = "GetTransformedBilinearInterpolation()";
#endif
            MyBitmapBlender destWriter = new MyBitmapBlender(destCB);
            PointF          ptInPlane = new PointF();
            int             x1, x2, y1, y2;
            double          dab, dbc, dcd, dda;
            float           dx1, dx2, dy1, dy2, dx1y1, dx1y2, dx2y1, dx2y2;
            int             rectWidth  = _destBounds.Width;
            int             rectHeight = _destBounds.Height;
            Vector          ab_vec     = _AB;
            Vector          bc_vec     = _BC;
            Vector          cd_vec     = _CD;
            Vector          da_vec     = _DA;
            int             rectLeft   = _destBounds.Left;
            int             rectTop    = _destBounds.Top;

            int srcW_lim = _srcW - 1;
            int srcH_lim = _srcH - 1;

            using (TempMemPtr.FromBmp(_srcBmp, out int *bufferPtr))
            {
                BufferReader4 reader = new BufferReader4(bufferPtr, _srcBmp.Width, _srcBmp.Height);
                for (int y = 0; y < rectHeight; ++y)
                {
                    for (int x = 0; x < rectWidth; ++x)
                    {
                        PointF srcPt = new PointF(x, y);
                        srcPt.Offset(rectLeft, rectTop);
                        if (!IsOnPlaneABCD(srcPt))
                        {
                            continue;
                        }
                        //-------------------------------------
                        dab = Math.Abs(MyVectorHelper.NewFromTwoPoints(_p0, srcPt).CrossProduct(ab_vec));
                        dbc = Math.Abs(MyVectorHelper.NewFromTwoPoints(_p1, srcPt).CrossProduct(bc_vec));
                        dcd = Math.Abs(MyVectorHelper.NewFromTwoPoints(_p2, srcPt).CrossProduct(cd_vec));
                        dda = Math.Abs(MyVectorHelper.NewFromTwoPoints(_p3, srcPt).CrossProduct(da_vec));

                        ptInPlane.X = (float)(_srcW * (dda / (dda + dbc)));
                        ptInPlane.Y = (float)(_srcH * (dab / (dab + dcd)));
                        x1          = (int)ptInPlane.X;
                        y1          = (int)ptInPlane.Y;

                        if (x1 >= 0 && x1 < srcW_lim &&
                            y1 >= 0 && y1 < srcH_lim)
                        {
                            //x2 = (x1 == srcW - 1) ? x1 : x1 + 1;
                            //y2 = (y1 == srcH - 1) ? y1 : y1 + 1;

                            x2 = x1 + 1;
                            y2 = y1 + 1;

                            dx1 = ptInPlane.X - x1;
                            if (dx1 < 0)
                            {
                                dx1 = 0;
                            }
                            dx1 = 1f - dx1;
                            dx2 = 1f - dx1;
                            //
                            //
                            dy1 = ptInPlane.Y - y1;
                            if (dy1 < 0)
                            {
                                dy1 = 0;
                            }
                            dy1 = 1f - dy1;
                            dy2 = 1f - dy1;
                            //
                            //
                            dx1y1 = dx1 * dy1;
                            dx1y2 = dx1 * dy2;
                            dx2y1 = dx2 * dy1;
                            dx2y2 = dx2 * dy2;
                            //use 4 points

                            reader.SetStartPixel(x1, y1);


                            Drawing.Color x1y1Color;
                            Drawing.Color x2y1Color;
                            Drawing.Color x1y2Color;
                            Drawing.Color x2y2Color;

                            reader.Read4(out x1y1Color, out x2y1Color, out x1y2Color, out x2y2Color);

                            //Drawing.Color x1y1Color = srcCB.GetPixel(x1, y1);
                            //Drawing.Color x2y1Color = srcCB.GetPixel(x2, y1);
                            //Drawing.Color x1y2Color = srcCB.GetPixel(x1, y2);
                            //Drawing.Color x2y2Color = srcCB.GetPixel(x2, y2);
                            float a = (x1y1Color.A * dx1y1) + (x2y1Color.A * dx2y1) + (x1y2Color.A * dx1y2) + (x2y2Color.A * dx2y2);
                            float b = (x1y1Color.B * dx1y1) + (x2y1Color.B * dx2y1) + (x1y2Color.B * dx1y2) + (x2y2Color.B * dx2y2);
                            float g = (x1y1Color.G * dx1y1) + (x2y1Color.G * dx2y1) + (x1y2Color.G * dx1y2) + (x2y2Color.G * dx2y2);
                            float r = (x1y1Color.R * dx1y1) + (x2y1Color.R * dx2y1) + (x1y2Color.R * dx1y2) + (x2y2Color.R * dx2y2);
                            destWriter.SetPixel(x, y, new Drawing.Color((byte)a, (byte)r, (byte)g, (byte)b));
                        }
                    }
                }
                return(destCB);
            }
        }