图片压缩问题

来源:互联网 发布:虚拟机ubuntu无法联网 编辑:程序博客网 时间:2024/05/22 02:30

最近做论坛功能,发帖的时候需要用到从相册中选取图片然后上传,由于每次上传图片的最大数量为9张,所以需要对图片进行压缩。开始时用了以前经常用的压缩的方法:

[objc] view plain copy

//压缩图片质量

+(UIImage *)reduceImage:(UIImage *)image percent:(float)percent

{

    NSData *imageData = UIImageJPEGRepresentation(image, percent);

    UIImage *newImage = [UIImage imageWithData:imageData];

    return newImage;

}

//压缩成指定大小

+ (UIImage*)imageWithImageSimple:(UIImage*)image scaledToSize:(CGSize)newSize

{

    // Create a graphics image context

    UIGraphicsBeginImageContext(newSize);

    // new size

    [image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];

    // Get the new image from the context

    UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();

    

    // End the context

    UIGraphicsEndImageContext();

    // Return the new image.

    return newImage;

}

//等比压缩

- (UIImage*)imageByScalingAndCroppingForSize:(CGSize)targetSize

{

    UIImage *sourceImage = self;

    UIImage *newImage = nil;

    CGSize imageSize = sourceImage.size;

    CGFloat width = imageSize.width;

    CGFloat height = imageSize.height;

    CGFloat targetWidth = targetSize.width;

    CGFloat targetHeight = targetSize.height;

    CGFloat scaleFactor = 0.0;

    CGFloat scaledWidth = targetWidth;

    CGFloat scaledHeight = targetHeight;

    CGPoint thumbnailPoint = CGPointMake(0.0,0.0);

    

    if (CGSizeEqualToSize(imageSize, targetSize) ==NO)

    {

        CGFloat widthFactor = targetWidth / width;

        CGFloat heightFactor = targetHeight / height;

        

        if (widthFactor > heightFactor)

            scaleFactor = widthFactor; // scale to fit height

        else

            scaleFactor = heightFactor; // scale to fit width

        scaledWidth  = width * scaleFactor;

        scaledHeight = height * scaleFactor;

        

        // center the image

        if (widthFactor > heightFactor)

        {

            thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5;

        }

        else

            if (widthFactor < heightFactor)

            {

                thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;

            }

    }

    

    UIGraphicsBeginImageContext(targetSize); // this will crop

    

    CGRect thumbnailRect = CGRectZero;

    thumbnailRect.origin = thumbnailPoint;

    thumbnailRect.size.width  = scaledWidth;

    thumbnailRect.size.height = scaledHeight;

    

    [sourceImage drawInRect:thumbnailRect];

    

    newImage = UIGraphicsGetImageFromCurrentImageContext();

    if(newImage ==nil)

        NSLog(@"could not scale image");

        

        //pop the context to get back to the default

        UIGraphicsEndImageContext();

        return newImage;

}


@end



上面的方法比较常见,可是需要加载到内存中来处理图片,当图片数量多了的时候就会收到内存警告,程序崩溃。研究半天终于在一篇博客中找到了解决方法:

[objc] view plain copy

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

    ALAssetRepresentation *rep = (__bridgeid)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.

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

    }

    

    return countRead;

}


static void releaseAssetCallback(voidvoid *info) {

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

    // This release balances that retain.

    CFRelease(info);

}


// Returns a UIImage for the given asset, with size length at most the passed size.

// The resulting UIImage will be already rotated to UIImageOrientationUp, so its CGImageRef

// can be used directly without additional rotation handling.

// This is done synchronously, so you should call this method on a background queue/thread.

- (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((voidvoid *)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) {

        returnnil;

    }

    

    UIImage *toReturn = [UIImage imageWithCGImage:imageRef];

    

    CFRelease(imageRef);

    

    return toReturn;

}


采用上面的方法之后内存占用率很低!


0 0
原创粉丝点击