title author date CreateTime categories
win10 uwp 修改图片质量压缩图片
lindexi
2019-03-21 15:29:20 +0800
2019-03-21 12:52:22 +0800
Win10 UWP

本文告诉大家如何在 UWP 通过修改图片的质量减少图片大小,这个方法只支持输出 jpg 文件

通过创建 BitmapEncoder 的时候指定 BitmapPropertySet 可以设置图片的质量,只有对 JPG 格式才能设置图片质量

图片质量的值是从 0 到 1 其中 1 表示质量最好

    var propertySet = new BitmapPropertySet();
// 图片质量,值范围是 0到1 其中 1 的质量最好
var qualityValue = new BitmapTypedValue(imageQuality,
Windows.Foundation.PropertyType.Single);
propertySet.Add("ImageQuality", qualityValue);
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, imageWriteAbleStream,
propertySet);

这里的 imageQuality 就是图片质量,这个需要传入

从一个图片文件压缩图片大小的方法可以这样写,创建一个方法传入原图文件,和需要输出的文件,和图片质量

        private async Task<StorageFile> ConvertImageToJpegAsync(StorageFile sourceFile, StorageFile outputFile,
double imageQuality)

先获取图片大小,这样可以知道压缩了多少,对比原图的文件大小和压缩之后的图片大小

            var sourceFileProperties = await sourceFile.GetBasicPropertiesAsync();
var fileSize = sourceFileProperties.Size;

获取文件大小更简单的方法是通过 WinRTXamlToolkit 的 StorageItemExtensions.GetSizeAsync 拿到文件大小

读取原图文件,需要先解码原图,然后通过编码的时候修改图片质量

            var imageStream = await sourceFile.OpenReadAsync();

解码的方法是不需要知道图片的格式

                var decoder = await BitmapDecoder.CreateAsync(imageStream);
var pixelData = await decoder.GetPixelDataAsync();
var detachedPixelData = pixelData.DetachPixelData();

打开输出文件,进行编码

                var imageWriteAbleStream = await outputFile.OpenAsync(FileAccessMode.ReadWrite);

在创建编码的时候设置图片质量

    var propertySet = new BitmapPropertySet();
// 图片质量,值范围是 0到1 其中 1 的质量最好
var qualityValue = new BitmapTypedValue(imageQuality,
Windows.Foundation.PropertyType.Single);
propertySet.Add("ImageQuality", qualityValue);
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, imageWriteAbleStream,
propertySet);

将编码写入到文件

    encoder.SetPixelData(decoder.BitmapPixelFormat, decoder.BitmapAlphaMode, decoder.OrientedPixelWidth,
decoder.OrientedPixelHeight, decoder.DpiX, decoder.DpiY, detachedPixelData);
await encoder.FlushAsync();
await imageWriteAbleStream.FlushAsync();

拿到压缩只有的文件的大小,对比一下

    var jpegImageSize = imageWriteAbleStream.Size;
// 欢迎访问我博客 https://blog.lindexi.com/ 里面有大量 UWP WPF 博客
Debug.WriteLine($"压缩之后比压缩前的文件小{fileSize - jpegImageSize}");

这个压缩图片的方法的代码虽然看起来很多,但是看起来还是很简单先打开原来的图片文件对原图进行解密然后输出到新的文件

        /// <summary>
