How to Display GIF image from URL in Imageview? - ios

Earlier i used SDWebimage third party to display images, now i removed that 3rd party due some other reason. is there any other way to Display GIF image from URL in Imageview without using third party...

Well you can do it simply by following next steps:
Add the following functions
#import <ImageIO/ImageIO.h>
#import <MobileCoreServices/MobileCoreServices.h>
UIImage *GIFFromData(NSData *data) {
if (!data) {
return nil;
}
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)(data), NULL);
UIImage *image = nil;
if (GIFSourceContainsAnimatedGIF(source)) {
image = GIFFromImageSource(source);
} else {
image = [UIImage imageWithData:data];
}
if (source) {
CFRelease(source);
}
return image;
}
BOOL GIFSourceContainsAnimatedGIF(CGImageSourceRef source) {
return (source && UTTypeConformsTo(CGImageSourceGetType(source), kUTTypeGIF) && CGImageSourceGetCount(source) > 1);
}
UIImage *GIFFromImageSource(CGImageSourceRef source) {
CFRetain(source);
NSUInteger numberOfFrames = CGImageSourceGetCount(source);
NSMutableArray<UIImage *> *images = [NSMutableArray arrayWithCapacity:numberOfFrames];
NSTimeInterval duration = 0.0;
for (NSUInteger i = 0; i < numberOfFrames; ++i) {
CGImageRef image = CGImageSourceCreateImageAtIndex(source, i, NULL);
if (image) {
UIImage *frameImage = [UIImage imageWithCGImage:image scale:1.0 orientation:UIImageOrientationUp];
[images addObject:frameImage];
CFRelease(image);
} else {
continue;
}
duration += GIFSourceGetFrameDelay(source, i);
}
CFRelease(source);
return [UIImage animatedImageWithImages:images duration:duration];
}
NSTimeInterval GIFSourceGetFrameDelay(CGImageSourceRef source, NSUInteger index) {
NSTimeInterval frameDelay = 0;
CFDictionaryRef imageProperties = CGImageSourceCopyPropertiesAtIndex(source, index, NULL);
if (!imageProperties) {
return frameDelay;
}
CFDictionaryRef gifProperties = nil;
if (CFDictionaryGetValueIfPresent(imageProperties, kCGImagePropertyGIFDictionary, (const void **)&gifProperties)) {
const void *durationValue = nil;
if (CFDictionaryGetValueIfPresent(gifProperties, kCGImagePropertyGIFUnclampedDelayTime, &durationValue)) {
frameDelay = [(__bridge NSNumber *)durationValue doubleValue];
if (frameDelay <= 0) {
if (CFDictionaryGetValueIfPresent(gifProperties, kCGImagePropertyGIFDelayTime, &durationValue)) {
frameDelay = [(__bridge NSNumber *)durationValue doubleValue];
}
}
}
}
CFRelease(imageProperties);
return frameDelay;
}
Download your GIF with NSURLSession
Display it
UIImage *image = GIFFromData(data);
UIImageView *view = [[UIImageView alloc] initWithImage:image];
Hope this helps :)

