Merge pull request #3370 from dreampiggy/bugfix_pdf_draw_bitmap_dpi
Fix the PDF image without thumbnailPixelSize will result huge bitmap size, now fixed into 72 DPI matching PDFKit
This commit is contained in:
commit
4d4e631183
|
@ -198,13 +198,6 @@ static NSString * kSDCGImageDestinationRequestedFileSize = @"kCGImageDestination
|
||||||
exifOrientation = kCGImagePropertyOrientationUp;
|
exifOrientation = kCGImagePropertyOrientationUp;
|
||||||
}
|
}
|
||||||
|
|
||||||
CFStringRef uttype = CGImageSourceGetType(source);
|
|
||||||
// Check vector format
|
|
||||||
BOOL isVector = NO;
|
|
||||||
if ([NSData sd_imageFormatFromUTType:uttype] == SDImageFormatPDF) {
|
|
||||||
isVector = YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
NSMutableDictionary *decodingOptions;
|
NSMutableDictionary *decodingOptions;
|
||||||
if (options) {
|
if (options) {
|
||||||
decodingOptions = [NSMutableDictionary dictionaryWithDictionary:options];
|
decodingOptions = [NSMutableDictionary dictionaryWithDictionary:options];
|
||||||
|
@ -214,22 +207,6 @@ static NSString * kSDCGImageDestinationRequestedFileSize = @"kCGImageDestination
|
||||||
CGImageRef imageRef;
|
CGImageRef imageRef;
|
||||||
BOOL createFullImage = thumbnailSize.width == 0 || thumbnailSize.height == 0 || pixelWidth == 0 || pixelHeight == 0 || (pixelWidth <= thumbnailSize.width && pixelHeight <= thumbnailSize.height);
|
BOOL createFullImage = thumbnailSize.width == 0 || thumbnailSize.height == 0 || pixelWidth == 0 || pixelHeight == 0 || (pixelWidth <= thumbnailSize.width && pixelHeight <= thumbnailSize.height);
|
||||||
if (createFullImage) {
|
if (createFullImage) {
|
||||||
if (isVector) {
|
|
||||||
if (thumbnailSize.width == 0 || thumbnailSize.height == 0) {
|
|
||||||
// Provide the default pixel count for vector images, simply just use the screen size
|
|
||||||
#if SD_WATCH
|
|
||||||
thumbnailSize = WKInterfaceDevice.currentDevice.screenBounds.size;
|
|
||||||
#elif SD_UIKIT
|
|
||||||
thumbnailSize = UIScreen.mainScreen.bounds.size;
|
|
||||||
#elif SD_MAC
|
|
||||||
thumbnailSize = NSScreen.mainScreen.frame.size;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
CGFloat maxPixelSize = MAX(thumbnailSize.width, thumbnailSize.height);
|
|
||||||
NSUInteger DPIPerPixel = 2;
|
|
||||||
NSUInteger rasterizationDPI = maxPixelSize * DPIPerPixel;
|
|
||||||
decodingOptions[kSDCGImageSourceRasterizationDPI] = @(rasterizationDPI);
|
|
||||||
}
|
|
||||||
imageRef = CGImageSourceCreateImageAtIndex(source, index, (__bridge CFDictionaryRef)[decodingOptions copy]);
|
imageRef = CGImageSourceCreateImageAtIndex(source, index, (__bridge CFDictionaryRef)[decodingOptions copy]);
|
||||||
} else {
|
} else {
|
||||||
decodingOptions[(__bridge NSString *)kCGImageSourceCreateThumbnailWithTransform] = @(preserveAspectRatio);
|
decodingOptions[(__bridge NSString *)kCGImageSourceCreateThumbnailWithTransform] = @(preserveAspectRatio);
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
#import "UIImage+Metadata.h"
|
#import "UIImage+Metadata.h"
|
||||||
#import "SDImageIOAnimatedCoderInternal.h"
|
#import "SDImageIOAnimatedCoderInternal.h"
|
||||||
|
|
||||||
|
// Specify DPI for vector format in CGImageSource, like PDF
|
||||||
|
static NSString * kSDCGImageSourceRasterizationDPI = @"kCGImageSourceRasterizationDPI";
|
||||||
// Specify File Size for lossy format encoding, like JPEG
|
// Specify File Size for lossy format encoding, like JPEG
|
||||||
static NSString * kSDCGImageDestinationRequestedFileSize = @"kCGImageDestinationRequestedFileSize";
|
static NSString * kSDCGImageDestinationRequestedFileSize = @"kCGImageDestinationRequestedFileSize";
|
||||||
|
|
||||||
|
@ -52,6 +54,31 @@ static NSString * kSDCGImageDestinationRequestedFileSize = @"kCGImageDestination
|
||||||
return coder;
|
return coder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma mark - Utils
|
||||||
|
+ (CGRect)boxRectFromPDFFData:(nonnull NSData *)data {
|
||||||
|
CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data);
|
||||||
|
if (!provider) {
|
||||||
|
return CGRectZero;
|
||||||
|
}
|
||||||
|
CGPDFDocumentRef document = CGPDFDocumentCreateWithProvider(provider);
|
||||||
|
CGDataProviderRelease(provider);
|
||||||
|
if (!document) {
|
||||||
|
return CGRectZero;
|
||||||
|
}
|
||||||
|
|
||||||
|
// `CGPDFDocumentGetPage` page number is 1-indexed.
|
||||||
|
CGPDFPageRef page = CGPDFDocumentGetPage(document, 1);
|
||||||
|
if (!page) {
|
||||||
|
CGPDFDocumentRelease(document);
|
||||||
|
return CGRectZero;
|
||||||
|
}
|
||||||
|
|
||||||
|
CGRect boxRect = CGPDFPageGetBoxRect(page, kCGPDFMediaBox);
|
||||||
|
CGPDFDocumentRelease(document);
|
||||||
|
|
||||||
|
return boxRect;
|
||||||
|
}
|
||||||
|
|
||||||
#pragma mark - Decode
|
#pragma mark - Decode
|
||||||
- (BOOL)canDecodeFromData:(nullable NSData *)data {
|
- (BOOL)canDecodeFromData:(nullable NSData *)data {
|
||||||
return YES;
|
return YES;
|
||||||
|
@ -88,13 +115,39 @@ static NSString * kSDCGImageDestinationRequestedFileSize = @"kCGImageDestination
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
UIImage *image = [SDImageIOAnimatedCoder createFrameAtIndex:0 source:source scale:scale preserveAspectRatio:preserveAspectRatio thumbnailSize:thumbnailSize options:nil];
|
CFStringRef uttype = CGImageSourceGetType(source);
|
||||||
|
SDImageFormat imageFormat = [NSData sd_imageFormatFromUTType:uttype];
|
||||||
|
// Check vector format
|
||||||
|
NSDictionary *decodingOptions = nil;
|
||||||
|
if (imageFormat == SDImageFormatPDF) {
|
||||||
|
// Use 72 DPI (1:1 inch to pixel) by default, matching Apple's PDFKit behavior
|
||||||
|
NSUInteger rasterizationDPI = 72;
|
||||||
|
CGFloat maxPixelSize = MAX(thumbnailSize.width, thumbnailSize.height);
|
||||||
|
if (maxPixelSize > 0) {
|
||||||
|
// Calculate DPI based on PDF box and pixel size
|
||||||
|
CGRect boxRect = [self.class boxRectFromPDFFData:data];
|
||||||
|
CGFloat maxBoxSize = MAX(boxRect.size.width, boxRect.size.height);
|
||||||
|
if (maxBoxSize > 0) {
|
||||||
|
rasterizationDPI = rasterizationDPI * (maxPixelSize / maxBoxSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
decodingOptions = @{
|
||||||
|
// This option will cause ImageIO return the pixel size from `CGImageSourceCopyProperties`
|
||||||
|
// If not provided, it always return 0 size
|
||||||
|
kSDCGImageSourceRasterizationDPI : @(rasterizationDPI),
|
||||||
|
};
|
||||||
|
// Already calculated DPI, avoid re-calculation based on thumbnail information
|
||||||
|
preserveAspectRatio = YES;
|
||||||
|
thumbnailSize = CGSizeZero;
|
||||||
|
}
|
||||||
|
|
||||||
|
UIImage *image = [SDImageIOAnimatedCoder createFrameAtIndex:0 source:source scale:scale preserveAspectRatio:preserveAspectRatio thumbnailSize:thumbnailSize options:decodingOptions];
|
||||||
CFRelease(source);
|
CFRelease(source);
|
||||||
if (!image) {
|
if (!image) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
image.sd_imageFormat = [NSData sd_imageFormatForImageData:data];
|
image.sd_imageFormat = imageFormat;
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,12 @@
|
||||||
#import "UIColor+SDHexString.h"
|
#import "UIColor+SDHexString.h"
|
||||||
#import <SDWebImageWebPCoder/SDWebImageWebPCoder.h>
|
#import <SDWebImageWebPCoder/SDWebImageWebPCoder.h>
|
||||||
|
|
||||||
|
@interface SDImageIOCoder ()
|
||||||
|
|
||||||
|
+ (CGRect)boxRectFromPDFFData:(nonnull NSData *)data;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
@interface SDWebImageDecoderTests : SDTestCase
|
@interface SDWebImageDecoderTests : SDTestCase
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -437,15 +443,14 @@ withLocalImageURL:(NSURL *)imageUrl
|
||||||
CGFloat pixelHeight = inputImage.size.height;
|
CGFloat pixelHeight = inputImage.size.height;
|
||||||
expect(pixelWidth).beGreaterThan(0);
|
expect(pixelWidth).beGreaterThan(0);
|
||||||
expect(pixelHeight).beGreaterThan(0);
|
expect(pixelHeight).beGreaterThan(0);
|
||||||
// check vector format supports thumbnail with screen size
|
// check vector format should use 72 DPI
|
||||||
if (isVector) {
|
if (isVector) {
|
||||||
#if SD_UIKIT
|
CGRect boxRect = [SDImageIOCoder boxRectFromPDFFData:inputImageData];
|
||||||
CGFloat maxScreenSize = MAX(UIScreen.mainScreen.bounds.size.width, UIScreen.mainScreen.bounds.size.height);
|
expect(boxRect.size.width).beGreaterThan(0);
|
||||||
#else
|
expect(boxRect.size.height).beGreaterThan(0);
|
||||||
CGFloat maxScreenSize = MAX(NSScreen.mainScreen.frame.size.width, NSScreen.mainScreen.frame.size.height);
|
// Since 72 DPI is 1:1 from inch size to pixel size
|
||||||
#endif
|
expect(boxRect.size.width).equal(pixelWidth);
|
||||||
expect(pixelWidth).equal(maxScreenSize);
|
expect(boxRect.size.height).equal(pixelHeight);
|
||||||
expect(pixelHeight).equal(maxScreenSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check thumbnail with scratch
|
// check thumbnail with scratch
|
||||||
|
|
Loading…
Reference in New Issue