小工具:assembly中嵌入图片抓取器(C#)

最近有点需要这个东东,本来打算自己写一个,无意发现CodeProject最近有这么篇文章,很高兴地拿来用之,并且通过看别人的东西反省自己想法的不足.顺便做下广告以示感谢:

Extracting Embedded Images From An Assembly By Josh Smith


[介绍]
该文介绍了一个非常实用的小工具:assembly中嵌入图像抓取器, 可以从.NET的assembly里面查看,保存和复制潜入的图片,图标,鼠标图案. 小工具是用.NET framework 2.0编译的, 但如有必要,核心代码很容易移植到1.0.

[背景]
首先回顾一下嵌入的资源. 创建一个assembly时, 可在其中嵌入任意的资源文件, 如BMP位图, XML文件等. 这些文件被称作嵌入的资源. 在assembly中嵌入资源有以下好处:

简化部署 (需要管理的文件变少了). 
简化资源使用 (运行时不可能找不到文件了).

Visual Studio .NET中可以如下步骤方便地嵌入资源:
1. 添加一个图片到工程中:
2. Solution Explorer中, 右键点击该图片文选择"属性".
3. 在"属性"窗口中"生成操作"(Build Action)选择"嵌入的资源"(Embedded Resource)
4. 编译项目.

如你所想,.NET framework提供了编程时取得嵌入的资源的支持,将在后文介绍.

[使用] 

(译者:使用及其简单,就不啰嗦了)值得一提的是支持拖放操作:

[代码]
从assembly中提取图片并显示在UI上的方法是主要LoadImagesFromAssembly.

private  void LoadImagesFromAssembly(  string assemblyPath )
{
   // Try to load the assembly at the specified location.
   Assembly assembly = this.LoadAssembly( assemblyPath, true );
   if( assembly == null )
      return;

   this.currentAssembly = assembly;

   // Dispose of the images currently being displayed, if any.
   ifthis.bindingSource.DataSource != null )
      foreach( ImageInfo imgInfo in this.bindingSource.DataSource 
                                      as List<ImageInfo> )
         imgInfo.Dispose();

   // Bind to a list of every image embedded in the assembly.
   this.bindingSource.DataSource = 
     this.ExtractImagesFromAssembly( this.currentAssembly );
}

如上, ImageGrabberForm 用BindingSource组件存储图片供数据绑定. BindingNavigator, DataGridView, PropertyGrid 和PictureBox都绑定到这一数据源,就可以相当简单地在各UI元素间保持一致.

从assembly中提取图片的实际工作是在ExtractImagesFromAssembly 方法中:

private List<ImageInfo> ExtractImagesFromAssembly( Assembly assembly )
{
   List<ImageInfo> imageInfos = new List<ImageInfo>();

   foreachstring name in assembly.GetManifestResourceNames() )
   {
      using( Stream stream = assembly.GetManifestResourceStream( name ) )
      {
         // Treat the resource as an icon.
         try
         {
            Icon icon = new Icon( stream );
            imageInfos.Add( new ImageInfo( icon, name ) );
            continue;
         }

         catch( ArgumentException )
         {
            stream.Position = 0;
         }



         // Treat the resource as a cursor.
         try
         {
            Cursor cursor = new Cursor( stream );
            imageInfos.Add( new ImageInfo( cursor, name ) );
            continue;
         }

         catch( ArgumentException )
         {
            stream.Position = 0;
         }



         // Treat the resource as an image.
         try
         {
            Image image = Image.FromStream( stream );

            // If the image is an animated GIF, do not add it to the 
            
// collection because the Image class cannot handle them and
            
// will throw an exception when the image is displayed.
            FrameDimension frameDim = 
               new FrameDimension( image.FrameDimensionsList[0] );
            bool isAnimatedGif = image.GetFrameCount( frameDim ) > 1;
            if( !isAnimatedGif )
               imageInfos.Add( new ImageInfo( image, name ) );
            else
               image.Dispose();

            continue;
         }

         catch( ArgumentException )
         {
            stream.Position = 0;
         }



         // Treat the resource as a resource file.
         try
         {
            // The embedded resource in the stream is not an image, so
            
// read it into a ResourceReader and extract the values
            
// from there.
            using( IResourceReader reader = new ResourceReader( stream ) )
            {
               foreach( DictionaryEntry entry in reader )
               {
                  if( entry.Value is Icon )
                  {
                     imageInfos.Add( new ImageInfo( entry.Value, name ) );
                  }

                  else if( entry.Value is Image )
                  {
                     imageInfos.Add( new ImageInfo( entry.Value, name ) );
                  }

                  else if( entry.Value is ImageListStreamer )
                  {
                     // Load an ImageList with the ImageListStreamer and
                     
// store a reference to every image it contains.
                     using( ImageList imageList = new ImageList() )
                     {
                        imageList.ImageStream = 
                           entry.Value as ImageListStreamer;
                        foreach( Image image in imageList.Images )
                           imageInfos.Add( new ImageInfo( image, name ) );
                     }

                  }

               }

            }

         }

         catch( Exception )
         {
         }

      }
            
   }


   return imageInfos;
}

上面的代码在assembly中为每个已命名资源都打开一个流,然后依次尝试从流中创建图标Icon, (失败的话创建)光标Cursor, (失败的话创建)图片Image, 全部失败的话通过System.Resources.ResourceReader读取内容. 这个resource reader可以把图片,图标和ImageList中的图片从资源文件.resx中提取出来. ImageInfo类是用来存取图片及其辅助信息的.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值