그림 압축 방법

6143 단어
두 가지 이미지 압축 방법
이미지 품질 압축(quality), 이미지 크기 압축(size)
압축 이미지 품질
NSData *data = UIImageJPEGRepresentation(image, compression);
UIImage *resultImage = [UIImage imageWithData:data];

또는
NSData *data = UIImagePNGRepresentation(UIImage * __nonnull image); 
UIImage *resultImage = [UIImage imageWithData:data];

전자는 압축 비율을 조절할 수 있고 후자가 차지하는 바이트보다 적기 때문에 그림의 질에 대한 요구가 비교적 높지 않으면 보통 JPEG의 압축 방식을 사용한다.
압축 이미지 크기
UIGraphicsBeginImageContext(targetSize);
[image drawInRect:CGRectMake(0, 0, targetSize.width, targetSize.height)];
resultImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

필요한 그림 크기를 targetsize로 지정하면,resultImage는 원래 그림의 이미지를 targetsize 크기로 그립니다.

그림을 압축해서 그림 파일을 지정한 크기보다 작게 합니다


만약에 사진의 선명도에 대한 요구가 높지 않고 사진의 업로드, 다운로드 속도가 빨라야 한다면 사진을 업로드하기 전에 사진을 압축해야 한다.어느 정도로 압축하는지는 구체적인 상황을 보아야 하지만, 일반적으로 그림 파일의 최대 값을 설정한다. 예를 들어 100KB이다.상술한 두 가지 방법을 채택하여 그림을 압축할 수 있다.그림이 변환된 NSData 대상이 데이터라고 가정하면 4data.length그림의 바이트 크기를 얻을 수 있다.
압축 이미지 품질
비교적 쉽게 생각할 수 있는 방법은 그림이 지정한 크기(maxLength)보다 조금 작을 때까지 순환을 통해 그림의 질을 점차적으로 줄이는 것이다.
+ (UIImage *)compressImageQuality:(UIImage *)image toByte:(NSInteger)maxLength {
    CGFloat compression = 1;
    NSData *data = UIImageJPEGRepresentation(image, compression);
    while (data.length > maxLength && compression > 0) {
        compression -= 0.02;
        data = UIImageJPEGRepresentation(image, compression); // When compression less than a value, this code dose not work
    }
    
    UIImage *resultImage = [UIImage imageWithData:data];
    return resultImage

이렇게 순환하는 횟수가 많고 효율이 낮으며 시간이 오래 걸린다.이분법을 통해 최적화할 수 있다.
+ (UIImage *)compressImageQuality:(UIImage *)image toByte:(NSInteger)maxLength {
    CGFloat compression = 1;
    NSData *data = UIImageJPEGRepresentation(image, compression);
    if (data.length < maxLength) return image;
    CGFloat max = 1;
    CGFloat min = 0;
    for (int i = 0; i < 6; ++i) {
        compression = (max + min) / 2;
        data = UIImageJPEGRepresentation(image, compression);
        if (data.length < maxLength * 0.9) {
            min = compression;
        } else if (data.length > maxLength) {
            max = compression;
        } else {
            break;
        }
    }
    UIImage *resultImage = [UIImage imageWithData:data];
    return resultImage;
}

그림 크기가 maxLength 보다 작고 maxlength * 0.9 보다 크면 더 이상 압축하지 않습니다.최대 6회, 1/(2^6)= 0.015625 <0.02도 순환마다compression이 0.02를 줄이는 효과에 도달할 수 있다.이런 압축 횟수는 순환 감소compression보다 적고 소모 시간이 짧다.주의해야 할 것은 그림의 질이 어느 정도 낮을 때 계속 압축하면 효과가 없다는 것이다.즉, compression은 계속 줄어들고 데이터도 더 이상 줄어들지 않는다는 것이다.
압축 그림의 품질의 장점은 가능한 한 그림의 선명도를 보존하고 그림이 뚜렷하게 모호하지 않다는 데 있다.단점은 그림이 압축된 후 지정된 크기보다 작다는 것을 보장할 수 없다는 것이다.
압축 이미지 크기
이전과 유사하게 비교적 쉽게 생각할 수 있는 방법은 그림의 크기를 지정한 크기(maxLength)보다 조금 작을 때까지 순환을 통해 점차적으로 줄이는 것이다.구체적인 코드가 생략되다.같은 문제는 순환 횟수가 많고 효율이 낮으며 시간이 오래 걸린다는 것이다.이분법으로 효율을 높일 수 있으며 구체적인 코드는 생략할 수 있다.이분법보다 더 좋고 압축 횟수가 적으며 그림을 압축한 후 지정한 크기보다 꼭 작게 할 수 있는 또 다른 방법을 소개한다(maxLength*0.9뿐만 아니라).
+ (UIImage *)compressImageSize:(UIImage *)image toByte:(NSUInteger)maxLength {
    UIImage *resultImage = image;
    NSData *data = UIImageJPEGRepresentation(resultImage, 1);
    NSUInteger lastDataLength = 0;
    while (data.length > maxLength && data.length != lastDataLength) {
        lastDataLength = data.length;
        CGFloat ratio = (CGFloat)maxLength / data.length;
        CGSize size = CGSizeMake((NSUInteger)(resultImage.size.width * sqrtf(ratio)),
                                 (NSUInteger)(resultImage.size.height * sqrtf(ratio))); // Use NSUInteger to prevent white blank
        UIGraphicsBeginImageContext(size);
        // Use image to draw (drawInRect:), image is larger but more compression time
        // Use result image to draw, image is smaller but less compression time
        [resultImage drawInRect:CGRectMake(0, 0, size.width, size.height)];
        resultImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        data = UIImageJPEGRepresentation(resultImage, 1);
    }
    return resultImage;
}

그림의 크기를 압축하면 그림이 지정한 크기보다 작지만 그림이 뚜렷하게 모호해진다. (압축된 그림보다 질이 모호하다.)
두 가지 사진 압축 방법이 결합되다
만약 그림의 선명도를 확보하려면 그림의 질을 압축하는 것을 선택하는 것을 권장한다.만약 그림이 반드시 지정된 크기보다 작게 하려면, 그림의 크기를 압축하면 만족할 수 있다.이후의 수요에 따라 먼저 그림의 질을 압축할 수 있다. 만약에 지정한 크기보다 작으면 뚜렷한 그림을 얻을 수 있고 그렇지 않으면 그림의 사이즈를 압축할 수 있다.
+ (UIImage *)compressImage:(UIImage *)image toByte:(NSUInteger)maxLength {
    // Compress by quality
    CGFloat compression = 1;
    NSData *data = UIImageJPEGRepresentation(image, compression);
    if (data.length < maxLength) return image;
    
    CGFloat max = 1;
    CGFloat min = 0;
    for (int i = 0; i < 6; ++i) {
        compression = (max + min) / 2;
        data = UIImageJPEGRepresentation(image, compression);
        if (data.length < maxLength * 0.9) {
            min = compression;
        } else if (data.length > maxLength) {
            max = compression;
        } else {
            break;
        }
    }
    UIImage *resultImage = [UIImage imageWithData:data];
    if (data.length < maxLength) return resultImage;
    
    // Compress by size
    NSUInteger lastDataLength = 0;
    while (data.length > maxLength && data.length != lastDataLength) {
        lastDataLength = data.length;
        CGFloat ratio = (CGFloat)maxLength / data.length;
        CGSize size = CGSizeMake((NSUInteger)(resultImage.size.width * sqrtf(ratio)),
                                 (NSUInteger)(resultImage.size.height * sqrtf(ratio))); // Use NSUInteger to prevent white blank
        UIGraphicsBeginImageContext(size);
        [resultImage drawInRect:CGRectMake(0, 0, size.width, size.height)];
        resultImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        data = UIImageJPEGRepresentation(resultImage, compression);
    }
    
    return resultImage;
}

좋은 웹페이지 즐겨찾기