Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Programmatically create image from UILabel

I want to use a UILabel to create an RGBA stream of bytes image representation programmatically (at runtime).

For example, I want to create a UILabel in a specific font and with specific text, turn this in to an NSData of RGBA unsigned bytes, and then from that point I can easily turn it in to an OpenGL texture and display it however I want.

It's important that I can know the dimensions of the resulting image, although if absolutely necessary I can create a very wide "blank" canvas to render this in to, and then at runtime detect the width and height myself by checking the bytes.

If I can achieve this through UIImage/CG it's a definite plus - and a solution with multiple render targets isn't reasonable/desired.

Edit: Placed a bounty; I had originally gotten this good-looking answer below from meronix, but now I got time to try it out and it does not work properly. I need this working "yesterday" and am quite frustrated. There's some nuance here, that someone who knows Cocoa drawing state better than me can surely catch.

like image 260
Nektarios Avatar asked Apr 02 '11 05:04

Nektarios


2 Answers

You can "capture" (take a snapShot of) your UILabel, it's a subclass of UIView, so you can get its image.

use this class "CaptureView":

CaptureView.h

#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#import <QuartzCore/CALayer.h>


@interface CaptureView : UIView {
@private
    UIImage *_imageCapture;
}

@property(nonatomic, retain) UIImage *imageCapture;

// Init
- (id)initWithView:(UIView *)view;

@end

CaptureView.m

#import "CaptureView.h"

// Private
@interface CaptureView (/* Private */)
- (void)settingImageFromView:(UIView *)view;
@end

// Public
@implementation CaptureView

@synthesize imageCapture = _imageCapture;

// Standard // UILabel
- (id)initWithFrame:(CGRect)frame {

    if ((self = [super initWithFrame:frame])) {
        // Initialization code.
    }
    return self;
}

// Init
- (id)initWithView:(UIView *)view {
    if ((self = [super initWithFrame:[view frame]])) {
//  if ((self = [super initWithFrame: CGRectMake(0, 0, 100, 100)])) {
        // Initialization code.
        [self settingImageFromView:view];
    }
    return self;  
}

/*!
 @method     imageFromView:view
 @abstract   Esegue una Grab di una intera view
 @discussion Imposta l'immagine catturata eseguendo una copia dell'intera view 
 */
- (void)settingImageFromView:(UIView *)view {
    CGRect rect = [view bounds];  
 //   CGRect rect = CGRectMake(20, 30, 100, 100);  
    UIGraphicsBeginImageContext(rect.size);  
    CGContextRef context = UIGraphicsGetCurrentContext();  
    [view.layer renderInContext:context];  
    UIImage *imageCaptureRect;

    imageCaptureRect = UIGraphicsGetImageFromCurrentImageContext();  
    _imageCapture = imageCaptureRect;
//    _imageCapture = UIGraphicsGetImageFromCurrentImageContext();  
//    [_imageCapture retain];
    UIGraphicsEndImageContext();   
}


// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // Drawing code.
    CGPoint accPoint = CGPointMake(0,0);
    [_imageCapture drawAtPoint:accPoint];
}


- (void)dealloc {
    [_imageCapture release];
    [super dealloc];
}

@end

so just initiate it passing your UILabel to it, so you'll get a Class with the UIImage *imageCapture property, so just get it and use it...

// in your class which wanna manage the captured image:
// in .h : #import "CaptureView.h"
CaptureView *cloneView = [[CaptureView alloc] initWithView:aUILabel];
//  [yourUIView addSubview:cloneView]; // eventually, to see it...
UIImage *myCapt = cloneView.imageCapture;
// ... your code to use myCapt
[cloneView release];

EDIT:

download this project:

http://meronix.altervista.org/captureUILabel.zip

the centered black-backGround text is a capture (an instance of the class: CaptureView) of the Gray-BackGround text (a UILabel) on top

like image 72
meronix Avatar answered Oct 02 '22 16:10

meronix


This should work:

UIGraphicsBeginImageContext(yourLabel.bounds.size);
[yourLabel.layer renderInContext:UIGraphicsGetCurrentContext()];
CGImageRef viewImage = [UIGraphicsGetImageFromCurrentImageContext() CGImage];
UIGraphicsEndImageContext();

UIGraphicsGetImageFromCurrentImageContext() returns an instance of UIImage.

like image 20
Alessandro Vendruscolo Avatar answered Oct 02 '22 16:10

Alessandro Vendruscolo