È possibile creare una GIF animata utilizzando il framework Image I/O (che fa parte dell'SDK di iOS). Dovrai anche includere il framework MobileCoreServices
, che definisce la costante di tipo GIF. È necessario aggiungere questi quadri al vostro obiettivo, e importare le loro intestazioni nel file di cui si desidera creare l'immagine GIF animata, in questo modo:
#import <ImageIO/ImageIO.h>
#import <MobileCoreServices/MobileCoreServices.h>
E 'più facile da spiegare con l'esempio. Ti mostrerò il codice che ho usato per fare questa GIF sul mio iPhone 5:
In primo luogo, ecco una funzione di supporto che prende una dimensione e un angolo e restituisce un UIImage
del disco rosso in quel angolo:
static UIImage *frameImage(CGSize size, CGFloat radians) {
UIGraphicsBeginImageContextWithOptions(size, YES, 1); {
[[UIColor whiteColor] setFill];
UIRectFill(CGRectInfinite);
CGContextRef gc = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(gc, size.width/2, size.height/2);
CGContextRotateCTM(gc, radians);
CGContextTranslateCTM(gc, size.width/4, 0);
[[UIColor redColor] setFill];
CGFloat w = size.width/10;
CGContextFillEllipseInRect(gc, CGRectMake(-w/2, -w/2, w, w));
}
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
Ora possiamo creare la GIF. Per prima cosa definiamo una costante per il numero di fotogrammi, perché abbiamo bisogno di due volte in seguito:
static void makeAnimatedGif(void) {
static NSUInteger const kFrameCount = 16;
avremo bisogno di un dizionario di proprietà per specificare il numero di volte in cui l'animazione deve ripetere:
NSDictionary *fileProperties = @{
(__bridge id)kCGImagePropertyGIFDictionary: @{
(__bridge id)kCGImagePropertyGIFLoopCount: @0, // 0 means loop forever
}
};
E avremo bisogno di un altro dizionario proprietà, che ci attribuiamo ad ogni fotogramma, specificando quanto tempo quel lasso dovrebbe essere visualizzato:
NSDictionary *frameProperties = @{
(__bridge id)kCGImagePropertyGIFDictionary: @{
(__bridge id)kCGImagePropertyGIFDelayTime: @0.02f, // a float (not double!) in seconds, rounded to centiseconds in the GIF data
}
};
creeremo anche un URL per il GIF in nostro Do cumenti directory:
NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:nil];
NSURL *fileURL = [documentsDirectoryURL URLByAppendingPathComponent:@"animated.gif"];
Ora possiamo creare una CGImageDestination
che scrive una GIF all'URL specificato:
CGImageDestinationRef destination = CGImageDestinationCreateWithURL((__bridge CFURLRef)fileURL, kUTTypeGIF, kFrameCount, NULL);
CGImageDestinationSetProperties(destination, (__bridge CFDictionaryRef)fileProperties);
ho scoperto che passando fileProperties
come ultimo argomento di CGImageDestinationCreateWithURL
fa non lavoro. Devi usare CGImageDestinationSetProperties
.
Ora siamo in grado di creare e scrivere i nostri telai:
for (NSUInteger i = 0; i < kFrameCount; i++) {
@autoreleasepool {
UIImage *image = frameImage(CGSizeMake(300, 300), M_PI * 2 * i/kFrameCount);
CGImageDestinationAddImage(destination, image.CGImage, (__bridge CFDictionaryRef)frameProperties);
}
}
Nota che passiamo le proprietà del frame dictionary lungo ogni immagine frame con.
Dopo abbiamo aggiunto esattamente il numero di fotogrammi specificato, abbiamo finalizzare la destinazione e rilasciarlo:
if (!CGImageDestinationFinalize(destination)) {
NSLog(@"failed to finalize image destination");
}
CFRelease(destination);
NSLog(@"url=%@", fileURL);
}
Se si esegue questo sul simulatore, è possibile copiare l'URL dalla console di debug e incolla nel tuo browser per vedere l'immagine. Se lo si esegue sul dispositivo, è possibile utilizzare la finestra Xcode Organizer per scaricare la sandbox dell'app dal dispositivo e osservare l'immagine. Oppure puoi utilizzare un'app come iExplorer
che ti consente di sfogliare direttamente il filesystem del dispositivo. (Questo non richiede il jailbreak.)
Ho provato questo sul mio iPhone 5 con iOS 6.1, ma credo che il codice dovrebbe funzionare fin da iOS 4.0.
Ho messo tutto il codice in this gist per una facile copia.
Questo è qualcosa che stavo cercando da un po '. (Creazione di GIF animate). La generazione effettiva dell'immagine è abbastanza banale e abbastanza facile da sostituire con il codice dalla mia applicazione. Il difficile è creare l'immagine GIF attuale e mi hai dato tutto ciò di cui ho bisogno per farlo. Grazie! (Votato) –
D'accordo con Duncan - grazie Rob! Devo ancora dare un vortice a questa sera, ma è tutto quello che stavo cercando ... grazie ancora !! – crgt
Rob, oggi ho lavorato con la tua tecnica, ma c'è un grosso limite. Il sistema conserva i dati per tutte le immagini nella sequenza di animazione in memoria fino al completamento della chiamata finalizzata. Sto creando alcune sequenze GIF piuttosto grandi, e con 30 FPS non ci vuole molto per esaurire memoria e crash. C'è un modo per tamponare i frame su disco in qualche modo? Sto creando i miei CGImages da OpenGL e utilizzando un fornitore di dati. Esiste una forma di fornitore di dati che legge i contenuti da un file. Mi chiedo se leggerà ogni frame a turno e lo rilascerà mentre finalizza la GIF. –