Use pre-rendering to accelerate image display on iOS devices

Source: Internet
Author: User

I recently made a UITableView example and found that the rolling performance is good. But when you scroll back and forth, the image displayed for the first time is not as smooth as the image displayed again, and there will be a slight pause before it appears.

So I guess the displayed image must have been cached. After checking the document, I found that it is true.

Later, I found some tips in other articles: when the image is displayed, decompression and re-sampling will consume a lot of CPU time. If the image is drawn in a bitmap context in advance, then cache the image to save the effort.

Then I wrote a subprogram for verification:

 
 
  1. //  ImageView.h 
  2.  
  3. #import <UIKit/UIKit.h> 
  4.  
  5.  
  6. @interface ImageView : UIView { 
  7.     UIImage *image; 
  8.  
  9. @property (retain, nonatomic) UIImage *image; 
  10.  
  11. @end 
 
 
  1. //  ImageView.m 
  2.  
  3. #include <mach/mach_time.h> 
  4. #import "ImageView.h" 
  5.  
  6.  
  7. @implementation ImageView 
  8.  
  9. #define LABEL_TAG 1 
  10.  
  11. static const CGRect imageRect = {{0, 0}, {100, 100}}; 
  12. static const CGPoint imagePoint = {0, 0}; 
  13.  
  14. @synthesize image; 
  15.  
  16. - (void)awakeFromNib { 
  17.     if (!self.image) { 
  18.         self.image = [UIImage imageNamed:@"random.jpg"]; 
  19.     } 
  20.  
  21. - (void)drawRect:(CGRect)rect { 
  22.     if (CGRectEqualToRect(rect, imageRect)) { 
  23.         uint64_t start = mach_absolute_time(); 
  24.         [image drawAtPoint:imagePoint]; 
  25.         uint64_t drawTime = mach_absolute_time() - start; 
  26.          
  27.         NSString *text = [[NSString alloc] initWithFormat:@"%ld", drawTime]; 
  28.         UILabel *label = (UILabel *)[self viewWithTag:LABEL_TAG]; 
  29.         label.text = text; 
  30.         [text release]; 
  31.     } 
  32.  
  33. - (void)dealloc { 
  34.     [super dealloc]; 
  35.     [image release]; 
  36.  
  37. @end 

I will not list the Controller code. When I click a button, update view (call [self. view setNeedsDisplayInRect: imageRect]), draw a picture, and display the time consumed in the label.

It is worth mentioning that on the simulator, you can use the clock () function to obtain the precision in microseconds, but on iOS devices, the precision is 10 milliseconds. So I found mach_absolute_time (), which has a nanosecond precision on Mac and iOS devices.

The test uses a 300 x pixel JPEG image, which is named with @ 2x added. It takes about microseconds for the first display on iPhone 4 and 65 microseconds for the second display.

The next step is to witness the miracle and add this code to the program:

 
 
  1. static const CGSize imageSize = {100, 100}; 
  2.  
  3. - (void)awakeFromNib { 
  4.     if (!self.image) { 
  5.         self.image = [UIImage imageNamed:@"random.jpg"]; 
  6.         if (NULL != UIGraphicsBeginImageContextWithOptions) 
  7.             UIGraphicsBeginImageContextWithOptions(imageSize, YES, 0); 
  8.         else 
  9.             UIGraphicsBeginImageContext(imageSize); 
  10.         [image drawInRect:imageRect]; 
  11.         self.image = UIGraphicsGetImageFromCurrentImageContext(); 
  12.         UIGraphicsEndImageContext(); 
  13.     } 

Here, you need to determine whether uigraphicsbeginimagecontextwitexceptions is NULL because it is added to iOS 4.0.

Since the JPEG image is not transparent, the second parameter is set to YES.

The third parameter is the scaling ratio, iPhone 4 is 2.0, and others are 1.0. Although [UIScreen mainScreen]. scale can be used here, the system automatically sets the correct proportion after it is set to 0.

It is worth mentioning that the image itself also has a scaling ratio. The common image is 1.0 (except for UIImage imageNamed:, most APIs can only obtain this image, and the zoom ratio cannot be changed), the HD image is 2.0. The image points and pixels on the screen are calculated based on the scaling ratio of the two. For example, a normal image is on the retina display, while a high-definition image is on the retina display.

Next, drawInRect: draws the image to the current image context, and completes understanding of compression and re-sampling. Then obtain the new image from the image context. The scaling ratio of the image can also be correctly matched with the device.

Click the button again to find that the time has been reduced to about 12 microseconds, and the drawing is stable at around 15 microseconds.

Can it be faster? Let's try Core Graphics.

First, define a global CGImageRef variable:

 
 
  1. static CGImageRef imageRef; 

Set its value in awakeFromNib:

 
 
  1. imageRef = self.image.CGImage; 

Finally, draw in drawRect:

 
 
  1. CGContextRef context = UIGraphicsGetCurrentContext(); 
  2. CGContextDrawImage(context, imageRect, imageRef); 

After running the task, we found that the time was increased to about 33 microseconds, and the image was upside down and upside down.

This is because the Y axis of the coordinate system of UIKit and Core Graphics is the opposite, so we can add two lines of code to fix it:

 
 
  1. CGContextRef context = UIGraphicsGetCurrentContext(); 
  2. CGContextTranslateCTM(context, 0, 100); 
  3. CGContextScaleCTM(context, 1, -1); 
  4. CGContextDrawImage(context, imageRect, imageRef); 

It seems that the time is reduced to about 14 microseconds, and the result is not very effective. It seems that it is good to use-drawAtPoint: And-drawInRect: directly. Of course, the correct method for this example is viewDidLoad or loadView, but I am too lazy to list the Controller code, so I put it in awakeFromNib.

Related Article

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.