C#中OpenFileDialog的使用

在Winform中没有一个控件可以实现选择本地某个文件的功能。那么我们可以用一个Button来模拟实现,点击button,在button的处理事件中生成一个OpenFileDialog对象,然后调用ShowDialog方法。显示对话框,来实现这个功能。


OpenFileDialog 类:

作用:提示用户检查某个文件是否存在并可以选中打开该文件。
命名控件:System.Windows.Forms



属性:
InitialDirectory: 对话框要打开的初始目录  例如:"c:\\"
Filter:对话框显示的文件筛选器例如下如所示:
它的格式设置:All files(*.*)|*.* 前者表示显示的内容,后者表示格式。如若有多个选项,只需要继续添加就可以了。
FilterIndex :对话框中选择文件筛选器的索引,如果默认第一项就设置为1
RestoreDirectory:控制对话框在关闭之前是否恢复当前目录。
FileName:获取或设置一个字符串,其中包含在文件对话框中选定的文件的完整路径。

Title:获取或者设置在文件对话框的标题中显示的文本。



方法:

ShowDialog ():显示通用对话框

OpenFile:为用户使用OpenFileDialog选定的文件打开只读流

OpenFiles:创建一个数组,其中包含与用户使用 OpenFileDialog 选定的每个文件一一对应的只读流。




使用方法案例:

 private void browseButton_Click(object sender, EventArgs e)
        {
            
            string filePath; //文件路径
            string fileName; //文件名称
            string fileExtension;//文件后缀名
            string[] strExtension = new string[] { ".gif", ".jpg", ".jpeg", ".png" };
            OpenFileDialog openFileDialog1 = new OpenFileDialog();//实例化一个对象
            

            //InitialDirectory 默认打开文件夹的位置
            openFileDialog1.InitialDirectory = "d:\\";
            //Filter 允许打开文件的格式  显示在Dialg中的Files of Type
            openFileDialog1.Filter = "All files (*.*)|*.*";
            //显示在Dialg中的Files of Type的选择
            openFileDialog1.FilterIndex = 1;

            openFileDialog1.RestoreDirectory = true;
            openFileDialog1.Title = "Choose Image File";

            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                //文件路径 和文件名字
                filePath = openFileDialog1.FileName;
                fileName = Path.GetFileName(filePath);
                // 获取文件后缀
                fileExtension = Path.GetExtension(filePath);
                //设置一个text控件,显示更新txtShow的显示内容
                txtShow.Text = fileName;

                if (!strExtension.Contains(fileExtension))//验证读取文件的格式,设置为只能读取以下几种格式的图片
                {
                    MessageBox.Show("仅打开.gif, .jpeg, .jpg, .png格式的图片!");
                }
                else
                {
                        // Insert code to read the stream here.
                        ValuateRGB(filePath);
                        //MessageBox.Show(fileName); 
                }
            }

        }
设计一个Button,点击Button则生成OpenFileDialog对话框,效果如下图所示:


点击浏览,则会弹出对话框,



选中一个图片之后,我想获得整张图片的每个像素的RGB值。如何实现呢。先来介绍下Bitmap


Bitmap


MSDN地址:http://msdn.microsoft.com/en-us/library/system.drawing.bitmap.aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1

语法:

public sealed class Bitmap : Image


构造函数:

Bitmap(String) Initializes a new instance of the Bitmap class from the specified file.


属性:

width :Gets the width, in pixels, of this Image.

Height:Gets the Height, in pixels, of this Image.

PixelFormat:Gets the pixel format for image


方法:

GetPixelGets the color of the specified pixel in this Bitmap.  函数原型:返回Color对象

public Color GetPixel(
	int x,
	int y
)


SetPixelSets the color of the specified pixel in this Bitmap.


LockBits(Rectangle, ImageLockMode, PixelFormat)Locks a Bitmap into system memory.   

            

UnlockBitsUnlocks this Bitmap from system memory.


使用方法案例:

 private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                // Retrieve the image. 我的F盘下面有一个fail1.png图像
                image1 = new Bitmap(@"F:\fail1.png", true);
		//image1 = new Bitmap("F:\\fail1.png",true); 注意两种方式的区别 +@则不需要转义字符
                int x, y;

                // Loop through the images pixels to reset color. 
                for (x = 0; x < image1.Width; x++)
                {
                    for (y = 0; y < image1.Height; y++)
                    {
                        Color pixelColor = image1.GetPixel(x, y);
                        Color newColor = Color.FromArgb(pixelColor.R, 0, 0);
                        image1.SetPixel(x, y, newColor);
                    }
                }

                

                // Display the pixel format in text控件.
                txtShow.Text = "Pixel format:" + image1.PixelFormat.ToString();

            }
            catch (ArgumentException)
            {
                MessageBox.Show("There was an error." +
                    "Check the path to the image file.");
            }
}


