I've been struggling with this for awhile now, since there is little documentation on the subject. I have a UIImagePickerController in my iPhone application that I use to select an image to be applied as the background of a view later. This is easy enough to do. Unfortunately, if a user selects a large image from their camera roll it needs to be resized and cropped in order to look decent.
It's easy enough to toggle picker.allowsEditing to YES and get the image editor up, but the default crop dimensions are too small. I need to set it to the full dimensions of the iPhone screen (320 for the old models, 640 for the new). How do you do that? I've been Googling and looking at Apple's documentation, but I can't find anything. The best I found is a slightly buggy solution from 2009 (http://blog.stormyprods.com/2009/06/image-picker-sample.html) that almost works, but it shifts the image down about 20px. (Plus, it's a bit over-complicated.) Surely there's an elegant, simple solution that I'm missing?
One year later - Hi, like you, i haven't found anything useful, so i created this Project
- a custom size crop and zoom editing UIImagePicker Popover for the iPad.
You could easily change it for the iphone, hope that helps someone.
Here it is - https://github.com/yogev77/UIImagePickerWithEditor
May be this should work :
-(UIImage *)imageWithImage:(UIImage *)image CovertToSize:(CGSize)size {
UIGraphicsBeginImageContext(size);
[image drawInRect:CGRectMake(0, 0, size.width, size.height)];
UIImage *destImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return destImage;
}
Related
I'm working on a comic viewer app that downloads the latest content from a server. It downloads a single file regardless of the screen scale. What I'd like to do is make this file work correctly on both screens.
What's the procedure for this and how should I size the photos to fit? The trouble I'm having is that the graphics are retina screen size, but the iPhone doesn't interpret them as such. That means they're displayed twice as large as they should be.
CGImageRef cgImage = [myImage cgImage];
UIImage *retinaImage = [UIImage imageWithCGImage:cgImage scale:2.0 orientation:UIImageOrientationUp];
You could also change your image's dpi value in an image editor to make UIImage recognize the scale automatically.
Generally though, you should use lower-resolution images on devices that don't have a retina display because otherwise you're wasting precious memory.
For normal screen, you can resize them programmatically, by adding a scale category to the UIImage class by example, there are many code samples on stackoverflow like :
UIImage resize (Scale proportion)
For retina, you need to set the scale of the UIImage to let the ios know for what screen size it is used (you can set this with the initWithCGImage:scale:orientation: method of UIImage).
I'm trying to apply the cameraViewTransform from my UIImagePickerController to the UIImagePickerControllerOriginalImage (the out coming UIImage from the camera). The only way I managed to do this is by printing the UIImage on an UIImageView and then using UIGraphicsBeginImageContext(); to take a screenshot of the UIImageView I have.
The thing is, printing the UIImagePickerControllerOriginalImage to an UIImageView, and then zooming and taking a screenshot takes a long time to process and also freezes the iPhone. (That's because that UIImage is in full resolution, and I also want it to stay in full resolution.)
My Question is... is there a better way to apply the cameraViewTransform to the UIImagePickerControllerOriginalImage image? Or is there a faster way to print my image on the image view?
Thank you so much guys for your time, I really appreciate it!!! :)
I have to perform some image editing operation like cropping, gray scale, rotating
image, Polaroid-effects etc.
From these I found some of functionality like cropping, gray scale. But from this we have to manage separate functions iN there. Is there any valid API or Library available for iPhone to perform image processing?
I use the following function for cropping:
-(UIImage *)imageByCropping:(UIImage *)imageToCrop toRect:(CGRect)rect
{
CGImageRef imageRef = CGImageCreateWithImageInRect([imageToCrop CGImage], rect);
UIImage *cropped = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
return cropped;
}
for this I have not idea, how to set cropping rectangle on my actual image...and how to re-size that rectangle.
Is there any method in iPhone like Android we direct crop image after capture image... by setting it`s some property we can achieve this in iPhone.
for gray scale I found something here, but for this if we perform Polaroid effect we have to manage separate enums...,
I found one Image Magik API for this but many people said apple reject app due to private API.and also not get how to use it.
If for this or any-other API available than tell me about it and its tutorial.
check the Quartz Demo code sample by apple... especially QuartzClippingView and QuartzMaskingView...
and if you want to learn core graphics basics for image editing, a quick look at Quartz 2D Programming Guide and Drawing and Printing Guide would really help...
also, if you are planning to go for better cropping check Cropped Image .. this is for mac but it can be useful for creating similar implementation for iPhone by using Cocoa Touch counterparts of the same classes they have used e.g. instead of NSBezierPath for mac use UIBezierPath for iPhone ...
No , Using ImageMagick is absolutely valid.
Pl. follow this discussion.
I want to show some images as a thumbnail in View controller but i dont know how to do this. Can anyone please give me some ideas or sample code if possible.
Are you asking how to create thumbnails from larger images, or about how to build a view controller which displays them nicely?
Building a view controller:
You could use TTPhotoViewController from the Three20 project (description), which acts similarly to the iPhone's built in camera roll to view images.
You can look at the Scrolling sample code from apple, referred to in this question about using it for thumbnails.
If you want to build one yourself, you might consider using a GridView from the moriarty library, either as a large grid in a UIScrollView, or on a more efficient row-by-row basis in a UITableView. There's a previous question on optimized image loading in a UIScrollView.
Creating thumbnails from larger images:
The code-easiest way to scale down an image is to simply display it in a UIImageView with a frame set to the smaller size that you want - it's scaled for you.
If you want to save a thumbnail, or care about memory usage, you can create a hard-scaled version. The sample code below is taken from this blog post, and can be added to UIImage as a category method:
- (UIImage*) imageScaledToSize: (CGSize) newSize {
UIGraphicsBeginImageContext(newSize);
[self drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Finally, here's a previous question on masking out round corners on an image, similar to the app icons used on the home screen.
Added
Using an image's built-in thumbnail:
There's a nice function called CGImageSourceCreateThumbnailAtIndex that understands built-in thumbnails in certain image data formats. You can see some useful sample code for this under Creating a Thumbnail Image from an Image Source in the Image I/O Programming Guide from Apple.
There are multiple issues with thumbnails; perhaps you could clarify which ones you are most concerned about?
How to display a smaller version of an existing image
How to speed up paging by caching the thumbnails (instead of just dynamically shrinking the originals)
How to allow the user to page through the thumbnails
How to synchronize the thumbnails with the originals, in the event that your images are editable or the user can add to them
I am trying to capture the contents of a UIWebView including that which is not visible to the user. i.e. The whole web page even though the user is only looking at the top.
Looking around I found the best way to capture a UIView is to retrieve its layer and use renderInContext.
However, UIWebView seems to be using its own CALayer implementation which is behaving a lot more like CATiledLayer, although it is still claiming to be a standard CALayer. When I call renderInContext I only get one portion of the web page, up to 940px down, as opposed to the whole page.
Has anyone got any ideas on how to either: force the UIWebView to scroll down another 940px (obviously that is far from ideal) or tell whatever breed of CALayer it is backing the WebView to render all of its content when I ask it to.
Cheers
EDIT: I should add that currently change the frame of the webview to fit the size of the page retrieved through javascript.
I've released an app (Web2Pic) doing that, and please trust me that UIGraphicsBeginImageContext(webView.frame.size);
can do nothing except getting a small image from the visible area in our UIWebView ;-(
The right way is a bit complex but it just works:
1.Use JavaScript in our UIWebView to get these float values:
//Whole page size in HTML coordinate
document.body.scrollWidth
document.body.scrollHeight
//UIWebView visible size in HTML coordinate
window.innerWidth
window.innerHeight
2.Now we can 'cut' the whole page into dozens of UIWebView-sized small pieces. Then we can capture every small pieces individually and save them into our Cache. I implemented this by calculating page-offsets and use UIGraphicsBeginImageContext(webView.frame.size); to get a array of images. In addition, you should cache the image array into the file system, or the app will eventually crash!
3.When we finally got all the small pieces, we can start a full-resolution context: UIGraphicsBeginImageContext(CGSizeMake(document.body.scrollWidth,document.body.scrollHeight));
4.Render every small images into the big context based on the coordinates. And be careful to the corners, the last image in every line/row may not be a full image.
5.There is still one step left: saving the big image. Do not save it into the PhotoAlbum, because iOS will automatically cut down the resolution of images in the album. Instead, we can save it into the file system and enable the app's iTunes File Share support, or even write a simple in-app photo manager.
Hope these can help ;-)
Yichao Peak Ji
It looks to me like UIWebView renders on demand (witness the checkerboard as you scroll downwards rapidly on a large page), so there won't be anything in the part of the layer below what you can reach until the user scrolls down there. The layer won't be able to write out what it doesn't have, so I don't think you'll be able to capture the whole area.
As far as scrolling, there aren't any obvious exposed API methods that I can think of to move it down. The web view seems to host a UIScrollView or something similar, which you could try to access by traversing the view hierarchy and use its scrollRectToVisible:animated:, but that doesn't sound like a good long-term solution.
Just to answer one of my questions, you can scroll the view by using javascript.
So you use stringByEvaluatingJavaScriptFromString: with a javascript of window.scrollTo(0,%i);, where %i is where you want to scroll to. You can also use scrollY to retrieve the current scroll value.
Resizing the Webview is the way I solved it. If you want a bigger image with more detail, you just have to zoom in before calling this method. Beware that large dimensions could infulence the performance.
- (UIImage*) imageFromWebview:(UIWebView*) webview{
//store the original framesize to put it back after the snapshot
CGRect originalFrame = webview.frame;
//get the width and height of webpage using js (you might need to use another call, this doesn't work always)
int webViewHeight = [[webview stringByEvaluatingJavaScriptFromString:#"document.body.scrollHeight;"] integerValue];
int webViewWidth = [[webview stringByEvaluatingJavaScriptFromString:#"document.body.scrollWidth;"] integerValue];
//set the webview's frames to match the size of the page
[webview setFrame:CGRectMake(0, 0, webViewWidth, webViewHeight)];
//make the snapshot
UIGraphicsBeginImageContextWithOptions(webview.frame.size, false, 0.0);
[webview.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//set the webview's frame to the original size
[webview setFrame:originalFrame];
//and VOILA :)
return image;
}
All UIViews have a size limit of 1024x1024, so you will probably have programmatically scroll, capture the page in chunks, and stitch them together somehow.
Set the height of webview equal to the contentsize of scrollview of webview.
-(UIImage *)captureImage:(UIWebView *)webvw
{
webvw.frame=CGRectMake(webvw.frame.origin.x, webvw.frame.origin.y, webvw.frame.size.width, webvw.scrollView.contentSize.height);
UIGraphicsBeginImageContextWithOptions(webvw.frame.size, NO, 0.0f);
[webvw.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext();
return screenshot;
}