Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【愚公系列】2024年01月 GDI+绘图专题 DrawImage

【愚公系列】2024年01月 GDI+绘图专题 DrawImage

原创
作者头像
愚公搬代码
发布于 2024-01-03 00:31:17
发布于 2024-01-03 00:31:17
5080
举报
文章被收录于专栏:历史专栏历史专栏

🏆 作者简介,愚公搬代码 🏆《头衔》:华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,阿里云专家博主,腾讯云优秀博主,掘金优秀博主,51CTO博客专家等。 🏆《近期荣誉》:2022年CSDN博客之星TOP2,2022年华为云十佳博主等。

🏆《博客内容》:.NET、Java、Python、Go、Node、前端、IOS、Android、鸿蒙、Linux、联网、络安全、数据、工智能、U3D游戏、小程序等相关领域知识。

🏆🎉欢迎 👍点赞✍评论⭐收藏

🚀前言

在WinForm中,可以使用Graphics类的DrawImage方法来绘制图像。具体步骤如下:

  1. 准备好要绘制的图片,通常可以使用Image类来加载图片。
  2. 创建一个Graphics对象,指定要绘制的目标画布。
  3. 调用Graphics对象的DrawImage方法,传入要绘制的图片和位置信息,即可在指定位置绘制图片。

以下是示例代码:

代码语言:csharp
AI代码解释
复制
public partial class Form1 : Form
{
    private Image image;  // 要绘制的图片

    public Form1()
    {
        InitializeComponent();

        // 加载图片
        image = Image.FromFile("image.jpg");
    }

    private void Form1_Paint(object sender, PaintEventArgs e)
    {
        // 创建Graphics对象
        Graphics g = e.Graphics;

        // 绘制图片,位置为(10, 10)
        g.DrawImage(image, 10, 10);
    }
}

在上述示例中,我们通过重写Form的Paint事件,在窗体加载时绘制图片。当然,也可以在其他事件中绘制图片,比如Button的Click事件。

🚀一、DrawImage

🔎1.显示图像

使用DrawImage方法显示图像需要先创建一个Bitmap对象,并将其传递给Graphics对象的DrawImage方法。以下是演示如何在WinForms中使用DrawImage方法显示图像的代码示例:

代码语言:csharp
AI代码解释
复制
private void OnPaint(object sender, PaintEventArgs e)
{
    Graphics g = e.Graphics;
    Bitmap bmp = new Bitmap(@"C:\Users\Happy\Pictures\Saved Pictures\e841dee27110095a301f5cc828af68e0.jpg");
    g.DrawImage(bmp, 0, 0);//屏幕上图像的大小为屏幕分辨率和图像分辨率的比值

    Console.WriteLine(g.DpiX);
    Console.WriteLine(g.DpiY);
    Console.WriteLine(bmp.HorizontalResolution);
    Console.WriteLine(bmp.VerticalResolution);

    //为了显示和原始图像一样物理尺寸的大小,又由于屏幕分辨率比较低,所以图像的分辨率实际上降低了
    Console.WriteLine($"图像像素{bmp.Size}");
    SizeF s = new SizeF(bmp.Width * (g.DpiX / bmp.HorizontalResolution), bmp.Height * (g.DpiY / bmp.VerticalResolution));
    Console.WriteLine($"屏幕图像像素{s}");

    Rectangle r = new Rectangle(0, 100, bmp.Width, bmp.Height);
    Rectangle sourceR = new Rectangle(0, 0, bmp.Width, bmp.Height);
    g.DrawImage(bmp, r, sourceR, GraphicsUnit.Pixel);//源矩形和目标矩形大小相同时,就不进行图像的缩放,目标矩形大于原始矩形则放大,否则缩小
}

在上面的代码中,首先创建了一个Bitmap对象,然后获取了当前窗体的Graphics对象,并调用其DrawImage方法绘制图像。在绘制图像时,需要传入以下参数:

  1. Bitmap对象:要绘制的图像。
  2. Point对象:绘制图像的左上角位置。
  3. Rectangle对象:要绘制的Bitmap对象中需要呈现的区域。
  4. GraphicsUnit枚举:指定坐标和显示单位。

🔎2.改变图像分辨率对图像显示的影响

下面是一个简单的示例,说明Bitmap的SetResolution方法改变图像分辨率对图像显示的影响:

