C#照片批量压缩小工具

原文:C#照片批量压缩小工具

做了一个照片批量压缩工具,其实核心代码几分钟就完成了,但整个小工具做下来还是花了一天的时间。中间遇到了大堆问题,并寻求最好的解决方案予以解决。现在就分享一下这个看似简单的小工具所使用的技术。

软件界面如下:

要做真实场景的测试,拿的都是单反照的大相片:图片尺寸3888*2592  图片大小5.37M:

其中遇到的问题与解决方案分享:

1.用listview显示图片缩略图非常慢的问题

这个问题是始料未及的,如果不做也可以,但是没有缩略图就有损软件体验,这是所有最求完美的程序员所不能容忍的,我当然也不例外。

最初的代码如下:(此方法加载每张5M左右的图片需要200-500ms)

            listView1.Items.Clear();
            imageList1.Images.Clear();

            DirectoryInfo TheFolder = new DirectoryInfo(folderBrowserDialog1.SelectedPath);//文件路径
            List<string> ImgNames = new List<string>();
            string allowImg = ".jpg.jpeg.png.bmp";
            FileInfo[] Files = TheFolder.GetFiles();
            for (int i = 0; i < Files.Length; i++)//遍历文件夹
            {
                if (Files[i].Length > 0 &&allowImg.IndexOf(Files[i].Extension.ToLower())>-1)//或者jpg,png 文件大小要大于0且是图片文件
                {
                    Image image = Image.FromFile(Files[i].DirectoryName + "\\" + Files[i].Name);    //获取文件
                    ImgNames.Add(Files[i].Name);//添加文件名
                    imageList1.Images.Add(image);//添加图片
                }
            }
            //初始化设置
            this.listView1.View = View.LargeIcon;

            this.listView1.LargeImageList = this.imageList1;

            //开始绑定
            this.listView1.BeginUpdate();

            for (int i = 0; i < ImgNames.Count; i++)
            {
                ListViewItem lvi = new ListViewItem();

                lvi.ImageIndex = i;

                lvi.Text = ImgNames[i];

                this.listView1.Items.Add(lvi);
            }

            this.listView1.EndUpdate();

  解决办法是用微软提供的Windows API Code Pack 1.0.1库,通过该库可以直接使用到win7/vista/win8系统的一些特性功能,如资源管理器、桌面、任务栏等等。详细介绍见官方主页 

本程序使用WindowsApiCode完成对文件夹下的图片迅速建缩略图的代码如下:

先在界面上添加一个该库提供的explorerBrowser控件,然后初始化该控件:

            //设置图片展示控件属性
            explorerBrowser1.ContentOptions.ViewMode = ExplorerBrowserViewMode.List;
            explorerBrowser1.NavigationOptions.PaneVisibility.Navigation = PaneVisibilityState.Hide;
            explorerBrowser1.NavigationOptions.PaneVisibility.CommandsView = PaneVisibilityState.Hide;
            explorerBrowser1.NavigationOptions.PaneVisibility.CommandsOrganize = PaneVisibilityState.Hide;
            explorerBrowser1.NavigationOptions.PaneVisibility.Commands = PaneVisibilityState.Hide;
            explorerBrowser1.SelectionChanged += new EventHandler(explorerBrowser1_SelectionChanged);

完成打开文件夹并显示图片缩略图的代码非常简单:

       //打开图片文件夹
        private void btnOpenDir_Click(object sender, EventArgs e)
        {
            // 创建打开文件夹对话框
            CommonOpenFileDialog cfd = new CommonOpenFileDialog();

            // 设置对话框属性
            cfd.IsFolderPicker = true;
            cfd.AllowNonFileSystemItems = true;

            // 弹出对话框并返回用户的选择
            CommonFileDialogResult result = cfd.ShowDialog();

            //如果用户确定
            if (result == CommonFileDialogResult.Ok)
            {
                // 获取选择对象的ShellObject形式
                ShellObject resultItem = cfd.FileAsShellObject;
                //用explorerBrowser控件显示图片列表
                explorerBrowser1.Navigate(resultItem);
            }
        }

采用这种方法打开图片缩略图列表时间可以忽略不计。

 

2.好看的图片界面库

