Creating Thumbnail from Video - Improving Speed Performance - AVAsset - iPhone [duplicate] - iphone

This question already has an answer here:
Grabbing First Frame of a Video - Thumbnail Resolution - iPhone
(1 answer)
Closed 3 years ago.
I am using code based on the code in the following thread to generate a video thumbnail :
Getting a thumbnail from a video url or data in iPhone SDK
My code is as follows :
if (selectionType == kUserSelectedMedia) {
NSURL * assetURL = [info objectForKey:UIImagePickerControllerReferenceURL];
AVURLAsset *asset=[[AVURLAsset alloc] initWithURL:assetURL options:nil];
AVAssetImageGenerator *generator = [[AVAssetImageGenerator alloc] initWithAsset:asset];
generator.appliesPreferredTrackTransform=TRUE;
[asset release];
CMTime thumbTime = CMTimeMakeWithSeconds(0,30);
//NSLog(#"Starting Async Queue");
AVAssetImageGeneratorCompletionHandler handler = ^(CMTime requestedTime, CGImageRef im, CMTime actualTime, AVAssetImageGeneratorResult result, NSError *error){
if (result != AVAssetImageGeneratorSucceeded) {
NSLog(#"couldn't generate thumbnail, error:%#", error);
}
//NSLog(#"Updating UI");
selectMediaButton.hidden = YES;
selectedMedia.hidden = NO;
cancelMediaChoiceButton.hidden = NO;
whiteBackgroundMedia.hidden = NO;
//Convert CGImage thumbnail to UIImage.
UIImage * thumbnail = [UIImage imageWithCGImage:im];
int checkSizeW = thumbnail.size.width;
int checkSizeH = thumbnail.size.height;
NSLog(#"Image width is %d", checkSizeW);
NSLog(#"Image height is %d", checkSizeH);
if (checkSizeW >=checkSizeH) {
//This is a landscape image or video.
NSLog(#"This is a landscape image - will resize automatically");
}
if (checkSizeH >=checkSizeW) {
//This is a portrait image or video.
selectedIntroHeight = thumbnail.size.height;
}
//Set the image once resized.
selectedMedia.image = thumbnail;
//Set out confirm button BOOL to YES and check if we need to display confirm button.
mediaReady = YES;
[self checkIfConfirmButtonShouldBeDisplayed];
//[button setImage:[UIImage imageWithCGImage:im] forState:UIControlStateNormal];
//thumbImg=[[UIImage imageWithCGImage:im] retain];
[generator release];
};
CGSize maxSize = CGSizeMake(320, 180);
generator.maximumSize = maxSize;
[generator generateCGImagesAsynchronouslyForTimes:[NSArray arrayWithObject:[NSValue valueWithCMTime:thumbTime]] completionHandler:handler];
}
}
The issue is that there is a delay of about 5-10 seconds in generating the thumbnail image. Is there anyway that I could improve the speed of this code and generate the thumbnail quicker ?
Thank you.

This is a generic code, you should just pass a path for the media file and set the ratio between 0 and 1.0.
+ (UIImage*)previewFromFileAtPath:(NSString*)path ratio:(CGFloat)ratio
{
AVAsset *asset = [AVURLAsset assetWithURL:[NSURL fileURLWithPath:path]];
AVAssetImageGenerator *imageGenerator = [[AVAssetImageGenerator alloc]initWithAsset:asset];
CMTime duration = asset.duration;
CGFloat durationInSeconds = duration.value / duration.timescale;
CMTime time = CMTimeMakeWithSeconds(durationInSeconds * ratio, (int)duration.value);
CGImageRef imageRef = [imageGenerator copyCGImageAtTime:time actualTime:NULL error:NULL];
UIImage *thumbnail = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
return thumbnail;
}

Swift solution:
func previewImageForLocalVideo(url:NSURL) -> UIImage?
{
let asset = AVAsset(URL: url)
let imageGenerator = AVAssetImageGenerator(asset: asset)
imageGenerator.appliesPreferredTrackTransform = true
var time = asset.duration
//If possible - take not the first frame (it could be completely black or white on camara's videos)
time.value = min(time.value, 2)
do {
let imageRef = try imageGenerator.copyCGImageAtTime(time, actualTime: nil)
return UIImage(CGImage: imageRef)
}
catch let error as NSError
{
print("Image generation failed with error \(error)")
return nil
}
}

Related

How to retrieve images from Instagram which has special hashtag?

My client wants to share an image on Instagram. I have implemeted sharing image on instagram.But i could not share it with a special hashtag. Here is my code so far.
- (IBAction)sharePhotoOnInstagram:(id)sender {
UIImagePickerController *imgpicker=[[UIImagePickerController alloc] init];
imgpicker.delegate=self;
[self storeimage];
NSURL *instagramURL = [NSURL URLWithString:#"instagram://app"];
if ([[UIApplication sharedApplication] canOpenURL:instagramURL])
{
CGRect rect = CGRectMake(0 ,0 , 612, 612);
NSString *jpgPath = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents/15717.ig"];
NSURL *igImageHookFile = [[NSURL alloc] initWithString:[[NSString alloc] initWithFormat:#"file://%#", jpgPath]];
dic.UTI = #"com.instagram.photo";
dic.delegate = self;
dic = [self setupControllerWithURL:igImageHookFile usingDelegate:self];
dic = [UIDocumentInteractionController interactionControllerWithURL:igImageHookFile];
dic.delegate = self;
[dic presentOpenInMenuFromRect: rect inView: self.view animated: YES ];
// [[UIApplication sharedApplication] openURL:instagramURL];
}
else
{
// NSLog(#"instagramImageShare");
UIAlertView *errorToShare = [[UIAlertView alloc] initWithTitle:#"Instagram unavailable " message:#"You need to install Instagram in your device in order to share this image" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
errorToShare.tag=3010;
[errorToShare show];
}
}
- (void) storeimage
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *savedImagePath = [documentsDirectory stringByAppendingPathComponent:#"15717.ig"];
UIImage *NewImg = [self resizedImage:picTaken :CGRectMake(0, 0, 612, 612) ];
NSData *imageData = UIImagePNGRepresentation(NewImg);
[imageData writeToFile:savedImagePath atomically:NO];
}
-(UIImage*) resizedImage:(UIImage *)inImage: (CGRect) thumbRect
{
CGImageRef imageRef = [inImage CGImage];
CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo(imageRef);
// There's a wierdness with kCGImageAlphaNone and CGBitmapContextCreate
// see Supported Pixel Formats in the Quartz 2D Programming Guide
// Creating a Bitmap Graphics Context section
// only RGB 8 bit images with alpha of kCGImageAlphaNoneSkipFirst, kCGImageAlphaNoneSkipLast, kCGImageAlphaPremultipliedFirst,
// and kCGImageAlphaPremultipliedLast, with a few other oddball image kinds are supported
// The images on input here are likely to be png or jpeg files
if (alphaInfo == kCGImageAlphaNone)
alphaInfo = kCGImageAlphaNoneSkipLast;
// Build a bitmap context that's the size of the thumbRect
CGContextRef bitmap = CGBitmapContextCreate(
NULL,
thumbRect.size.width, // width
thumbRect.size.height, // height
CGImageGetBitsPerComponent(imageRef), // really needs to always be 8
4 * thumbRect.size.width, // rowbytes
CGImageGetColorSpace(imageRef),
alphaInfo
);
// Draw into the context, this scales the image
CGContextDrawImage(bitmap, thumbRect, imageRef);
// Get an image from the context and a UIImage
CGImageRef ref = CGBitmapContextCreateImage(bitmap);
UIImage* result = [UIImage imageWithCGImage:ref];
CGContextRelease(bitmap); // ok if NULL
CGImageRelease(ref);
return result;
}
- (UIDocumentInteractionController *) setupControllerWithURL: (NSURL*) fileURL usingDelegate: (id <UIDocumentInteractionControllerDelegate>) interactionDelegate
{
UIDocumentInteractionController *interactionController = [UIDocumentInteractionController interactionControllerWithURL:fileURL];
interactionController.delegate = self;
return interactionController;
}
- (void)documentInteractionControllerWillPresentOpenInMenu:(UIDocumentInteractionController *)controller
{
}
- (BOOL)documentInteractionController:(UIDocumentInteractionController *)controller canPerformAction:(SEL)action
{
// NSLog(#"5dsklfjkljas");
return YES;
}
- (BOOL)documentInteractionController:(UIDocumentInteractionController *)controller performAction:(SEL)action
{
// NSLog(#"dsfa");
return YES;
}
- (void)documentInteractionController:(UIDocumentInteractionController *)controller didEndSendingToApplication:(NSString *)application
{
// NSLog(#"fsafasd;");
}
Note : This is working fine.
I have followed their documentation on http://instagram.com/developer/iphone-hooks/ but couldn't get better idea from it!. Now don't know what to do next step for sharing an image with hashtag and other information.
Secondly I want to retrieve all the images shared with a particular hashtag into the application.
Please guide me! Thanks in advance!
First, from iPhone Hooks, under 'Document Interaction':
To include a pre-filled caption with your photo, you can set the annotation property on the document interaction request to an NSDictionary containing an NSString under the key "InstagramCaption". Note: this feature will be available on Instagram 2.1 and later.
You'll need to add something like:
dic.annotation = [NSDictionary dictionaryWithObject:#"#yourTagHere" forKey:#"InstagramCaption"];
Second, you'll need to take a look at Tag Endpoints if you want to pull down images with a specific tag.

image size on device is different after uploaing image on server

I am doing following operation before uploading image. If I check size of image before uploading and after uploading it gets double(i.e if I have uploaded 2 MB image I can see 4 MB image on server).
NSTimeInterval timeInterval = [assetDate timeIntervalSince1970];
ALAssetRepresentation *rep = [temp defaultRepresentation];
CGImageRef iref = [rep fullResolutionImage];
StrPath = [StrPath stringByAppendingFormat:#"%d.%#",(int)timeInterval,strImageType];
UIImage *image =[UIImage imageWithCGImage:iref scale:[rep scale] orientation:(UIImageOrientation)[rep orientation]];
NSData *dataObj = nil;
dataObj = UIImageJPEGRepresentation(image, 1.0);
NSString* StrFileData = [Base64 encode:dataObj];
NSString* strFileHash = [dataObj md5Test];
Use following method for specific hight and width with image
+ (UIImage*)resizeImage:(UIImage*)image withWidth:(int)width withHeight:(int)height
{
CGSize newSize = CGSizeMake(width, height);
float widthRatio = newSize.width/image.size.width;
float heightRatio = newSize.height/image.size.height;
if(widthRatio > heightRatio)
{
newSize=CGSizeMake(image.size.width*heightRatio,image.size.height*heightRatio);
}
else
{
newSize=CGSizeMake(image.size.width*widthRatio,image.size.height*widthRatio);
}
UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
This method return NewImage, It will not be resiz :)
I have few suggestions. If you note these.. It should help you
You can get the ALAsset image NSData directly from ALAsset defaultRepresentation
getBytes:fromOffset:length:error: method.
Use ALAsset thumbnail image instead of retrieving full resolution image
CGImageRef iref = [myasset aspectRatioThumbnail];
ALAsset Libraay block will execute in seperate thread. So do the server upload in main thread
dispatch_async(dispatch_get_global_queue(0, 0), ^{
// do the server upload
});

ALAsset thumbnail at specific timestamp

I'm working working on an iPhone application for uploading video files to a specific platform, and one feature I would really love is to be able to present, say, ten different thumbnails for the same video for the user to pick from.
The problem is, that ALAsset only provides a thumbnail method, which just returns the default thumbnail. I have read through the ALAssetRepresentation and ALAsset documentation and I can't seem to find a way to get a thumbnail for a specific timestamp.
I guess one option would be to use something along the lines of libav to get thumbnails but that seems a little "over the top" for something like this. Can anyone help me on this one?
Best regards,
Nick
i think this will help you , and
you can also see through this prompt
Video File thumbnail timestamp missing in ALAsset
{
if ([theAsset valueForProperty:ALAssetPropertyType] == ALAssetTypeVideo) {
// Black semi-transparent background at the bottom of the item
CGRect containerFrame = CGRectMake(0, frame.size.height - AGIPC_ITEM_HEIGHT, frame.size.width, AGIPC_ITEM_HEIGHT);
UIView *containerForMovieInfo = [[[UIView alloc] initWithFrame:containerFrame] autorelease];
containerForMovieInfo.backgroundColor = [UIColor blackColor];
containerForMovieInfo.alpha = 0.7f;
// Movie icon on left side
CGRect movieFrame = CGRectMake(4, 60, 26, 15);
UIImageView *movieImageView = [[[UIImageView alloc] initWithFrame:movieFrame] autorelease];
if (IS_IPAD()) {
movieImageView.image = [UIImage imageNamed:#"AGIPC-Movie-iPad"];
} else {
movieImageView.image = [UIImage imageNamed:#"AGIPC-Movie-iPhone"];
}
[containerForMovieInfo addSubview:movieImageView];
// Movie duration on right side
if ([theAsset valueForProperty:ALAssetPropertyDuration] != ALErrorInvalidProperty) {
NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
[formatter setDateFormat:#"mm:ss"];
CGRect durationFrame = CGRectMake(frame.size.width - 26 - 4, 60, 26, 15);
UILabel *durationView = [[[UILabel alloc] initWithFrame:durationFrame] autorelease];
durationView.backgroundColor = [UIColor clearColor];
durationView.textColor = [UIColor whiteColor];
durationView.text = [formatter stringFromDate:[NSDate dateWithTimeIntervalSince1970:[[theAsset valueForProperty:ALAssetPropertyDuration] doubleValue]]];
durationView.font = [UIFont systemFontOfSize:10];
[containerForMovieInfo addSubview:durationView];
}
[self addSubview:containerForMovieInfo];
}
}
last but not least, you must creat the image of the camera on your own.
// Get URL from ALAsset* asset:
NSURL* assetURL = [asset valueForProperty:ALAssetPropertyAssetURL];
// Create AVURLAsset using this URL (assetOptions is optional):
NSDictionary* assetOptions = nil;
// assetOptions = #{AVURLAssetPreferPreciseDurationAndTimingKey : #(YES)};
AVAsset* avAsset = [[AVURLAsset alloc] initWithURL:assetURL options:assetOptions];
// Create generator:
AVAssetImageGenerator* generator = [[AVAssetImageGenerator alloc] initWithAsset:avAsset];
generator.appliesPreferredTrackTransform = YES;
// Create array with CMTimes of thumbnails using your own logic.
// (Use +(NSValue*)valueWithCMTime:(CMTime)time to add CMTime in array).
NSArray* times = [self generateThumbnailTimesForVideo:avAsset];
// Generate thumbnail images asynchronously:
[generator generateCGImagesAsynchronouslyForTimes:times
completionHandler:^(CMTime requestedTime,
CGImageRef image,
CMTime actualTime,
AVAssetImageGeneratorResult result,
NSError* error)
{
// This block is performed for each CMTime in times array.
UIImage* thumbnail = [[UIImage alloc] initWithCGImage:image];
}
];
Synchronous method to get thumbnail at any time is
// PS: SYNC method:
CGImageRef imgRef = [generator copyCGImageAtTime:time actualTime:NULL error:&error];
UIImage* thumbnail = [[UIImage alloc] initWithCGImage:image];

CoreImage Memory problems in ios5

Does anyone knows how to release memory while using core image framework to apply HUE changes on image?
Here is my code:-
CIImage *inputImage = [[CIImage alloc] initWithImage:currentImage];
CIFilter * controlsFilter = [CIFilter filterWithName:#"CIHueAdjust"];
[controlsFilter setValue:inputImage forKey:kCIInputImageKey];
[controlsFilter setValue:[NSNumber numberWithFloat:slider.value] forKey:#"inputAngle"];
CIImage *displayImage = controlsFilter.outputImage;
UIImage *finalImage = [UIImage imageWithCIImage:displayImage];
CIContext *context = [CIContext contextWithOptions:nil];
if (displayImage == nil || finalImage == nil) {
// We did not get output image. Let's display the original image itself.
photoEditView.image = currentImage;
}else {
// We got output image. Display it.
photoEditView.image = [UIImage imageWithCGImage:[context createCGImage:displayImage fromRect:displayImage.extent]];
}
context = nil;
[inputImage release];
I think you need to release this one as well :
[context createCGImage:displayImage fromRect:displayImage.extent]
by using the CGImageRelease(CGImageRef) method.

How can I get image file size which selected by UIImagePickerController?

I want to know that the image file size in IPhone PhotoAlbum which selected by UIImagePickerController.
I've tried this code with 1,571,299 byte jpeg image.
UIIamge *selectedImage = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
NSData *imageData;
if ( /* PNG IMAGE */ )
imageData = UIImagePNGReprensentation(selectedImage);
else
imageData = UIImageJPEGReprensentation(selectedImage);
NSUInteger fileLength = [imageData length];
NSLog(#"file length : [%u]", fileLength);
But when I run the code, it print 362788 byte.
Is there anybody who know this?
If you have code like this to take a picture:
UIImagePickerController *controller = [[[UIImagePickerController alloc] init] autorelease];
controller.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
controller.delegate = self;
[self presentModalViewController:controller animated:YES];
Then you can retrieve a file size of the picked image in the following way:
NSURL *assetURL = [info objectForKey:#"UIImagePickerControllerReferenceURL"];
ALAssetsLibrary *library = [[[ALAssetsLibrary alloc] init] autorelease];
[library assetForURL:assetURL resultBlock:^(ALAsset *asset) {
NSLog(#"Size: %lld", asset.defaultRepresentation.size);
} failureBlock:nil];
If the source type is UIImagePickerControllerSourceTypeCamera, you must save the in-memory image to disk before retrieving its file size.
As some commenters have said, even if we assume the methodology is correct you are reprocessing the image anyway so the byte sizes will not match. I use the following method for JPG images, ymmv for PNG:
+ (NSInteger)bytesInImage:(UIImage *)image {
CGImageRef imageRef = [image CGImage];
return CGImageGetBytesPerRow(imageRef) * CGImageGetHeight(imageRef);
}
The above, as a commenter noted, does return the uncompressed size however.
here is in Swift 4
extension UIImage {
var memorySize: Int {
guard let imageRef = self.cgImage else { return 0 }
return imageRef.bytesPerRow * imageRef.height
}
}