下面是c# 图像读取几种方法:文章转载自:http://blog.csdn.net/lulu831110/article/details/4820377


者:http://conner-wang.spaces.live.com转载

使用C#进行图像处理的几种方法

本文讨论了C#图像处理中Bitmap类、BitmapData类和unsafe代码的使用以及字节对齐问题。

Bitmap类

命名空间:System.Drawing

封装 GDI+ 位图,此位图由图形图像及其属性的像素数据组成。Bitmap 是用于处理由像素数据定义的图像的对象。 

该类的主要方法和属性如下:

1.       GetPixel方法和 SetPixel方法:获取和设置一个图像的指定像素的颜色.

2.       PixelFormat属性:返回图像的像素格式.

3.       Palette属性:获取和设置图像所使用的颜色调色板.

4.       Height Width属性:返回图像的高度和宽度.

5.       LockBits 方法和UnlockBits方法:分别锁定和解锁系统内存中的位图像素.在基于像素点的图像处理方法中使用LockBits 和UnlockBits是一个很好的方式,这两种方法可以使我们指定像素的范围来控制位图的任意一部分,从而消除了通过循环对位图的像素逐个进行处理,每调用LockBits 之后都应该调用一次UnlockBits.

利用C#类进行图像处理,最方便的是使用Bitmap类,使用该类的GetPixel()与SetPixel()来访问图像的每个像素点。下面是MSDN中的示例代码:

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


    可见,Bitmap类使用一种优雅的方式来操作图像,但是带来的性能的降低却是不可忽略的。比如对一个800*600的彩色图像灰度化,其耗费的时间都要以秒为单位来计算。在实际项目中进行图像处理,这种速度是决对不可忍受的。

 

BitmapData类

命名空间:System.Drawing.Imaging

指定位图图像的属性。BitmapData 类由 Bitmap 类的 LockBits 和 UnlockBits 方法使用。不可继承。

    好在我们还有BitmapData类,通过BitmapData BitmapData LockBits ( )可将 Bitmap 锁定到系统内存中。该类的公共属性有:

  • Width           获取或设置 Bitmap 对象的像素宽度。这也可以看作是一个扫描行中的像素数。
  • Height          获取或设置 Bitmap 对象的像素高度。有时也称作扫描行数。
  • PixelFormat  获取或设置返回此 BitmapData 对象的 Bitmap 对象中像素信息的格式。
  • Scan0            获取或设置位图中第一个像素数据的地址。它也可以看成是位图中的第一个扫描行。
  • Stride            获取或设置 Bitmap 对象的跨距宽度(也称为扫描宽度)。

    下面的MSDN中的示例代码演示了如何使用 PixelFormat、Height、Width 和 Scan0 属性;LockBits 和 UnlockBits 方法;以及 ImageLockMode 枚举。

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. 
    int bytes  = bmpData.Stride * bmp.Height; 
    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);
} 


    上面的代码演示了如何用数组的方式来访问一幅图像,而不在使用低效的GetPixel()和SetPixel()。

 

unsafe代码

    而在实际中上面的做法仍然不能满足我们的要求,图像处理是一种运算量比较大的操作,不同于我们写的一般的应用程序。我们需要的是一种性能可以同C++程序相媲美的图像处理程序。C++是怎么提高效率的呢,答曰:指针。幸运的是.Net也允许我们使用指针,只能在非安全代码块中使用指针。何谓非安全代码?

    为了保持类型安全,默认情况下,C# 不支持指针运算。不过,通过使用 unsafe 关键字,可以定义可使用指针的不安全上下文。在公共语言运行库 (CLR) 中,不安全代码是指无法验证的代码。C# 中的不安全代码不一定是危险的,只是其安全性无法由 CLR 进行验证的代码。因此,CLR 只对在完全受信任的程序集中的不安全代码执行操作。如果使用不安全代码,由您负责确保您的代码不会引起安全风险或指针错误。不安全代码具有下列属性:

  • 方法、类型和可被定义为不安全的代码块。
  • 在某些情况下,通过移除数组界限检查,不安全代码可提高应用程序的性能。
  • 当调用需要指针的本机函数时,需要使用不安全代码。
  • 使用不安全代码将引起安全风险和稳定性风险。
  • 在 C# 中,为了编译不安全代码,必须用 /unsafe 编译应用程序。

    正如《C#语言规范》中所说无论从开发人员还是从用户角度来看,不安全代码事实上都是一种“安全”功能。不安全代码必须用修饰符 unsafe 明确地标记,这样开发人员就不会误用不安全功能,而执行引擎将确保不会在不受信任的环境中执行不安全代码。

    以下代码演示如何借助BitmapData类采用指针的方式来遍历一幅图像,这里的unsafe代码块中的代码就是非安全代码。在使用非安全代码的时候需要把VS设置一下,首先选中工程,右键点击并且选中properties,然后选中build,选择allow unsafe code,看图片