从前面的界面可以看出,本工具的界面并不丑,可以说还很精美,这也是花了心思的。

本工具的界面我采用的是

官方主页为http://www.componentfactory.com/

 

3.充分利用多核并行计算,提高图片处理速度

处理批量任务当然要考虑速度,否则就失去了工具的意义了

.netFrameWork4.0里面提供了Parallel系列、Task系列来支持并行运算,让并行计算变得如此简单(为什么不跟着微软走呢,后悔了吧 ^_^)。

并行指的是利用现在的CUP多核,同时开启多个任务。跟以往的并发计算不同的是,并发的多个线程其实并非真正同时在运行,他们只是按照时间片,走走停停,逻辑上在同时进行,而并行则是在多个完全独立的核上同时运行任务,是真正的同时在跑。

本程序中并行进行图片压缩的代码如下:

            ParallelOptions po = new ParallelOptions();
            po.MaxDegreeOfParallelism = 15; //最多并发15个任务
            //并行进行图片压缩
            Parallel.ForEach(imgtoComp, po, (o) =>
            {
                System.Drawing.Image sourceImg = System.Drawing.Image.FromFile(o.ParsingName);
                int iWidth = 0;
                int iHeight = 0;
                if (rbtper.Checked)
                {
                    int per = int.Parse(txtper.Text);
                    iWidth = sourceImg.Width * per / 100;
                    iHeight = sourceImg.Height * per / 100;
                }

                if (rbtheight.Checked)//最大高度
                {
                    iHeight = int.Parse(txtheight.Text);
                    iWidth = iHeight * sourceImg.Width / sourceImg.Height;
                }

                if (rbtwidth.Checked)//最大宽度
                {
                    iWidth = int.Parse(txtwidth.Text);
                    iHeight = iWidth * sourceImg.Height / sourceImg.Width;
                }

                System.Drawing.Image ThumbImg = ImgCompress.GetImageThumb(sourceImg, iWidth, iHeight);

                if (rbtpng.Checked) ThumbImg.Save(FileSavePath+o.Name,System.Drawing.Imaging.ImageFormat.Png);
                if (rbtgif.Checked) ThumbImg.Save(FileSavePath + o.Name, System.Drawing.Imaging.ImageFormat.Gif);
                if (rbtjpg.Checked) ThumbImg.Save(FileSavePath + o.Name, System.Drawing.Imaging.ImageFormat.Jpeg);

                sourceImg.Dispose();
                ThumbImg.Dispose();

                ifinish++;
                this.Invoke(this.mysetFinish, new Object[] { ifinish }); //刷新进度条等
            });

这里主要强调一下并发任务数量的设置、以及资源的显示释放。

并发数量通过ParallelOptions参数的MaxDegreeOfParallelism来设置,这里必须设置,否则几百张5M的图片同时跑,立马内存就占满了。

资源的显式释放:sourceImg.Dispose();  ThumbImg.Dispose();  这点也非常重要,处理大图片是非常耗内存的,测试过程中就因为没有显式释放内存,偷懒想着.net的自动垃圾回收机制会帮忙善后,结果跑到40多张图片的时候就内存不足了。显式处理资源释放后,压缩图片的速度也因为空余的内存比较多而变快了。

 

下载本程序  Demo

 

时间: 2024-09-28 20:48:53

C#照片批量压缩小工具的相关文章

用PS给旅游照片批量调色小技巧

  旅游回来,拍了大量照片,想修好再发朋友圈,可那么多图一张张修真的是好烦啊?别着急,今天分享一个用PS原生滤镜Adobe Camera Raw一键批量修图的小技巧,主要用到的就是ACR的预设保存和应用,另外会送专业修图公司onOne出品的一套预设给大家哟. AdobeCamera Raw(后面简称ACR)是PS自带的一款滤镜,是专门处理无损Raw格式图片的软件,用过的人都说好,还不了解的小伙伴可以出门左拐问度娘哈.用李涛老师的话说,ACR与Lightroom在使用上是一脉相通的,那我们都知道L

