zoukankan      html  css  js  c++  java
  • iOS 史上最全的图片压缩方法集合

      做上传图片功能,特别是类似于微信,QQ里面,公布9张图片, 少不了碰到一个问题,就是图片压缩问题,当然我也遇到了.

    我研究了这个问题,发现网上普遍的方法是例如以下

    1. //压缩图片质量  
    2. +(UIImage *)reduceImage:(UIImage *)image percent:(float)percent  
    3. {  
    4.     NSData *imageData = UIImageJPEGRepresentation(image, percent);  
    5.     UIImage *newImage = [UIImage imageWithData:imageData];  
    6.     return newImage;  
    7. }  
    8. //压缩图片尺寸  
    9. + (UIImage*)imageWithImageSimple:(UIImage*)image scaledToSize:(CGSize)newSize  
    10. {  
    11.     // Create a graphics image context  
    12.     UIGraphicsBeginImageContext(newSize);  
    13.     // new size  
    14.     [image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];  
    15.     // Get the new image from the context  
    16.     UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();  
    17.       
    18.     // End the context  
    19.     UIGraphicsEndImageContext();  
    20.     // Return the new image.  
    21.     return newImage;  
    22. }  
    上面的方法比較常见,但是须要载入到内存中来处理图片,当图片数量多了的时候就会收到内存警告,程序崩溃,

    我測试过上面方法,上面方法真不好用,真的不推荐大家用.那么我推荐以下这种方法:

    1. static size_t getAssetBytesCallback(voidvoid *info, voidvoid *buffer, off_t position, size_t count) {  
    2.     ALAssetRepresentation *rep = (__bridge id)info;  
    3.       
    4.     NSError *error = nil;  
    5.     size_t countRead = [rep getBytes:(uint8_t *)buffer fromOffset:position length:count error:&error];  
    6.       
    7.     if (countRead == 0 && error) {  
    8.         // We have no way of passing this info back to the caller, so we log it, at least.  
    9.         NDDebug(@"thumbnailForAsset:maxPixelSize: got an error reading an asset: %@", error);  
    10.     }  
    11.       
    12.     return countRead;  
    13. }  
    14.   
    15. static void releaseAssetCallback(voidvoid *info) {  
    16.     // The info here is an ALAssetRepresentation which we CFRetain in thumbnailForAsset:maxPixelSize:.  
    17.     // This release balances that retain.  
    18.     CFRelease(info);  
    19. }  
    20.   
    21. // Returns a UIImage for the given asset, with size length at most the passed size.  
    22. // The resulting UIImage will be already rotated to UIImageOrientationUp, so its CGImageRef  
    23. // can be used directly without additional rotation handling.  
    24. // This is done synchronously, so you should call this method on a background queue/thread.  
    25. - (UIImage *)thumbnailForAsset:(ALAsset *)asset maxPixelSize:(NSUInteger)size {  
    26.     NSParameterAssert(asset != nil);  
    27.     NSParameterAssert(size > 0);  
    28.       
    29.     ALAssetRepresentation *rep = [asset defaultRepresentation];  
    30.       
    31.     CGDataProviderDirectCallbacks callbacks = {  
    32.         .version = 0,  
    33.         .getBytePointer = NULL,  
    34.         .releaseBytePointer = NULL,  
    35.         .getBytesAtPosition = getAssetBytesCallback,  
    36.         .releaseInfo = releaseAssetCallback,  
    37.     };  
    38.       
    39.     CGDataProviderRef provider = CGDataProviderCreateDirect((voidvoid *)CFBridgingRetain(rep), [rep size], &callbacks);  
    40.     CGImageSourceRef source = CGImageSourceCreateWithDataProvider(provider, NULL);  
    41.       
    42.     CGImageRef imageRef = CGImageSourceCreateThumbnailAtIndex(source, 0, (__bridge CFDictionaryRef) @{  
    43.                                                                                                       (NSString *)kCGImageSourceCreateThumbnailFromImageAlways : @YES,  
    44.                                                                                                       (NSString *)kCGImageSourceThumbnailMaxPixelSize : [NSNumber numberWithInt:size],  
    45.                                                                                                       (NSString *)kCGImageSourceCreateThumbnailWithTransform : @YES,  
    46.                                                                                                       });  
    47.     CFRelease(source);  
    48.     CFRelease(provider);  
    49.       
    50.     if (!imageRef) {  
    51.         return nil;  
    52.     }  
    53.       
    54.     UIImage *toReturn = [UIImage imageWithCGImage:imageRef];  
    55.       
    56.     CFRelease(imageRef);  
    57.       
    58.     return toReturn;  
    59. }  

    採用上面的方法之后内存占用率非常低。

    上面这么长的东西,大家一定看的非常费劲,那么我直接上我源代码,给大家看看,照着我的源代码,写就好了.





    static size_t getAssetBytesCallback(void *info, void *buffer, off_t position, size_t count) {

        ALAssetRepresentation *rep = (__bridge id)info;

        

        NSError *error = nil;

        size_t countRead = [rep getBytes:(uint8_t *)buffer fromOffset:position length:count error:&error];

        

        if (countRead == 0 && error) {

            // We have no way of passing this info back to the caller, so we log it, at least.

            NSLog(@"thumbnailForAsset:maxPixelSize: got an error reading an asset: %@", error);

        }

        

        return countRead;

    }

    static void releaseAssetCallback(void *info) {

        // The info here is an ALAssetRepresentation which we CFRetain in thumbnailForAsset:maxPixelSize:.

        // This release balances that retain.

        CFRelease(info);

    }


    //压缩图片

    - (UIImage *)thumbnailForAsset:(ALAsset *)asset maxPixelSize:(NSUInteger)size

    {

        NSParameterAssert(asset != nil);

        NSParameterAssert(size > 0);

        

        ALAssetRepresentation *rep = [asset defaultRepresentation];

        

        CGDataProviderDirectCallbacks callbacks =

        {

            .version = 0,

            .getBytePointer = NULL,

            .releaseBytePointer = NULL,

            .getBytesAtPosition = getAssetBytesCallback,

            .releaseInfo = releaseAssetCallback,

        };

        

        CGDataProviderRef provider = CGDataProviderCreateDirect((void *)CFBridgingRetain(rep), [rep size], &callbacks);

        

        CGImageSourceRef source = CGImageSourceCreateWithDataProvider(provider, NULL);

        

        CGImageRef imageRef = CGImageSourceCreateThumbnailAtIndex(source, 0, (__bridge CFDictionaryRef)

                                                                  @{   (NSString *)kCGImageSourceCreateThumbnailFromImageAlways@YES,

                                                                       (NSString *)kCGImageSourceThumbnailMaxPixelSize : [NSNumber numberWithInt:size],

                                                                       (NSString *)kCGImageSourceCreateThumbnailWithTransform :@YES,

                                                                       });

        

        CFRelease(source);

        CFRelease(provider);

        

        if (!imageRef) {

            return nil;

        }

        

        UIImage *toReturn = [UIImage imageWithCGImage:imageRef];

        

        CFRelease(imageRef);

        

        return toReturn;

    }

    把上面的代码拷贝到project里面,然后调用这种方法就好了,例如以下图:


    好了,有问题,欢迎评论给我.....

    本文部分内容參考自http://www.lyitnews.com/portal.php?mod=view&aid=1206,感谢他的分享....


  • 相关阅读:
    出差常熟,郁闷中 沧海
    ABAP中程序之间传递参数的办法 沧海
    LSMW中出现No logical path specified. 沧海
    请认真对待生活 沧海
    escape sequence 沧海
    休假一周 沧海
    Print Program and Form Modify 沧海
    下周回南京 沧海
    LO020真麻烦 沧海
    函数讲解函数列表(ZT) 沧海
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/5114382.html
Copyright © 2011-2022 走看看