From 9d52266f823daf5cb83e3eebe1b9f57594bc9d4a Mon Sep 17 00:00:00 2001 From: matt handler Date: Wed, 20 Apr 2011 14:39:20 -0400 Subject: first commit --- Classes/AsyncImageView.m | 144 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 Classes/AsyncImageView.m (limited to 'Classes/AsyncImageView.m') diff --git a/Classes/AsyncImageView.m b/Classes/AsyncImageView.m new file mode 100644 index 0000000..d978e82 --- /dev/null +++ b/Classes/AsyncImageView.m @@ -0,0 +1,144 @@ +// +// AsyncImageView.m +// Postcard +// +// Created by markj on 2/18/09. +// Copyright 2009 Mark Johnson. You have permission to copy parts of this code into your own projects for any use. +// www.markj.net +// + +#import "AsyncImageView.h" + +@interface UIImage (Extras) + +- (UIImage*)imageByScalingAndCroppingForSize:(CGSize)targetSize; + +@end + +@implementation UIImage (Extras) + +#pragma mark - +#pragma mark Scale and crop image + +- (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 + + +// This class demonstrates how the URL loading system can be used to make a UIView subclass +// that can download and display an image asynchronously so that the app doesn't block or freeze +// while the image is downloading. It works fine in a UITableView or other cases where there +// are multiple images being downloaded and displayed all at the same time. + +@implementation AsyncImageView + +- (void)dealloc { + [connection cancel]; //in case the URL is still downloading + [connection release]; + [data release]; + [super dealloc]; +} + + +- (void)loadImageFromURL:(NSURL*)url { + NSLog(@"%@",url); + if (connection!=nil) { [connection release]; } //in case we are downloading a 2nd image + if (data!=nil) { [data release]; } + + NSURLRequest* request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0]; + connection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; //notice how delegate set to self object + //TODO error handling, what if connection is nil? +} + + +//the URL connection calls this repeatedly as data arrives +- (void)connection:(NSURLConnection *)theConnection didReceiveData:(NSData *)incrementalData { + if (data==nil) { data = [[NSMutableData alloc] initWithCapacity:2048]; } + [data appendData:incrementalData]; +} + +//the URL connection calls this once all the data has downloaded +- (void)connectionDidFinishLoading:(NSURLConnection*)theConnection { + //so self data now has the complete image + [connection release]; + connection=nil; + if ([[self subviews] count]>0) { + //then this must be another image, the old one is still in subviews + [[[self subviews] objectAtIndex:0] removeFromSuperview]; //so remove it (releases it also) + } + + //make an image view for the image + UIImageView* imageView = [[[UIImageView alloc] initWithImage:[[UIImage imageWithData:data] imageByScalingAndCroppingForSize:CGSizeMake(100,100)]] autorelease]; + //make sizing choices based on your needs, experiment with these. maybe not all the calls below are needed. + imageView.contentMode = UIViewContentModeScaleAspectFill; + imageView.autoresizingMask = ( UIViewAutoresizingFlexibleWidth || UIViewAutoresizingFlexibleHeight ); + [self addSubview:imageView]; + imageView.frame = self.bounds; + [imageView setNeedsLayout]; + [self setNeedsLayout]; + + [data release]; //don't need this any more, its in the UIImageView now + data=nil; +} + +//just in case you want to get the image directly, here it is in subviews +- (UIImage*) image { + UIImageView* iv = [[self subviews] objectAtIndex:0]; + return [iv image]; +} + +@end -- cgit v1.2.3