代码语言:csharp
AI代码解释
复制
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace WinFormDemo
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }

        private void OnPaint(object sender, PaintEventArgs e)
        {
            // 读取图像
            Bitmap bitmap = new Bitmap(@"C:\Users\Happy\Pictures\Saved Pictures\e841dee27110095a301f5cc828af68e0.jpg");

            // 打印原始图像的分辨率
            MessageBox.Show($"原始图像分辨率:{bitmap.HorizontalResolution} × {bitmap.VerticalResolution} DPI");

            // 设置新的分辨率
            bitmap.SetResolution(200, 200);

            // 打印更改后的图像的分辨率
            MessageBox.Show($"更改后图像分辨率:{bitmap.HorizontalResolution} × {bitmap.VerticalResolution} DPI");

            // 绘制图像
            e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
            e.Graphics.DrawImage(bitmap, 0, 0, 400, 400);
        }
    }
}

在该示例中,我们读取了一张图像,并分别打印了原始图像和更改后的图像的分辨率。然后,我们在绘制图像时使用了更改后的Bitmap,并将图像大小设置为300×300像素。由于我们将分辨率设置为200×200 DPI,因此该图像的实际大小为2英寸×2英寸。

运行示例后,可以看到更改后的图像比原始图像更小,但更加清晰。当然,具体影响取决于实际情况,该示例只是为了演示Bitmap的SetResolution方法的使用方式。

🔎3.使用插值算法对图像进行缩放

在WinForm中使用DrawImage方法进行图像缩放时,可以使用插值算法来提高图像的质量。插值算法是一种通过已知数据点来估计未知点的方法。在图像缩放时,插值算法通过已知像素点的颜色值来估计未知像素点的颜色值,从而实现图像的缩放。

.NET Framework提供了多种插值算法,可以通过Graphics类的InterpolationMode属性来设置。以下是常用的插值算法:

  • NearestNeighbor:使用最近邻插值算法,在图像缩放时只考虑最接近像素点的颜色值,速度快但质量较低。
  • Bilinear:使用双线性插值算法,在图像缩放时考虑最近的四个像素点的颜色值,速度较快,质量较高。
  • HighQualityBilinear:使用高质量双线性插值算法,在图像缩放时考虑最近的四个像素点的颜色值,质量更高,但速度较慢。
  • Bicubic:使用双三次插值算法,在图像缩放时考虑最近的16个像素点的颜色值,质量最高,但速度最慢。

以下是使用Bilinear插值算法对图像进行缩放的示例代码:

代码语言:csharp
AI代码解释
复制
private void OnPaint(object sender, PaintEventArgs e)
{
    Graphics g = e.Graphics;
    // 读取图像
    Bitmap bmp = new Bitmap(@"C:\Users\Happy\Pictures\Saved Pictures\e841dee27110095a301f5cc828af68e0.jpg");

    g.DrawImage(bmp, 0, 0);//屏幕上图像的大小为屏幕分辨率和图像分辨率的比值

    g.InterpolationMode = InterpolationMode.NearestNeighbor;
    Rectangle r = new Rectangle(0, 100, bmp.Width, bmp.Height);
    Rectangle sourceR = new Rectangle(0, 0, bmp.Width, bmp.Height);
    g.DrawImage(bmp, r, sourceR, GraphicsUnit.Pixel);//源矩形和目标矩形大小相同时,就不进行图像的缩放,目标矩形大于原始矩形则放大,否则缩小

    g.InterpolationMode = InterpolationMode.HighQualityBicubic;
    r = new Rectangle(500, 100, bmp.Width, bmp.Height);
    g.DrawImage(bmp, r, sourceR, GraphicsUnit.Pixel);
}

🔎4.图像裁剪

可以使用Graphics对象的DrawImage方法绘制图像,并通过参数指定绘制的位置和大小。在指定绘制大小时,可以使用Rectangle结构体指定裁剪的区域。

下面是一个示例代码,演示如何在WinForm中裁剪图像:

代码语言:csharp
AI代码解释
复制
private void OnPaint(object sender, PaintEventArgs e)
{
    // 读取图像
    Bitmap image = new Bitmap(@"C:\Users\Happy\Pictures\Saved Pictures\e841dee27110095a301f5cc828af68e0.jpg");

    // 指定裁剪区域
    Rectangle sourceRect = new Rectangle(50, 50, 100, 100);

    // 指定绘制区域
    Rectangle destRect = new Rectangle(0, 0, 200, 200);

    // 绘制图像,只绘制裁剪区域
    e.Graphics.DrawImage(image, destRect, sourceRect, GraphicsUnit.Pixel);
}

在上面的代码中,首先通过From.File方法加载图像,然后使用Rectangle结构体指定裁剪区域和绘制区域。最后使用Graphics对象的DrawImage方法绘制图像,只绘制裁剪区域。

🔎5.图像的变形(仿射变换)