//创建图像 
Bitmap image =  new Bitmap( "c://images//image.gif" ); 
//获取图像的BitmapData对像 
BitmapData data = image.LockBits( new Rectangle( 0 , 0 , image.Width , image.Height ) , ImageLockMode.ReadWrite  , PixelFormat.Format24bppRgb  );  
//循环处理 
unsafe 
{  
       byte* ptr = ( byte* )( data.Scan0 );  
       for( int i = 0 ; i < data.Height ; i ++ ) 
       { 
          for( int j = 0 ;  j < data.Width ;  j ++ ) 
           { 
             // write the logic implementation here 
             ptr += 3;   
           } 
         ptr += data.Stride - data.Width * 3; 
       } 
}


    毫无疑问,采用这种方式是最快的,所以在实际工程中都是采用指针的方式来访问图像像素的。

 

字节对齐问题 
    上例中ptr += data.Stride - data.Width * 3,表示跨过无用的区域,其原因是图像数据在内存中存储时是按4字节对齐的,具体解释如下:

    假设有一张图片宽度为6,假设是Format24bppRgb格式的(每像素3字节,在以下的讨论中,除非特别说明,否则Bitmap都被认为是24位RGB)。显然,每一行需要6*3=18个字节存储。对于Bitmap就是如此。但对于BitmapData,虽然data.Width还是等于image.Width,但大概是出于显示性能的考虑,每行的实际的字节数将变成大于等于它的那个离它最近的4的整倍数,此时的实际字节数就是Stride。就此例而言,18不是4的整倍数,而比18大的离18最近的4的倍数是20,所以这个data.Stride = 20。显然,当宽度本身就是4的倍数时,data.Stride = image.Width * 3。

    画个图可能更好理解

    首先用data.Scan0找到第0个像素的第0个分量的地址,这个地址指向的是个byte类型,所以当时定义为byte* ptr。行扫描时,在当前指针位置(不妨看成当前像素的第0个颜色分量)连续取出三个值(3个原色分量。注意,0 1 2代表的次序是B G R。在取指针指向的值时,貌似p[n]和p += n再取p[0]是等价的),然后下移3个位置(ptr += 3,看成指到下一个像素的第0个颜色分量)。做过Bitmap.Width次操作后,就到达了Bitmap.Width * 3的位置,应该要跳过图中标记为X的字节了(共有Stride - Width * 3个字节),代码中就是 ptr += dataIn.Stride - dataIn.Width * 3。

    通过阅读本文,相信你已经对使用C#进行图像处理可能用到的几种方法有了一个了解。至于采用哪种方式,取决于你的性能要求。其中第一种方式最优雅;第三种方式最快,但不是安全代码;第二种方式取了个折中,保证是安全代码的同时又提高了效率。熟悉C/C++编程的人可能会比较偏向于第三种方式,我个人也比较喜欢第三种方式。

 

四.Image类

  这个类提供了位图和元文件操作的函数.Image类被声明为abstract,也就是说Image类不能实例化对象,而只能做为一个基类.

1.FromFile方法:它根据输入的文件名产生一个Image对象,它有两种函数形式:

public static Image FromFile(string filename);

public static Image FromFile(string filename, bool useEmbeddedColorManagement);

2.FromHBitmap方法:它从一个windows句柄处创建一个bitmap对象, 它也包括两种函数形式:

public static bitmap fromhbitmap(intptr hbitmap);

public static bitmap fromhbitmap(intptr hbitmap, intptr hpalette);

3. FromStream方法:从一个数据流中创建一个image对象,它包含三种函数形式 :

public static image fromstream(stream stream);

public static image fromstream(stream stream, bool useembeddedcolormanagement);

fromstream(stream stream, bool useembeddedcolormanagement, bool validateimagedata);

 

获得图像格式的方法:

 

方法一://判断图像格式,如果是gif则不能操作
   string fileformat=curBitmap.RawFormat.ToString();
 
   if (fileformat == "[ImageFormat: b96b3cb0-0728-11d3-9d7b-0000f81ef32e]")
        {
           MessageBox.Show("不能处理gif格式文件");
             return;
            }
方法二:
if (curBitmap.RawFormat.Guid == System.Drawing.Imaging.ImageFormat.Gif.Guid)
 {
      MessageBox.Show("不能处理gif格式文件");
      return ;
 }



  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值