skip to Main Content

I need to apply a custom shape (this, a .jpg) to any image I load into my application, using Windows Forms if possible (since my whole project is made in Winforms), but I guess I can use WPF if it’s needed.

So for example if I have a photo like this, the result should be like this (I made this with Photoshop for you to see), maybe even without the white borders if possible (please note that the image was resized and centered to fit the custom shape, and that’s how it should be).

I can’t figure out how to do this, but from what I’ve searched I suppose it has something to do with brushes (TextureBrush, ImageBrush, etc).

Regards.

2

Answers


  1. Here is an example tuned for the image you linked to:

            using (var source = (Bitmap) Image.FromFile(@"image filename"))
            {
                using (var target = new Bitmap(source.Width, source.Height))
                {
                    using (var graphics = Graphics.FromImage(target))
                    {
                        using (var path = new GraphicsPath())
                        {
                            path.StartFigure();
                            path.AddLine(161, 665, 223, 624);
                            path.AddLine(223, 624, 252, 568);
                            path.AddLine(252, 568, 239, 525);
                            path.AddLine(239, 525, 200, 432);
                            path.AddLine(200, 432, 178, 343);
                            path.AddLine(178, 343, 156, 198);
                            path.AddLine(156, 198, 161, 131);
                            path.AddLine(161, 131, 248, 38);
                            path.AddLine(248, 38, 366, 4);
                            path.AddLine(366, 4, 657, 10);
                            path.AddLine(657, 10, 735, 70);
                            path.AddLine(735, 70, 741, 195);
                            path.AddLine(741, 195, 746, 282);
                            path.AddLine(746, 282, 762, 410);
                            path.AddLine(762, 410, 730, 498);
                            path.AddLine(730, 498, 686, 582);
                            path.AddLine(686, 582, 727, 669);
                            path.CloseFigure();
                            graphics.Clip = new Region(path);
                        }
    
                        graphics.DrawImage(source, 0, 0);
                    }
    
                    this.PictureBox.Image = new Bitmap(target);
                }
            }
    
    Login or Signup to reply.
  2. it seems to me that you want to apply a mask, you could do it with something like this (using /unsafe code):

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace testImageBlender
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            Bitmap imBase;
            Bitmap imMask,imMask2;
            Bitmap blendedImage;
    
            private void Form1_Load(object sender, EventArgs e)
            {
                if (openFileDialog1.ShowDialog() == DialogResult.OK)
                {
                    if (openFileDialog2.ShowDialog() == DialogResult.OK)
                    {
                        imBase = new Bitmap(openFileDialog1.FileName);
                        imMask = new Bitmap(openFileDialog2.FileName);
                        blendedImage = new Bitmap(openFileDialog2.FileName);
                        blendImage();
                    }
                }
            }
    
            private void Form1_Paint(object sender, PaintEventArgs e)
            {
                if (imBase != null)
                {
                    if (imMask != null)
                    {
                        if (blendedImage != null)
                        {
                            e.Graphics.DrawImage(blendedImage, e.ClipRectangle);
                        }
                    }
                }
            }
    
            private void blendImage()
            {
                Rectangle mRec = new Rectangle(0, 0, imMask.Width, imMask.Height);
                float intensity = 0;
                //playing around with images to get pixel format 24bpp RGB, most probably a very bad way of doing it, but I don't know enough about image format and lockbits to do it nice and clean yet
                imMask2 = new Bitmap(imMask);
    
                Graphics.FromImage(imBase).DrawImage(imBase, 0, 0, imMask.Width, imMask.Height);
                Graphics.FromImage(blendedImage).DrawImage(imMask, 0, 0, imMask.Width, imMask.Height);
                Graphics.FromImage(imMask2).DrawImage(imMask, 0, 0, imMask.Width, imMask.Height);
    
                BitmapData imageData = imBase.LockBits(mRec, ImageLockMode.ReadOnly, imBase.PixelFormat);
                BitmapData maskData = imMask2.LockBits(mRec, ImageLockMode.ReadOnly, imMask.PixelFormat);
                BitmapData blendedData = blendedImage.LockBits(mRec, ImageLockMode.WriteOnly, blendedImage.PixelFormat);
    
                unsafe
                {
    
                    byte* imagePointer = (byte*)imageData.Scan0;
                    byte* maskPointer = (byte*)maskData.Scan0;
                    byte* blendedPointer = (byte*)blendedData.Scan0;
    
                    for (int i = 0; i < mRec.Height; i++)
                    {
                        for (int j = 0; j < mRec.Width; j++)
                        {
                            intensity = 1-((float)(maskPointer[0] + maskPointer[1] + maskPointer[2])) / ((float)3 * 255);
                            for (int k = 0; k < 3; k++)
                            {
                                blendedPointer[k] =  (intensity>0.8)?(byte)((float)imagePointer[k]):(byte)255;
                            }
                            // 3 bytes per pixel
                            imagePointer += 3;
                            maskPointer += 3;
                            blendedPointer += 3;
                        }
    
                        // Moving the pointers to the next pixel row
                        imagePointer += imageData.Stride - (mRec.Width * 3);
                        maskPointer += maskData.Stride - (mRec.Width * 3);
                        blendedPointer += blendedData.Stride - (mRec.Width * 3);
                    }
    
                }
    
                imBase.UnlockBits(imageData);
                imMask2.UnlockBits(maskData);
                blendedImage.UnlockBits(blendedData);
            }
        }
    }
    

    this is very much inspired by Balazs Tihanyi answers on Draw image on top of another image with blending mode color

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search