CSharp 的图片处理

总结在 C# 读取图片的基础操作

什么是 GDI+

  • GDI 是 Graphics Device Interface 的缩写,含义是图形设备接口,它的主要任务是负责系统与绘图程序之间的信息交换,处理所有 Windows 程序的图形输出
  • GDI+(Graphics Device Interface plus)是 Windows XP 中的一个子系统,它主要负责在显示屏幕和打印设备输出有关信息,它是一组通过 C++ 类实现的应用程序编程接口。顾名思义,GDI + 是以前版本 GDI 的继承者
  • GDI+ 支持以下文件格式: BMP、GIF、EXIF、JPG、PNG 和 TIFF
  • 作为图形设备接口的 GDI + 使得应用程序开发人员在输出屏幕和打印机信息的时候无需考虑具体显示设备的细节,他们只需调用 GDI + 库输出的类的一些方法即可完成图形操作,真正的绘图工作由这些方法交给特定的设备驱动程序来完成,GDI + 使得图形硬件和应用程序相互隔离。从而使开发人员编写设备无关的应用程序变得非常容易

什么是位图?

  • 位图图像(bitmap),亦称为点阵图像或栅格图像,是由图形图像及其属性的像素数据组成
  • 当放大位图时,可以看见赖以构成整个图像的无数单个方块。扩大位图尺寸的效果是增大单个像素,从而使线条和形状显得参差不齐。然而,如果从稍远的位置观看它,位图图像的颜色和形状又显得是连续的
  • 位图的特点是可以表现色彩的变化和颜色的细微过渡,产生逼真的效果,缺点是在保存时需要记录每一个像素的位置和颜色值,占用较大的存储空间

什么是矢量图?

  • 所谓矢量图,就是使用直线和曲线来描述的图形,构成这些图形的元素是一些点、线、矩形、多边形、圆和弧线等,它们都是通过数学公式计算获得的,具有编辑后不失真的特点。例如一幅画的矢量图形实际上是由线段形成外框轮廓,由外框的颜色以及外框所封闭的颜色决定画显示出的颜色

位图与矢量图比较?

什么是 Bitmap 类?

  • 命名空间:System.Drawing 封装 GDI+ 位图,此位图由图形图像及其属性的像素数据组成
  • Bitmap 是用于处理由像素数据定义的图像的对象
  • 用 C# 类进行图像处理,最方便的是使用 Bitmap 类,使用该类的 GetPixel () 与 SetPixel () 来访问图像的每个像素点
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public void GetPixel_Example(PaintEventArgs e) 
    {
    // Create a Bitmap object from an image file.
    Bitmap myBitmap = new Bitmap("Grapes.jpg");
    // Get the color of a pixel within myBitmap.
    Color pixelColor = myBitmap.GetPixel(50, 50);
    // Fill a rectangle with pixelColor.
    SolidBrush pixelBrush = new SolidBrush(pixelColor);
    e.Graphics.FillRectangle(pixelBrush, 0, 0, 100, 100);
    }

什么是 Bitmapdata 类?

  • 命名空间: System. Drawing. Imaging 指定位图图像的属性
  • BitmapData 类由 Bitmap 类的 LockBits 和 UnlockBits 方法使用。不可继承
  • 用数组的方式来访问一幅图像,而不在使用低效的 GetPixel () 和 SetPixel ()
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    private void LockUnlockBitsExample(PaintEventArgs e) 
    {
    // Create a new bitmap.
    Bitmap bmp = new Bitmap("c:\\fakePhoto.jpg");
    // Lock the bitmap's bits.
    Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
    System.Drawing.Imaging.BitmapData bmpData =
    bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
    bmp.PixelFormat);
    // Get the address of the first line.
    IntPtr ptr = bmpData.Scan0;
    // Declare an array to hold the bytes of the bitmap.
    // This code is specific to a bitmap with 24 bits per pixels.
    int bytes = bmp.Width * bmp.Height * 3;
    byte[] rgbValues = new byte[bytes];
    // Copy the RGB values into the array.
    System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);
    // Set every red value to 255.
    for (int counter = 0; counter < rgbValues.Length; counter+=3)
    rgbValues[counter] = 255;
    // Copy the RGB values back to the bitmap
    System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);
    // Unlock the bits.
    bmp.UnlockBits(bmpData);
    // Draw the modified image.
    e.Graphics.DrawImage(bmp, 0, 150);
    }

