iOS图片尺寸变换性能测试

502 阅读2分钟

图片尺寸变换在App里常用的一个功能,特别是对于图片处理较为频繁的项目,所以对图片处理常用的几个方式进行了性能测试,找到空间和时间最优的方式来处理图片尺寸问题;

我们测试使用的是XCTest进行的,主要测量的指标是时间和空间,即耗时及内存;

图片压缩方式一:

func normalizedImageScale(toMaxLength maxLength:CGFloat) -> UIImage {
        
        
        let realSize = CGSize.init(width: Int(size.width * scale), height: Int(size.height * scale))
        let fMaxLength = CGFloat(maxLength)
        var targetSize : CGSize
        if realSize.width < fMaxLength && realSize.height < fMaxLength {
            targetSize = size
        } else{
            if realSize.width > realSize.height {
                targetSize = CGSize.init(width: Int(maxLength), height: Int(realSize.height / (realSize.width / maxLength)))
            } else{
                targetSize = CGSize.init(width: Int(realSize.width / (realSize.height / maxLength)), height: Int(maxLength))
            }
        }
        UIGraphicsBeginImageContext(targetSize)
        draw(in: CGRect.init(origin: .zero, size:targetSize))
        let normalizedImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return normalizedImage ?? UIImage()
    }

图片压缩方式二:

func resizeImage(with image: UIImage, targetSize: CGSize) -> UIImage {
  	let render = UIGraphicsImageRenderer(bounds: CGRect(origin: .zero, size: targetSize))
  	let result = render.image { (context) in
                    image.draw(in: CGRect(origin: .zero, size: CGSize(width: 480, height: 640)))
     }
  	return result
}

图片压缩方式三:

#import "UIImage+Resize.h"

- (UIImage *)resizedImage:(CGSize)newSize interpolationQuality:(CGInterpolationQuality)quality {
    BOOL drawTransposed;
    switch ( self.imageOrientation )
    {
        case UIImageOrientationLeft:
        case UIImageOrientationLeftMirrored:
        case UIImageOrientationRight:
        case UIImageOrientationRightMirrored:
	    drawTransposed = YES;
	    break;
        default:
	    drawTransposed = NO;
    }
        
    CGAffineTransform transform = [self transformForOrientation:newSize];
    
  	CGFloat scale = MAX(1.0f, self.scale);
    CGRect newRect = CGRectIntegral(CGRectMake(0, 0, newSize.width*scale, newSize.height*scale));
    CGRect transposedRect = CGRectMake(0, 0, newRect.size.height, newRect.size.width);
    CGImageRef imageRef = self.CGImage;
    
    // Fix for a colorspace / transparency issue that affects some types of 
    // images. See here: http://vocaro.com/trevor/blog/2009/10/12/resize-a-uiimage-the-right-way/comment-page-2/#comment-39951
        
	CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef bitmap = CGBitmapContextCreate(
                                                NULL,
                                                newRect.size.width,
                                                newRect.size.height,
                                                8, /* bits per channel */
                                                (newRect.size.width * 4), /* 4 channels per pixel * numPixels/row */
                                                colorSpace,
                                                kCGImageAlphaPremultipliedLast
                                                );
    CGColorSpaceRelease(colorSpace);
	
    // Rotate and/or flip the image if required by its orientation
    CGContextConcatCTM(bitmap, transform);
    
    // Set the quality level to use when rescaling
    CGContextSetInterpolationQuality(bitmap, quality);
    
    // Draw into the context; this scales the image
    CGContextDrawImage(bitmap, drawTransposed ? transposedRect : newRect, imageRef);
    
    // Get the resized image from the context and a UIImage
    CGImageRef newImageRef = CGBitmapContextCreateImage(bitmap);
    UIImage *newImage = [UIImage imageWithCGImage:newImageRef scale:self.scale orientation:UIImageOrientationUp];
    
    // Clean up
    CGContextRelease(bitmap);
    CGImageRelease(newImageRef);
    
    return newImage;
}

测试一张图片(2400*3200, 1.5M),压缩100次平均值:

方案时间内存
方案一23.3ms13.8k
方案二46.2ms10.7k
方案三19.2ms9.42k

测试100张图片,压缩5次平均值:

方案时间内存
方案一2.86s573k
方案二5.38s362k
方案三2.44s593k

由上述测试结果可知:

在处理图片数量较少时,方案三略优于方案一,都优于方案二;当处理图片较多时,方案二的内存占用更低,但是耗时大概是另外两种方案2倍。

注:以上测试都跑在iPhone11模拟器上。

除此之外,还有其他图片压缩方案,这里不再列举,可参考文章: Image Resizing Techniques