UIImageView* animatedImageView = [[UIImageView alloc] initWithFrame:self.view.bounds];
animatedImageView.animationImages = [NSArray arrayWithObjects:
[UIImage imageNamed:#"image1.gif"],
[UIImage imageNamed:#"image2.gif"],
[UIImage imageNamed:#"image3.gif"],
[UIImage imageNamed:#"image4.gif"], nil];
animatedImageView.animationDuration = 1.0f;
animatedImageView.animationRepeatCount = 0;
[animatedImageView startAnimating];
[self.view addSubview: animatedImageView];
Add animated Gif image in Iphone UIImageView

Related

iOS Creating video from images and get EXC_BAD_ACCESS for second try

I'm making an app what makes video from images.
Here I make a new array:
self.imageList = [NSMutableArray<UIImage *> new];
And then add lots of images to this array.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
for (NSString *framePath in _effect.framePathList)
{
#autoreleasepool
{
NSString *filePath = [NSString stringWithFormat:#"%#/%#", documentsDirectory,framePath];
UIImage *frame = [[UIImage alloc] initWithContentsOfFile:filePath];
i++;
self.selectedEffect.image = [self applyEffect:frame];
CGRect rect = [_backgroundView bounds];
UIGraphicsBeginImageContextWithOptions(rect.size,NO,0.0f);
CGContextRef context = UIGraphicsGetCurrentContext();
[self.backgroundView.layer renderInContext:context];
UIImage *capturedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
if (capturedImage.scale * capturedImage.size.height > 640)
{
CGSize newSize = CGSizeMake(640, 640);
UIGraphicsBeginImageContext(newSize);
[capturedImage drawInRect:CGRectMake(0, 0, newSize.height, newSize.height)];
UIImage *destImage = UIGraphicsGetImageFromCurrentImageContext();
capturedImage = destImage;
destImage = nil;
UIGraphicsEndImageContext();
}
dispatch_sync(dispatch_get_main_queue(), ^
{
if (self.updateLoadingState)
{
self.updateLoadingState((float)i / framaCount * 100.0);
}
});
if (capturedImage)
{
[_imageList addObject:capturedImage];
}
}
}
Then try to create the video. Here are the methods
[self.movieMaker createMovieFromImages:_imageList withCompletion:^(NSURL *fileURL)
{
{
if (_finishBlock)
{
_finishBlock();
}
}
}];
This method is in the movieMaker class.
- (void) createMovieFromSource:(NSArray *)images extractor:(CEMovieMakerUIImageExtractor)extractor withCompletion:(CEMovieMakerCompletion)completion {self.completionBlock = completion;
[self.assetWriter startWriting];
[self.assetWriter startSessionAtSourceTime:kCMTimeZero];
dispatch_queue_t mediaInputQueue = dispatch_queue_create("mediaInputQueue", NULL);
__block NSInteger i = 0;
NSInteger frameNumber = [images count];
[self.writerInput requestMediaDataWhenReadyOnQueue:mediaInputQueue usingBlock:^{
while (YES)
{
#autoreleasepool
{
if (i >= frameNumber)
{
break;
}
if ([self.writerInput isReadyForMoreMediaData])
{
CVPixelBufferRef sampleBuffer;
NSMutableArray *test = [NSMutableArray arrayWithArray:images];
UIImage *img = extractor([test objectAtIndex:i]);
if (img == nil) {
i++;
NSLog(#"Warning: could not extract one of the frames");
continue;
}
CGImageRef img2 = [img CGImage];
sampleBuffer = [self newPixelBufferFromCGImage:img2];
CGImageRelease(img2);
if (sampleBuffer) {
if (i == 0)
{
[self.bufferAdapter appendPixelBuffer:sampleBuffer withPresentationTime:kCMTimeZero];
}
else
{
CMTime lastTime = CMTimeMake(i-1, self.frameTime.timescale);
CMTime presentTime = CMTimeAdd(lastTime, self.frameTime);
[self.bufferAdapter appendPixelBuffer:sampleBuffer withPresentationTime:presentTime];
}
CFRelease(sampleBuffer);
i++;
}
}
}
}
[self.writerInput markAsFinished];
[self.assetWriter finishWritingWithCompletionHandler:^{
dispatch_async(dispatch_get_main_queue(), ^{
self.completionBlock(self.fileURL);
});
}];
CVPixelBufferPoolRelease(self.bufferAdapter.pixelBufferPool);
}];
}
Without the CGImageRelease(img2); everything working but I have a huge memory leak. I have more then 100 images in the array. If I use CGImageRelease(img2); the first run is ok no memory leak. But If I try it again I get EXC_BAD_ACCESS in this line: self.imageList = [NSMutableArray<UIImage *> new];
Here is the error
What can I do? Thanks in advance!

Issue while generating PDF from Table View

I have to generate PDf from UITableView having multiple sections and rows.
I have generated the pdf as well but the problem is while creating PDF it is cutting the data of some rows and showing on other page.
So Please suggest any dynamic logic that will help in creating PDf having data on the page without going to other Page .
Also Please find code below which I have used to create PDF.
CGRect priorBounds = self.tableView.bounds;
CGSize fittedSize = [self.tableView sizeThatFits:CGSizeMake(priorBounds.size.width, self.tableView.contentSize.height)];
self.tableView.bounds = CGRectMake(0, 0, 612, fittedSize.height);
CGRect pdfPageBounds = CGRectMake(0, 0, 612, 792); // Change this as your need
NSMutableData *pdfData = [[NSMutableData alloc] init];
UIGraphicsBeginPDFContextToData(pdfData, pdfPageBounds, nil); {
for (CGFloat pageOriginY = 0; pageOriginY < fittedSize.height; pageOriginY += pdfPageBounds.size.height) {
UIGraphicsBeginPDFPageWithInfo(pdfPageBounds, nil);
CGContextSaveGState(UIGraphicsGetCurrentContext()); {
CGContextTranslateCTM(UIGraphicsGetCurrentContext(), 0, -pageOriginY);
[self.tableView.layer renderInContext:UIGraphicsGetCurrentContext()];
} CGContextRestoreGState(UIGraphicsGetCurrentContext());
}
} UIGraphicsEndPDFContext();
self.tableView.bounds = priorBounds; // Reset the tableView
// Use the pdfData to
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];
//Get the docs directory
NSString *filePathPDF = [documentsPath stringByAppendingPathComponent:#"image.pdf"]; //Add the file name
[pdfData writeToFile:filePathPDF atomically:YES];
Any help will be appreciated.
After doing a lot R&D on this, finally I got the solution.
I know this to too late to post answer of above question, but I am posting my solution so it may help someone in future.
The trick which I used to avoid this issue is, Run the loop each section wise and took picture of each dynamic cell.
Then I started combining images of cells by below function,
- (UIImage*)imageByCombiningImage:(UIImage*)firstImage withImage:(UIImage*)secondImage {
UIImage *image1 = firstImage;
UIImage *image2 = secondImage;
CGSize size = CGSizeMake(image1.size.width, image1.size.height + image2.size.height);
UIGraphicsBeginImageContext(size);
[image1 drawInRect:CGRectMake(0,0,size.width, image1.size.height)];
[image2 drawInRect:CGRectMake(0,image1.size.height,size.width, image2.size.height)];
UIImage *finalImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//set finalImage to IBOulet UIImageView
return finalImage;
}
and to generate combined image, I used below logic. In that I checked the height of combine image, if it is greater than screen size or not.
Below is my whole logic of code,
CGRect priorBounds = self.tableView.bounds;
CGSize fittedSize = [self.tableView sizeThatFits:CGSizeMake(priorBounds.size.width, self.tableView.contentSize.height)];
self.tableView.bounds = CGRectMake(0, 0, fittedSize.width, fittedSize.height);
pdfViews = [[NSMutableArray alloc] init];
NSMutableData *pdfData = [[NSMutableData alloc] init];
float sections = [self.tableView numberOfSections];
for (int C = 0; C < sections; C++)
{
int rows = 0;
rows = [self.tableView numberOfRowsInSection:C];
for (int I = 0; I < rows; I++)
{
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:I inSection:C];
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
UIGraphicsBeginImageContextWithOptions(cell.bounds.size, cell.opaque, 0.0);
[cell.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *cellImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[pdfViews addObject:cellImage];
}
}
NSArray *pageArray = pdfViews;
UIImage *pdfFinalImage = [[UIImage alloc] init];
UIImage *addOnImage = [[UIImage alloc] init];
NSMutableArray *finalA = [[NSMutableArray alloc] init];
int checkHeight;
checkHeight = 1024;
for (int Z = 0; Z < [pdfViews count]; Z++)
{
if (Z == 0)
{
pdfFinalImage = [pageArray objectAtIndex:Z];
}else if (Z+1 == [pdfViews count])
{
addOnImage = [pageArray objectAtIndex:Z];
if (pdfFinalImage.size.height+addOnImage.size.height > checkHeight)
{
[finalA addObject:pdfFinalImage];
pdfFinalImage = [pageArray objectAtIndex:Z];
[finalA addObject:pdfFinalImage];
}else
{
pdfFinalImage = [self imageByCombiningImage:pdfFinalImage withImage:addOnImage];
[finalA addObject:pdfFinalImage];
}
}else
{
UIImage *heightCheckImage = [pageArray objectAtIndex:Z];
if (pdfFinalImage.size.height+heightCheckImage.size.height > checkHeight)
{
[finalA addObject:pdfFinalImage];
pdfFinalImage = [pageArray objectAtIndex:Z];
}else
{
addOnImage = [pageArray objectAtIndex:Z];
pdfFinalImage = [self imageByCombiningImage:pdfFinalImage withImage:addOnImage];
}
}
}
UIGraphicsBeginPDFContextToData(pdfData, CGRectMake(0, 0, 768, 1024), nil);
for (int IC = 0; IC < [finalA count]; IC++)
{
UIGraphicsBeginPDFPage();
UIImage *mainImage = [finalA objectAtIndex:IC];
NSData *jpegData = UIImageJPEGRepresentation(mainImage, 0.5);
CGDataProviderRef dp = CGDataProviderCreateWithCFData((__bridge CFDataRef)jpegData);
CGImageRef cgImage = CGImageCreateWithJPEGDataProvider(dp, NULL, true, kCGRenderingIntentDefault);
[[UIImage imageWithCGImage:cgImage] drawInRect:CGRectMake(0, 0, mainImage.size.width, mainImage.size.height)];
}
UIGraphicsEndPDFContext();
self.tableView.bounds = priorBounds;
[pdfData writeToFile:tmpPdfPath atomically:YES];

Issue using displaying Image with NSMutableArray

I am very new to xcode and I am playing around with image arrays and NSMutableArray. When I run the code below it just print out the names of the image for example "image1.png". Any tips to fix this problem would be appreciated. Thanks.
- (NSMutableArray*)restaurantArray;
{
if (_restaurantArray == nil) {
_restaurantArray = [[NSMutableArray alloc] initWithObjects:
#"image1.png",
#"image2.png",
#"image3.png",
nil];
}
return _restaurantArray;
}
-(NSString*) randomRestaurant
{
int random = arc4random_uniform(self.restaurantArray.count);
return [self.restaurantArray objectAtIndex:random];
}
You could do it in this way also.
- (NSMutableArray*)restaurantArray;
{
if (_restaurantArray == nil) {
_restaurantArray = [[NSMutableArray alloc] initWithObjects:[UIImage imageNamed:#"image1.png"],
[UIImage imageNamed:#"image2.png"],
[UIImage imageNamed:#"image3.png"],
nil];
}
return _restaurantArray;
}
Do you mean this?:
NSString *imageName = [self randomRestaurant];
UIImage *image = [UIImage imageName:imageName];
If you want to display the image then do this:
Suppose you have an imageview name imgView,
imgView.image = [UIImage imageNamed:[self randomRestaurant]];
Or, if you just want the image, then call this:
UIImage *img = [UIImage imageNamed:[self randomRestaurant]];
In you given code, you are just returning the name of the image, not the actual image. If you want an array of image then you can do it by this way:
-(NSMutableArray*) restaurantArray;
{
if (_restaurantArray == nil) {
UIImage *img = [UIImage imageNamed:#"image1.png"];
UIImage *img1 = [UIImage imageNamed:#"image2.png"];
UIImage *img2 = [UIImage imageNamed:#"image3.png"];
_restaurantArray = [[NSMutableArray alloc] initWithObjects:
img,
img1,
img2,
nil];
}
return _restaurantArray;
}
-(UIImage*) randomRestaurant
{
int random = arc4random_uniform(self.restaurantArray.count);
return [self.restaurantArray objectAtIndex:random];
}
Hope this helps.. :)

Clipping images using BezierPath and combining the images after clipping

I want to develop a small Jigsaw puzzle game but having problem when combining the image pieces. I can split image but cannot combine them as per my requirement. Here is what I am doing.
For cropping:
[customImageView setImage:[self cropImage:self.mainImage withRect:mCropFrame]];
- (UIImage *) cropImage:(UIImage*)originalImage withRect:(CGRect)rect
{
return [UIImage imageWithCGImage:CGImageCreateWithImageInRect([originalImage CGImage], rect)];
}
For Clipping:
[self setClippingPath:[pieceBezierPathsMutArray_ objectAtIndex:i]:view];
- (UIImageView *) setClippingPath:(UIBezierPath *)clippingPath : (UIImageView *)imgView;
{
if (![[imgView layer] mask])
{
[[imgView layer] setMask:[CAShapeLayer layer]];
}
[(CAShapeLayer*) [[imgView layer] mask] setPath:[clippingPath CGPath]];
return imgView;
}
For Combining:
-(id)initByCombining:(id)oneView andOther:(id)twoView withRegularSize:(CGSize)pieceSize;
{
CustomImageView *one = oneView;//[oneView copy];
CustomImageView *two = twoView;
CGPoint onepoint, twopoint;
if (one.frame.origin.x < two.frame.origin.x)
{
onepoint.x = 0;
twopoint.x = onepoint.x + one.frame.size.width;
}
else
{
onepoint.x = onepoint.x + one.frame.size.width;
twopoint.x = 0;
}
if (one.frame.origin.y < two.frame.origin.y)
{
onepoint.y = 0;
twopoint.y = 0;
}
else
{
onepoint.y = 0;
twopoint.y = 0;
}
CGRect frame;
frame.origin = CGPointZero;
frame.size.width = onepoint.x + one.frame.size.width + two.frame.size.width;
frame.size.height = MAX(one.frame.size.height , two.frame.size.height);
if (self = [self initWithFrame:frame])
{
UIGraphicsPushContext(UIGraphicsGetCurrentContext());
UIGraphicsBeginImageContext(frame.size);
[one.image drawAtPoint:onepoint];
[two.image drawAtPoint:twopoint];
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
self.image = UIGraphicsGetImageFromCurrentImageContext();
self.backgroundColor = [UIColor redColor];
UIGraphicsEndImageContext();
UIGraphicsPopContext();
self.center = one.center;
self.transform = CGAffineTransformScale(incomingTransform, 0.5, 0.5);
self.previousRotation = self.transform;
}
return self;
}
My initial image is this:
After cropping and clipping it becomes like this:
It should look like this after combining.
But it is becoming like this.
When You want to combine the Images I would suggest you to place the Clipping within another UIView , so that the UIView becomes a SuperView of all the Placed Clippings, after the Images have been Placed you can do something like this,
UIGraphicsBeginImageContextWithOptions(superView.bounds.size, superView.opaque, 0.0);
[superView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * CombinedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return CombinedImage;
and Then just save it as follows..
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library writeImageToSavedPhotosAlbum:[CombinedImage CGImage] orientation:(ALAssetOrientation)[SAVEIMAGE imageOrientation] completionBlock:^(NSURL *assetURL, NSError *error){
if (error) {
// TODO: error handling
UIAlertView *al=[[UIAlertView alloc]initWithTitle:#"" message:#"Error saving image, Please try again" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[al show];
} else {
NSData *imageData = UIImagePNGRepresentation(CombinedImage);
UIImage *finalImage=[UIImage imageWithData:imageData];
}
..Hope this helps

Loop add UIImageView Cocoa Touch

having a problem adding multiple ImageViews to my view. I have an array of images and what to cycle through them and add to my view. This snippet adds an image to view, but with no frame!
- (void)cycleImages:(NSArray *)images {
//create an image view
int fromLeft = 5;
int profilesCount = [images count] - 1;
for(int n = 0; n <= profilesCount; n++){
//add image view to view
[self.view addSubview:[[[UIImageView alloc] initWithFrame:CGRectMake(5, fromLeft, 48, 48)] initWithImage:[[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[images objectAtIndex:n]]]]]];
fromLeft = fromLeft + 53;
NSLog(#"%d", fromLeft);
}
}
Thanks for your help!
Dex
Its hard to read such code and you have mem leaks. Please, try this.
- (void)cycleImages:(NSArray *)images
{
int fromLeft = 5;
NSURL* url = nil;
UIImage* img = nil;
UIImageView* imgView = nil;
NSData* imgData = nil;
for (NSString* imgURLStr in images)//Using enumeration much more easy and in ObjC style
{
//Put breakpoint here and check all varibles initialized coorecly step by step
url = [NSURL URLWithString:imgURLStr];
imgData = [NSData dataWithContentsOfURL:url];
img = [[UIImage alloc] initWithData:imgData];
imgView = [[UIImageView alloc] initWithImage:img];
imgView.frame = CGRectMake(5, fromLeft, 48, 48);
[self.view addSubView:imgView];
fromLeft = fromLeft + 53;
NSLog(#"%d", fromLeft);
//Clean up
[img release];
[imgView release];
}
}
Thanks!

Resources