什么是 Graphice 类?

  • 是 GDH + 的关键所在。许多对象都是由 Graphics 类表示的,该类定义了绘制和填充图形对象的方法和属性。一个应用程序只要需要进行绘制或着色,它就必须使用 Graphics 对象

如何在大的 Bitmap 上裁剪出一个小区域?

  • 1
    2
    3
    4
    5
    6
    7
    8
    Rectangle cropRect = new Rectangle(0,0,400, 400);
    Bitmap target = new Bitmap(cropRect.Width, cropRect.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);


    using (Graphics g = Graphics.FromImage(target))
    {
    g.DrawImage(src, new Rectangle(0, 0, target.Width, target.Height),cropRect,GraphicsUnit.Pixel);
    }

如何在 Picturebox 做 Bitmap 图的叠加?

  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    	Bitmap finalImage = new Bitmap(bmp.Width, bmp.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
    using (Graphics g = Graphics.FromImage(finalImage))
    {
    //set background color
    g.Clear(Color.Black);
    g.DrawImage(bmp1, new Rectangle(0, 0, bmp.Width, bmp.Height));
    g.DrawImage(bmp2, new Rectangle(leftTopPointX, leftTopPointY, colorImage.Width, colorImage.Height));
    }


    this.pictureBox.Image = finalImage;

C# 上的 Bitmap 如何保存到本地 ?

  • 1
    2
    3
    4
    5
    int width = 100;
    int height = 100;
    Bitmap bitmap = new Bitmap(width, height);
    //前一段为保存路径加文件名,后一段为保存格式,我这里保存为bmp格式,也可以为.jpeg或者.png之类的
    bitmap.Save(@"D:\bmp\test.bmp", System.Drawing.Imaging.ImageFormat.Bmp);

C# 上如何做 Bitmap 的格式转换 ?

  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    	// 24rgb转32Argb
    Bitmap orig = new Bitmap(@"24bpp.bmp");
    Bitmap clone = new Bitmap(orig.Width, orig.Height,
    System.Drawing.Imaging.PixelFormat.Format32bppPArgb);


    using (Graphics gr = Graphics.FromImage(clone)) {
    gr.DrawImage(orig, new Rectangle(0, 0, clone.Width, clone.Height));
    }

C # 读取 16 -bit 的 tif 灰度图片?

  • 使用 TiffBitmapDecoder 来读取 TIFF 格式的图片文件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    Stream imageStreamSource = new FileStream(ImageFileName, FileMode.Open, FileAccess.Read, FileShare.Read);
    var decoder = new TiffBitmapDecoder(imageStreamSource, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
    BitmapSource bitmapSource = decoder.Frames[0];
    Int32 PixelHeight = bitmapSource.PixelHeight; // 图像高度
    Int32 PixelWidth = bitmapSource.PixelWidth; // 图像宽度
    Int32 Stride = (PixelWidth * bitmapSource.Format.BitsPerPixel + 7) / 8; // 跨距宽度
    if (bitmapSource.Format.BitsPerPixel == 16)
    {
    ushort[] gray16 = new ushort[PixelHeight * PixelWidth];//16bit 位深
    bitmapSource.CopyPixels(gray16, Stride, 0);
    }
    else if (bitmapSource.Format.BitsPerPixel == 8)
    {
    Byte[] gray8 = new Byte[PixelHeight * PixelWidth];//8bit 位深
    bitmapSource.CopyPixels(gray8, Stride, 0);
    }
    else
    {
    Console.WriteLine("暂不支持的tiff");
    }