Repository: SDWebImage/SDWebImage
File: SDWebImage/Core/SDImageIOCoder.m (Objective-C)

Code before:
    
    // `CGPDFDocumentGetPage` page number is 1-indexed.
    CGPDFPageRef page = CGPDFDocumentGetPage(document, pageNumber + 1);
    if (!page) {
        CGPDFDocumentRelease(document);
        return nil;
    }
    
    CGPDFBox box = kCGPDFMediaBox;
    CGRect rect = CGPDFPageGetBoxRect(page, box);
    CGRect targetRect = rect;
    if (!CGSizeEqualToSize(targetSize, CGSizeZero)) {
        targetRect = CGRectMake(0, 0, targetSize.width, targetSize.height);
    }
    
    CGFloat xRatio = targetRect.size.width / rect.size.width;
    CGFloat yRatio = targetRect.size.height / rect.size.height;
    CGFloat xScale = preserveAspectRatio ? MIN(xRatio, yRatio) : xRatio;
    CGFloat yScale = preserveAspectRatio ? MIN(xRatio, yRatio) : yRatio;
    
    // `CGPDFPageGetDrawingTransform` will only scale down, but not scale up, so we need calculate the actual scale again
    CGRect drawRect = CGRectMake( 0, 0, targetRect.size.width / xScale, targetRect.size.height / yScale);
    CGAffineTransform scaleTransform = CGAffineTransformMakeScale(xScale, yScale);
    CGAffineTransform transform = CGPDFPageGetDrawingTransform(page, box, drawRect, 0, preserveAspectRatio);
    
    SDGraphicsBeginImageContextWithOptions(targetRect.size, NO, 0);
    CGContextRef context = SDGraphicsGetCurrentContext();
    
#if SD_UIKIT || SD_WATCH
    // Core Graphics coordinate system use the bottom-left, UIKit use the flipped one
    CGContextTranslateCTM(context, 0, targetRect.size.height);
    CGContextScaleCTM(context, 1, -1);
#endif
    
    CGContextConcatCTM(context, scaleTransform);
    CGContextConcatCTM(context, transform);
    
    CGContextDrawPDFPage(context, page);
    
    image = SDGraphicsGetImageFromCurrentImageContext();
    SDGraphicsEndImageContext();
    
    CGPDFDocumentRelease(document);
    
    return image;
}

#pragma mark - Decode
- (BOOL)canDecodeFromData:(nullable NSData *)data {
    return YES;
}

Review comment (performance):
This change does not do anything performance benefit. `UIGraphicsImageRenderer` should be only used **When render this CGImage into screen, need dynamic bitmap info**

Learn WWDC: https://developer.apple.com/videos/play/wwdc2018/219/. Which tell you `How UIKit introduce dynamic CGContext and optimize memory size based on what you actually draw (grayscale color or colorful color)`

> Now, one new feature and optimization that we have in iOS 12 is that the size of the elements in that backing store will, actually, grow dynamically depending on whether you're drawing any color content. And whether that color content is within or outside of the standard color range. So, if you're drawing wide color content using extended SRGB colors, the backing store will, actually, be larger than the backing store would be if you used only colors within the zero to one range. Now, in previous versions of iOS, you could set the contents format property on CALayer as a hint to Core Animation saying, ''I know I am not going to need to support wide color content in this view'', or, ''I know I am going to need to support wide color content in this view''. Now, if you do this, you're actually going to be disabling the optimization that we introduced in iOS 12. So, check your implementations of layerWillDraw. Make sure you're not going to accidentally defeat an optimization that could benefit your code when running on iOS 12.

The encode or export usage, just create CGBitmapContext or CGPDFContext for your own

Code after:
    }
    
    // `CGPDFDocumentGetPage` page number is 1-indexed.
    CGPDFPageRef page = CGPDFDocumentGetPage(document, pageNumber + 1);
    if (!page) {
        CGPDFDocumentRelease(document);
        return nil;
    }
    
    CGPDFBox box = kCGPDFMediaBox;
    CGRect rect = CGPDFPageGetBoxRect(page, box);
    CGRect targetRect = rect;
    if (!CGSizeEqualToSize(targetSize, CGSizeZero)) {
        targetRect = CGRectMake(0, 0, targetSize.width, targetSize.height);
    }
    
    CGFloat xRatio = targetRect.size.width / rect.size.width;
    CGFloat yRatio = targetRect.size.height / rect.size.height;
    CGFloat xScale = preserveAspectRatio ? MIN(xRatio, yRatio) : xRatio;
    CGFloat yScale = preserveAspectRatio ? MIN(xRatio, yRatio) : yRatio;
    
    // `CGPDFPageGetDrawingTransform` will only scale down, but not scale up, so we need calculate the actual scale again
    CGRect drawRect = CGRectMake( 0, 0, targetRect.size.width / xScale, targetRect.size.height / yScale);
    CGAffineTransform scaleTransform = CGAffineTransformMakeScale(xScale, yScale);
    CGAffineTransform transform = CGPDFPageGetDrawingTransform(page, box, drawRect, 0, preserveAspectRatio);
    
    SDGraphicsImageRendererFormat *format = [[SDGraphicsImageRendererFormat alloc] init];
    format.opaque = NO;
    SDGraphicsImageRenderer *renderer = [[SDGraphicsImageRenderer alloc] initWithSize:targetRect.size format:format];
    image = [renderer imageWithActions:^(CGContextRef  _Nonnull context) {
        
#if SD_UIKIT || SD_WATCH
        // Core Graphics coordinate system use the bottom-left, UIKit use the flipped one
        CGContextTranslateCTM(context, 0, targetRect.size.height);
        CGContextScaleCTM(context, 1, -1);
#endif
        
        CGContextConcatCTM(context, scaleTransform);
        CGContextConcatCTM(context, transform);
        
        CGContextDrawPDFPage(context, page);
    }];
    
    CGPDFDocumentRelease(document);
    
    return image;
}

#pragma mark - Decode
- (BOOL)canDecodeFromData:(nullable NSData *)data {
    return YES;