1.I use below code for take screenshot.is it necessary to change it for high resolution
UIGraphicsBeginImageContext(self.view.bounds.size);
[self.view.window.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
2.what does happen if i just use one image with 640*960 resolution for both low and high quality ? (means that don't use image with #2x)
That will only take normal (320x480) resolution screenshots. So in answer to 1, yes. Older generation devices can do double resolution too, the screen just can't display it.
To take a screenshot at the res of the device you can do this:
CGSize size = self.view.bounds.size;
CGFloat scale = 1.0f;
if ([[UIScreen mainScreen] respondsToSelector:#selector(scale)]) {
scale = [[UIScreen mainScreen] scale];
size = CGSizeApplyAffineTransform(size, CGAffineTransformMakeScale(scale, scale));
}
UIGraphicsBeginImageContext(size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextScaleCTM(context, scale, scale);
[self.view.layer renderInContext:context];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Taking double res on older devices does work, and will be scaled back down if displayed on screen. But is not recommended, and simply a waste.
Related
I have an application in which i am cropping the image taken from the camera.all are going well.but after the cropping the image seems to blured and streched.
CGRect rect = CGRectMake(20,40,280,200);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
// translated rectangle for drawing sub image
CGRect drawRect = CGRectMake(-rect.origin.x, -rect.origin.y,280,200);
// clip to the bounds of the image context
// not strictly necessary as it will get clipped anyway?
CGContextClipToRect(context, CGRectMake(0, 0, rect.size.width, rect.size.height));
// draw image
[image drawInRect:drawRect];
// grab image
UIImage* croppedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGSize size = [croppedImage size];
NSLog(#" = %#",NSStringFromCGSize(size));
NSData* pictureData = UIImagePNGRepresentation(croppedImage);
Can anybody help me in finding out where i am going wrong?
try replacing
UIGraphicsBeginImageContext(rect.size);
with
UIGraphicsBeginImageContextWithOptions(rect.size, NO, [[UIScreen mainScreen] scale]);
to account for retina
I am using the following code for capture a view on the screen but it is not as sharp as on the screen. the imageView size is 200x200point but the scale is 2.0 (with retina screen). The saved img size is 200x200 px. how could i make the img as sharp as the original one? Any help will be appreciated!
- (UIImage*)captureView:(UIView *)theView {
CGRect rect = theView.frame;
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
[theView.layer renderInContext:context];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
Try like that:
CGRect screenRect = [[UIScreen mainScreen] bounds];
UIGraphicsBeginImageContextWithOptions(screenRect.size, NO, 0.0);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
You are using the old way of creating the image context. Use this instead:
UIGraphicsBeginImageContextWithOptions(rect.size, YES, [UIScreen mainScreen].scale);
The older UIGraphicsBeginImageContext function always assumes a scale of 1.0.
Replace 'YES' with 'NO' if you need the alpha channel.
I make a picture with phone (640*480) and put it inside uiimageview (300*300) with scale to fill options set.
I need to send the same image that is displayed inside uiimageview (300*300, croped, resized) to server....
How can i get it?
There is a quick a dirty way to do this, by rendering the UIImageView layer to a graphics context.
UIGraphicsBeginImageContext(self.bounds.size);
[self.imageView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *resultingImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
you will need to import <QuartzCore/QuartzCore.h> for this.
The other way would be to do the calculations for AspectFill your self.
CGSize finalImageSize = CGSizeMake(300,300);
CGImageRef sourceImageRef = yourImage.CGImage;
CGFloat horizontalRatio = finalImageSize.width / CGImageGetWidth(sourceImageRef);
CGFloat verticalRatio = finalImageSize.height / CGImageGetHeight(sourceImageRef);
CGFloat ratio = MAX(horizontalRatio, verticalRatio); //AspectFill
CGSize aspectFillSize = CGSizeMake(CGImageGetWidth(sourceImageRef) * ratio, CGImageGetHeight(sourceImageRef) * ratio);
CGContextRef context = CGBitmapContextCreate(NULL,
finalImageSize.width,
finalImageSize.height,
CGImageGetBitsPerComponent(sourceImageRef),
0,
CGImageGetColorSpace(sourceImageRef),
CGImageGetBitmapInfo(sourceImageRef));
//Draw our image centered vertically and horizontally in our context.
CGContextDrawImage(context,
CGRectMake((finalImageSize.width-aspectFillSize.width)/2,
(finalImageSize.height-aspectFillSize.height)/2,
aspectFillSize.width,
aspectFillSize.height),
sourceImageRef);
//Start cleaning up..
CGImageRelease(sourceImageRef);
CGImageRef finalImageRef = CGBitmapContextCreateImage(context);
UIImage *finalImage = [UIImage imageWithCGImage:finalImageRef];
CGContextRelease(context);
CGImageRelease(finalImageRef);
return finalImage;
From the documentation:
UIViewContentModeScaleToFill
Scales the content to fit the size of itself by changing the aspect
ratio of the content if necessary.
You can do the maths. Or if you are feeling particularly lazy, there is this hack way.
I am merging two images and then I take a screenshot by applying this code:
UIGraphicsBeginImageContext(size);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
img_AddText=viewImage;
[dragView removeFromSuperview];
imgV_SelectedImg.image=nil;
imgV_SelectedImg.image=img_AddText;
UIImageWriteToSavedPhotosAlbum(viewImage, nil, nil, nil);
The problem is that when the final image loses its quality it blurs.
Try using the withOptions version of UIGraphicsBeginImageContext
UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);
i got the snapshot with good quality and particular location of screen. By this code.
-(UIImage *)takeScreenShot
{
CGRect grabRect;
grabRect = CGRectMake(0,70,320,260);
UIGraphicsBeginImageContextWithOptions(grabRect.size, self.view.opaque, 0.0);
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(ctx, -grabRect.origin.x, -grabRect.origin.y);
[self.view.layer renderInContext:ctx];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return viewImage;
}
it gives me excellent snapshot..
I've made a category on UIImage class that may help you. It goes like this:
+ (UIImage*)imageWithView:(UIView *)view opaque:(BOOL)opaque bgColor:(UIColor*)bgColor{
UIGraphicsBeginImageContextWithOptions(view.bounds.size, opaque, [[UIScreen mainScreen] scale]);
if(!opaque){
[bgColor set];
}
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
It works fine for me. No bluring was detected. Try to use it. If you'll still have it then most likely the problem is in your saving code...
Cheers... :)
UIGraphicsBeginImageContextWithOptions(size, NO, 2.0);
this solve my prblem by increasing scale from 1.0 to 2.0
Did you provide an image for retina display? You should check it. You might be running in a simulator (in retina).
I'm currently using two images for a menu that I've built. I was using this code a while ago for normal display systems and it was working fine, with the retina display I'm having some issues with CGImageRef creating the right masked image on a depress for the background display. I've tried importing using the Image extensions for retina images. The images are supplied using:
[UIImage imageNamed:#"filename.png"]
I've provided both a standard and a retina image with both the filename.png and the filename#2x.png names.
The problem comes when choosing the mask for the selected area. The code works fine with lower resolution resources, and a high resolution main resource, but when I use
CGImageCreateWithImageInRect
And specify the rect that I want to create the image within, the image's scale is increased meaning that the main button's resolution is fine, but the image that is returned and superimposed on the button downpress is not the correct resolution, but oddly scaled to twice the pixel density, which looks terrible.
I've tried both
UIImage *img2 = [UIImage imageWithCGImage:cgImg scale:[img scale] orientation:[img imageOrientation]];
UIImage *scaledImage = [UIImage imageWithCGImage:[img2 CGImage] scale:4.0 orientation:UIImageOrientationUp];
And I seem to be getting nowhere when I take the image and drawInRect:(Selected Rect)
I have been tearing my hair out for about 2 hours now, and can't seem to find a decent solution, does anyone have any ideas?
I figured out what is necessary to be done in this instance. I created a helper method that would take the scale of the image into account when building the pressed state image and made it scale the CGRect by the image scale like so
- (UIImage *)imageFromImage:(UIImage *)image inRect:(CGRect)rect {
rect.size.height = rect.size.height * [image scale];
rect.size.width = rect.size.width * [image scale];
rect.origin.x = rect.origin.x * [image scale];
rect.origin.y = rect.origin.y * [image scale];
CGImageRef sourceImageRef = [image CGImage];
CGImageRef newImageRef = CGImageCreateWithImageInRect(sourceImageRef, rect);
UIImage *newImage = [UIImage imageWithCGImage:newImageRef scale:[image scale] orientation:[image imageOrientation]];
CGImageRelease(newImageRef);
return newImage;
}
That should fix anyone having similar issues for mapping.