在WinForm中,可以使用Graphics类的DrawImage方法进行图像的绘制。在绘制时,可以使用PointF类型的参数指定图像的位置和大小,从而实现比例缩放和平移等变换。

如果需要进行仿射变换,可以使用Matrix类的TransformPoints方法将图像的顶点进行变换,然后使用Graphics类的DrawImage方法绘制变换后的图像。

以下是一个简单的示例:

代码语言:csharp
AI代码解释
复制
private void OnPaint(object sender, PaintEventArgs e)
{
    // 读取图像
    Bitmap bmp = new Bitmap(@"C:\Users\Happy\Pictures\Saved Pictures\e841dee27110095a301f5cc828af68e0.jpg");

    // 定义变换矩阵
    Matrix matrix = new Matrix();
    matrix.Translate(50, 50);    // 平移
    matrix.Scale(0.5f, 0.5f);    // 缩放
    PointF[] points = {
        new PointF(0, 0),       // 左上角
        new PointF(bmp.Width, 100),    // 右上角
        new PointF(0, bmp.Height)   // 左下角
    };
    matrix.TransformPoints(points);    // 变换顶点

    // 绘制图像
    e.Graphics.DrawImage(bmp, points);
}

在上述示例中,首先将图像进行平移和缩放,然后将顶点进行变换,最后使用DrawImage方法绘制变换后的图像。

🔎6.图像翻转(上下对折)

在WinForm中使用DrawImage方法进行图像翻转(上下对折),可以通过以下步骤实现:

  1. 加载图像资源
代码语言:csharp
AI代码解释
复制
Bitmap bitmap = new Bitmap("ImageFilePath.png");
  1. 创建Graphics对象
代码语言:csharp
AI代码解释
复制
Graphics graphics = this.CreateGraphics();
  1. 创建Point对象
代码语言:csharp
AI代码解释
复制
Point startPoint = new Point(0, 0); // 图像绘制的起点,这里设为左上角
  1. 创建Rectangle对象
代码语言:csharp
AI代码解释
复制
Rectangle srcRect = new Rectangle(0, 0, bitmap.Width, bitmap.Height); // 原图像的大小
Rectangle destRect = new Rectangle(0, 0, bitmap.Width, bitmap.Height); // 目标图像的大小
  1. 调用Graphics对象的DrawImage方法,将原图像绘制在目标图像上
代码语言:csharp
AI代码解释
复制
graphics.DrawImage(bitmap, destRect, srcRect, GraphicsUnit.Pixel);
  1. 调用Graphics对象的ScaleTransform方法,对图像进行上下对折
代码语言:csharp
AI代码解释
复制
graphics.ScaleTransform(1, -1); // 上下对折
  1. 调用Graphics对象的TranslateTransform方法,将图像移动到正确的位置
代码语言:csharp
AI代码解释
复制
graphics.TranslateTransform(0, -bitmap.Height); // 向上移动原图像的高度
  1. 再次调用DrawImage方法,将上下对折后的图像绘制在窗口上
代码语言:csharp
AI代码解释
复制
graphics.DrawImage(bitmap, destRect, srcRect, GraphicsUnit.Pixel);

完整代码示例:

代码语言:csharp
AI代码解释
复制
private void OnPaint(object sender, PaintEventArgs e)
{
    // 读取图像
    Bitmap bitmap = new Bitmap(@"C:\Users\Happy\Pictures\Saved Pictures\e841dee27110095a301f5cc828af68e0.jpg");

    Graphics graphics = this.CreateGraphics();

    Rectangle srcRect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
    Rectangle destRect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);

    graphics.DrawImage(bitmap, destRect, srcRect, GraphicsUnit.Pixel);
    graphics.ScaleTransform(1, -1);
    graphics.TranslateTransform(0, -bitmap.Height);
    graphics.DrawImage(bitmap, destRect, srcRect, GraphicsUnit.Pixel);
}

🔎7.旋转

在WinForm中使用DrawImage进行旋转,可以使用Graphics类中的RotateTransform方法来实现。该方法可以将图像沿着指定的角度旋转,并且可以选择以图像中心点为中心旋转或者以指定的点为中心旋转。需要注意的是,该方法旋转的是整个绘图区域,而不是单个图像,因此需要在旋转之前将绘图区域设置到指定的图像位置。

下面是一个使用Point进行旋转的示例代码:

