public void Sharpen(IBitmapSrc img, int radius)
        {
            unsafe
            {
                TempMemPtr bufferPtr = img.GetBufferPtr();
                int[]      output    = new int[bufferPtr.LengthInBytes / 4]; //TODO: review here again

                fixed(int *outputPtr = &output[0])
                {
                    byte *srcBuffer     = (byte *)bufferPtr.Ptr;
                    int * srcBuffer1    = (int *)srcBuffer;
                    int * outputBuffer1 = (int *)outputPtr;
                    int   stride        = img.Stride;
                    int   w             = img.Width;
                    int   h             = img.Height;

                    MemHolder srcMemHolder = new MemHolder((IntPtr)srcBuffer1, bufferPtr.LengthInBytes / 4);//
                    Surface   srcSurface   = new Surface(stride, w, h, srcMemHolder);
                    //
                    MemHolder destMemHolder = new MemHolder((IntPtr)outputPtr, bufferPtr.LengthInBytes / 4);
                    Surface   destSurface   = new Surface(stride, w, h, destMemHolder);
                    //
                    SharpenRenderer shRenderer1 = new SharpenRenderer();

                    shRenderer1.Amount = radius;
                    shRenderer1.Render(srcSurface, destSurface, new PixelFarm.Drawing.Rectangle[] {
                        new PixelFarm.Drawing.Rectangle(0, 0, w, h)
                    }, 0, 1);
                }

                bufferPtr.Release();
                //ActualImage.SaveImgBufferToPngFile(output, img.Stride, img.Width + 1, img.Height + 1, "d:\\WImageTest\\test_1.png");
                img.ReplaceBuffer(output);
            }
        }
Beispiel #2
0
        public unsafe static TempMemPtr FromBmp(MemBitmap bmp, out byte *headPtr)
        {
            TempMemPtr ptr = MemBitmap.GetBufferPtr(bmp);

            headPtr = (byte *)ptr.Ptr;
            return(ptr);
        }
Beispiel #3
0
        public unsafe static TempMemPtr FromBmp(IBitmapSrc actualBmp, out int *headPtr)
        {
            TempMemPtr ptr = actualBmp.GetBufferPtr();

            headPtr = (int *)ptr.Ptr;
            return(ptr);
        }
Beispiel #4
0
        public unsafe static TempMemPtr FromBmp(MemBitmap memBmp, out int *headPtr)
        {
            TempMemPtr ptr = MemBitmap.GetBufferPtr(memBmp);

            headPtr = (int *)ptr.Ptr;
            return(ptr);
        }
        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);
                }
            }
        }
Beispiel #6
0
        public static void CopyFromGdiPlusBitmapSameSize(
            Bitmap windowsBitmap,
            MemBitmap actualImage)
        {
            int h = windowsBitmap.Height;
            int w = windowsBitmap.Width;
            //byte[] targetBuffer = ActualImage.GetBuffer(actualImage);

            BitmapData bitmapData1 = windowsBitmap.LockBits(
                new Rectangle(0, 0,
                              w,
                              h),
                System.Drawing.Imaging.ImageLockMode.ReadWrite,
                windowsBitmap.PixelFormat);
            IntPtr scan0  = bitmapData1.Scan0;
            int    stride = bitmapData1.Stride;

            //TODO: review here
            //use buffer copy

            unsafe
            {
                //target
                TempMemPtr targetMemPtr = MemBitmap.GetBufferPtr(actualImage);
                byte *     target       = (byte *)targetMemPtr.Ptr;
                int        startRowAt   = ((h - 1) * stride);
                byte *     src          = (byte *)scan0;
                for (int y = h; y > 0; --y)
                {
                    // byte* target = targetH + ((y - 1) * stride);
                    //System.Runtime.InteropServices.Marshal.Copy(
                    //      (IntPtr)src,//src
                    //      targetBuffer, startRowAt, stride);
                    MemMx.memcpy(target + startRowAt, src, stride);
                    startRowAt -= stride;
                    src        += stride;
                }
                targetMemPtr.Dispose();
                //////////////////////////////////////////////////////////////////
                //fixed (byte* targetH = &targetBuffer[0])
                //{
                //    byte* src = (byte*)scan0;
                //    for (int y = h; y > 0; --y)
                //    {
                //        byte* target = targetH + ((y - 1) * stride);
                //        for (int n = stride - 1; n >= 0; --n)
                //        {
                //            *target = *src;
                //            target++;
                //            src++;
                //        }
                //    }
                //}
            }
            windowsBitmap.UnlockBits(bitmapData1);
        }