/// 将原来的图片转换图片质量和压缩质量
/// </summary>
/// <param name="sourceFile">原来的图片</param>
/// <param name="outputFile">输出的文件</param>
/// <param name="imageQuality">图片质量,取值范围是 0 到 1 其中 1 的质量最好,这个值设置只对 jpg 图片有效</param>
/// <returns></returns>
private async Task<StorageFile> ConvertImageToJpegAsync(StorageFile sourceFile, StorageFile outputFile,
double imageQuality)
{
var sourceFileProperties = await sourceFile.GetBasicPropertiesAsync();
var fileSize = sourceFileProperties.Size;
var imageStream = await sourceFile.OpenReadAsync();
using (imageStream)
{
var decoder = await BitmapDecoder.CreateAsync(imageStream);
var pixelData = await decoder.GetPixelDataAsync();
var detachedPixelData = pixelData.DetachPixelData();
var imageWriteAbleStream = await outputFile.OpenAsync(FileAccessMode.ReadWrite);
using (imageWriteAbleStream)
{
var propertySet = new BitmapPropertySet();
// 图片质量,值范围是 0到1 其中 1 的质量最好
var qualityValue = new BitmapTypedValue(imageQuality,
Windows.Foundation.PropertyType.Single);
propertySet.Add("ImageQuality", qualityValue);
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, imageWriteAbleStream,
propertySet);
//key thing here is to use decoder.OrientedPixelWidth and decoder.OrientedPixelHeight otherwise you will get garbled image on devices on some photos with orientation in metadata
encoder.SetPixelData(decoder.BitmapPixelFormat, decoder.BitmapAlphaMode, decoder.OrientedPixelWidth,
decoder.OrientedPixelHeight, decoder.DpiX, decoder.DpiY, detachedPixelData);
await encoder.FlushAsync();
await imageWriteAbleStream.FlushAsync();
var jpegImageSize = imageWriteAbleStream.Size;
// 欢迎访问我博客 https://blog.lindexi.com/ 里面有大量 UWP WPF 博客
Debug.WriteLine($"压缩之后比压缩前的文件小{fileSize - jpegImageSize}");
}
} return outputFile;
}

于是下面写一个测试的程序

在界面创建一个按钮

        <Button Content="压缩图片" HorizontalAlignment="Center" VerticalAlignment="Center" Click="Button_OnClick" />

在按钮拿到一个文件,然后在自己的临时文件夹里面创建输出文件,如果真的需要用这个程序压缩图片那么请让用户再选一个文件

        private async void Button_OnClick(object sender, RoutedEventArgs e)
{
var pick = new FileOpenPicker();
pick.FileTypeFilter.Add(".jpg");
var file = await pick.PickSingleFileAsync(); if (file != null)
{
await ConvertImageToJpegAsync(file,
await ApplicationData.Current.TemporaryFolder.CreateFileAsync("lindexi"),
0.75);
}
}

现在尝试运行代码,点击界面的按钮,就可以看到点击按钮选择

代码放在 github

这个代码参考了Alex Sorokoletov的代码

How to convert image to JPEG and specify quality parameter in UWP C# XAML

BitmapEncoder options reference - Windows UWP applications

Create, edit, and save bitmap images - Windows UWP applications

2019-3-21-win10-uwp-修改图片质量压缩图片的更多相关文章

  1. win10 uwp 修改Pivot Header 颜色

    我们在xaml创建一个Pivot <Pivot Grid.Row="1"> <PivotItem Header="lindexi">&l ...

  2. win10 uwp 修改CalendarDatePicker图标颜色

    CalendarDatePicker 是一个好用的东西,但是我发现想要修改他右边的那个图标,显示日历的图标颜色,没有这个选项. 如果不知道我说的是哪个,请看下面的图. 左边颜色变化的就是我们要修改的图 ...

  3. win10 uwp win2d CanvasVirtualControl 与 CanvasAnimatedControl

    本文来告诉大家 CanvasVirtualControl ,在什么时候使用这个控件. 在之前的入门教程win10 uwp win2d 入门 看这一篇就够了我直接用的是CanvasControl,实际上 ...

  4. win10 uwp 读取保存WriteableBitmap 、BitmapImage

    我们在UWP,经常使用的图片,数据结构就是 BitmapImage 和 WriteableBitmap.关于 BitmapImage 和 WriteableBitmap 区别,我就不在这里说.主要说的 ...

  5. win10 uwp 商业游戏

    本文告诉大家去做一个商业游戏,游戏很简单,几乎没有什么技术 游戏的开始,需要添加框架库,于是引用我自己写的库. 首先是创建一个启动页面,这个页面是显示启动的. 在显示启动的时候,是需要加载游戏需要使用 ...

  6. Win10 UWP开发系列:使用VS2015 Update2+ionic开发第一个Cordova App

    安装VS2015 Update2的过程是非常曲折的.还好经过不懈的努力,终于折腾成功了. 如果开发Cordova项目的话,推荐大家用一下ionic这个框架,效果还不错.对于Cordova.PhoneG ...

  7. Win10 UWP开发系列:实现Master/Detail布局

    在开发XX新闻的过程中,UI部分使用了Master/Detail(大纲/细节)布局样式.Win10系统中的邮件App就是这种样式,左侧一个列表,右侧是详情页面.关于这种 样式的说明可参看MSDN文档: ...

  8. 【Win10 UWP】后台任务与动态磁贴

    动态磁贴(Live Tile)是WP系统的大亮点之一,一直以来受到广大用户的喜爱.这一讲主要研究如何在UWP应用里通过后台任务添加和使用动态磁贴功能. 从WP7到Win8,再到Win10 UWP,磁贴 ...

  9. win10 uwp 列表模板选择器

    本文主要讲ListView等列表可以根据内容不同,使用不同模板的列表模板选择器,DataTemplateSelector. 如果在 UWP 需要定义某些列的显示和其他列不同,或者某些行的显示和其他行不 ...

