Code Optimization

Interesting things about software development and code optimization

Print on Wood - Image overlay


Hello my dear friends,


in this post I will show you how to overlay one image over another image like if you would print an image over wood.

In this example we need two images, one is a wood image and another one is just a photo or whatever image do you like.

To make such effect we will do a few simple steps, here you are:

- create an empty image that will be a result image;

- draw your wood texture over that empty image;

- combine colors of the wood image and a photo, using the following formula c1 * c2 / 255.0;


The main thing here is to multiply each component of colors and divide it by 255.0. You do not need to do anything with alpha,

here is the short code:

for (int y = 0; y < surfWood.Bounds.Height; y++)

{

for (int x = 0; x < surfWood.Bounds.Width; x++)

{

color = surfWood.GetPixel(x, y);

color2 = surfSrc.GetPixel(x, y);

surfWood.SetPixelAsIs((byte)((double)color.R*(double)color2.R/255.0)

,(byte)((double)color.G*(double)color2.G/255.0)

,(byte)((double)color.B*(double)color2.B/255.0)

,color.A

, x, y);

}

}


 the result you will get is like the following:



so looks like you have printed out on a wood plate.


Thank you



1vqHSTrq1GEoEF7QsL8dhmJfRMDVxhv2y



C#.Net - Perspective Image Transform

Hello,


Today, I'm going to share one interesting thing that everyone may need - perspective image transformation.

Its 2D transformation that makes image look like in perspective view like 3D but without any 3D:


So, the main thing there is math. We take an image, specify four points and math will do the trick.

First step is to create and calculate matrices from the new four points:

//original points

Point p1 = new Point(0, 0);

Point p2 = new Point(width, 0);

Point p3 = new Point(width, height);

Point p4 = new Point(0, height);

//create matrix

A = Matrix3x3.Homogenous(p1, p2, p3, p4);

//new points

Point n1 = points[0];

Point n2 = points[1];

Point n3 = points[2];

Point n4 = points[3];

B = Matrix3x3.Homogenous(n1, n2, n3, n4);

A.Inverse();

C = B.MultMat(A);

C.Inverse();

Second step is to go through each pixel on your image and calculate new pixel:

Point ptDest = new Point(0, 0);

PointF ptOriginF = new Point(0, 0);

int iOrigX = 0;

Color pix = new Color();

for (int x = 0; x < width; ++x)

