UIImage decompression causing scrolling lag

后端 未结 3 1407
执念已碎
执念已碎 2021-01-30 07:26

I have this app with a full screen tableView that displays a bunch of tiny images. Those images are pulled from the web, processed on a background thread, and then saved to disk

相关标签:
3条回答
  • 2021-01-30 07:59

    Another way image decompression:

     NS_INLINE void forceImageDecompression(UIImage *image)
     {
      CGImageRef imageRef = [image CGImage];
      CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
      CGContextRef context = CGBitmapContextCreate(NULL, CGImageGetWidth(imageRef), CGImageGetHeight(imageRef), 8, CGImageGetWidth(imageRef) * 4, colorSpace,kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little);
      CGColorSpaceRelease(colorSpace);
      if (!context) { NSLog(@"Could not create context for image decompression"); return; }
      CGContextDrawImage(context, (CGRect){{0.0f, 0.0f}, {CGImageGetWidth(imageRef), CGImageGetHeight(imageRef)}}, imageRef);
      CFRelease(context);
    }
    

    Using:

        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
      UIImage *image = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%u.jpg", pageIndex]];
      forceImageDecompression(image);
    
      dispatch_async(dispatch_get_main_queue(), ^{ 
        [((UIImageView*)page)setImage:image];
      });
    }
    
    0 讨论(0)
  • 2021-01-30 08:00

    Your problem is that +imageWithContentsOfFile: is cached and lazy loading. If you want to do something like this, instead use this code on your background queue:

    // Assuming ARC
    NSData* imageFileData = [[NSData alloc] initWithContentsOfFile:thumbPath];
    UIImage* savedImage = [[UIImage alloc] initWithData:imageFileData];
    
    // Dispatch back to main queue and set image...
    

    Now, with this code, the actual decompression of the image data will still be lazy and cost a little bit, but not nearly as much as the file access hit you're getting with the lazy loading in your code example.

    Since you're still seeing a performance issue, you can also force UIImage to decompress the image on the background thread:

    // Still on background, before dispatching to main
    UIGraphicsBeginImageContext(CGSizeMake(100, 100)); // this isn't that important since you just want UIImage to decompress the image data before switching back to main thread
    [savedImage drawAtPoint:CGPointZero];
    UIGraphicsEndImageContext();
    
    // dispatch back to main thread...
    
    0 讨论(0)
  • 2021-01-30 08:05

    Jason's tip about pre-drawing the image to decompress it is the key, but you'll get even better performance by copying the whole image and discarding the original.

    Images created at runtime on iOS seem to be better optimised for drawing than ones that have been loaded from a file, even after you've forced them to decompress. For that reason, you should load like this (it's also a good idea to put the decompressed image into an NSCache so you don't have to keep reloading it):

    - (void)loadImageWithPath:(NSString *)path block:(void(^)(UIImage *image))block
    {
        static NSCache *cache = nil;
        if (!cache)
        {
            cache = [[NSCache alloc] init];
        }
    
        //check cache first
        UIImage *image = [cache objectForKey:path];
        if (image)
        {
            block(image);
            return;
        }
    
        //switch to background thread
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
    
            //load image
            UIImage *image = [UIImage imageWithContentsOfFile:path];
    
            //redraw image using device context
            UIGraphicsBeginImageContextWithOptions(image.size, YES, 0);
            [image drawAtPoint:CGPointZero];
            image = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();
    
            //back to main thread
            dispatch_async(dispatch_get_main_queue(), ^{
    
                //cache the image
                [cache setObject:image forKey:path];
    
                //return the image
                block(image);
            });
        });
    }
    
    0 讨论(0)
提交回复
热议问题