I've been developing my project on iPhone 4S and the iPhone5. In my project, after the picture is taken, I crop it and then resize the image to apply photo filters. The iPhone 5 seems to handle this very well however on the iPhone 4S, it seems to crash at different points during the picture taking process. I checked to see if there we're any memory leaks that I may have missed. Here is the code below:
[stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error)
{
[captureSession stopRunning];
NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer];
UIImage *newImage = [[UIImage alloc] initWithData:imageData];
After this, I automatically detect the orientation of the picture taken and rotate the picture so that it is always upright.
After this, I crop the image into a square using NYXImagesKit
float filteringSquareRatio = 307.0/320.0;
UIImage *cropped = [newImage cropToSize:CGSizeMake(filteringSquareRatio * newImage.size.width, filteringSquareRatio * newImage.size.width) usingMode:NYXCropModeCenter];
Lastly, I resize the image using MGImageUtilities
UIImage *resized = [cropped imageScaledToFitSize:CGSizeMake(320, 320)];
Is there a better way to do this? I'm currently using AVCaptureSessionPresetPhoto because I would like to save the original high resolution photo on the device and send the cropped and resized version to the server. I don't want to use any of the video presets because the camera is zoomed in. What can be causing the crashing?
If you weren't able to find a solution to this (I see this problem too), you could perhaps detect the 4s and use the "high" preset instead which has lower resolution.
Related
I have managed using the YouTube API to fetch thumbnails for my list of videos, however they have black bars top and bottom of the UIImage I get. How can I fetch a thumbnail without these bars and even better a higher quality thumbnail?
Here is the code I use currently:
GDataEntryBase *entry = [[feed entries] objectAtIndex:i];
NSArray *thumbnails = [[(GDataEntryYouTubeVideo *)entry mediaGroup] mediaThumbnails];
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:[[thumbnails objectAtIndex:0] URLString]]];
UIImage *thumbnail = [UIImage imageWithData:data];
It's also worth noting that all thumbnails are currently in a 4:3 aspect ratio, for historical purposes. If the underlying video is 16:9 and you plan on using a 16:9 player, then it makes sense to position the thumbnail so that the top and bottom black bars are hidden. That's independent of whether you use a lower-resolution or higher-resolution thumbnail.
Well this answer gave me the hint, so I went ahead and took a guess.
How do I get a YouTube video thumbnail from the YouTube API?
Turns out if I just change the index from 0, to 1 of my data object I get a higher quality thumbnail. Magic, easy.
I am working on an iOS project that uses AV-Out to show contents in a 1280x720 window on a second screen.
I have a MPMoviePlayerController's view as background and on top of that different other elements like UIImages and UILabels.
The background movie plays in a loop.
Now I want to overlay the whole view including all visible elements with another fullscreen animation that has transparency so that only parts of the underlying view are visible.
I first tried a png animation with UIImageView.
I was surprised to find that actually works on iPhone5, but of course the pngs are so big in size that this uses way too much ram and it crashes on everything below iPhone4s.
So i need another way.
I figured out how to play a second movie at the same time using AVFoundation.
So far, so good. Now i can play the overlay video, but of course it is not trasparent yet.
I also learned that with the GPUImage library I can use GPUImageChromaKeyBlendFilter to filter a color out of a video to make it transparent and then combine it with another video.
What i don't understand yet is the best way to implement it in my case to get the result that i want.
Can i use the whole view hierarchy below the top video as first input for the GPUImageChromaKeyBlendFilter and a greenscreen-style video as second input and show the result live in 720p? how would i do that?
Or would it be better to use GPUImageChromaKeyFilter and just filter the greenscreen-style video, and play it in a view above all other views? Would the background of this video be transparent then?
Thanks for your help!
You'll need to build a custom player using AVFoundation.framework and then use a video with alpha channel. The AVFoundation framework allows much more robust handeling of video without many of the limitations of MPMedia framework. Building a custom player isn't as hard as people make it out to be. I've written a tutorial on it here:http://www.sdkboy.com/?p=66
OTHER WAY..........
The SimpleVideoFileFilter example in the framework shows how to load a movie, filter it, and
encode it back to disk. Modifying this to perform chroma keying gives the following:
NSURL *sampleURL = [[NSBundle mainBundle] URLForResource:#"sample" withExtension:#"m4v"];
movieFile = [[GPUImageMovie alloc] initWithURL:sampleURL];
filter = [[GPUImageChromaKeyBlendFilter alloc] init];
[filter setColorToReplaceRed:0.0 green:0.0 blue:1.0];
[filter setThresholdSensitivity:0.4];
[movieFile addTarget:filter];
UIImage *inputImage = [UIImage imageNamed:#"background.jpg"];
sourcePicture = [[GPUImagePicture alloc] initWithImage:inputImage smoothlyScaleOutput:YES];
[sourcePicture addTarget:filter];
NSString *pathToMovie = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents/Movie.m4v"];
NSURL *movieURL = [NSURL fileURLWithPath:pathToMovie];
movieWriter = [[GPUImageMovieWriter alloc] initWithMovieURL:movieURL size:CGSizeMake(480.0, 640.0)];
[filter addTarget:movieWriter];
[movieWriter startRecording];
[movieFile startProcessing];
[movieWriter setCompletionBlock:^{
[filter removeTarget:movieWriter];
[movieWriter finishRecording];
}];
The above code will load a movie from the application's resources called sample.m4v, feed it into a chroma key filter that is set to key off of pure blue with a sensitivity of 0.4, attach a background image to use for the chroma keying, and then send all that to a movie encoder which writes Movie.m4v in the application's /Documents directory.
You can adjust the threshold and specific blue tint to match your needs, as well as replace the input image with another movie or other source as needed. This process can also be applied to live video from the iOS device's camera, and you can display the results to the screen if you'd like.
On an iPhone 4 running iOS 5.0, chroma keying takes 1.8 ms (500+ FPS) for 640x480 frames of video, 65 ms for 720p frames (15 FPS). The newer A5-based devices are 6-10X faster than that for these operations, so they can handle 1080p video without breaking a sweat. I use iOS 5.0's fast texture caches for both frame uploads and retrievals, which accelerates the processing on that OS version over 4.x.
The one caution I have about this is that I haven't quite gotten the audio to record right in my movie encoding, but I'm working on that right now.
The SimpleVideoFileFilter example in the framework shows how to load a movie, filter it, and encode it back to disk. Modifying this to perform chroma keying gives the following:
NSURL *sampleURL = [[NSBundle mainBundle] URLForResource:#"sample" withExtension:#"m4v"];
movieFile = [[GPUImageMovie alloc] initWithURL:sampleURL];
filter = [[GPUImageChromaKeyBlendFilter alloc] init];
[filter setColorToReplaceRed:0.0 green:0.0 blue:1.0];
[filter setThresholdSensitivity:0.4];
[movieFile addTarget:filter];
UIImage *inputImage = [UIImage imageNamed:#"background.jpg"];
sourcePicture = [[GPUImagePicture alloc] initWithImage:inputImage smoothlyScaleOutput:YES];
[sourcePicture addTarget:filter];
NSString *pathToMovie = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents/Movie.m4v"];
NSURL *movieURL = [NSURL fileURLWithPath:pathToMovie];
movieWriter = [[GPUImageMovieWriter alloc] initWithMovieURL:movieURL size:CGSizeMake(480.0, 640.0)];
[filter addTarget:movieWriter];
[movieWriter startRecording];
[movieFile startProcessing];
[movieWriter setCompletionBlock:^{
[filter removeTarget:movieWriter];
[movieWriter finishRecording];
}];
The above code will load a movie from the application's resources called sample.m4v, feed it into a chroma key filter that is set to key off of pure blue with a sensitivity of 0.4, attach a background image to use for the chroma keying, and then send all that to a movie encoder which writes Movie.m4v in the application's /Documents directory.
You can adjust the threshold and specific blue tint to match your needs, as well as replace the input image with another movie or other source as needed. This process can also be applied to live video from the iOS device's camera, and you can display the results to the screen if you'd like.
On an iPhone 4 running iOS 5.0, chroma keying takes 1.8 ms (500+ FPS) for 640x480 frames of video, 65 ms for 720p frames (15 FPS). The newer A5-based devices are 6-10X faster than that for these operations, so they can handle 1080p video without breaking a sweat. I use iOS 5.0's fast texture caches for both frame uploads and retrievals, which accelerates the processing on that OS version over 4.x.
The one caution I have about this is that I haven't quite gotten the audio to record right in my movie encoding, but I'm working on that right now.
I have a video which was recorded on blue screen.
Is there a way to make it transparent on iOS devices? I know I can do it with pixel shaders and openGL but I m afraid that the process of decoding video frame/ uploading openGL texture and eliminate fragments with pixel shader will be too slow.
Any suggestions?
It sounds like you want to do some sort of chroma keying with your video. I just added the capability to do this to my GPUImage framework, which as the name indicates uses GPU-based processing to perform these operations many times faster than CPU-bound filters could.
The SimpleVideoFileFilter example in the framework shows how to load a movie, filter it, and encode it back to disk. Modifying this to perform chroma keying gives the following:
NSURL *sampleURL = [[NSBundle mainBundle] URLForResource:#"sample" withExtension:#"m4v"];
movieFile = [[GPUImageMovie alloc] initWithURL:sampleURL];
filter = [[GPUImageChromaKeyBlendFilter alloc] init];
[filter setColorToReplaceRed:0.0 green:0.0 blue:1.0];
[filter setThresholdSensitivity:0.4];
[movieFile addTarget:filter];
UIImage *inputImage = [UIImage imageNamed:#"background.jpg"];
sourcePicture = [[GPUImagePicture alloc] initWithImage:inputImage smoothlyScaleOutput:YES];
[sourcePicture addTarget:filter];
NSString *pathToMovie = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents/Movie.m4v"];
NSURL *movieURL = [NSURL fileURLWithPath:pathToMovie];
movieWriter = [[GPUImageMovieWriter alloc] initWithMovieURL:movieURL size:CGSizeMake(480.0, 640.0)];
[filter addTarget:movieWriter];
[movieWriter startRecording];
[movieFile startProcessing];
[movieWriter setCompletionBlock:^{
[filter removeTarget:movieWriter];
[movieWriter finishRecording];
}];
The above code will load a movie from the application's resources called sample.m4v, feed it into a chroma key filter that is set to key off of pure blue with a sensitivity of 0.4, attach a background image to use for the chroma keying, and then send all that to a movie encoder which writes Movie.m4v in the application's /Documents directory.
You can adjust the threshold and specific blue tint to match your needs, as well as replace the input image with another movie or other source as needed. This process can also be applied to live video from the iOS device's camera, and you can display the results to the screen if you'd like.
On an iPhone 4 running iOS 5.0, chroma keying takes 1.8 ms (500+ FPS) for 640x480 frames of video, 65 ms for 720p frames (15 FPS). The newer A5-based devices are 6-10X faster than that for these operations, so they can handle 1080p video without breaking a sweat. I use iOS 5.0's fast texture caches for both frame uploads and retrievals, which accelerates the processing on that OS version over 4.x.
The one caution I have about this is that I haven't quite gotten the audio to record right in my movie encoding, but I'm working on that right now.
If you mean you want to render the video, but set the blue pixels to transparent, then the only efficient way to do this is with OpenGL. This should be easily possible for iOS devices, video decoding is handled in hardware, and I have several projects where I transfer video frames to OpenGL using glTexSubImage2D, works fine.
Well this may be a very easy Question but I'm not getting the answer after searching a lot.
I have one application in which I send the image taken from camera. The path of image captured from camera is stored in database. So in mail attachment code I load image from path and attach like this:
UIImage *myImage = [UIImage imageWithContentsOfFile:ImagePath];
NSData *imageData = UIImagePNGRepresentation(myImage);
[mailer addAttachmentData:imageData mimeType:#"image/png" fileName:#"Spotted"];
but the image is rotated by 90 Degree left every time. Can anyone guide me what am I doing wrong here??
P.S.: NSLog of ImagePath -->
/var/mobile/Applications/4BFB1BD9-DD83-42AF-A2BF-A5E4CC0DEAE3/Documents/459443.png
There has been some discussion on the Apple site about this issue in pictures sent by mail.
Unless you need it to be a PNG, I suggest converting it to a JPEG. JPEGs are more compressed (useful when it comes to email) and don't seem to have this rotating problem. Try using NSData *imageData = UIImageJPEGRepresentation(myImage); instead.
I've twisted my brain on this problem for several days as well. If you need it to be a PNG, here's a pretty good write up of what I learned on the topic: iOS PNG Image rotated 90 degrees
I'm trying to take a screen shot of my app's current view and save it to photo album (to then be emailed or MMS'ed).
UIGraphicsBeginImageContext(self.view.bounds.size);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageWriteToSavedPhotosAlbum(viewImage, self, #selector(savedPhotoImage:didFinishSavingWithError:contextInfo:), nil);
This works but the resulting image apears to be larger (533x800px) and heavily compressed when I email it from the photo library.
I've tried first writing the UIImage to file and then saving to album but still get the same issue.
If I used the in-built screenshot functionality on the iPhone the view saves correctly to photo album at 320x480 but the above code appears to save a larger image for some reason?
Thanks!
I found a decent workaround, which is to essentially rewrap the UIImage as a PNG, then save the rewrapped version. Code looks something like this:
UIImage* im = [UIImage imageWithCGImage:myCGRef]; // make image from CGRef
NSData* imdata = UIImagePNGRepresentation ( im ); // get PNG representation
UIImage* im2 = [UIImage imageWithData:imdata]; // wrap UIImage around PNG representation
UIImageWriteToSavedPhotosAlbum(im2, nil, nil, nil); // save to photo album
I had that same error, on my part, that was solved when I rounded the decimal points to be the same scale as the iPhone, try it, make sure the scale is 1.0, 2.0, etc and not 3.1, that will throw it off.