我需要按比例缩小图像,但要采用清晰的方式。例如,在Photoshop中,图像尺寸缩小选项为“ Bicubic Smoother”(模糊)和“ Bicubic Sharper”。
这个图像缩小算法是在某个地方开源或记录的,还是SDK提供了执行此操作的方法?
我需要按比例缩小图像,但要采用清晰的方式。例如,在Photoshop中,图像尺寸缩小选项为“ Bicubic Smoother”(模糊)和“ Bicubic Sharper”。
这个图像缩小算法是在某个地方开源或记录的,还是SDK提供了执行此操作的方法?
Answers:
仅仅使用imageWithCGImage
是不够的。它将缩放,但是无论缩放还是缩小,结果都将是模糊且欠佳的。
如果您想正确地使用别名并摆脱“锯齿”,则需要这样的东西:http : //vocaro.com/trevor/blog/2009/10/12/resize-a-uiimage-the-right-方式/。
我的工作测试代码如下所示,这是Trevor的解决方案,并做了一些小的调整才能与我的透明PNG一起使用:
- (UIImage *)resizeImage:(UIImage*)image newSize:(CGSize)newSize {
CGRect newRect = CGRectIntegral(CGRectMake(0, 0, newSize.width, newSize.height));
CGImageRef imageRef = image.CGImage;
UIGraphicsBeginImageContextWithOptions(newSize, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
// Set the quality level to use when rescaling
CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
CGAffineTransform flipVertical = CGAffineTransformMake(1, 0, 0, -1, 0, newSize.height);
CGContextConcatCTM(context, flipVertical);
// Draw into the context; this scales the image
CGContextDrawImage(context, newRect, imageRef);
// Get the resized image from the context and a UIImage
CGImageRef newImageRef = CGBitmapContextCreateImage(context);
UIImage *newImage = [UIImage imageWithCGImage:newImageRef];
CGImageRelease(newImageRef);
UIGraphicsEndImageContext();
return newImage;
}
transformForOrientation
。该功能真的必要吗?仅适用于带有方向元数据的JPG吗?
imageOrientation
(我假设是EXIF数据?)并根据其值进行额外的转换。不知道是否有必要。我会玩的。
[[UIColor whiteColor] set]; UIRectFill(newRect);
对于那些使用Swift的用户,以下是Swift中公认的答案:
func resizeImage(image: UIImage, newSize: CGSize) -> (UIImage) {
let newRect = CGRectIntegral(CGRectMake(0,0, newSize.width, newSize.height))
let imageRef = image.CGImage
UIGraphicsBeginImageContextWithOptions(newSize, false, 0)
let context = UIGraphicsGetCurrentContext()
// Set the quality level to use when rescaling
CGContextSetInterpolationQuality(context, kCGInterpolationHigh)
let flipVertical = CGAffineTransformMake(1, 0, 0, -1, 0, newSize.height)
CGContextConcatCTM(context, flipVertical)
// Draw into the context; this scales the image
CGContextDrawImage(context, newRect, imageRef)
let newImageRef = CGBitmapContextCreateImage(context) as CGImage
let newImage = UIImage(CGImage: newImageRef)
// Get the resized image from the context and a UIImage
UIGraphicsEndImageContext()
return newImage
}
CGContextConcatCTM(context, flipVertical)
?
如果有人正在寻找Swift版本,这是@Dan Rosenstark接受的答案的Swift版本:
func resizeImage(image: UIImage, newHeight: CGFloat) -> UIImage {
let scale = newHeight / image.size.height
let newWidth = image.size.width * scale
UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight))
image.drawInRect(CGRectMake(0, 0, newWidth, newHeight))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage
}
对于Swift 3
func resizeImage(image: UIImage, newSize: CGSize) -> (UIImage) {
let newRect = CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height).integral
UIGraphicsBeginImageContextWithOptions(newSize, false, 0)
let context = UIGraphicsGetCurrentContext()
// Set the quality level to use when rescaling
context!.interpolationQuality = CGInterpolationQuality.default
let flipVertical = CGAffineTransform(a: 1, b: 0, c: 0, d: -1, tx: 0, ty: newSize.height)
context!.concatenate(flipVertical)
// Draw into the context; this scales the image
context?.draw(image.cgImage!, in: CGRect(x: 0.0,y: 0.0, width: newRect.width, height: newRect.height))
let newImageRef = context!.makeImage()! as CGImage
let newImage = UIImage(cgImage: newImageRef)
// Get the resized image from the context and a UIImage
UIGraphicsEndImageContext()
return newImage
}
newRect.size
,它将为我提供正确的缩小尺寸。但是,如果我进行打印newImage.size
,则可以看到的原始尺寸image
。有什么想法吗?弄清楚了。UIGraphicsBeginImageContextWithOptions(newSize, false, 0)
防止任何缩放。scale参数为0
。如果UIGraphicsBeginImageContext(newRect.size)
改用,一切都很好。
@YAR您的解决方案工作正常。
只有一件事不符合我的要求:调整了整个图像的大小。我写了一个方法,就像photos app on iphone
。这样可以计算出“较长的一面”,并切断“覆盖层”,从而获得与图像质量有关的更好的结果。
- (UIImage *)resizeImageProportionallyIntoNewSize:(CGSize)newSize;
{
CGFloat scaleWidth = 1.0f;
CGFloat scaleHeight = 1.0f;
if (CGSizeEqualToSize(self.size, newSize) == NO) {
//calculate "the longer side"
if(self.size.width > self.size.height) {
scaleWidth = self.size.width / self.size.height;
} else {
scaleHeight = self.size.height / self.size.width;
}
}
//prepare source and target image
UIImage *sourceImage = self;
UIImage *newImage = nil;
// Now we create a context in newSize and draw the image out of the bounds of the context to get
// A proportionally scaled image by cutting of the image overlay
UIGraphicsBeginImageContext(newSize);
//Center image point so that on each egde is a little cutoff
CGRect thumbnailRect = CGRectZero;
thumbnailRect.size.width = newSize.width * scaleWidth;
thumbnailRect.size.height = newSize.height * scaleHeight;
thumbnailRect.origin.x = (int) (newSize.width - thumbnailRect.size.width) * 0.5;
thumbnailRect.origin.y = (int) (newSize.height - thumbnailRect.size.height) * 0.5;
[sourceImage drawInRect:thumbnailRect];
newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
if(newImage == nil) NSLog(@"could not scale image");
return newImage ;
}
对于快速4.2:
extension UIImage {
func resized(By coefficient:CGFloat) -> UIImage? {
guard coefficient >= 0 && coefficient <= 1 else {
print("The coefficient must be a floating point number between 0 and 1")
return nil
}
let newWidth = size.width * coefficient
let newHeight = size.height * coefficient
UIGraphicsBeginImageContext(CGSize(width: newWidth, height: newHeight))
draw(in: CGRect(x: 0, y: 0, width: newWidth, height: newHeight))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage
}
}
该扩展名应该缩放图像,同时保持原始的宽高比。其余图像被裁剪。(快速3)
extension UIImage {
func thumbnail(ofSize proposedSize: CGSize) -> UIImage? {
let scale = min(size.width/proposedSize.width, size.height/proposedSize.height)
let newSize = CGSize(width: size.width/scale, height: size.height/scale)
let newOrigin = CGPoint(x: (proposedSize.width - newSize.width)/2, y: (proposedSize.height - newSize.height)/2)
let thumbRect = CGRect(origin: newOrigin, size: newSize).integral
UIGraphicsBeginImageContextWithOptions(proposedSize, false, 0)
draw(in: thumbRect)
let result = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return result
}
}