ImageIO and image decoding in iOS

Source: Internet
Author: User

ImageIO to open up the object has Cgimagesourceref, Cgimagedestinationref, not open to the object has cgimagemetadataref. There are cgimageref and Cgdataprovider objects in coregraphics that often deal with ImageIO, and then look at the roles that these five objects assume in creating a uiimage.

Using Timeprofiler Step-by-step to create a function called internally during the UIImage process can help us solve the problem, because the Timeprofiler statistical function stack is counted once for a period of time, resulting in no calls to all functions, and each function stack may be inconsistent, So it's impossible to tell exactly how a function stack is called, but it's possible to guess what each step does.

The code from CFDATAREF to UIImage is as follows

NSString *resource = [[nsbundle mainbundle] pathforresource:@ "the_red _batman " ofType:@" PNG "];

NSData *data = [nsdata datawithcontentsoffile: Resource options:0 Error : nil];

Cfdataref Dataref = (__bridge cfdataref)data;

Cgimagesourceref Source = cgimagesourcecreatewithdata(dataref, Nil );

Cgimageref cgimage = cgimagesourcecreateimageatindex(source, 0, Nil);

UIImage *image = [UIImage imagewithcgimage: Cgimage];

Cgimagsourcecreatewithdata

The intrinsic function _cgimagereadcreate is called, which means that cgimagesourceref is related to reading the image data.

Cgimagesourcecreateimageatindex

_cg_png_read_info and cgimagemetadatacreatemutable are called, and when the Cgimageref is built, the underlying data and metadata of the image are read, and the underlying data includes the header chunk of the image, such as PNG's IHDR. Meta data is abstracted by Cgimagemetadataref. And did not read the image of other data, but also do not do the decoding action.

Interestingly, if you call Cgimagesourcecopypropertiesatindex

Cgimagesourcecopypropertiesatindex's intrinsic function calls the cgimagemetadataref, and if you add a comment to the imageio/cgimagemetadata.h file

@description cgimagemetadata APIs allow clients to view and modify metadata

For popular image formats. ImageIO supports the EXIF, IPTC, and XMP

Metadata specifications. Refer to CGImageSource.h for functions to

Read metadata from a cgimagesource, and CGImageDestination.h for functions to

Write metadata to a cgimagedestination. Cgimagedestinationcopyimagesource can

be used to modify metadata without recompressing the image.

The Description Cgimagemetadataref abstracts the metadata of the Exif, IPTC, and XMP formats in the image, and if you want to get cgimagemetadataref you have to go through cgimagesourceref.

Similarly, look at the internal function call for Cgdataproviderref, the code is as follows

Change Cgimagesourceref from Cgdataproviderref to create

Cfdataref Dataref = (__bridge cfdataref)data;

Cgdataproviderref Dataprovider = cgdataprovidercreatewithcfdata(dataref);

Cgimagesourceref Source = cgimagesourcecreatewithdataprovider(dataprovider, nil);

The test is obtained by Cgimageref Cgdataproviderref and created by Cgdataproviderref Cgimageref

Cgdataproviderref Newdataprovider = cgimagegetdataprovider(cgimage);

size_t Width = cgimagegetwidth(cgimage);

size_t Height = cgimagegetheight(cgimage);

Cgcolorspaceref Space = cgimagegetcolorspace(cgimage);

size_t bitspercomponent = cgimagegetbitspercomponent(cgimage);

size_t bitsperpixel = cgimagegetbitsperpixel(cgimage);

size_t Bytesperrow = cgimagegetbytesperrow(cgimage);

Cgbitmapinfo bitmapinfo = cgimagegetbitmapinfo(cgimage);

Cgdataproviderref Newdataprovider = cgimagegetdataprovider(cgimage);

Cgimageref newimage = cgimagecreate(width, height, Bitspercomponent, bitsperpixel, bytesperrow, space, Bitmapinfo, newdataprovider, NULL, false, Kcgrenderingintentdefault);

Unfortunately, there is no function call to find out about Cgdataproviderref. Could not conclude what Cgdataproviderref had done.

Look at the internal function calls for Cgimagedestinationref, and the code and intrinsic functions are called as follows

Cfmutabledataref Buffer = cfdatacreatemutable(kcfallocatordefault, 0); cgimagedestinationref Destination = cgimagedestinationcreatewithdata(buffer , kuttypepng, 1, NULL);

Cgimagedestinationaddimage(destination, cgimage, nil);

Cgimagedestinationfinalize(destination);

Cgimagedestinationref writes the image data to the destination, and is responsible for image coding or image compression.

Test conclusion

CGIMAGESOURCEREF abstract the channel to read the image data, read the image through it, it itself does not read any data of the image, when you call Cgimagesourcecopypropertiesatindex will read the image metadata.

Cgimagemetadataref abstract The image of Exif, IPTC, XMP format metadata, obtained through the cgimagesourceref.

