Write text on image in objective-c iPhone, Font size of simulator different from on iPhone itself - objective-c

I'm having something really weird going, I'm adding caption to an image and everything works fine on simulator but on the device itself the font is really small...
I have a problem when using this code :
-(UIImage*) drawTextOnPic:(NSString*) bottomText
inImage:(UIImage*) image
{
UIFont *font = [UIFont boldSystemFontOfSize:48];
UIGraphicsBeginImageContext(image.size);
[image drawInRect:CGRectMake(0,0,image.size.width,image.size.height)];
CGRect = CGRectMake(10.0f,10.0f,image.size.width-20.0f, image.size.height);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetShadow(context, CGSizeMake(2.5f, 2.5f), 5.0f);
[[UIColor whiteColor] set];
[bottomText drawInRect:CGRectIntegral(rect) withFont:font lineBreakMode:UILineBreakModeClip alignment:UITextAlignmentCenter];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Does someone know why it works only on simulator as I expected? BTW, I'm using the SDK for iOS6, Can it be something there?
Is it something with the retina display? How to fix that?

When you call UIGraphicsBeginImageContext, you should be using the extended call to pass in screen scale, like this:
UIGraphicsBeginImageContextWithOptions(image.size, YES, [[UIScreen mainScreen] scale]);
That will create the image context at the scale of your screen. Note that the second argument, here YES, is whether or not you need the image to be opaque. If there's transparency in your image, set this to NO.

I choose the default font size (on my case it's 48) and then checked the image size according to some ref size (in my case 640x480), I did that by sqrtf(area(a)/area(ref)) then multiply this result on font size.
That's the only way it works for me.
Hope that would help others...

// Drawing text on image
+ (UIImage*) drawText:(NSString*)text withColor:(UIColor *) textColor inImage:(UIImage*)image atPoint:(CGPoint)point {
UIFont *font = [UIFont boldSystemFontOfSize:12];
UIGraphicsBeginImageContext(image.size);
[image drawInRect:CGRectMake(0,0,image.size.width,image.size.height)];
CGRect rect = CGRectMake(point.x, point.y, image.size.width, image.size.height);
[textColor set];
[text drawInRect:CGRectIntegral(rect) withFont:font];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}

Related

UIImageView cropped being displayed wrong on device

I have an image and i am cropping part of it. The problem is that in the simulator it is displayed correctly, but on the device it is much more zoomed in. It's quite a bit difference. What am i doing wrong? (first image is from the simulator and second from the iphone device)
// create bounds and initialise default image
CGRect imageSizeRectangle = CGRectMake(0, 0, 300, 300);
UIImage *df_Image = [UIImage imageNamed:#"no_selection.png"];
self.imageView = [[UIImageView alloc] initWithFrame:imageSizeRectangle];
[imageView setImage:df_Image];
[self.view addSubview:imageView];
//crop image
CGRect test = CGRectMake(0, 0, 150,150);
CGImageRef imageRef = CGImageCreateWithImageInRect([photo.image CGImage], test);
UIImage *croppedImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
The problem here is that retina devices are 2x the size of normal devices. You could check if the device is retina or not with the following method;
+(BOOL)iPhoneRetina{
return ([[UIScreen mainScreen] respondsToSelector:#selector(displayLinkWithTarget:selector:)] && ([UIScreen mainScreen].scale == 2.0))?1:0;
}
And increase/decrease the size of your rect according to the BOOL value returned.
Note* displayLinkWithTarget:selector: is just a random method that works in iOS 4.0+ but not previous versions. You don't need to pay much attention to it.
Edit*
CGRect rect;
if([self iPhoneRetina]){rect = CGRectMake(0,0,300,300);}//Retina
else{rect = CGRectMake(0,0,150,150);}//Non retina
//Then the rest of your code
if you want to simplize your code you may use
CGRectMake(0,0,[UIScreen mainScreen].scale*150,[UIScreen mainScreen].scale*150)

Screenshot/Snapshot from mapView stores a blank Map

I want to take a screenshot of a MapView and save to photos
This is the used source:
- (IBAction)screenshot:(id)sender {
if ([[UIScreen mainScreen] respondsToSelector:#selector(scale)])
UIGraphicsBeginImageContextWithOptions(mapView.frame.size, NO, [UIScreen mainScreen].scale);
else
UIGraphicsBeginImageContext(mapView.frame.size);
[mapView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageWriteToSavedPhotosAlbum(viewImage, nil, nil, nil);
}
The action is successful, but the photo looks like this here
MapView Screenshot
I do not know what is wrong. I've already tried some codes. All with the same result. If I make a screenshot of the entire view, the map also looks like the picture above.
Does anyone have any idea or can help me?
EDIT:
- (UIImage*) ImageFromMapView
{
UIGraphicsBeginImageContext(self.frame.size);
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
//[[[yourmapView.layer sublayers] objectAtIndex:1] renderInContext:UIGraphicsGetCurrentContext()]; try this upper fails
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
Try using UIGraphicsBeginImageContextWithOptions instead of UIGraphicsBeginImageContext:
UIGraphicsBeginImageContextWithOptions(self.frame.size, NO, 0.0);
Note: Starting from iOS 4, UIGraphicsBeginImageContextWithOptions allows you to provide with a scale factor. A scale factor of zero sets it to the scale factor of the device's main screen. This enables you to get the sharpest, highest-resolustion snapshot of the display, including a Retina Display.

iPhone4 iOS take screenshot of the view without NavBar and TabBar?

I got this code to be able to take a screenshot of the view.
UIGraphicsBeginImageContext(scrollView.bounds.size);
[scrollView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData * data = UIImagePNGRepresentation(image);
However, even if I set the context to be 320x480, parts of the scroll view are still not shown. The view that the scrollview manages can perfectly fit within the 320x480 frame, but parts of it are covered by the status bar, navBar and TabBar.
I would like to take full screen (320x480) screenshot of the view with the parts of the view, covered by status bar, TabBar and NavBar visible. Any pointers on how to do this?
An extra question, which may be related: the resulting image is using x1 scale, and looks very blurry on the retina display, which scales takes a larger image and scales it down. This means I'll need to render the 640x960 screenshot to reproduce the original crisp quality. How would I go about doing that?
Thank you!
I found the following on this site: http://www.icodeblog.com/2009/07/27/1188/
UIGraphicsBeginImageContext(YourView.frame.size);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageWriteToSavedPhotosAlbum(viewImage, nil, nil, nil);
You may also want to check out this (Apple's example of how to make a screenshot): http://developer.apple.com/library/ios/#qa/qa1703/_index.html
First make a screenshot of the whole screen:
// Create a graphics context with the target size
// On iOS 4 and later, use UIGraphicsBeginImageContextWithOptions to take the scale into consideration
// On iOS prior to 4, fall back to use UIGraphicsBeginImageContext
CGSize imageSize = [[UIScreen mainScreen] bounds].size;
if (NULL != UIGraphicsBeginImageContextWithOptions)
UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0.0);
else
UIGraphicsBeginImageContext(imageSize);
CGContextRef context = UIGraphicsGetCurrentContext();
// Iterate over every window from back to front
for (UIWindow *window in [[UIApplication sharedApplication] windows])
{
if (![window respondsToSelector:#selector(screen)] || [window screen] == [UIScreen mainScreen])
{
// -renderInContext: renders in the coordinate space of the layer,
// so we must first apply the layer's geometry to the graphics context
CGContextSaveGState(context);
// Center the context around the window's anchor point
CGContextTranslateCTM(context, [window center].x, [window center].y);
// Apply the window's transform about the anchor point
CGContextConcatCTM(context, [window transform]);
// Offset by the portion of the bounds left of and above the anchor point
CGContextTranslateCTM(context,
-[window bounds].size.width * [[window layer] anchorPoint].x,
-[window bounds].size.height * [[window layer] anchorPoint].y);
// Render the layer hierarchy to the current context
[[window layer] renderInContext:context];
// Restore the context
CGContextRestoreGState(context);
}
}
// Retrieve the screenshot image
UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext();
Then crop it to the right size
CGImageRef subImageRef = CGImageCreateWithImageInRect(screenshot.CGImage, rect);
CGRect smallBounds = CGRectMake(0, 64, 320, 372); //You should remove the hard coded numbers
UIGraphicsBeginImageContext(smallBounds.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextDrawImage(context, smallBounds, subImageRef);
UIImage* cropped = [UIImage imageWithCGImage:subImageRef];
UIGraphicsEndImageContext();

Image Cropping API for iOS

Is there any cropping image API for objective C that crops images dynamically in Xcode project? Please provide some tricks or techniques how could I crop camera images in iPhone.
You can use below simple code to crop an image. You have to pass the image and the CGRect which is the cropping area. Here, I crop image so that I get center part of original image and returned image is square.
// Returns largest possible centered cropped image.
- (UIImage *)centerCropImage:(UIImage *)image
{
// Use smallest side length as crop square length
CGFloat squareLength = MIN(image.size.width, image.size.height);
// Center the crop area
CGRect clippedRect = CGRectMake((image.size.width - squareLength) / 2, (image.size.height - squareLength) / 2, squareLength, squareLength);
// Crop logic
CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], clippedRect);
UIImage * croppedImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
return croppedImage;
}
EDIT - Swift Version
let imageView = UIImageView(image: image)
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
All these solutions seem quite complicated and many of them actually degrade the quality the image.
You can do much simpler using UIImageView's out of the box methods.
Objective-C
self.imageView.contentMode = UIViewContentModeScaleAspectFill;
[self.imageView setClipsToBounds:YES];
[self.imageView setImage:img];
This will crop your image based on the dimensions you've set for your UIImageView (I've called mine imageView here).
It's that simple and works much better than the other solutions.
You can use CoreGraphics framework to cropping image dynamically.
Here is a example code part of dynamic image crop. I hope this will be helpful for you.
- (void)drawMaskLineSegmentTo:(CGPoint)ptTo withMaskWidth:(CGFloat)maskWidth inContext:(NXMaskDrawContext)context{
if (context == nil)
return;
if (context.count <= 0){
[context addObject:[NSValue valueWithCGPoint:ptTo]];
return;
}
CGPoint ptFrom = [context.lastObject CGPointValue];
UIGraphicsBeginImageContext(self.maskImage.size);
[self.maskImage drawInRect:CGRectMake(0, 0, self.maskImage.size.width, self.maskImage.size.height)];
CGContextRef graphicsContext = UIGraphicsGetCurrentContext();
CGContextSetBlendMode(graphicsContext, kCGBlendModeCopy);
CGContextSetRGBStrokeColor(graphicsContext, 1, 1, 1, 1);
CGContextSetLineWidth(graphicsContext, maskWidth);
CGContextSetLineCap(graphicsContext, kCGLineCapRound);
CGContextMoveToPoint(graphicsContext, ptFrom.x, ptFrom.y);
CGContextAddLineToPoint(graphicsContext, ptTo.x, ptTo.y);
CGContextStrokePath(graphicsContext);
self.maskImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIGraphicsBeginImageContext(self.displayableMaskImage.size);
[self.displayableMaskImage drawInRect:CGRectMake(0, 0, self.displayableMaskImage.size.width, self.displayableMaskImage.size.height)];
graphicsContext = UIGraphicsGetCurrentContext();
CGContextSetBlendMode(graphicsContext, kCGBlendModeCopy);
CGContextSetStrokeColorWithColor(graphicsContext, self.displayableMaskColor.CGColor);
CGContextSetLineWidth(graphicsContext, maskWidth);
CGContextSetLineCap(graphicsContext, kCGLineCapRound);
CGContextMoveToPoint(graphicsContext, ptFrom.x, ptFrom.y);
CGContextAddLineToPoint(graphicsContext, ptTo.x, ptTo.y);
CGContextStrokePath(graphicsContext);
self.displayableMaskImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[context addObject:[NSValue valueWithCGPoint:ptTo]];
}
Xcode 5, iOS 7, and 4-inch screen example: Here is an open source example of a
SimpleImageCropEditor (Project Zip and Source Code Example. You can load the Image Crop Editor as a Modal View Controller and reuse. Look at the code and please leave constructive comments concerning if this example code answers the question "Image Cropping API for iOS".
Demonstrates, is example source Objective-C code, use of UIImagePickerController, #protocol, UIActionSheet, UIScrollView, UINavigationController, MFMailComposeViewController, and UIGestureRecognizer.

UITableViewCell's imageView fit to 40x40

I use the same big images in a tableView and detailView.
Need to make imageView filled in 40x40 when an imags is showed in tableView, but stretched on a half of a screen. I played with several properties but have no positive result:
[cell.imageView setBounds:CGRectMake(0, 0, 50, 50)];
[cell.imageView setClipsToBounds:NO];
[cell.imageView setFrame:CGRectMake(0, 0, 50, 50)];
[cell.imageView setContentMode:UIViewContentModeScaleAspectFill];
I am using SDK 3.0 with build in "Cell Objects in Predefined Styles".
I put Ben's code as an extension in my NS-Extensions file so that I can tell any image to make a thumbnail of itself, as in:
UIImage *bigImage = [UIImage imageNamed:#"yourImage.png"];
UIImage *thumb = [bigImage makeThumbnailOfSize:CGSizeMake(50,50)];
Here is .h file:
#interface UIImage (PhoenixMaster)
- (UIImage *) makeThumbnailOfSize:(CGSize)size;
#end
and then in the NS-Extensions.m file:
#implementation UIImage (PhoenixMaster)
- (UIImage *) makeThumbnailOfSize:(CGSize)size
{
UIGraphicsBeginImageContextWithOptions(size, NO, UIScreen.mainScreen.scale);
// draw scaled image into thumbnail context
[self drawInRect:CGRectMake(0, 0, size.width, size.height)];
UIImage *newThumbnail = UIGraphicsGetImageFromCurrentImageContext();
// pop the context
UIGraphicsEndImageContext();
if(newThumbnail == nil)
NSLog(#"could not scale image");
return newThumbnail;
}
#end
I cache a thumbnail version since using large images scaled down on the fly uses too much memory.
Here's my thumbnail code:
- (UIImage *)thumbnailOfSize:(CGSize)size {
if( self.previewThumbnail )
return self.previewThumbnail; // returned cached thumbnail
UIGraphicsBeginImageContext(size);
// draw scaled image into thumbnail context
[self.preview drawInRect:CGRectMake(0, 0, size.width, size.height)];
UIImage *newThumbnail = UIGraphicsGetImageFromCurrentImageContext();
// pop the context
UIGraphicsEndImageContext();
if(newThumbnail == nil)
NSLog(#"could not scale image");
self.previewThumbnail = newThumbnail;
return self.previewThumbnail;
}
Just make sure you properly clear the cached thumbnail if you change your original image (self.preview in my case).
I have mine wrapped in a UIView and use this code:
imageView.contentMode = UIViewContentModeScaleAspectFit;
imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth |UIViewAutoresizingFlexibleHeight;
[self addSubview:imageView];
imageView.frame = self.bounds;
(self is the wrapper UIView, with the dimensions I want - I use AsyncImageView).
I thought Ben Lachman's suggestion of generating thumbnails in advance rather than on the fly was smart, so I adapted his code so it could handle a whole array and to make it more portable (no hard-coded property names).
- (NSArray *)arrayOfThumbnailsOfSize:(CGSize)size fromArray:(NSArray*)original {
NSMutableArray *temp = [NSMutableArray arrayWithCapacity:[original count]];
for(UIImage *image in original){
UIGraphicsBeginImageContext(size);
[image drawInRect:CGRectMake(0,0,size.width,size.height)];
UIImage *thumb = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[temp addObject:thumb];
}
return [NSArray arrayWithArray:temp];
}
you might be able to use this?
yourTableViewController.rowImage = [UIImage imageNamed:#"yourImage.png"];
and/or
cell.image = yourTableViewController.rowImage;
and if your images are already 40x40 then you shouldn't have to worry about setting bounds and stuff... but, i'm also new to this, so, i wouldn't know, haven't played around with Table View row/cell images much
hope this helps.
I was able to make this work using interface builder and a tableviewcell. You can set the "Mode" properties for an image view to "Aspect Fit". I'm not sure how to do this programatically.
Try setting UIImageView.autoresizesSubviews and/or UIImageView.contentStretch.