{

for (int y = 0; y < height; ++y)

{

ptDest.X = x;

ptDest.Y = y;

ptOriginF = C.Update(ptDest);

if (ptOriginF.X >= -5 && ptOriginF.X < width && ptOriginF.Y >= -5 && ptOriginF.Y < height)

{


iOrigX = (int)ptOriginF.X; // round to lowest integer

int iOrigY = (int)ptOriginF.Y; // round to lowest integer

double dx = ptOriginF.X - iOrigX;

double dy = ptOriginF.Y - iOrigY;

Point ptOrigin = new Point(iOrigX, iOrigY);

if (dx != 0.0f || dy != 0.0)

{

Color pix1 = Color.FromArgb(0, 255, 255, 255);

Color pix2 = Color.FromArgb(0, 255, 255, 255);

Color pix3 = Color.FromArgb(0, 255, 255, 255);

Color pix4 = Color.FromArgb(0, 255, 255, 255);

//

// Correct square's direction

//

int idx = (dx >= 0.0) ? 1 : -1;

int idy = (dy >= 0.0) ? 1 : -1;


dx = Math.Abs(dx);

dy = Math.Abs(dy);

//

// Get pixels of square

//

if (ptOrigin.X >= 0 && ptOrigin.X < width && ptOrigin.Y >= 0 && ptOrigin.Y < height)

pix1 = src.GetPixel(ptOrigin.X, ptOrigin.Y);

if (ptOrigin.X + idx >= 0 && ptOrigin.X + idx < width && ptOrigin.Y >= 0 && ptOrigin.Y < height)

pix2 = src.GetPixel(ptOrigin.X + idx, ptOrigin.Y);

if (ptOrigin.X >= 0 && ptOrigin.X < width && ptOrigin.Y + idy >= 0 && ptOrigin.Y + idy < height)

pix3 = src.GetPixel(ptOrigin.X, ptOrigin.Y + idy);

if (ptOrigin.X + idx >= 0 && ptOrigin.X + idx < width && ptOrigin.Y + idy >= 0 && ptOrigin.Y + idy < height)

pix4 = src.GetPixel(ptOrigin.X + idx, ptOrigin.Y + idy);

//

// Use bilinear interpolation

//

double r = pix1.R + (pix2.R - pix1.R) * dx + (pix3.R - pix1.R) * dy + (pix1.R - pix2.R - pix3.R + pix4.R) * dx * dy;

double g = pix1.G + (pix2.G - pix1.G) * dx + (pix3.G - pix1.G) * dy + (pix1.G - pix2.G - pix3.G + pix4.G) * dx * dy;

double b = pix1.B + (pix2.B - pix1.B) * dx + (pix3.B - pix1.B) * dy + (pix1.B - pix2.B - pix3.B + pix4.B) * dx * dy;

double a = pix1.A + (pix2.A - pix1.A) * dx + (pix3.A - pix1.A) * dy + (pix1.A - pix2.A - pix3.A + pix4.A) * dx * dy;

pix = Color.FromArgb((byte)a, (byte)r, (byte)g, (byte)b);

}

else

{

pix = src.GetPixel(ptOrigin.X, ptOrigin.Y);

}

dst.SetPixel(ptDest.X, ptDest.Y, pix);

}

}

}

So this is bilinear interpolation is the main thing to transform your image.


Thank you.

PS

will extend this and provide source code if you will request.