代码语言:csharp
AI代码解释
复制
private void OnPaint(object sender, PaintEventArgs e)
{
    // 读取图像
    Bitmap bitmap = new Bitmap(@"C:\Users\Happy\Pictures\Saved Pictures\e841dee27110095a301f5cc828af68e0.jpg");

    Point point = new Point(100, 100);
    float angle = 45;

    // 将绘图区域设置到指定图像位置
    e.Graphics.TranslateTransform(point.X, point.Y);

    // 以图像中心点为中心旋转
    e.Graphics.RotateTransform(angle, System.Drawing.Drawing2D.MatrixOrder.Prepend);

    // 将图像移回原始位置
    e.Graphics.TranslateTransform(-point.X, -point.Y);

    // 绘制图像
    e.Graphics.DrawImage(bitmap, point);

}

在该示例中,通过调用TranslateTransform方法将绘图区域设置到指定的图像位置,然后调用RotateTransform方法进行旋转。旋转完成后,再调用TranslateTransform方法将图像移回原始位置,最后调用DrawImage方法绘制图像。

🔎8.复制图像

代码语言:csharp
AI代码解释
复制
private void OnPaint(object sender, PaintEventArgs e)
{
    Graphics g = e.Graphics;
    // 原始图像
    Bitmap bmp = new Bitmap(@"C:\Users\Happy\Pictures\Saved Pictures\e841dee27110095a301f5cc828af68e0.jpg");
    Bitmap bmp2 = bmp.Clone(new Rectangle(50, 50, bmp.Width - 50, bmp.Height - 50), PixelFormat.DontCare);

    g.DrawImage(bmp, 0, 0);
    g.DrawImage(bmp2, 200, 0);

}

🔎9.在内存中创建位图

如果要在内存中创建位图并使用DrawImage方法绘制到控件上,可以使用以下代码示例:

代码语言:csharp
AI代码解释
复制
private void OnPaint(object sender, PaintEventArgs e)
{
    // 创建一个位图
    Bitmap bitmap = new Bitmap(100, 100);

    // 获取位图的Graphics对象
    Graphics bitmapGraphics = Graphics.FromImage(bitmap);

    // 绘制位图
    Pen pen = new Pen(Color.Red);
    bitmapGraphics.DrawLine(pen, 0, 0, 100, 100);
    pen.Dispose();
    bitmapGraphics.Dispose();

    // 在控件上绘制位图
    e.Graphics.DrawImage(bitmap, 0, 0);

    // 释放位图对象
    bitmap.Dispose();
}

在上面的示例中,我们首先创建了一个100x100大小的位图。接着,我们获取位图的Graphics对象,使用它来绘制线条。最后,我们在控件上使用DrawImage方法绘制位图,并释放位图对象。

🔎10.双倍缓存

在WinForm中使用GDI+绘图时,如果不使用双倍缓存,会出现画面闪烁的问题。为了解决这个问题,可以使用双倍缓存进行绘图。

双倍缓存的原理是在内存中创建一个与屏幕大小相同的位图,先将所有绘图操作在位图中进行,最后一次性将整个位图绘制到屏幕上,从而避免了在屏幕上绘制不完整的图像,从而消除了闪烁问题。

代码语言:csharp
AI代码解释
复制
public class DoubleBufferedPanel : Panel
{
    public DoubleBufferedPanel()
    {
   	    //this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
        //this.SetStyle(ControlStyles.AllPaintingInWmPaint ,true);
        //this.SetStyle(ControlStyles.UserPaint ,true );

        DoubleBuffered = true;
    }
}

public partial class Form1 : Form
{
    private Bitmap m_buffer;

    public Form1()
    {
        InitializeComponent();

        // 创建位图
        m_buffer = new Bitmap(ClientSize.Width, ClientSize.Height);

        // 绑定绘图事件
        doubleBufferedPanel1.Paint += doubleBufferedPanel1_Paint;
    }

    private void doubleBufferedPanel1_Paint(object sender, PaintEventArgs e)
    {
        Graphics g = e.Graphics;

        // 在位图上进行绘制操作
        using (Graphics bufferGraphics = Graphics.FromImage(m_buffer))
        {
            // 在位图上绘制图像
            bufferGraphics.DrawImage(image, 0, 0);
        }

        // 将整个位图一次性绘制到屏幕上
        g.DrawImage(m_buffer, 0, 0);
    }
}

在上面的代码中,我们首先在构造函数中创建了一个与窗口大小相同的位图 m_buffer,然后在双倍缓存面板的绘图事件中,先使用 Graphics.FromImage 方法获取位图的绘图对象,然后再在位图上进行绘制操作,最后一次性将整个位图绘制到屏幕上。

这样就可以消除闪烁问题,让绘图效果更加平滑。

🔎11.处理图像中的alpha成分

