将自定义形状应用于任何图像

时间:2015-03-15 19:45:14

标签: c# wpf image winforms

我需要将自定义形状(this,.jpg)应用到我加载到我的应用程序中的任何图像,如果可能的话使用Windows窗体(因为我的整个项目是在Winforms中制作的),但我想我如果需要,可以使用WPF。

例如,如果我有像this这样的照片,结果应该像this(我用Photoshop制作这个就可以看到),如果可能的话甚至可能没有白色边框(请请注意,图像已调整大小并居中以适应自定义形状,以及它应该如何)。

我无法弄清楚如何做到这一点,但从我搜索的内容来看,我认为它与画笔(TextureBrush,ImageBrush等)有关。

问候。

2 个答案:

答案 0 :(得分:1)

在我看来,你想要应用一个掩码,你可以用这样的东西(使用/不安全的代码)来做:

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);
        }
    }
}

这很受Balazs Tihanyi在Draw image on top of another image with blending mode color

的回答的启发

答案 1 :(得分:0)

以下是针对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);
            }
        }