Showing posts with label UIImage. Show all posts
Showing posts with label UIImage. Show all posts

Monday, November 29, 2010

Drawing Part of a UIImage

Happy Thanksgiving, and sorry for the relative lack of posts here lately. Things are crazier than ever and it's been a challenge finding time to shower, let alone blog.

I do have something to share, today, though. No, it's not the next chapter of OpenGL ES 2.0 for iOS. It's a category that some of you may find useful: a method that allows you to draw only part of a UIImage rather than the entire thing.

On the Mac, NSImage has a handy instance method called drawInRect:fromRect:operation:fraction: that lets you specify exactly which part of an image to draw. On UIImage, we've only got the ability to draw the entire image either unless we drop down to Core Graphics calls. We don't have a nice, easy, convenient way using just UIImage to draw a portion of the image it represents.

I needed this ability in an application I'm working on, so I hacked out the following category. At first glance, this may look to be inefficient, since we're making a copy of the instance's backing CGImage in order to create the sub-image, however I believe that CGImageCreateWithImageInRect() references the original image's bitmap data. I haven't confirmed that it doesn't make a copy of the bitmap data, but the documentation certainly seems to imply it. Anyone know?

Anyway, here is the category; I've even commented the code more pedantically than is normal for me in case anyone might be confused about what's going on. Improvements and bug fixes are, as always, welcome.

@implementation UIImage(MCDrawSubImage)
- (void)drawInRect:(CGRect)drawRect fromRect:(CGRect)fromRect blendMode:(CGBlendMode)blendMode alpha:(CGFloat)alpha
{
CGImageRef drawImage = CGImageCreateWithImageInRect(self.CGImage, fromRect);
if (drawImage != NULL)
{
CGContextRef context = UIGraphicsGetCurrentContext();

// Push current graphics state so we can restore later
CGContextSaveGState(context);

// Set the alpha and blend based on passed in settings
CGContextSetBlendMode(context, blendMode);
CGContextSetAlpha(context, alpha);

// Take care of Y-axis inversion problem by translating the context on the y axis
CGContextTranslateCTM(context, 0, drawRect.origin.y + fromRect.size.height);

// Scaling -1.0 on y-axis to flip
CGContextScaleCTM(context, 1.0, -1.0);

// Then accommodate the translate by adjusting the draw rect
drawRect.origin.y = 0.0f;

// Draw the image
CGContextDrawImage(context, drawRect, drawImage);

// Clean up memory and restore previous state
CGImageRelease(drawImage);

// Restore previous graphics state to what it was before we tweaked it
CGContextRestoreGState(context);
}

}

@end

Sunday, March 22, 2009

Image Processing on the iPhone

Chris Greening has started a project on Google Code containing classes to handle a number of common image processing tasks on UIImages. Having tried to work with the underlying bitmap data from UIImages before, I can say this is a very welcome bit of functionality. Great stuff.

Thursday, March 5, 2009

UIImage and NSCoding

Here is a category to conform UIImage to NSCoding so you can archive it. This is untested - I hacked this up a few minutes in response to a question posed on Twitter. Please let me know if it needs any corrections:

UIImage-NSCoding.h
//
// UIImage-NSCoding.h

#import <Foundation/Foundation.h>

@interface UIImageNSCoding <NSCoding>
- (id)initWithCoder:(NSCoder *)decoder;
- (void)encodeWithCoder:(NSCoder *)encoder;
@end



UIImage-NSCoding.m
//
// UIImage-NSCoding.m

#import "UIImage-NSCoding.h"
#define kEncodingKey @"UIImage"

@implementation UIImage(NSCoding)
- (id)initWithCoder:(NSCoder *)decoder
{
if ((self = [super init]))
{
NSData *data = [decoder decodeObjectForKey:kEncodingKey];
self = [self initWithData:data];
}


return self;
}

- (void)encodeWithCoder:(NSCoder *)encoder
{
NSData *data = UIImagePNGRepresentation(self);
[encoder encodeObject:data forKey:kEncodingKey];
}

@end



This is also checked into Google Code if you prefer to grab it from there.

Wednesday, October 22, 2008

Getting the contents of a UIView as a UIImage

In Cocoa, it's really easy to take the contents of an NSView and convert them to an NSImage using dataWithPDFInsideRect:. I needed to do the same task on the iPhone, so immediately looked for a comparable method. I didn't find one.

Thankfully, Google came to the rescue. Josh Goebel shows how to do it right here.

Note: To use this in your project, you'll have to link to the QuartzCore framework and also #import <QuartzCore/QuartzCore.h>