IOS about GIF pictures that little thing

Source: Internet
Author: User

Objective

One of the things that we did in our project group a few days ago was that we stored animated GIFs into albums in our app, and saved the images into static images. While Weibo can be saved correctly, this is not a technology is not achievable. Shortly before I saw Apple's guide to the ImageIO framework, I took this opportunity to investigate the story.

Using UIImage to read GIF pictures is insufficient

The UIImage class is the most commonly used storage image class in the Uikit framework. This class provides a class method that can be instantiated using either the picture path or the picture data. The UIImage class uses the ImageIO framework to read the picture data, respectively, +imagewithcontentsoffile: and +imagewithdata: The stack of calls.

Image stack. png

From the stack we can see the approximate flow of picture reads as follows:

    1. Generate Cgimagesource based on file path or data;

    2. Then call the Cgimagesourcecreateimageatindex method to get a picture of a frame, type cgimage;

    3. Let the UIImage object hold the Cgimage.

The cgimagesource generated in the first step of the process still retains all of the GIF's information. And in the second step of the process there is a problem. A dynamic GIF is different from a static format picture, and it contains multiple static images. Cgimagesourcecreateimageatindex can only return images of indexed values, and other picture information is missing. Therefore, we only get one frame of the picture. Out of curiosity, I chose a four-frame gif that was completely different, and by testing it, UIImage gets the first frame of the picture. Since we cannot use uiimage or cgimage to manipulate GIFs, can we downgrade them and use the IMAGEIO framework to deal with them? The answer is yes.

Using the ImageIO framework to parse GIF pictures

I refer to the design of the Yyimage framework, which defines two classes that are responsible for parsing the GIF image data for the Jwgifdecoder and Jwgifframe,jwgifdecoder classes, and jwgifframe representing the frames. The header files for both are as follows:

#import

#import "JWGifFrame.h"

@Interface jwgifdecoder : nsobject

@Property (nonatomic,readonly) nsdata *data; /**

#import

#import

@Interface jwgifframe : nsobject

@Property (nonatomic,assign) nsuinteger index; /**

Jwgifdecoder internally uses Cgimagesource to parse the image data. At the time of instantiation, the class uses the Cgimagesourcecreatewithdata () method (where the C language method ignores parameters) and then uses the Cgimagesourcegetcount () Cgimagesource Gets the number of images inside it, which is the frame count. When the frame object is generated, the Cgimagesourcecopypropertiesatindex () method is used to obtain the properties of the corresponding frame, and the image is obtained by the Cgimagesourcecreateimageatindex () method.

#import "JWGifDecoder.h"

#import

@Interface jwgifdecoder ()

{

cgimagesourceref _source;

}

@End

@Implementation Jwgifdecoder

+(instancetype)decoderwithdata:(nsdata *)data

{

if ( ! Data ) return nil;

Jwgifdecoder *Decoder = [[jwgifdecoder alloc] init];

[Decoder _decoderpreparewithdata:data];

return decoder;

}

- (void)dealloc

{

cfrelease(_source);

}

-(void)_decoderpreparewithdata:(nsdata *)data

{

_data = data;

_source = cgimagesourcecreatewithdata((__bridge cfdataref)data, NULL );

_framecount = cgimagesourcegetcount(_source);

Cfdictionaryref Properties = cgimagesourcecopyproperties(_source , NULL);

cfdictionaryref gifproperties = cfdictionarygetvalue(properties , Kcgimagepropertygifdictionary);

Cftyperef Loop = cfdictionarygetvalue(gifproperties , Kcgimagepropertygifloopcount);

if (loop) cfnumbergetvalue(loop, Kcfnumbernsintegertype, &_loopcount);

cfrelease(properties);

}

-(jwgifframe *)frameatindex:(nsuinteger)index

{

if ( index >= _framecount ) return nil;

jwgifframe *Frame = [[jwgifframe alloc] init];

frame. Index = index;

nstimeinterval Duration = 0;

cfdictionaryref frameproperties = cgimagesourcecopypropertiesatindex(_source, index, NULL);

cfdictionaryref gifframeproperties = cfdictionarygetvalue(frameproperties, kcgimagepropertygifdictionary);

cftyperef delaytime = cfdictionarygetvalue(gifframeproperties , Kcgimagepropertygifunclampeddelaytime);

if(delaytime) cfnumbergetvalue(delaytime, Kcfnumberdoubletype, &duration);

cfrelease(frameproperties);

frame. Duration = duration;

cgimageref cgimage = cgimagesourcecreateimageatindex(_source, index, NULL);

UIImage *Image = [UIImage imagewithcgimage:cgimage];

frame. Image = image;

cfrelease(cgimage);

return frame;

}

Save GIF images to albums

The UIImage only retains one frame of information, while the picture's data has all the GIF data. Therefore, there is a principle that the album reads the GIF format Picture: When you save the picture to the album, you must save the picture's data instead of the UIImage object.

IOS8 The following alassetslibrary framework handles albums, and above IOS8, the photos framework is used. In this blog (HTTP://WWW.JIANSHU.COM/P/AD391F4D0BCB) said that the use of photos in IOS8 will not be saved, because there is no IOS8 system of mobile phones, I can not do the relevant tests. Currently testing my hand on the IOS10 system of iphone6s, can be saved successfully, save the GIF picture can be successfully sent in. The code to save the album is as follows:

NSString *Path = [[nsbundle mainbundle] pathforresource:@"Niconiconi " ofType:@" gif "];

NSData *Data = [nsdata datawithcontentsoffile:path];

if ([uidevice currentdevice]. Systemversion. Floatvalue >= 9.0f) {

[[phphotolibrary sharedphotolibrary] performchanges: ^{

phassetresourcecreationoptions *Options = [[phassetresourcecreationoptions Alloc ] init];

[[phassetcreationrequest creationrequestforasset] addresourcewithtype: Phassetresourcetypephoto Data:data options:options];

} completionhandler: ^(BOOL success, nserror * _ Nullable error) {

NSLog(@"Save succeeded:%d",success);

}];

}

Else {

alassetslibrary *Library = [[alassetslibrary alloc] init];

[Library writeimagedatatosavedphotosalbum:data metadata:nil Completionblock: ^(nsurl *asseturl, nserror *error) {

}];

}

Conclusion

The ImageIO framework gives us a more powerful picture processing capability, which can handle images in GIF format that uiimage cannot cope with. For things that the more advanced API can't handle, try a lower-level framework to see if it's working. Found a lot of content in the Apple Guide is explained, later need to look more.

There are a lot of things that are not covered in this article, such as a photo album that reads GIF images, or a code that saves a picture as a GIF (which is mentioned in Apple's Guide), and so on.

Reference

    • Image I/O Programming Guide

      Http://t.cn/RfPbLdM

    • iOS Development-gif image upload

      Http://t.cn/Rt39huW

    • Github:yywebimage

      Http://t.cn/RUSClXb

    • ImageIO and image decoding in iOS

      http://t.cn/RtwyP52

IOS about GIF pictures that little thing

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.