随机推荐

  1. VC++1.5太伟大了

    功能样样俱全,一点不比现在的VS系列差 VC++1.5全貌,虽然很古老,但是已经可以了. 新建的文档试图,多文档工程,很像样 文档试图,单文档工程,已经非常像样了,和记事本差不多了 这是资源编辑器,寒 ...

  2. js判断两个对象是否相等

    function isObjectValueEqual(a, b) { if(typeof a == 'number' && typeof b == 'number'){ return ...

  3. JasperReport查看和打印报告7

    报表填充过程JasperPrint对象的输出可以使用内置的浏览器组件来查看,打印或导出到更多的流行的文件格式,如PDF,HTML,RTF,XLS,ODT,CSV或XML.Jasper文件查看和打印将包 ...

  4. Tarjan求LCA(离线)

    基本思想 把要求的点对保存下来,在dfs时顺带求出来. 方法 将每个已经遍历的点指向它回溯的最高节点(遍历它的子树时指向自己),每遍历到一个点就处理它存在的询问如果另一个点已经遍历,则lca就是另一个 ...

  5. 2017年8月9日学习内容存放 #socket通信介绍

    2017年8月9日学习内容存放 #socket通信介绍 ''' OSI七层 应用 表示 会话 传输 网络 ip 数据链路 mac 物理层 网线 http smtp dns ftp ssh snmp i ...

  6. IOS下的 click 点击失效

    当委托给一个元素添加click事件时,如果事件是委托到 document 或 body 上,并且委托的元素是默认不可点击的(如 div, span 等),此时 click 事件会失效. demo: & ...

  7. Linux 基础命令4进程

    ID和PID的产生 ps( process status) 查看现在的进程 上例中,列出了两个进程,进程 5198 和进程 10129,各自代表命令 bash 和 ps.正如我们所看到的, 默认情况下 ...

  8. 【同余最短路】洛谷 P2662 牛场围栏

    关于同余最短路的部分 [同余最短路]P3403跳楼机/P2371墨墨的等式 [P2662牛场围栏] 题目背景 小L通过泥萌的帮助,成功解决了二叉树的修改问题,并因此写了一篇论文, 成功报送了叉院(羡慕 ...

  9. day38 03-Spring的IOC和DI的区别

    在IOC中有一个DI的概念. IOC是控制反转,DI是依赖注入.现在编写的类里面是没有其他的属性的.如果你学过像UML设计的话, 电视没有遥控器,按按钮也可以,但是紧密的那种,像人和四肢,人如果没有了 ...

  10. thinkcmf 导航高亮制作方法(适用于多级导航)(通用)

    平时用thinkcmf网站开发经常需要导航点击之后高亮,就写了一些实现方法分享一下. 思路很简单,先获取当前页面的顶级栏目的地址,然后与导航中的地址比较,相同的就加上一个class,把下面函数理解了不 ...