在WinForm中使用CompositingMode处理图像中的alpha成分是一种非常有效的处理方法,该方法可以将图像的alpha值与背景混合,从而达到半透明的效果。

代码语言:csharp
AI代码解释
复制
private void OnPaint(object sender, PaintEventArgs e)
{
    Graphics gForm = e.Graphics;
    gForm.CompositingMode = CompositingMode.SourceOver;

    for (int i = 1; i < 7; i++)
    {
        Rectangle rectangle = new Rectangle(i * 30, 0, 15, this.ClientRectangle.Height);
        gForm.FillRectangle(Brushes.Orange, rectangle);
    }

    Bitmap bitmap = new Bitmap(260, 260, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
    Graphics gBmp = Graphics.FromImage(bitmap);

    gBmp.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;//更改已有得像素和alpha


    Color color = Color.FromArgb(0x60, 0xff, 0, 0);
    Brush redBrush = new SolidBrush(color);
    gBmp.FillEllipse(redBrush, 70, 70, 160, 160);

    Color green = Color.FromArgb(0x40, 0, 0xff, 0);
    Brush greenBrush = new SolidBrush(green);
    gBmp.FillRectangle(greenBrush, 10, 10, 140, 140);


    gForm.DrawImage(bitmap, 20, 20, bitmap.Width, bitmap.Height);
}

处理alpha有两种方式,一种是覆盖原有得像素以及alpha,对应得CompositingMode.SourceCopy,另一种是和原有的像素进行混合,对应的CompositingMode.SourceOver。

设置CompositingMode属性为CompositingMode.SourceOver,表示采用前景与背景的透明度混合方式。最后,我们调用Graphics对象的DrawImage方法,将前景图像绘制到背景图像上,最终得到一个混合后的半透明图像。最后,将处理后的Bitmap对象赋值给PictureBox的Image属性,就可以在界面上显示处理后的图像。

需要注意的是,这种方式处理透明度时需要保证背景和前景图像的尺寸一致,否则会出现边缘不透明或者重叠的问题。此外,还需要注意CompositingMode属性的正确设置,否则处理后的图像效果可能不正确。

🔎12.获取和设置像素

🦋12.1 GetPixel,SetPixel

代码语言:csharp
AI代码解释
复制
private void OnPaint(object sender, PaintEventArgs e)
{
    // 原始图像
    Bitmap bmp = new Bitmap(@"C:\Users\Happy\Pictures\Saved Pictures\e841dee27110095a301f5cc828af68e0.jpg");

    Graphics g = e.Graphics;

    int width = bmp.Width;
    int height = bmp.Height;
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            Color color = bmp.GetPixel(j, i);//getpixel的第一个参数是图像X坐标,第二个参数是图像Y坐标
            Color newColor = Color.FromArgb(255, 255, 0, 0);
            bmp.SetPixel(j, i, newColor);

            Console.WriteLine($"r:{color.R},g:{color.G},b:{color.B},a:{color.A}");
        }
    }

    g.DrawImage(bmp, new PointF(0, 0));

}

🦋12.2 在系统内存中操作图像

代码语言:csharp
AI代码解释
复制
private void OnPaint(object sender, PaintEventArgs e)
{

    // 原始图像
    Bitmap bmp = new Bitmap(@"C:\Users\Happy\Pictures\Saved Pictures\e841dee27110095a301f5cc828af68e0.jpg");

    Graphics g = e.Graphics;

    byte[] bytes = GetBGRValues(bmp);
    Bitmap newBitmap = SetBGRValues(bytes, bmp);

    g.DrawImage(newBitmap, new PointF(0, 0));

}
public static byte[] GetBGRValues(Bitmap bmp)
{
    var rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
    var bmpData = bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat);//将bitmap锁到系统内存操作
    int stride = bmpData.Stride;//获取图像的扫描宽度

    var rowBytes = bmpData.Width * System.Drawing.Image.GetPixelFormatSize(bmp.PixelFormat) / 8;//获取一行像素数量,要考虑图像位的深度
    var imgBytes = bmp.Height * rowBytes;//获取图像中所有像素个数
    byte[] rgbValues = new byte[imgBytes];
    IntPtr ptr = bmpData.Scan0;//获取第一个像素地址
    for (var i = 0; i < bmp.Height; i++)
    {
        Marshal.Copy(ptr, rgbValues, i * rowBytes, rowBytes);//一行一行的复制
        ptr += stride; // next row,地址不能通过rows来更改,因为有可能扫描宽度大于图像宽度(rowBytes)
    }
    bmp.UnlockBits(bmpData);//将bitmap从内存释放

    return rgbValues;
}

