Создать и экспортировать анимированный GIF через iOS?

У меня есть серия настроенных пользователем изображений в приложении для iOS, которые анимируются в простом, покадровом стиле флипбук.

У меня такой вопрос: есть ли способ разрешить пользователям экспортировать свою анимацию в виде анимированного GIF? В идеале, я бы хотел, чтобы они могли по электронной почте, в социальных сетях (T /FB) или (в худшем случае ...) сохранять анимированный GIF-файл в папку с документами для поиска через iTunes.

Я знаю, как сохранить файл .png в библиотеке фотографий, и я нашел способ записать анимацию в виде файла QT ( http://www.cimgf.com/2009/02/03/record-your-core-animation-animation/) , но я не нашел способ просто выкинуть простой старый анимированный GIF. Я что-то упускаю в Core Animation или где-то еще? Есть ли какие-либо подходы, рамки или ресурсы, которые кто-нибудь может порекомендовать? Извините, если вопрос слишком общий - трудно найти отправную точку.

70 голосов | спросил crgt 17 FebruaryEurope/MoscowbSun, 17 Feb 2013 01:09:32 +0400000000amSun, 17 Feb 2013 01:09:32 +040013 2013, 01:09:32

3 ответа


0

Вы можете создать анимированный GIF-файл с помощью инфраструктуры ввода-вывода изображения (которая является частью iOS SDK). Вы также захотите включить структуру MobileCoreServices, которая определяет константу типа GIF. Вам нужно добавить эти фреймворки к вашей цели и импортировать их заголовки в файл, где вы хотите создать анимированный GIF, например:

#import <ImageIO/ImageIO.h>
#import <MobileCoreServices/MobileCoreServices.h>

Это проще всего объяснить на примере. Я покажу вам код, который использовал для создания этого GIF-файла на моем iPhone 5:

анимированный GIF, созданный с помощью показанного кода

Во-первых, вот вспомогательная функция, которая принимает размер и угол и возвращает UIImage красного диска под этим углом:

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;
}

Теперь мы можем создать GIF. Сначала мы определим константу для количества кадров, потому что она понадобится нам дважды позже:

static void makeAnimatedGif(void) {
    static NSUInteger const kFrameCount = 16;

Нам понадобится словарь свойств, чтобы указать, сколько раз анимация должна повторяться:

    NSDictionary *fileProperties = @{
        (__bridge id)kCGImagePropertyGIFDictionary: @{
            (__bridge id)kCGImagePropertyGIFLoopCount: @0, // 0 means loop forever
        }
    };

И нам понадобится еще один словарь свойств, который мы будем прикреплять к каждому фрейму, определяя, как долго должен отображаться этот фрейм:

    NSDictionary *frameProperties = @{
        (__bridge id)kCGImagePropertyGIFDictionary: @{
            (__bridge id)kCGImagePropertyGIFDelayTime: @0.02f, // a float (not double!) in seconds, rounded to centiseconds in the GIF data
        }
    };

Мы также создадим URL для GIF в нашем каталоге документов:

    NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:nil];
    NSURL *fileURL = [documentsDirectoryURL URLByAppendingPathComponent:@"animated.gif"];

Теперь мы можем создать CGImageDestination, который записывает GIF в указанный URL-адрес:

    CGImageDestinationRef destination = CGImageDestinationCreateWithURL((__bridge CFURLRef)fileURL, kUTTypeGIF, kFrameCount, NULL);
    CGImageDestinationSetProperties(destination, (__bridge CFDictionaryRef)fileProperties);

Я обнаружил, что передача fileProperties в качестве последнего аргумента CGImageDestinationCreateWithURL не работает. Вы должны использовать CGImageDestinationSetProperties.

Теперь мы можем создавать и записывать наши фреймы:

    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);
        }
    }

Обратите внимание, что мы передаем словарь свойств кадра вместе с каждым изображением кадра.

После того, как мы добавили ровно указанное количество кадров, мы завершим пункт назначения и освободим его:

    if (!CGImageDestinationFinalize(destination)) {
        NSLog(@"failed to finalize image destination");
    }
    CFRelease(destination);

    NSLog(@"url=%@", fileURL);
}

Если вы запустите это на симуляторе, вы можете скопировать URL-адрес из консоли отладки и вставить его в браузер, чтобы увидеть изображение. Если вы запустите его на устройстве, вы можете использовать окно Xcode Organizer, чтобы загрузить изолированную программную среду приложения с устройства и посмотреть изображение. Или вы можете использовать приложение вроде iExplorer, которое позволяет вам напрямую просматривать файловую систему вашего устройства. (Это не требует джейлбрейка.)

Я проверил это на своем iPhone 5 под управлением iOS 6.1, но я считаю, что код должен работать еще в iOS 4.0.

Я поместил весь код в этот список для удобства копирования.

ответил rob mayoff 17 FebruaryEurope/MoscowbSun, 17 Feb 2013 03:01:36 +0400000000amSun, 17 Feb 2013 03:01:36 +040013 2013, 03:01:36
0

Если вы ищете решение Swift 3, вы можете взглянуть на https://github.com /onmyway133 /GifMagic . У него есть Encoder и Decoder, который собирает и разбирает gif файл.

По сути, вы должны использовать среду Image IO с этими функциями CGImageDestinationCreateWithURL, CGImageDestinationSetProperties, CGImageDestinationAddImage, CGImageDestinationFinalize

Также с Swift https: //developer. apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/WorkingWithCocoaDataTypes.html

  

Базовые объекты Foundation, возвращаемые из аннотированных API, автоматически управляются памятью в Swift - вам не нужно самим вызывать функции CFRetain, CFRelease или CFAutorelease.

ответил onmyway133 1 PM000000120000001931 2017, 12:02:19
0

Для Swift 3

import Foundation
import UIKit
import ImageIO
import MobileCoreServices

extension UIImage {
    static func animatedGif(from images: [UIImage]) {
        let fileProperties: CFDictionary = [kCGImagePropertyGIFDictionary as String: [kCGImagePropertyGIFLoopCount as String: 0]]  as CFDictionary
        let frameProperties: CFDictionary = [kCGImagePropertyGIFDictionary as String: [(kCGImagePropertyGIFDelayTime as String): 1.0]] as CFDictionary

        let documentsDirectoryURL: URL? = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
        let fileURL: URL? = documentsDirectoryURL?.appendingPathComponent("animated.gif")

        if let url = fileURL as CFURL? {
            if let destination = CGImageDestinationCreateWithURL(url, kUTTypeGIF, images.count, nil) {
                CGImageDestinationSetProperties(destination, fileProperties)
                for image in images {
                    if let cgImage = image.cgImage {
                        CGImageDestinationAddImage(destination, cgImage, frameProperties)
                    }
                }
                if !CGImageDestinationFinalize(destination) {
                    print("Failed to finalize the image destination")
                }
                print("Url = \(fileURL)")
            }
        }
    }
}

Я преобразовал его из приведенного выше ответа . Надеюсь, это поможет.

Доступен в виде gist .

Изменения приветствуются.

ответил Nikhil Manapure 7 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowThu, 07 Sep 2017 15:05:37 +0300 2017, 15:05:37

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132