Beispiel #7
0
        public static void dbugSaveToJpgFile(this MemBitmap bmp, string filename)
        {
            TempMemPtr tmpMem = MemBitmap.GetBufferPtr(bmp);

            SaveImgBufferToJpgFileUnsafe(tmpMem,
                                         bmp.Stride,
                                         bmp.Width,
                                         bmp.Height,
                                         filename);
            tmpMem.Dispose();
        }
Beispiel #8
0
        public static void SaveImgBufferToPngFile(TempMemPtr imgBuffer, int stride, int width, int height, string filename)
        {
            if (s_saveToFile != null)
            {
                unsafe
                {
                    //fixed (int* head = imgBuffer.Ptr)

                    int *head = (int *)imgBuffer.Ptr;
                    {
                        s_saveToFile((IntPtr)head, stride, width, height, filename);
                    }
                }
            }
        }
Beispiel #9
0
 /// <summary>
 /// copy from actual image direct to hBmpScan0
 /// </summary>
 /// <param name="actualImage"></param>
 /// <param name="hBmpScan0"></param>
 public static void CopyToWindowsBitmapSameSize(
     MemBitmap actualImage,
     IntPtr hBmpScan0)
 {
     //1st, fast
     //byte[] rawBuffer = ActualImage.GetBuffer(actualImage);
     unsafe
     {
         TempMemPtr memPtr = MemBitmap.GetBufferPtr(actualImage);
         MemMx.memcpy((byte *)hBmpScan0, (byte *)memPtr.Ptr, actualImage.Stride * actualImage.Height);
         memPtr.Dispose();
     }
     //System.Runtime.InteropServices.Marshal.Copy(rawBuffer, 0,
     //   hBmpScan0, rawBuffer.Length);
 }
Beispiel #10
0
 public static unsafe void SaveImgBufferToJpgFileUnsafe(
     TempMemPtr tmpMem,
     int stride,
     int width,
     int height,
     string filename)
 {
     if (s_saveToFile != null)
     {
         unsafe
         {
             //fixed (int* head = &imgBuffer[0])
             int *head = (int *)tmpMem.Ptr;
             {
                 s_saveToFile((IntPtr)head, stride, width, height, filename);
             }
         }
     }
 }
Beispiel #11
0
        public static void CopyFromGdiPlusBitmapSameSizeTo32BitsBuffer(
            Bitmap srcWindowsBitmap,
            MemBitmap dstMemBmp)
        {
            int h = srcWindowsBitmap.Height;
            int w = srcWindowsBitmap.Width;

            TempMemPtr targetBufferPtr = MemBitmap.GetBufferPtr(dstMemBmp);
            BitmapData bmpData         = srcWindowsBitmap.LockBits(
                new Rectangle(0, 0,
                              w,
                              h),
                System.Drawing.Imaging.ImageLockMode.ReadOnly,
                System.Drawing.Imaging.PixelFormat.Format32bppArgb);           //read as 32 bits

            unsafe
            {
                PixelFarm.CpuBlit.NativeMemMx.MemCopy(
                    (byte *)targetBufferPtr.Ptr,
                    (byte *)bmpData.Scan0,
                    bmpData.Stride * dstMemBmp.Height
                    );
            }

            srcWindowsBitmap.UnlockBits(bmpData);



            //int stride = bitmapData1.Stride;

            ////test
            ////in this version we decided that
            ////Agg's image should use Big-endian bytes.

            ////so we convert the byte order for

            //unsafe
            //{

            //    byte* targetH = (byte*)targetBufferPtr.Ptr;
            //    int startRowAt = ((h - 1) * stride);
            //    byte* src = (byte*)scan0;
            //    for (int y = h; y > 0; --y)
            //    {

            //        //System.Runtime.InteropServices.Marshal.Copy(
            //        //      (IntPtr)src,//src
            //        //      targetBuffer, startRowAt, stride);
            //        MemMx.memcpy(targetH + startRowAt, src, stride);
            //        startRowAt -= stride;
            //        src += stride;
            //    }

            //    //////////////////////////////////////////////////////////////////
            //    //fixed (byte* targetH = &targetBuffer[0])
            //    //{
            //    //    byte* src = (byte*)scan0;
            //    //    for (int y = h; y > 0; --y)
            //    //    {
            //    //        byte* target = targetH + ((y - 1) * stride); //start at first column of the current row

            //    //        for (int n = stride - 1; n >= 0;) //n steps
            //    //        {
            //    //            //*target = *src;
            //    //            //target++;
            //    //            //src++;

            //    //            //the win gdi+ is
            //    //            *(target + 2) = *src; //R, 0->2
            //    //            *(target + 1) = *(src + 1); //G 1->1
            //    //            *(target + 0) = *(src + 2); //B 2->0
            //    //            *(target + 3) = *(src + 3); //A 3->3

            //    //            //#if !RGBA
            //    //            //       //eg OpenGL,
            //    //            //       /// <summary>
            //    //            //        /// order b
            //    //            //        /// </summary>
            //    //            //        public const int B = 0;
            //    //            //        /// <summary>
            //    //            //        /// order g
            //    //            //        /// </summary>
            //    //            //        public const int G = 1;
            //    //            //        /// <summary>
            //    //            //        /// order b
            //    //            //        /// </summary>
            //    //            //        public const int R = 2;
            //    //            //        /// <summary>
            //    //            //        /// order a
            //    //            //        /// </summary>
            //    //            //        public const int A = 3;
            //    //            //#else
            //    //            //        //RGBA (Windows GDI+)

            //    //            //        /// <summary>
            //    //            //        /// order b
            //    //            //        /// </summary>
            //    //            //        public const int B = 2;
            //    //            //        /// <summary>
            //    //            //        /// order g
            //    //            //        /// </summary>
            //    //            //        public const int G = 1;
            //    //            //        /// <summary>
            //    //            //        /// order b
            //    //            //        /// </summary>
            //    //            //        public const int R = 0;
            //    //            //        /// <summary>
            //    //            //        /// order a
            //    //            //        /// </summary>
            //    //            //        public const int A = 3;
            //    //            //#endif

            //    //            target += 4;
            //    //            src += 4;
            //    //            //target++;
            //    //            //src++;
            //    //            n -= 4;
            //    //        }
            //    //    }
            //    //}
            //}
        }