public static Bitmap SetBGRValues(byte[] bytes, Bitmap bmp)
{
    var rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
    var bmpData = bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat);//将bitmap锁到系统内存操作
    int stride = bmpData.Stride;//获取图像的扫描宽度

    var rowBytes = bmpData.Width * System.Drawing.Image.GetPixelFormatSize(bmp.PixelFormat) / 8;//获取一行像素数量,要考虑图像位的深度
    var imgBytes = bmp.Height * rowBytes;//获取图像中所有像素个数
    byte[] rgbValues = new byte[bytes.Length];//数组的值都是0



    IntPtr ptr = bmpData.Scan0;//获取第一个像素地址
    for (var i = 0; i < bmp.Height; i++)
    {
        Marshal.Copy(rgbValues, i * rowBytes, ptr, rowBytes);//将bytes托管数组复制到非托内存指针
        ptr += stride; // next row,地址不能通过rows来更改,因为有可能扫描宽度大于图像宽度(rowBytes)
    }
    bmp.UnlockBits(bmpData);//将bitmap从内存释放

    return bmp;
}

🔎13.创建半透明的图像

代码语言:csharp
AI代码解释
复制
private void OnPaint(object sender, PaintEventArgs e)
{

    // 原始图像
    Bitmap bmp = new Bitmap(@"C:\Users\Happy\Pictures\Saved Pictures\e841dee27110095a301f5cc828af68e0.jpg");

    Graphics g = e.Graphics;

    g.DrawImage(bmp, new PointF(0, 0));

    float[][] matrix = {
        new float []{ 1,0,0,0,0},
         new float []{ 0,1,0,0,0},
          new float []{ 0,0,1,0,0},
            new float []{ 0,0,0,0.1f,0},
             new float []{ 0,0,0,0,1},
    };
    ColorMatrix colorMatrix = new ColorMatrix(matrix);
    ImageAttributes imageAttributes = new ImageAttributes();

    imageAttributes.SetColorMatrix(colorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
    g.DrawImage(bmp, new Rectangle(200, 200, 220, 200), 0, 0, bmp.Width, bmp.Height, GraphicsUnit.Pixel, imageAttributes);

}

🔎14.播放动画

代码语言:csharp
AI代码解释
复制
public partial class MainForm : Form
{
    private Bitmap bmp;
    public MainForm()
    {
        InitializeComponent();
        Text = "HatchBrush Example";
        Size = new Size(400, 400);
        Paint += new PaintEventHandler(OnPaint);
    }

    private void FrameChange(object sender, EventArgs e)
    {
        this.Invalidate();
    }

    protected void OnPaint(object sender, PaintEventArgs e)
    {
        ImageAnimator.UpdateFrames();//刷新一帧
        e.Graphics.DrawImage(this.bmp, new PointF(0, 0));
    }

    private void MainForm_Load(object sender, EventArgs e)
    {
        bmp = new Bitmap(@"C:\Users\Happy\Pictures\Saved Pictures\2.gif");
        ImageAnimator.Animate(bmp, FrameChange);//将多帧图像显示为动画
    }
}

🔎15.图片类型转换

代码语言:csharp
AI代码解释
复制
public partial class MainForm : Form
{
    public MainForm()
    {
        InitializeComponent();
        Text = "HatchBrush Example";
        Size = new Size(400, 400);
        Paint += new PaintEventHandler(OnPaint);
    }

    protected void OnPaint(object sender, PaintEventArgs e)
    {
        Bitmap bmp = new Bitmap("1.bmp");
        bmp.Save("2.jpg", ImageFormat.Jpeg);


        ImageCodecInfo ici = GetImageEncoder("image/jpeg");
        System.Drawing.Imaging.Encoder enc = System.Drawing.Imaging.Encoder.ColorDepth;
        EncoderParameter ep = new EncoderParameter(enc, 0);//指定压缩等级为0-100

        EncoderParameters epa = new EncoderParameters(1);

        epa.Param[0] = ep;
        bmp.Save("30.jpg", ici, epa);
    }
    private static ImageCodecInfo GetImageEncoder(string mimeType)
    {
        int j;
        ImageCodecInfo[] imageCodecInfos;
        imageCodecInfos = ImageCodecInfo.GetImageEncoders();//获取图像编码器信息

        for (j = 0; j < imageCodecInfos.Length; j++)
        {
            if (imageCodecInfos[j].MimeType == mimeType)
            {
                return imageCodecInfos[j];
            }
        }
        return null;
    }
}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【愚公系列】2023年12月 GDI+绘图专题 图形图像编程基础
本章主要介绍使用C#进行图形图像编程基础,其中包括GDI+绘图基础、C#图像处理基础以及简单的图像处理技术。
愚公搬代码
2023/12/22
1K0
【愚公系列】2024年01月 GDI+绘图专题 DrawString
DrawString是C#中Graphics类的一个方法,用于在指定的位置绘制文本。在WinForm应用程序中使用DrawString,可以在窗体或控件上绘制文本。
愚公搬代码
2024/01/02
5960
【愚公系列】2023年12月 GDI+绘图专题 Brush
在WinForm中,Brush是用于填充绘制图形的对象,它们提供了不同的填充方式和样式。在绘制图形时,可以通过Graphics对象的Fill方法使用Brush进行填充。以下是一些常见的Brush类型:
愚公搬代码
2023/12/29
3340
C#一些常用的图片操作方法:生成文字图片 合并图片等
生成文字图片: 1 /// <summary> 2 /// 生成文字图片 3 /// </summary> 4 /// <param name="text"></param> 5 /// <param name="isBold"></param> 6 /// <param name="fontSize"></param> 7 public Image CreateImage(stri
晓晨
2018/06/22
1.5K0
C#下怎样处理并保存单色格式PNG图片?
用微软自带的画图,打开一个已经存在的单色PNG图片文件,然后复制图像粘贴上去,做点反色或其他处理再保存,可以得到黑白单色PNG图片;但是,如果有很多黑底白字的图片要想改成白纸黑字的单色PNG格式保存这就很麻烦了,譬如2,3百张BMP或JPG图片用来保存只有白纸黑字的书页真是浪费。可是,有些索引格式图像如单色位图,或者单色PNG,如果用C#的Graphics类处理之后,保存文件只能得到非索引色格式或者GIF格式,若想以原格式保存文件似乎没有直接方便的方法可用,不得已只能用自己的代码一点一点去写像。 以下代码,参考网上找了些的,加上实际证得:(注释并不是必需要的,有些编写代码过程中的记录,或者为了方便说明)
全栈程序员站长
2022/09/13
1K0
【愚公系列】2023年12月 GDI+绘图专题 Font
在WinForm中,Font是用于控件中显示文本的字体。它是一个封装了字体族、字号、字体样式的类。
愚公搬代码
2023/12/30
2330
工业党福利:使用PaddleX高效实现指针型表计读取系列文章(2)
最近在做一个工业巡检的项目,主要涉及的内容是指针型表计的读取。本系列文章主要介绍实现表计读取的全流程开发(立个FLAG,想想真是肝...留下了不争气的眼泪),其中主要使用的工具为百度开发的PaddleX和Visual studio 2019。
用户7699929
2020/08/27
1.7K0
工业党福利:使用PaddleX高效实现指针型表计读取系列文章(2)
【愚公系列】2024年01月 GDI+绘图专题(裁剪、变换、重绘)
裁剪(Clipping)指的是将图像或元素的一部分进行裁剪,只显示所需区域,而隐藏不需要的部分。
愚公搬代码
2024/01/11
7501
【愚公系列】2023年12月 GDI+绘图专题 图形图像的重绘
图形图像的重绘是指在对图形或图像进行修改后,需要重新绘制该图形或图像以反映修改后的结果。重绘可以在屏幕上直接进行,也可以在内存中进行,最后再将修改后的图形或图像显示在屏幕上。
愚公搬代码
2023/12/23
2980
Windows Forms:在C#中将图像转换成灰度图
本文翻译自Windows Forms: Convert an image into grayscale in C# 这篇文章向你展示在C# Windows窗体应用程序中如何将图像转换成灰度图。 创建一个新的Windows窗体应用程序项目,然后创建一个允许你可以打开图像,然后将图像转换成黑白图像的简单的UI,如下图所示:
ccf19881030
2021/03/02
1.7K0
Windows Forms:在C#中将图像转换成灰度图
C#生成缩略图
/**/ /// <summary> /// 生成缩略图 /// </summary> /// <param name="originalImagePath">源图路径(物理路径)</param> /// <param name="thumbnailPath">缩略图路径(物理路径)</param> /// <param name="width">缩略图宽度</param> /// <param name="height">缩略图高度</param> /// <param name="mode">生成缩略图的方式</param> public static void MakeThumbnail(string originalImagePath, string thumbnailPath, int width, int height, string mode,string type) { System.Drawing.Image originalImage = System.Drawing.Image.FromFile(originalImagePath);
jack.yang
2025/04/05
560
ImageHelper.cs-支持高清缩略图
using System; using System.Collections.Generic; using System.Text; using System.IO; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; namespace System { /// <summary> /// 图片处理类 /// </summary> public class
KenTalk
2018/09/11
9400
.net下灰度模式图像在创建Graphics时出现:无法从带有索引像素格式的图像创建graphics对象 问题的解决方案。
文章主要介绍了如何通过GDI+绘制椭圆,并给出了具体的实现代码和示例。主要步骤包括:定义一个基于GDI+的Bitmap对象,使用GraphicsPath绘制椭圆,将GraphicsPath转换为Bitmap,并使用RenderOptions.SetBitmapScalingMode进行缩放处理。
用户1138785
2018/01/03
5.7K1
.net下灰度模式图像在创建Graphics时出现:无法从带有索引像素格式的图像创建graphics对象 问题的解决方案。
【愚公系列】2023年12月 GDI+绘图专题 颜色获取和图形绘制
颜色获取是指从图像或者其他的颜色源中获取颜色值的过程。在计算机中,颜色值通常由RGB值来表示,即红、绿、蓝三原色的取值组合。通常可以通过鼠标选择选取颜色和颜色值,或者通过程序代码指定颜色值来获取颜色。
愚公搬代码
2023/12/24
2880
2020-10-22在线识图搜索引擎
最近在逛淘宝时发现了淘宝的图片搜索功能,可能是我太Low了这个技术点已经实现很长时间了。想想自己能不能实现这个功能,起初我是这么想的,对两张图片从左上角的第一个像素点一直比较到右下角的最后一个像素点,并在比较时记录它们的相似度,可能是我太天真了(主要还是知识限制了想象),这样做有很多问题,比如说两张图片大小不一致、核心要素点的位置不同等...最终只得借助网络了,找到了一种叫做均值哈希的算法(Average hash algorithm),接下来具体阐述它的基本思路以及适用场景。
爱笑的架构师
2020/10/28
1K0
2020-10-22在线识图搜索引擎
C# 使用OpenCV在一张图片里寻找人脸
例程中用到一个库叫做emgucv,是opencv\的net封装 编译打包好的稳定版,在这:https://sourceforge.net/projects/emgucv/files/emgucv/ 如果要最新代码,在这里获取:https://github.com/emgucv/emgucv
zls365
2020/08/19
2.8K0
C# 使用OpenCV在一张图片里寻找人脸
【愚公系列】2023年12月 GDI+绘图专题 Pen
Pen是在WinForm中用于绘制线条、轮廓和边框的对象。它定义了一个画笔,具有不同的颜色、宽度和样式。在绘制图形或图形对象时,Pen对象通常会与Graphics对象一起使用。
愚公搬代码
2023/12/28
2190
GDI+ 不求人之-自己画个验证码
GDI+ 不求人之-自己画个验证码 😃😃😃😃😃😃🤔🤔🤔🤔🤔🤔 简单来说就是画图的 先小试牛刀画个小图形 在点击事件里写下几行画正方形: Graphics g = this.CreateGraphics(); Pen pen = new Pen(Brushes.Black); Rectangle rec = new Rectangle(50,50,80,80); g.DrawRectangle(pen,rec); 在点击
用户9857551
2022/06/28
3970
GDI+ 不求人之-自己画个验证码
C#对图片文件的压缩、裁剪操作初探
在做项目时,对图片的处理,以前都采用在上传时,限制其大小的方式,这样带来诸多不便。毕竟网站运维人员不一定会对图片做处理,经常超出大小限制,即使会使用图片处理软件的,也由于个人水平方面原因,处理效果差强人意。 于是采用C#为我们提供的图像编辑功能,实现一站式上传,通过程序生成所需大小、尺寸的目标图片。 进入正题--> 先说图片压缩 第一步:需要读取一个图片文件,读取方法: // <param name="ImageFilePathAndName">图片文件的全路径名称</param> 说明: Image类:引
小端
2018/04/16
2.2K0
推荐一款DataGridView的打印解决方案
今天有朋友请教在CS的WinForm中如何打印DataGridView中的内容。 网上搜索一番之后,还是在藏宝库CodeProject中找到一篇好文章《DataGridView Printing by Selecting Columns and Rows》(http://www.codeproject.com/KB/grid/PrintDataGrid_CS.aspx) 效果图 【打印设置画面】
跟着阿笨一起玩NET
2018/09/18
1.9K0
推荐一款DataGridView的打印解决方案
推荐阅读
相关推荐
【愚公系列】2023年12月 GDI+绘图专题 图形图像编程基础
更多 >
领券
💥开发者 MCP广场重磅上线!
精选全网热门MCP server,让你的AI更好用 🚀
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档