PPS

    public class Matrix3x3
    {
        double [,] m_val = new double [3,3];

        public Matrix3x3()
        {
        }
        public Matrix3x3(Point p1, Point p2, Point p3)
        {
            m_val = new double[3, 3];
            m_val[0, 0] = p1.X;
            m_val[0, 1] = p2.X;
            m_val[0, 2] = p3.X;

            m_val[1, 0] = p1.Y;
            m_val[1, 1] = p2.Y;
            m_val[1, 2] = p3.Y;

            m_val[2, 0] = 1.0;
            m_val[2, 1] = 1.0;
            m_val[2, 2] = 1.0;
        }

        public double Determinant()
        {
            double result = 0;
            result = m_val[0, 0] * (m_val[1, 1] * m_val[2, 2] - m_val[1, 2] * m_val[2, 1]);
            result-= m_val[0, 1] * (m_val[1, 0] * m_val[2, 2] - m_val[1, 2] * m_val[2, 0]);
            result+= m_val[0, 2] * (m_val[1, 0] * m_val[2, 1] - m_val[1, 1] * m_val[2, 0]);

            return result;
        }
        public double a(int i, int j)
        {
            return m_val[i-1, j-1];
        }

        public void Inverse()
        {
            double a11 = a(2, 2) * a(3, 3) - a(2, 3) * a(3, 2);
            double a12 = a(2, 1) * a(3, 3) - a(2, 3) * a(3, 1);
            double a13 = a(2, 1) * a(3, 2) - a(2, 2) * a(3, 1);

            double a21 = a(1, 2) * a(3, 3) - a(1, 3) * a(3, 2);
            double a22 = a(1, 1) * a(3, 3) - a(1, 3) * a(3, 1);
            double a23 = a(1, 1) * a(3, 2) - a(1, 2) * a(3, 1);

            double a31 = a(1, 2) * a(2, 3) - a(1, 3) * a(2, 2);
            double a32 = a(1, 1) * a(2, 3) - a(1, 3) * a(2, 1);
            double a33 = a(1, 1) * a(2, 2) - a(1, 2) * a(2, 1);

            double od = 1.0/Determinant();

            m_val[0, 0] = od * a11;
            m_val[0, 1] = -od * a21;
            m_val[0, 2] = od * a31;

            m_val[1, 0] = -od * a12;
            m_val[1, 1] = od * a22;
            m_val[1, 2] = -od * a32;

            m_val[2, 0] = od * a13;
            m_val[2, 1] = -od * a23;
            m_val[2, 2] = od * a33;
        }

        public void MultByVec(double [] vector)
        {
            for (int row = 0; row < 3; ++row)
            {
                m_val[row, 0] *= vector[0];
                m_val[row, 1] *= vector[1];
                m_val[row, 2] *= vector[2];
            }
        }
        public PointD Update(PointD vector)
        {
            double x = a(1, 1) * vector.X + a(1, 2) * vector.Y + a(1, 3) * 1.0;
            double y = a(2, 1) * vector.X + a(2, 2) * vector.Y + a(2, 3) * 1.0;
            double z = a(3, 1) * vector.X + a(3, 2) * vector.Y + a(3, 3) * 1.0;
            //
            PointD result = new PointD();
            result.X = (x / z);
            result.Y = (y / z);
            return result;
        }

        public Matrix3x3 MultMat(Matrix3x3 B)
        {
            Matrix3x3 result = new Matrix3x3();

            result.m_val[0, 0] = a(1, 1) * B.a(1, 1) + a(1, 2) * B.a(2, 1) + a(1, 3) * B.a(3, 1);
            result.m_val[0, 1] = a(1, 1) * B.a(1, 2) + a(1, 2) * B.a(2, 2) + a(1, 3) * B.a(3, 2);
            result.m_val[0, 2] = a(1, 1) * B.a(1, 3) + a(1, 2) * B.a(2, 3) + a(1, 3) * B.a(3, 3);

            result.m_val[1, 0] = a(2, 1) * B.a(1, 1) + a(2, 2) * B.a(2, 1) + a(2, 3) * B.a(3, 1);
            result.m_val[1, 1] = a(2, 1) * B.a(1, 2) + a(2, 2) * B.a(2, 2) + a(2, 3) * B.a(3, 2);
            result.m_val[1, 2] = a(2, 1) * B.a(1, 3) + a(2, 2) * B.a(2, 3) + a(2, 3) * B.a(3, 3);

            result.m_val[2, 0] = a(3, 1) * B.a(1, 1) + a(3, 2) * B.a(2, 1) + a(3, 3) * B.a(3, 1);
            result.m_val[2, 1] = a(3, 1) * B.a(1, 2) + a(3, 2) * B.a(2, 2) + a(3, 3) * B.a(3, 2);
            result.m_val[2, 2] = a(3, 1) * B.a(1, 3) + a(3, 2) * B.a(2, 3) + a(3, 3) * B.a(3, 3);

            return result;
        }

        public static Matrix3x3 Homogenous(Point p1, Point p2, Point p3, Point p4)
        {
            Matrix3x3 Major = new Matrix3x3(p1, p2, p3);
            Matrix3x3 Minor1 = new Matrix3x3(p4, p2, p3);
            Matrix3x3 Minor2 = new Matrix3x3(p1, p4, p3);
            Matrix3x3 Minor3 = new Matrix3x3(p1, p2, p4);
            double MajorD = Major.Determinant();
            double Minor1D = Minor1.Determinant();
            double Minor2D = Minor2.Determinant();
            double Minor3D = Minor3.Determinant();

            double[] coeff = new double[3];
            coeff[0] = Minor1D / MajorD;
            coeff[1] = Minor2D / MajorD;
            coeff[2] = Minor3D / MajorD;
            //
            Major.MultByVec(coeff);

            return Major;
        }
    }





1vqHSTrq1GEoEF7QsL8dhmJfRMDVxhv2y