CGIMAGEREF abstract the basic data and metadata of the image, when it is created, it will read the basic data and metadata of the image through Cgimagesourceref, but no other data of the image is read, and no image decoding action is done.

Cgdataproviderref did not come up with useful information.

Cgimagedestinationref Abstract writes the channel of the image data, writes the image to pass it, when writes the picture The time also is responsible for the picture encoding.

Image decoding

You can see from the cfdataref until you create the uiimage, have not called the image decoding function, only read some of the image base data and metadata.

When did the image decode occur? In the Imageio/cgimagesource.h file Kcgimagesourceshouldcache the above actually has a clear comment.

Specifies whether image decoding and caching should happen at image creation time.

The value of this key must is a cfbooleanref. The default value is Kcfbooleanfalse (image decoding would happen at rendering time).

If you do not set the image manually, it will only wait until the screen is rendered and then decoded. Tested, that's true. This kcgimagesourceshouldcacheimmediately might as well be named kcgimagesourceshoulddecodeimmediately.

Where exactly is image decoding done?

If you render a picture on the canvas, the picture must be decoded. The following code runs the test again

size_t Width = cgimagegetwidth(cgimage);

size_t Height = cgimagegetheight(cgimage);

Cgimagealphainfo alphainfo = cgimagegetalphainfo(cgimage) & Kcgbitmapalphainfomask;

BOOL Hasalpha = NO;

If (alphainfo = = Kcgimagealphapremultipliedlast | |

alphainfo = = Kcgimagealphapremultipliedfirst | |

alphainfo = = Kcgimagealphalast | |

alphainfo = = Kcgimagealphafirst) {

Hasalpha = YES;

}

Cgbitmapinfo bitmapinfo = kcgbitmapbyteorder32host;

Bitmapinfo |= hasalpha ? kcgimagealphapremultipliedfirst : Kcgimagealphanoneskipfirst ;

Cgcontextref Context = cgbitmapcontextcreate(NULL, width, height , 8, 0, cgcolorspacecreatedevicergb(), bitmapinfo );

Cgcontextdrawimage(context, cgrectmake(0, 0, Width, height), cgimage);

Cgimageref newimage = cgbitmapcontextcreateimage(context);

There are no obvious decompress or decode words in the function names of all calls. And the above four function calls are the highest frequency. Based on the png_compress_idat of the cgimagedestinationref call, guessing Png_read_idat_data is the function of decoding.

The above is a PNG image as a test case, below to see the JPEG image

It is obvious that the Decode method of Applejpeg is to do the decoding function. JPEG and PNG call two of the same functions, while different images tune different decoding functions. When you draw a picture on the canvas, you call Imageprovidercopyimageblocksetcallback settings callback, then call Copyimageblock, and then call the set callback, However, the decoding function is called by Copyimageblock or by callback and cannot be verified.

Does that imageprovidercopyimageblocksetcallback have anything to do with Cgdataprovidercopydata? After testing, Imageprovidercopyimageblocksetcallback and Copyimageblock are also called inside the Cgdataprovidercopydata. And the cfdataref that Cgdataprovidercopydata gets is a decoded array of pixels.

Conclusion: Image decoding takes place within the Cgdataprovidercopydata function called the callback or Copyimageblock function of the Imageprovidercopyimageblocksetcallback setting, Different methods are called depending on the picture format.

Initialization method of Image

Imagewithdata from the invocation of an intrinsic function, Cgimagesourceref accesses the image data and creates a cgimageref.

Imagewithcontentsoffile internal calls are as follows

The file creates cgimageref by Mmap to memory and then accessing the image data through Cgimagesourceref.

Imagenamed first finds the resource path from the bundle, then also mmap the file into memory, and then accesses the image data through cgimagesourceref, creating cgimageref.

the cache for image

See if different methods have cached behavior by calling different UIImage initialization methods and then creating Uiimageview to display on the screen.

Imagenamed does not call ImageIO any method when the same image is displayed for the second time.

Imagewithdata and Imagewithcontentsoffile Call the ImageIO decoding method the second time they display the same image.

The uiimage created by the Imagewithdata and Imagewithcontentsoffile initialization methods will not invoke the ImageIO decoding method as long as they are not released.

The conclusion is that there are two kinds of caches for uiimage, one is the cache of the UIImage class, which guarantees that the uiimage of imagenamed initialization will only be decoded once. The other is the cache of the UIImage object, which guarantees that the uiimage is not decoded as long as it is not released.

The Kcgimagesourceshouldcache option for the Cgimagesourcecreateimageatindex method refers to the second kind of cache, and if set to false, I test out that the image is still not decoded when it is rendered again. It's a little strange. If you have a detailed knowledge of what is going on, please enlighten me.

Finally attach ImageIO's family photo

ImageIO and image decoding in iOS

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.