用PS给照片批量调色小技巧

  拍了大量照片,想修好再分享出去朋友圈,可那么多图一张张修却是一件烦人机械的活.今天分享一个用PS原生滤镜Adobe Camera Raw一键批量修图的小技巧,主要用到的就是ACR的预设保存和应用,另外会送专业修图公司onOne出品的一套预设给大家哟. AdobeCamera Raw(后面简称ACR)是PS自带的一款滤镜,是专门处理无损Raw格式图片的软件,用过的人都说好,还不了解的小伙伴可以出门左拐问度娘哈.用李涛老师的话说,ACR与Lightroom在使用上是一脉相通的,那我们都知道LR中

PHP 源代码压缩小工具_php实例

使用方法:(在命令行运行) 复制代码 代码如下: php compactor.php DESTINATION.php SOURCE.php 下载: compactor.php 复制代码 代码如下: #!/usr/bin/env php <?php /** * Compact PHP code. * * Strip comments, combine entire library into one file. */ if ($argc < 3) { print "Strip unece

PHP 源代码压缩小工具

#!/usr/bin/env php <?php /** * Compact PHP code. * * Strip comments, combine entire library into one file. */ if ($argc < 3) { print "Strip unecessary data from PHP source files.nntUsage: php compactor.php DESTINATION.php SOURCE.php"; exit

小工具 - 批量删除Maven下载失败的文件夹

用过Maven的应该都遇到过,当网速不好或者源有问题的时候,Maven的依赖包经常下载失败. 下载失败后在本地仓库对应的文件夹中有一个以.lastUpdated结尾的文件,如果不手动删除这个文件,就不能重新更新依赖,重新下载对应的jar包. 一般情况下遇到的时候可能直接手动找到目录删除. 当出现很多这样的情况时,一个个找起来也很麻烦. 因此本文提供一个小工具,就是一段Java代码,通过这段代码来删除. public class CleanMvn { public static void main

Linux系统如何批量压缩图片尺寸大小

现在的数码相机拍摄出来的照片像素都很高,大部份都会超过此限制,很多时候我们都要对图片进行批量压缩,Linux系统下如何批量压缩图片尺寸大小呢? 一个比较好用命令行下可以使用的 强大的免费图片工具 ImageMagick Centos系统的安装使用方法: yum install ImageMagick 再输入y确认即可安装完成 接下来调用 系统命令 其中上面 convert 中的 resize 参数可以修改imagemagick,它可以对图片进行格式转换.大小压缩.增加水印等操作,而不需要去写第三

2014年Windows平台软件推荐:神器小工具(骨灰级

原文  http://www.wtoutiao.com/a/120621.html 底层工具 "If you know how to use Process Monitor competently, people of both sexes will immediately find you more attractive." – Scott Hanselman Ultimate Boot CD 和 Ultimate Boot CD for Windows  – 这些光盘是程序员修电脑

i See批量压缩宝贝图片尺寸大小

  i See批量压缩宝贝图片尺寸大小.开网店的卖家,在宝贝上新的时候,都会要处理大量的宝贝图片. 要保证宝贝图片的宽度在淘宝网的限制范围之内,卖家的必做工作就是对宝贝图片进行压缩处理.(淘宝普通店 铺图片的最大宽度为500px,旺铺图片的最大宽度为800px.) iSee软件可以批量压缩宝贝图片大小,这样可以大大节省卖家在图片压缩上的时间. 下面是4张商品图片的尺寸,宽度不一致. 批量压缩图片尺寸的宽度为500px的宝贝图片. 批量压缩步骤: 1.iSee软件打开需要批量压缩的宝贝图片文件夹.

iSee如何批量压缩宝贝图片大小

开网店的卖家,在宝贝上新的时候,都会要处理大量的宝贝图片. 要保证宝贝图片的宽度在淘宝网的限制范围之内,卖家的必做工作就是对宝贝图片进行压缩处理.(淘宝普通店 铺图片的最大宽度为500px,旺铺图片的最大宽度为800px.) iSee软件可以批量压缩宝贝图片大小,这样可以大大节省卖家在图片压缩上的时间. 下面是4张商品图片的尺寸,宽度不一致.   批量压缩图片尺寸的宽度为500px的宝贝图片.   批量压缩步骤: 1.iSee软件打开需要批量压缩的宝贝图片文件夹. 点击主界面上方工具条----压