Beispiel #12
0
        /////////////////////////////////////////////////////////////////////////////////////
        public static void CopyToGdiPlusBitmapSameSizeNotFlip(
            MemBitmap srcMemBmp,
            Bitmap dstBitmap)
        {
            //agg store image buffer head-down
            //when copy to window bmp we here to flip
            //style1: copy row by row *** (fastest)***
            {
                //System.GC.Collect();
                //System.Diagnostics.Stopwatch sss = new System.Diagnostics.Stopwatch();
                //sss.Start();
                //for (int i = 0; i < 1000; ++i)
                //{
                int        h           = dstBitmap.Height;
                int        w           = dstBitmap.Width;
                BitmapData bitmapData1 = dstBitmap.LockBits(
                    new Rectangle(0, 0,
                                  w,
                                  h),
                    System.Drawing.Imaging.ImageLockMode.ReadWrite,
                    dstBitmap.PixelFormat);
                IntPtr scan0  = bitmapData1.Scan0;
                int    stride = bitmapData1.Stride;
                //byte[] srcBuffer = ActualImage.GetBuffer(actualImage);
                TempMemPtr srcBufferPtr = MemBitmap.GetBufferPtr(srcMemBmp);
                unsafe
                {
                    //fixed (byte* bufferH = &srcBuffer[0])
                    byte *srcBufferH = (byte *)srcBufferPtr.Ptr;
                    {
                        byte *target     = (byte *)scan0;
                        int   startRowAt = 0;
                        for (int y = 0; y < h; ++y)
                        {
                            //byte* src = bufferH + ((y - 1) * stride);
                            byte *src = srcBufferH + startRowAt;
                            //System.Runtime.InteropServices.Marshal.Copy(
                            //   srcBuffer,//src
                            //   startRowAt,
                            //   (IntPtr)target,
                            //   stride);
                            MemMx.memcpy(target, src, stride);

                            startRowAt += stride;
                            target     += stride;
                        }
                    }
                }
                srcBufferPtr.Dispose();
                dstBitmap.UnlockBits(bitmapData1);
                //}
                //sss.Stop();
                //long ms = sss.ElapsedMilliseconds;
            }
            //-----------------------------------
            //style2: copy all, then flip again
            //{
            //    System.GC.Collect();
            //    System.Diagnostics.Stopwatch sss = new System.Diagnostics.Stopwatch();
            //    sss.Start();
            //    for (int i = 0; i < 1000; ++i)
            //    {
            //        byte[] rawBuffer = ActualImage.GetBuffer(actualImage);
            //        var bmpdata = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height),
            //          System.Drawing.Imaging.ImageLockMode.ReadOnly,
            //         bitmap.PixelFormat);


            //        System.Runtime.InteropServices.Marshal.Copy(rawBuffer, 0,
            //            bmpdata.Scan0, rawBuffer.Length);

            //        bitmap.UnlockBits(bmpdata);
            //        bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
            //    }

            //    sss.Stop();
            //    long ms = sss.ElapsedMilliseconds;
            //}
            //-----------------------------------

            //-----------------------------------
            //style3: copy row by row +
            //{
            //    System.GC.Collect();
            //    System.Diagnostics.Stopwatch sss = new System.Diagnostics.Stopwatch();
            //    sss.Start();
            //    for (int i = 0; i < 1000; ++i)
            //    {
            //        int h = bitmap.Height;
            //        int w = bitmap.Width;
            //        BitmapData bitmapData1 = bitmap.LockBits(
            //                  new Rectangle(0, 0,
            //                      w,
            //                      h),
            //                      System.Drawing.Imaging.ImageLockMode.ReadWrite,
            //                      bitmap.PixelFormat);
            //        IntPtr scan0 = bitmapData1.Scan0;
            //        int stride = bitmapData1.Stride;
            //        byte[] buffer = ActualImage.GetBuffer(actualImage);
            //        unsafe
            //        {
            //            fixed (byte* bufferH = &buffer[0])
            //            {
            //                byte* target = (byte*)scan0;
            //                for (int y = h; y > 0; --y)
            //                {
            //                    byte* src = bufferH + ((y - 1) * stride);
            //                    for (int n = stride - 1; n >= 0; --n)
            //                    {
            //                        *target = *src;
            //                        target++;
            //                        src++;
            //                    }
            //                }
            //            }
            //        }
            //        bitmap.UnlockBits(bitmapData1);
            //    }
            //    sss.Stop();
            //    long ms = sss.ElapsedMilliseconds;
            //}
        }
        public void Fill(IBitmapSrc bufferToFillOn, int x, int y)
        {
            y -= imageHeight;
            unchecked // this way we can overflow the uint on negative and get a big number
            {
                if ((uint)x >= bufferToFillOn.Width || (uint)y >= bufferToFillOn.Height)
                {
                    return;
                }
            }
            _destImgRW = bufferToFillOn;
            TempMemPtr destBufferPtr = bufferToFillOn.GetBufferPtr();

            unsafe
            {
                imageWidth  = bufferToFillOn.Width;
                imageHeight = bufferToFillOn.Height;
                //reset new buffer, clear mem?
                pixelsChecked = new bool[imageWidth * imageHeight];

                int *destBuffer             = (int *)destBufferPtr.Ptr;
                int  startColorBufferOffset = bufferToFillOn.GetBufferOffsetXY32(x, y);

                int start_color = *(destBuffer + startColorBufferOffset);

                fillRule.SetStartColor(Drawing.Color.FromArgb(
                                           (start_color >> 16) & 0xff,
                                           (start_color >> 8) & 0xff,
                                           (start_color) & 0xff));


                LinearFill(destBuffer, x, y);

                while (ranges.Count > 0)
                {
                    Range range           = ranges.Dequeue();
                    int   downY           = range.y - 1;
                    int   upY             = range.y + 1;
                    int   downPixelOffset = (imageWidth * (range.y - 1)) + range.startX;
                    int   upPixelOffset   = (imageWidth * (range.y + 1)) + range.startX;
                    for (int rangeX = range.startX; rangeX <= range.endX; rangeX++)
                    {
                        if (range.y > 0)
                        {
                            if (!pixelsChecked[downPixelOffset])
                            {
                                int bufferOffset = bufferToFillOn.GetBufferOffsetXY32(rangeX, downY);

                                if (fillRule.CheckPixel(*(destBuffer + bufferOffset)))
                                {
                                    LinearFill(destBuffer, rangeX, downY);
                                }
                            }
                        }

                        if (range.y < (imageHeight - 1))
                        {
                            if (!pixelsChecked[upPixelOffset])
                            {
                                int bufferOffset = bufferToFillOn.GetBufferOffsetXY32(rangeX, upY);
                                if (fillRule.CheckPixel(*(destBuffer + bufferOffset)))
                                {
                                    LinearFill(destBuffer, rangeX, upY);
                                }
                            }
                        }
                        upPixelOffset++;
                        downPixelOffset++;
                    }
                }
            }
            destBufferPtr.Release();
        }
        //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);
            }
        }