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

软件界面如下:

要做真实场景的测试,拿的都是单反照的大相片:图片尺寸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; //最多并发50个任务
//并行进行图片压缩
System.Threading.ThreadPool.QueueUserWorkItem(w=>{
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 + Path.GetFileNameWithoutExtension(o.Name) + ".png", System.Drawing.Imaging.ImageFormat.Png);
if (rbtgif.Checked) ThumbImg.Save(FileSavePath + Path.GetFileNameWithoutExtension(o.Name) + ".gif", System.Drawing.Imaging.ImageFormat.Gif);
if (rbtjpg.Checked) ThumbImg.Save(FileSavePath + Path.GetFileNameWithoutExtension(o.Name) + ".jpg", System.Drawing.Imaging.ImageFormat.Jpeg); sourceImg.Dispose();
ThumbImg.Dispose(); Interlocked.Increment(ref ifinish);//ifinish++ this.Invoke(this.mysetFinish, new Object[] { ifinish }); //刷新进度条等 });
}, null);

  

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

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

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

下载本程序  Demo

程序源码 CODE

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

  1. 【游戏开发】Excel表格批量转换成CSV的小工具

    一.前言 在工作的过程中,我们有时可能会面临将Excel表格转换成CSV格式文件的需求.这尤其在游戏开发中体现的最为明显,策划的数据文档大多是一些Excel表格,且不说这些表格在游戏中读取的速度,但就 ...

  2. 用Photoshop软件实现批量压缩照片

    前提:手头有 "大" 照片,出于某种原因想把它变成 "小" 照片:电脑刚好安装有PS软件. 需知:如果您的压缩需求仅限于降低图片品质,降低图片像素,那么建议您采 ...

  3. 用C#Winform写个简单的批量清空文件内容和删除文件的小工具

    用C#Winform写个简单的批量清空文件内容和删除文件的小工具 本文介绍这个简单得不能再简单的小项目.做这个项目,有以下目的. 1 当然是做个能用的工具 2 学习使用Github 关于用VS2013 ...

  4. 批量下载网站图片的Python实用小工具(下)

    引子 在 批量下载网站图片的Python实用小工具 一文中,讲解了开发一个Python小工具来实现网站图片的并发批量拉取.不过那个工具仅限于特定网站的特定规则,本文将基于其代码实现,开发一个更加通用的 ...

  5. python 无损压缩照片,支持批量压缩,支持保留照片信息

    由于云盘空间有限,照片尺寸也是很大,所以写个Python程序压缩一下照片,腾出一些云盘空间 1.批量压缩照片 新建 photo_compress.py 代码如下 1 # -*- coding: utf ...

  6. 开源一个自动整理B站UWP客户端软件进行批量下载的视频文件的小工具BiliVideosReoganizeHelper​

    ​ 大家都知道B站是一个很受欢迎的视频学习网站,上面有很多无私的up主上传了大量优秀的教学视频,在此向B站致敬,向广大UP主致敬. 有时,我们需要下载收藏一些视频,以防止以后找不到了.那么我们可以用B ...

  7. 原创SQlServer数据库生成简单的说明文档包含(存储过程、视图、数据库批量备份)小工具(附源码)

    这是一款简单的数据库文档生成工具,主要实现了SQlServer生成说明文档的小工具,目前不够完善,主要可以把数据库的表以及表的详细字段信息,导出到 Word中,可以方便开发人员了解数据库的信息或写技术 ...

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

    原文  http://www.wtoutiao.com/a/120621.html 底层工具 “If you know how to use Process Monitor competently, ...

  9. Windows平台软件推荐:神器小工具(骨灰级)

    底层工具 "If you know how to use Process Monitor competently, people of both sexes will immediately ...

随机推荐

  1. HT图形组件设计之道(二)

    上一篇我们自定义CPU和内存的展示界面效果,这篇我们将继续采用HT完成一个新任务:实现一个能进行展开和合并切换动作的刀闸控件.对于电力SCADA和工业控制等领域的人机交互界面常需要预定义一堆的行业标准 ...

  2. JS魔法堂:IE5~9的Drag&Drop API

    一.前言     < HTML5魔法堂:全面理解Drag & Drop API>中提到从IE5开始已经支持DnD API,但IE5~9与HTML5的API有所不同,下面我们来了解一 ...

  3. ThroughRain第一次冲刺个人总结

    团队名:ThroughRain 项目确定:<餐厅到店点餐系统> 项目背景:本次项目是专门为餐厅开发的一套订餐系统.大家有没有发现在节假日去餐厅吃饭会超级麻烦,人很多, 热门的餐厅基本没有座 ...

  4. SQL Server视图复习

    视图的好处: 第一点:使用视图,可以定制用户数据,聚焦特定的数据. 第一点:使用视图,可以定制用户数据,聚焦特定的数据. 在实际过程中,公司有不同角色的工作人员,我们以销售公司为例的话,采购人员,可以 ...

  5. dp - Google Code jam Qualification Round 2015 --- Problem B. Infinite House of Pancakes

    Problem B. Infinite House of Pancakes Problem's Link:   https://code.google.com/codejam/contest/6224 ...

  6. 创建一个弹出DIV窗口

    创建一个弹出DIV窗口 摘自:   http://www.cnblogs.com/TivonStone/archive/2012/03/20/2407919.html 创建一个弹出DIV窗口可能是现在 ...

  7. 个人学习对UIView动画的总结

    我的博客之前已经开通五个月了,但是一直没有写东西.一是不敢写,二是也不知道写啥.毕竟是一个刚刚入行大半年的菜鸟,现在总想通过各种办法提高自己.之前总感觉用到一些东西,只是当时搞懂了一点,加上并没有总结 ...

  8. Oracle备份表结构和数据

    --创建一份表结构 create table BASE_GOODSPAYMENT_SETTING_BAK as select * from BASE_GOODSPAYMENT_SETTING ; -- ...

  9. Csharp: read excel file using Open XML SDK 2.5

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  10. 面向企业客户的制造业CRM系统的不成熟思考

    CRM就是客户关系管理(Customer Relationship Management),一直一知半解,最近有涉及这方面的需求,所以稍作研究,并思考一些相关问题. CRM是什么? CRM具体如何定义 ...