图片缩放的相关处理

图片缩放的相关处理

最近自己做的点东西上用到了图片的处理,不过没有找到合适的图片处理相关算法,倒是找到了几个获取缩略图的算法。代码不长,简单看了看原理也比较简单(其实不是简单是C#的封装的太多了,所以显得比较简单)。既然没有相关的统一调用的代码,索性,我来整理一套相关的处理代码然后公开出来吧。

图片处理的相关分析

其实我要用的图片处理非常简单,就是简单的压缩一下图片。然后把图片设置到对应大小而已。但是对于设置的方式,C#基础的函数中使用的Rect范围设置。这个范围设置计算起来可能相对头疼一些。所以我在考虑要不要让调用者在忽略Rect这个参数的情况愉快的调用接口呢?于是乎,我定义了几个图片缩放类型(Full、Zoom、Overflow、Original)。然后默认的让原始图片的中心点与输出图片的中心点对齐。然后根据缩放类型来对图片进行不同的缩放模式。

缩放模式

  1. Full:让图片放弃原来的比例,直接按照目标数据进行拉伸
  2. Zoom:让图片保持原有比例,并且保证原始图片在目标图片的正中央,没有图片的位置保留米白色
  3. Original:让图片保持原来的大小,输出图片类似于裁剪中间位置某个范围的图片
  4. Overflow:让图片保持原来的比例,并且保证输目标是被图片填满的不留空白

调用的范例

ImageHelper.GetInstance().ImageCompress(InputFile, Path.Combine(OutPutPath, item_file), new System.Drawing.Size(500, 300), ImageZoomType.Full, 50);

样品展示

原始图片

Full 300*500 

 

Full 500 * 300

 

Original 300 * 500

 

Original 500 * 300

 

Overflow 300 * 500

 

Overflow 500 * 300

 

Zoom 300 * 500

 

Zoom 500 * 300

存在的不足

  1. 压缩没有独到的技术
  2. 目前只支持JPEG格式的图片
  3. 部分图片进行缩放之后会留下一个1像素浅浅的边

后续的内容

图片处理不光是缩放,还有其他的很多东西比较实用(截图、压缩、按高缩放、按宽缩放、添加水印、添加隐藏水印),我准备把图片常用的相关处理。整理成一个帮助类,方便迁入到各个项目中去。

所以我建立了一个专门的图片处理的开源项目方便后续功能加入,地址如下:http://git.oschina.net/anxin1225/ImageCompress

 

压缩相关的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace ImageCompress
{
    public struct AnchorPoint
    {
        //public AnchorPoint() : this(0, 0) { }
        public AnchorPoint(double x, double y)
        {
            X = x;
            Y = y;
        }
 
        public double X, Y;
    }
 
    public enum ImageZoomType
    {
        Full,
        Zoom,
        Overflow,
        Original,
    }
 
    public delegate void ImageHandle(Image image, Bitmap bitmap);
 
    public class ImageHelper
    {
        private ImageHelper() { }
 
        private static ImageHelper _image_helper = null;
        private Dictionary<ImageZoomType, ImageHandle> _name_to_handle = new Dictionary<ImageZoomType, ImageHandle>();
 
        public static ImageHelper GetInstance()
        {
            if (_image_helper == null)
            {
                _image_helper = new ImageHelper();
 
                //填满
                _image_helper._name_to_handle[ImageZoomType.Full] = (image, bitmap) =>
                {
                    _image_helper.DrawImage(image, bitmap, new Rectangle(new Point(0, 0), bitmap.Size));
                };
 
                //原始
                _image_helper._name_to_handle[ImageZoomType.Original] = (image, bitmap) =>
                {
                    _image_helper.DrawImage(image, bitmap, 1, new AnchorPoint(0.5, 0.5), new AnchorPoint(0.5, 0.5));
                };
 
                //溢出
                _image_helper._name_to_handle[ImageZoomType.Overflow] = (image, bitmap) =>
                {
                    float proportion_x = (float)bitmap.Width / image.Width;
                    float proportion_y = (float)bitmap.Height / image.Height;
                    _image_helper.DrawImage(image, bitmap, proportion_x > proportion_y ? proportion_x : proportion_y, new AnchorPoint(0.5, 0.5), new AnchorPoint(0.5, 0.5));
                };
 
                //缩放
                _image_helper._name_to_handle[ImageZoomType.Zoom] = (image, bitmap) =>
                {
                    float proportion_x = (float)bitmap.Width / image.Width;
                    float proportion_y = (float)bitmap.Height / image.Height;
                    _image_helper.DrawImage(image, bitmap, proportion_x < proportion_y ? proportion_x : proportion_y, new AnchorPoint(0.5, 0.5), new AnchorPoint(0.5, 0.5));
                };
            }
 
            return _image_helper;
        }
 
        /// <summary>
        /// 压缩图片
        /// </summary>
        /// <param name="source_path">源数据位置</param>
        /// <param name="save_path">保存数据位置</param>
        /// <param name="save_size">保存图片大小</param>
        /// <param name="ztype">缩放模式</param>
        /// <param name="flag">图片保存品质</param>
        /// <returns>是否完成压缩</returns>
        public bool ImageCompress(string source_path, string save_path, Size save_size, ImageZoomType ztype, int flag)
        {
            bool success = false;
 
            Image source = null;
 
            while (true)
            {
                source = LoadImage(source_path);
                if (source == null)
                    break;
 
                Bitmap bitmap = new Bitmap(save_size.Width, save_size.Height);
 
                if (_name_to_handle.ContainsKey(ztype))
                {
                    _name_to_handle[ztype](source, bitmap);
                }
                else
                {
                    break;
                }
 
                success = SaveImage(bitmap, save_path, source.RawFormat, flag);
                break;
            }
 
            if (source != null)
                source.Dispose();
 
            return success;
        }
 
        public Image LoadImage(string source_path)
        {
            Image image = null;
            while (true)
            {
                if (!File.Exists(source_path))
                    break;
 
                try
                {
                    image = Image.FromFile(source_path);
                }
                catch
                {
                    break;
                }
 
                break;
            }
 
            return image;
        }
 
        /// <summary>
        /// 将BitMap保存到磁盘上
        /// </summary>
        /// <param name="image">需要保存的图片</param>
        /// <param name="save_path">保存的路径</param>
        /// <param name="format">保存格式</param>
        /// <param name="flag">保存质量</param>
        /// <returns></returns>
        public bool SaveImage(Bitmap image, string save_path, ImageFormat format, int flag)
        {
            //以下代码为保存图片时,设置压缩质量 
            EncoderParameters ep = new EncoderParameters();
            long[] qy = new long[1];
            qy[0] = flag;//设置压缩的比例1-100 
            EncoderParameter eParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, qy);
            ep.Param[0] = eParam;
            try
            {
                ImageCodecInfo[] arrayICI = ImageCodecInfo.GetImageEncoders();
                ImageCodecInfo jpegICIinfo = null;
                for (int x = 0; x < arrayICI.Length; x++)
                {
                    if (arrayICI[x].FormatDescription.Equals("JPEG"))
                    {
                        jpegICIinfo = arrayICI[x];
                        break;
                    }
                }
                if (jpegICIinfo != null)
                {
                    image.Save(save_path, jpegICIinfo, ep);//dFile是压缩后的新路径 
                }
                else
                {
                    image.Save(save_path, format);
                }
                return true;
            }
            catch
            {
                return false;
            }
            finally
            {
                image.Dispose();
            }
        }
 
        /// <summary>
        /// 画图
        /// </summary>
        /// <param name="source">原始图像</param>
        /// <param name="output">输出图像</param>
        /// <param name="souce_scale">原始图像的缩放值</param>
        /// <param name="souce_anchor"></param>
        /// <param name="graphics_anchor"></param>
        public void DrawImage(Image source, Bitmap output, float souce_scale, AnchorPoint souce_anchor, AnchorPoint graphics_anchor)
        {
            DrawImage(source, output, souce_scale, souce_anchor, new Point((int)(output.Width * graphics_anchor.X), (int)(output.Height * graphics_anchor.Y)));
        }
 
        /// <summary>
        /// 画图
        /// </summary>
        /// <param name="source">原始图像</param>
        /// <param name="output">输出凸显</param>
        /// <param name="source_scale">图像的所放值</param>
        /// <param name="source_anchor">源图像锚点</param>
        /// <param name="souce_point">图像位置</param>
        public void DrawImage(Image source, Bitmap output, float source_scale, AnchorPoint source_anchor, Point souce_point)
        {
            var pic_po = new Point((int)(souce_point.X - source.Size.Width * source_scale * source_anchor.X), (int)(souce_point.Y - source.Size.Height * source_scale * source_anchor.Y));
            DrawImage(source, output, new Rectangle(pic_po, new Size((int)(source.Width * source_scale), (int)(source.Height * source_scale))));
        }
 
        /// <summary>
        /// 画图
        /// </summary>
        /// <param name="source"></param>
        /// <param name="output"></param>
        /// <param name="rect"></param>
        public void DrawImage(Image source, Bitmap output, Rectangle rect)
        {
            Graphics g = Graphics.FromImage(output);
            g.Clear(Color.WhiteSmoke);
            g.CompositingQuality = CompositingQuality.HighQuality;
            g.SmoothingMode = SmoothingMode.HighQuality;
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.DrawImage(source, rect, 0, 0, source.Width, source.Height, GraphicsUnit.Pixel);
            g.Dispose();
        }
    }
}

  

 

PS:为了美观本文中的原始图片并不是原始图片,因为原始图片太大了。会造成页面滑动,所以我上传了一张较小的图片。Git的图片则是原始的图片

posted @   连程  阅读(1125)  评论(6编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示