Accord.Imaging.Filters.Blend.ProcessFilter C# (CSharp) Method

ProcessFilter() protected method

Process the image filter.
protected ProcessFilter ( UnmanagedImage sourceData, UnmanagedImage destinationData ) : void
sourceData Accord.Imaging.UnmanagedImage
destinationData Accord.Imaging.UnmanagedImage
return void
        protected override void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData)
        {

            // Locks the overlay image
            BitmapData overlayData = overlayImage.LockBits(
              new Rectangle(0, 0, overlayImage.Width, overlayImage.Height),
              ImageLockMode.ReadOnly, overlayImage.PixelFormat);


            // get source image size
            int width = sourceData.Width;
            int height = sourceData.Height;

            // get destination image size
            int newWidth = destinationData.Width;
            int newHeight = destinationData.Height;

            int srcPixelSize = System.Drawing.Image.GetPixelFormatSize(sourceData.PixelFormat) / 8;
            int orgPixelSize = System.Drawing.Image.GetPixelFormatSize(overlayData.PixelFormat) / 8;

            int srcStride = sourceData.Stride;
            int dstOffset = destinationData.Stride - newWidth * 4; // destination always 32bpp argb


            // Get center of first image
            Point center1 = new Point((int)(overlayImage.Width / 2f),
                                      (int)(overlayImage.Height / 2f));

            // Get center of second image
            Point center2 = this.center;



            // Compute maximum center distances
            float dmax1 = Math.Min(
                distance(center1.X, center1.Y, center2.X - imageSize.Width / 2f, center1.Y),
                distance(center1.X, center1.Y, center1.X, center1.Y + overlayImage.Height / 2f));

            float dmax2 = Math.Min(
                distance(center2.X, center2.Y, center2.X + imageSize.Width / 2f, center2.Y),
                distance(center2.X, center2.Y, center2.X, center2.Y + imageSize.Height / 2f));

            float dmax = -System.Math.Abs(dmax2 - dmax1);


            // fill values
            byte fillR = fillColor.R;
            byte fillG = fillColor.G;
            byte fillB = fillColor.B;
            byte fillA = 0;//fillColor.A;

            // Retrieve homography matrix as float array
            float[,] H = (float[,])homography;


            // do the job
            unsafe
            {
                byte* org = (byte*)overlayData.Scan0.ToPointer();
                byte* src = (byte*)sourceData.ImageData.ToPointer();
                byte* dst = (byte*)destinationData.ImageData.ToPointer();

                // destination pixel's coordinate relative to image center
                double cx, cy;

                // destination pixel's homogenous coordinate
                double hx, hy, hw;

                // source pixel's coordinates
                int ox, oy;



                // Copy the overlay image
                for (int y = 0; y < newHeight; y++)
                {
                    for (int x = 0; x < newWidth; x++, dst += 4)
                    {
                        ox = (int)(x + offset.X);
                        oy = (int)(y + offset.Y);

                        // validate source pixel's coordinates
                        if ((ox < 0) || (oy < 0) || (ox >= overlayData.Width) || (oy >= overlayData.Height))
                        {
                            // fill destination image with filler
                            dst[0] = fillB;
                            dst[1] = fillG;
                            dst[2] = fillR;
                            dst[3] = fillA;
                        }
                        else
                        {
                            int c = oy * overlayData.Stride + ox * orgPixelSize;

                            // fill destination image with pixel from original image

                            if (orgPixelSize == 3)
                            {
                                // 24 bpp
                                dst[0] = org[c + 0];
                                dst[1] = org[c + 1];
                                dst[2] = org[c + 2];
                                dst[3] = (byte)255;
                            }
                            else if (orgPixelSize == 4)
                            {
                                // 32 bpp
                                dst[0] = org[c + 0];
                                dst[1] = org[c + 1];
                                dst[2] = org[c + 2];
                                dst[3] = org[c + 3];
                            }
                            else
                            {
                                // 8 bpp
                                dst[0] = org[c];
                                dst[1] = org[c];
                                dst[2] = org[c];
                                dst[3] = org[c];
                            }
                        }
                    }
                    dst += dstOffset;
                }

                org = (byte*)overlayData.Scan0.ToPointer();
                src = (byte*)sourceData.ImageData.ToPointer();
                dst = (byte*)destinationData.ImageData.ToPointer();

                // Project and blend the second image
                for (int y = 0; y < newHeight; y++)
                {
                    for (int x = 0; x < newWidth; x++, dst += 4)
                    {
                        cx = x + offset.X;
                        cy = y + offset.Y;

                        // projection using homogenous coordinates
                        hw = (H[2, 0] * cx + H[2, 1] * cy + H[2, 2]);
                        hx = (H[0, 0] * cx + H[0, 1] * cy + H[0, 2]) / hw;
                        hy = (H[1, 0] * cx + H[1, 1] * cy + H[1, 2]) / hw;

                        // coordinate of the nearest point
                        ox = (int)(hx);
                        oy = (int)(hy);

                        // validate source pixel's coordinates
                        if ((ox >= 0) && (oy >= 0) && (ox < width) && (oy < height))
                        {
                            int c = oy * srcStride + ox * srcPixelSize;

                            // fill destination image with pixel from source image
                            if (srcPixelSize == 4 && src[c + 3] == 0)
                            {
                                // source pixel is fully transparent, nothing to copy
                            }
                            else if (dst[3] > 0)
                            {
                                float f1 = 0.5f, f2 = 0.5f;

                                if (Gradient)
                                {
                                    // there is a pixel from the other image here, blend
                                    float d1 = distance(x, y, center1.X, center1.Y);
                                    float d2 = distance(x, y, center2.X, center2.Y);
                                    f1 = Vector.Scale(d1 - d2, 0, dmax, 0, 1);

                                    if (f1 < 0) f1 = 0f;
                                    if (f1 > 1) f1 = 1f;
                                    f2 = (1f - f1);
                                }

                                if (!AlphaOnly)
                                {
                                    if (srcPixelSize == 3)
                                    {
                                        // 24 bpp
                                        dst[0] = (byte)(src[c + 0] * f2 + dst[0] * f1);
                                        dst[1] = (byte)(src[c + 1] * f2 + dst[1] * f1);
                                        dst[2] = (byte)(src[c + 2] * f2 + dst[2] * f1);
                                        dst[3] = (byte)255;
                                    }
                                    else if (srcPixelSize == 4)
                                    {
                                        // 32 bpp
                                        dst[0] = (byte)(src[c + 0] * f2 + dst[0] * f1);
                                        dst[1] = (byte)(src[c + 1] * f2 + dst[1] * f1);
                                        dst[2] = (byte)(src[c + 2] * f2 + dst[2] * f1);
                                        dst[3] = (byte)(src[c + 3] * f2 + dst[3] * f1);
                                    }
                                    else
                                    {
                                        // 8 bpp
                                        dst[0] = (byte)(src[c] * f2 + dst[0] * f1);
                                        dst[1] = (byte)(src[c] * f2 + dst[1] * f1);
                                        dst[2] = (byte)(src[c] * f2 + dst[2] * f1);
                                        dst[3] = (byte)255;
                                    }
                                }
                                else
                                {
                                    if (srcPixelSize == 3)
                                    {
                                        // 24 bpp
                                        dst[0] = (byte)(src[c + 0]);
                                        dst[1] = (byte)(src[c + 1]);
                                        dst[2] = (byte)(src[c + 2]);
                                    }
                                    else if (srcPixelSize == 4)
                                    {
                                        // 32 bpp
                                        dst[0] = (byte)(src[c + 0]);
                                        dst[1] = (byte)(src[c + 1]);
                                        dst[2] = (byte)(src[c + 2]);
                                    }
                                    else
                                    {
                                        // 8 bpp
                                        dst[0] = (byte)(src[c]);
                                        dst[1] = (byte)(src[c]);
                                        dst[2] = (byte)(src[c]);
                                    }
                                }
                            }
                            else
                            {
                                // just copy the source into the destination image

                                if (srcPixelSize == 3)
                                {
                                    // 24bpp
                                    dst[0] = src[c + 0];
                                    dst[1] = src[c + 1];
                                    dst[2] = src[c + 2];
                                    dst[3] = (byte)255;
                                }
                                else if (srcPixelSize == 4)
                                {
                                    // 32bpp
                                    dst[0] = src[c + 0];
                                    dst[1] = src[c + 1];
                                    dst[2] = src[c + 2];
                                    dst[3] = src[c + 3];
                                }
                                else
                                {
                                    // 8bpp
                                    dst[0] = src[c];
                                    dst[1] = src[c];
                                    dst[2] = src[c];
                                    dst[3] = 0;
                                }
                            }
                        }
                    }
                    dst += dstOffset;

                }
            }

            overlayImage.UnlockBits(overlayData);
        }