前言:还是这个图片浏览的小demo,在里面实现了对单张图片的放大缩小。现在把我已知的图片缩放的各种方法记录下来,方便以后查阅,毕竟图片缩放还是经常用到的。
正文:构建图像缩略图,通常有3种形式:保持图像比例不变调整大小;裁剪部分图像来匹配可用空间;通过匹配可用空间的长度和宽度来填充图像。
一、最简单的方法
UIGraphicsBeginImageContext(size); //size 为CGSize类型,即你所需要的图片尺寸
[sourceImage drawInRect:newImageRect]; //sourceImage为原图,newImageRect指定了图片绘制区域
newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
OK,newImage 就是你要的图。缺点:回丢失很多图片信息
二、利用UISrcollView的方法
_srcollView.minimumZoomScale=0.5f;//最小缩小倍数
_srcollView.maximumZoomScale=2.0f;//最大方法倍数
// return a view that will be scaled. if delegate returns nil, nothing happen
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
NSLog(@"viewForZoomingInScrollView");
for (id view in [_srcollView subviews]) {
if ([view isKindOfClass:[UIImageView class]]) {
return view;
}
}
return nil;
}
三、自己写缩放方法
1 #import <Foundation/Foundation.h>
2
3 #define CGAutorelease(x) (__typeof(x))[NSMakeCollectable(x) autorelease]
4
5 #define SUPPPORTS_UNDOCUMENTED_APIS 1
6
7 @interface ImageHelper : NSObject
8 // Create image
9 + (UIImage *) imageFromView: (UIView *) theView;
10
11 // Base Image Fitting
12 + (CGSize) fitSize: (CGSize)thisSize inSize: (CGSize) aSize;
13 + (UIImage *) unrotateImage: (UIImage *) image;
14
15 + (UIImage *) image: (UIImage *) image fitInSize: (CGSize) size; // retain proportions, fit in size
16 + (UIImage *) image: (UIImage *) image fitInView: (UIView *) view;
17
18 + (UIImage *) image: (UIImage *) image centerInSize: (CGSize) size; // center, no resize
19 + (UIImage *) image: (UIImage *) image centerInView: (UIView *) view;
20
21 + (UIImage *) image: (UIImage *) image fillSize: (CGSize) size; // fill all pixels
22 + (UIImage *) image: (UIImage *) image fillView: (UIView *) view;
23
24 #if SUPPPORTS_UNDOCUMENTED_APIS
25 + (UIImage *) image: (UIImage *) image withOrientation: (UIImageOrientation) orientation;
26 #endif
27
28 //截取view部分图片
29 + (UIImage *) imageFromViewWithRect:(UIView *)theView rect:(CGRect)rect;
30 @end
ImageHelper.h
1 #import "ImageHelper.h"
2 #import <QuartzCore/QuartzCore.h>
3
4 #if SUPPPORTS_UNDOCUMENTED_APIS
5 @interface UIImage (privateAPISForOrientation)
6 - (id)initWithCGImage:(struct CGImage *)fp8 imageOrientation:(int)fp12;
7 @end
8 #endif
9
10 @implementation ImageHelper
11
12 #pragma mark Create Image
13
14 // Screen shot the view
15 + (UIImage *) imageFromView: (UIView *) theView
16 {
17 UIGraphicsBeginImageContext(theView.frame.size);
18 CGContextRef context = UIGraphicsGetCurrentContext();
19 [theView.layer renderInContext:context];
20 UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext();
21 UIGraphicsEndImageContext();
22 return theImage;
23 }
24
25 #pragma mark Base Image Utility
26 + (CGSize) fitSize: (CGSize)thisSize inSize: (CGSize) aSize
27 {
28 CGFloat scale;
29 CGSize newsize = thisSize;
30
31
32 if (newsize.height && (newsize.height > aSize.height))//如果新图的高度不为0,且大于原图高度
33 {
34 scale = aSize.height / newsize.height;//比例为 原高/新高
35 newsize.width *= scale;//新图的宽度等于 =
36 newsize.height *= scale;
37 }
38
39 if (newsize.width && (newsize.width >= aSize.width))
40 {
41 scale = aSize.width / newsize.width;
42 newsize.width *= scale;
43 newsize.height *= scale;
44 }
45
46 return newsize;
47 }
48
49 #define MIRRORED ((image.imageOrientation == UIImageOrientationUpMirrored) || (image.imageOrientation == UIImageOrientationLeftMirrored) || (image.imageOrientation == UIImageOrientationRightMirrored) || (image.imageOrientation == UIImageOrientationDownMirrored))
50 #define ROTATED90 ((image.imageOrientation == UIImageOrientationLeft) || (image.imageOrientation == UIImageOrientationLeftMirrored) || (image.imageOrientation == UIImageOrientationRight) || (image.imageOrientation == UIImageOrientationRightMirrored))
51
52 + (UIImage *) doUnrotateImage: (UIImage *) image
53 {
54 CGSize size = image.size;
55 if (ROTATED90) size = CGSizeMake(image.size.height, image.size.width);
56
57 UIGraphicsBeginImageContext(size);
58 CGContextRef context = UIGraphicsGetCurrentContext();
59 CGAffineTransform transform = CGAffineTransformIdentity;
60
61 // Rotate as needed
62 switch(image.imageOrientation)
63 {
64 case UIImageOrientationLeft:
65 case UIImageOrientationRightMirrored:
66 transform = CGAffineTransformRotate(transform, M_PI / 2.0f);
67 transform = CGAffineTransformTranslate(transform, 0.0f, -size.width);
68 size = CGSizeMake(size.height, size.width);
69 CGContextConcatCTM(context, transform);
70 break;
71 case UIImageOrientationRight:
72 case UIImageOrientationLeftMirrored:
73 transform = CGAffineTransformRotate(transform, -M_PI / 2.0f);
74 transform = CGAffineTransformTranslate(transform, -size.height, 0.0f);
75 size = CGSizeMake(size.height, size.width);
76 CGContextConcatCTM(context, transform);
77 break;
78 case UIImageOrientationDown:
79 case UIImageOrientationDownMirrored:
80 transform = CGAffineTransformRotate(transform, M_PI);
81 transform = CGAffineTransformTranslate(transform, -size.width, -size.height);
82 CGContextConcatCTM(context, transform);
83 break;
84 default:
85 break;
86 }
87
88
89 if (MIRRORED)
90 {
91 // de-mirror
92 transform = CGAffineTransformMakeTranslation(size.width, 0.0f);
93 transform = CGAffineTransformScale(transform, -1.0f, 1.0f);
94 CGContextConcatCTM(context, transform);
95 }
96
97 // Draw the image into the transformed context and return the image
98 [image drawAtPoint:CGPointMake(0.0f, 0.0f)];
99 UIImage *newimg = UIGraphicsGetImageFromCurrentImageContext();
100 UIGraphicsEndImageContext();
101 return newimg;
102 }
103
104 + (UIImage *) unrotateImage: (UIImage *) image
105 {
106 if (image.imageOrientation == UIImageOrientationUp) return image;
107 return [ImageHelper doUnrotateImage:image];
108 }
109
110
111
112 // Proportionately resize, completely fit in view, no cropping
113 + (UIImage *) image: (UIImage *) image fitInSize: (CGSize) viewsize
114 {
115 // calculate the fitted size
116 CGSize size = [ImageHelper fitSize:image.size inSize:viewsize];
117
118 UIGraphicsBeginImageContext(viewsize);
119
120 float dwidth = (viewsize.width - size.width) / 2.0f;
121 float dheight = (viewsize.height - size.height) / 2.0f;
122
123 CGRect rect = CGRectMake(dwidth, dheight, size.width, size.height);
124 [image drawInRect:rect];
125
126 UIImage *newimg = UIGraphicsGetImageFromCurrentImageContext();
127 UIGraphicsEndImageContext();
128
129 return newimg;
130 }
131
132 + (UIImage *) image: (UIImage *) image fitInView: (UIView *) view
133 {
134 return [self image:image fitInSize:view.frame.size];
135 }
136
137 // No resize, may crop
138 + (UIImage *) image: (UIImage *) image centerInSize: (CGSize) viewsize
139 {
140 CGSize size = image.size;
141
142 UIGraphicsBeginImageContext(viewsize);
143 float dwidth = (viewsize.width - size.width) / 2.0f;
144 float dheight = (viewsize.height - size.height) / 2.0f;
145
146 CGRect rect = CGRectMake(dwidth, dheight, size.width, size.height);
147 [image drawInRect:rect];
148
149 UIImage *newimg = UIGraphicsGetImageFromCurrentImageContext();
150 UIGraphicsEndImageContext();
151
152 return newimg;
153 }
154
155 + (UIImage *) image: (UIImage *) image centerInView: (UIView *) view
156 {
157 return [self image:image centerInSize:view.frame.size];
158 }
159
160 // Fill every view pixel with no black borders, resize and crop if needed
161 + (UIImage *) image: (UIImage *) image fillSize: (CGSize) viewsize
162
163 {
164 CGSize size = image.size;
165
166 CGFloat scalex = viewsize.width / size.width;
167 CGFloat scaley = viewsize.height / size.height;
168 CGFloat scale = MAX(scalex, scaley);
169
170 UIGraphicsBeginImageContext(viewsize);
171
172 CGFloat width = size.width * scale;
173 CGFloat height = size.height * scale;
174
175 float dwidth = ((viewsize.width - width) / 2.0f);
176 float dheight = ((viewsize.height - height) / 2.0f);
177
178 CGRect rect = CGRectMake(dwidth, dheight, size.width * scale, size.height * scale);
179 [image drawInRect:rect];
180
181 UIImage *newimg = UIGraphicsGetImageFromCurrentImageContext();
182 UIGraphicsEndImageContext();
183
184 return newimg;
185 }
186
187 + (UIImage *) image: (UIImage *) image fillView: (UIView *) view
188 {
189 return [self image:image fillSize:view.frame.size];
190 }
191
192 #if SUPPPORTS_UNDOCUMENTED_APIS
193 + (UIImage *) image: (UIImage *) image withOrientation: (UIImageOrientation) orientation
194 {
195 UIImage *newimg = [[UIImage alloc] initWithCGImage:[image CGImage] imageOrientation:orientation];
196 return [newimg autorelease];
197 }
198 #endif
199
200 //截取view部分图片
201 + (UIImage *) imageFromViewWithRect:(UIView *)theView rect:(CGRect)rect
202 {
203 CGFloat scale = 1.0f;
204 if (UIGraphicsBeginImageContextWithOptions != NULL)
205 {
206 UIGraphicsBeginImageContextWithOptions(theView.bounds.size, NO, theView.layer.contentsScale);
207 scale = theView.layer.contentsScale;
208 }
209 else
210 {
211 UIGraphicsBeginImageContext(theView.bounds.size);
212 }
213
214 CALayer * curLayer = [theView layer];
215 CGContextRef context = UIGraphicsGetCurrentContext();
216 [curLayer renderInContext:context];
217
218 UIImage * pImage = UIGraphicsGetImageFromCurrentImageContext();
219 CGImageRef imageRef = pImage.CGImage;
220 CGRect rectSubImage = {rect.origin.x*scale,rect.origin.y*scale,rect.size.width*scale,rect.size.height*scale};
221 CGImageRef subImageRef = CGImageCreateWithImageInRect(imageRef, rectSubImage);
222 rect.size.width *=scale;
223 rect.size.height *=scale;
224 CGSize size = rect.size;
225 UIGraphicsBeginImageContext(size);
226 CGContextRef subcontext = UIGraphicsGetCurrentContext();
227 CGContextDrawImage(subcontext, rect, subImageRef);
228
229 UIImage * image = [UIImage imageWithCGImage:subImageRef scale:scale orientation:UIImageOrientationUp];
230 UIGraphicsEndImageContext();
231
232 CGImageRelease(subImageRef); //这里不必释放
233 UIGraphicsEndImageContext();
234
235 return image;
236 }
237 @end
ImageHelper.m
这份代码iphone开发秘籍这本书中给的,实现了开头介绍的3种缩放方法。下面会详细的分析这份代码。
+ (CGSize) fitSize: (CGSize)thisSize inSize: (CGSize) aSize; 计算出合适的尺寸
+ (UIImage *) image: (UIImage *) image fitInSize: (CGSize) size;成比例缩放,不裁剪,需重新测量尺寸
+ (UIImage *) image: (UIImage *) image centerInSize: (CGSize) size;不需要再重新测量,可能裁剪
+ (UIImage *) image: (UIImage *) image centerInSize: (CGSize) size;可能需要裁剪和重新测量,每个像素都会被使用
开始逐个介绍每一种缩放方法究竟是怎么实现的:
1、fitSize: (CGSize)thisSize inSize: (CGSize) aSize;第一个参数是原图尺寸,第二个是新View的尺寸
根据原图的尺寸,成比例的计算出新图的尺寸。
新图尺寸初始化:CGSize newSize = thisSize;先令新图的尺寸等于原图的尺寸
计算缩放比例:原W/原H = 新W/新H
1、fitInSize的实现
image: (UIImage *) image fitInSize: (CGSize) size; 第一个参数是原图,第二个参数是要构建的新图的尺寸
成比例的缩放自然要先