Calculate the DPI based on PDF mediaBox, support thumbnailPixelSize
Move the vector code from ImageIOAnimatedCoder to ImageIOCoder, since it's not animatable :)
This commit is contained in:
parent
f91d35ef8d
commit
f1fe4ca8b8
|
@ -197,13 +197,6 @@ static NSString * kSDCGImageDestinationRequestedFileSize = @"kCGImageDestination
|
|||
if (!exifOrientation) {
|
||||
exifOrientation = kCGImagePropertyOrientationUp;
|
||||
}
|
||||
|
||||
CFStringRef uttype = CGImageSourceGetType(source);
|
||||
// Check vector format
|
||||
BOOL isVector = NO;
|
||||
if ([NSData sd_imageFormatFromUTType:uttype] == SDImageFormatPDF) {
|
||||
isVector = YES;
|
||||
}
|
||||
|
||||
NSMutableDictionary *decodingOptions;
|
||||
if (options) {
|
||||
|
@ -214,11 +207,6 @@ static NSString * kSDCGImageDestinationRequestedFileSize = @"kCGImageDestination
|
|||
CGImageRef imageRef;
|
||||
BOOL createFullImage = thumbnailSize.width == 0 || thumbnailSize.height == 0 || pixelWidth == 0 || pixelHeight == 0 || (pixelWidth <= thumbnailSize.width && pixelHeight <= thumbnailSize.height);
|
||||
if (createFullImage) {
|
||||
if (isVector) {
|
||||
// Use 72 DPI by default, matching Apple's PDFKit behavior
|
||||
NSUInteger rasterizationDPI = 72;
|
||||
decodingOptions[kSDCGImageSourceRasterizationDPI] = @(rasterizationDPI);
|
||||
}
|
||||
imageRef = CGImageSourceCreateImageAtIndex(source, index, (__bridge CFDictionaryRef)[decodingOptions copy]);
|
||||
} else {
|
||||
decodingOptions[(__bridge NSString *)kCGImageSourceCreateThumbnailWithTransform] = @(preserveAspectRatio);
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
#import "UIImage+Metadata.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
|
||||
static NSString * kSDCGImageDestinationRequestedFileSize = @"kCGImageDestinationRequestedFileSize";
|
||||
|
||||
|
@ -52,6 +54,31 @@ static NSString * kSDCGImageDestinationRequestedFileSize = @"kCGImageDestination
|
|||
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
|
||||
- (BOOL)canDecodeFromData:(nullable NSData *)data {
|
||||
return YES;
|
||||
|
@ -88,13 +115,34 @@ static NSString * kSDCGImageDestinationRequestedFileSize = @"kCGImageDestination
|
|||
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 = @{
|
||||
kSDCGImageSourceRasterizationDPI : @(rasterizationDPI),
|
||||
};
|
||||
}
|
||||
|
||||
UIImage *image = [SDImageIOAnimatedCoder createFrameAtIndex:0 source:source scale:scale preserveAspectRatio:preserveAspectRatio thumbnailSize:thumbnailSize options:decodingOptions];
|
||||
CFRelease(source);
|
||||
if (!image) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
image.sd_imageFormat = [NSData sd_imageFormatForImageData:data];
|
||||
image.sd_imageFormat = imageFormat;
|
||||
return image;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,12 @@
|
|||
#import "UIColor+SDHexString.h"
|
||||
#import <SDWebImageWebPCoder/SDWebImageWebPCoder.h>
|
||||
|
||||
@interface SDImageIOCoder ()
|
||||
|
||||
+ (CGRect)boxRectFromPDFFData:(nonnull NSData *)data;
|
||||
|
||||
@end
|
||||
|
||||
@interface SDWebImageDecoderTests : SDTestCase
|
||||
|
||||
@end
|
||||
|
@ -437,15 +443,14 @@ withLocalImageURL:(NSURL *)imageUrl
|
|||
CGFloat pixelHeight = inputImage.size.height;
|
||||
expect(pixelWidth).beGreaterThan(0);
|
||||
expect(pixelHeight).beGreaterThan(0);
|
||||
// check vector format supports thumbnail with screen size
|
||||
// check vector format should use 72 DPI
|
||||
if (isVector) {
|
||||
#if SD_UIKIT
|
||||
CGFloat maxScreenSize = MAX(UIScreen.mainScreen.bounds.size.width, UIScreen.mainScreen.bounds.size.height);
|
||||
#else
|
||||
CGFloat maxScreenSize = MAX(NSScreen.mainScreen.frame.size.width, NSScreen.mainScreen.frame.size.height);
|
||||
#endif
|
||||
expect(pixelWidth).equal(maxScreenSize);
|
||||
expect(pixelHeight).equal(maxScreenSize);
|
||||
CGRect boxRect = [SDImageIOCoder boxRectFromPDFFData:inputImageData];
|
||||
expect(boxRect.size.width).beGreaterThan(0);
|
||||
expect(boxRect.size.height).beGreaterThan(0);
|
||||
// Since 72 DPI is 1:1 from inch size to pixel size
|
||||
expect(boxRect.size.width).equal(pixelWidth);
|
||||
expect(boxRect.size.height).equal(pixelHeight);
|
||||
}
|
||||
|
||||
// check thumbnail with scratch
|
||||
|
|
Loading…
Reference in New Issue