Merge pull request #2936 from dreampiggy/feature_better_vector_support_pdf
Feature - better support for vector format detection, now PDF rasterized bitmap is built-in
This commit is contained in:
commit
5c3c40288f
|
@ -75,6 +75,7 @@
|
|||
@"https://nokiatech.github.io/heif/content/images/ski_jump_1440x960.heic",
|
||||
@"https://nokiatech.github.io/heif/content/image_sequences/starfield_animation.heic",
|
||||
@"https://s2.ax1x.com/2019/11/01/KHYIgJ.gif",
|
||||
@"https://raw.githubusercontent.com/icons8/flat-color-icons/master/pdf/stack_of_photos.pdf",
|
||||
@"https://nr-platform.s3.amazonaws.com/uploads/platform/published_extension/branding_icon/275/AmazonS3.png",
|
||||
@"http://via.placeholder.com/200x200.jpg",
|
||||
nil];
|
||||
|
|
|
@ -23,6 +23,8 @@ static const SDImageFormat SDImageFormatTIFF = 3;
|
|||
static const SDImageFormat SDImageFormatWebP = 4;
|
||||
static const SDImageFormat SDImageFormatHEIC = 5;
|
||||
static const SDImageFormat SDImageFormatHEIF = 6;
|
||||
static const SDImageFormat SDImageFormatPDF = 7;
|
||||
static const SDImageFormat SDImageFormatSVG = 8;
|
||||
|
||||
/**
|
||||
NSData category about the image content type and UTI.
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
// Currently Image/IO does not support WebP
|
||||
#define kSDUTTypeWebP ((__bridge CFStringRef)@"public.webp")
|
||||
#define kSVGTagEnd @"</svg>"
|
||||
|
||||
@implementation NSData (ImageContentType)
|
||||
|
||||
|
@ -65,6 +66,24 @@
|
|||
}
|
||||
break;
|
||||
}
|
||||
case 0x25: {
|
||||
if (data.length >= 4) {
|
||||
//%PDF
|
||||
NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(1, 3)] encoding:NSASCIIStringEncoding];
|
||||
if ([testString isEqualToString:@"PDF"]) {
|
||||
return SDImageFormatPDF;
|
||||
}
|
||||
}
|
||||
}
|
||||
case 0x3C: {
|
||||
if (data.length > 100) {
|
||||
// Check end with SVG tag
|
||||
NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(data.length - 100, 100)] encoding:NSASCIIStringEncoding];
|
||||
if ([testString containsString:kSVGTagEnd]) {
|
||||
return SDImageFormatSVG;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return SDImageFormatUndefined;
|
||||
}
|
||||
|
@ -93,6 +112,12 @@
|
|||
case SDImageFormatHEIF:
|
||||
UTType = kSDUTTypeHEIF;
|
||||
break;
|
||||
case SDImageFormatPDF:
|
||||
UTType = kUTTypePDF;
|
||||
break;
|
||||
case SDImageFormatSVG:
|
||||
UTType = kUTTypeScalableVectorGraphics;
|
||||
break;
|
||||
default:
|
||||
// default is kUTTypePNG
|
||||
UTType = kUTTypePNG;
|
||||
|
@ -120,6 +145,10 @@
|
|||
imageFormat = SDImageFormatHEIC;
|
||||
} else if (CFStringCompare(uttype, kSDUTTypeHEIF, 0) == kCFCompareEqualTo) {
|
||||
imageFormat = SDImageFormatHEIF;
|
||||
} else if (CFStringCompare(uttype, kUTTypePDF, 0) == kCFCompareEqualTo) {
|
||||
imageFormat = SDImageFormatPDF;
|
||||
} else if (CFStringCompare(uttype, kUTTypeScalableVectorGraphics, 0) == kCFCompareEqualTo) {
|
||||
imageFormat = SDImageFormatSVG;
|
||||
} else {
|
||||
imageFormat = SDImageFormatUndefined;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#import "SDImageCodersManager.h"
|
||||
#import "SDImageFrame.h"
|
||||
#import "UIImage+MemoryCacheCost.h"
|
||||
#import "UIImage+Metadata.h"
|
||||
#import "SDImageAssetManager.h"
|
||||
#import "objc/runtime.h"
|
||||
|
||||
|
@ -298,3 +299,31 @@ static CGFloat SDImageScaleFromPath(NSString *string) {
|
|||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation SDAnimatedImage (Metadata)
|
||||
|
||||
- (BOOL)sd_isAnimated {
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (NSUInteger)sd_imageLoopCount {
|
||||
return self.animatedImageLoopCount;
|
||||
}
|
||||
|
||||
- (void)setSd_imageLoopCount:(NSUInteger)sd_imageLoopCount {
|
||||
return;
|
||||
}
|
||||
|
||||
- (SDImageFormat)sd_imageFormat {
|
||||
return self.animatedImageFormat;
|
||||
}
|
||||
|
||||
- (void)setSd_imageFormat:(SDImageFormat)sd_imageFormat {
|
||||
return;
|
||||
}
|
||||
|
||||
- (BOOL)sd_isVector {
|
||||
return NO;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -470,10 +470,10 @@
|
|||
// NSImageView use a subview. We need this subview's layer for actual rendering.
|
||||
// Why using this design may because of properties like `imageAlignment` and `imageScaling`, which it's not available for UIImageView.contentMode (it's impossible to align left and keep aspect ratio at the same time)
|
||||
- (NSView *)imageView {
|
||||
NSImageView *imageView = imageView = objc_getAssociatedObject(self, NSSelectorFromString(@"_imageView"));
|
||||
NSImageView *imageView = imageView = objc_getAssociatedObject(self, SD_SEL_SPI(imageView));
|
||||
if (!imageView) {
|
||||
// macOS 10.14
|
||||
imageView = objc_getAssociatedObject(self, NSSelectorFromString(@"_imageSubview"));
|
||||
imageView = objc_getAssociatedObject(self, SD_SEL_SPI(imageSubview));
|
||||
}
|
||||
return imageView;
|
||||
}
|
||||
|
|
|
@ -575,6 +575,10 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
|
|||
if (image.sd_isAnimated) {
|
||||
return NO;
|
||||
}
|
||||
// do not decode vector images
|
||||
if (image.sd_isVector) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
#import "SDAnimatedImageRep.h"
|
||||
#import "UIImage+ForceDecode.h"
|
||||
|
||||
// Specify DPI for vector format in CGImageSource, like PDF
|
||||
static NSString * kSDCGImageSourceRasterizationDPI = @"kCGImageSourceRasterizationDPI";
|
||||
|
||||
@interface SDImageIOCoderFrame : NSObject
|
||||
|
||||
@property (nonatomic, assign) NSUInteger index; // Frame index (zero based)
|
||||
|
@ -158,9 +161,33 @@
|
|||
exifOrientation = kCGImagePropertyOrientationUp;
|
||||
}
|
||||
|
||||
CFStringRef uttype = CGImageSourceGetType(source);
|
||||
// Check vector format
|
||||
BOOL isVector = NO;
|
||||
if ([NSData sd_imageFormatFromUTType:uttype] == SDImageFormatPDF) {
|
||||
isVector = YES;
|
||||
}
|
||||
|
||||
CGImageRef imageRef;
|
||||
if (thumbnailSize.width == 0 || thumbnailSize.height == 0 || (pixelWidth <= thumbnailSize.width && pixelHeight <= thumbnailSize.height)) {
|
||||
imageRef = CGImageSourceCreateImageAtIndex(source, index, NULL);
|
||||
if (thumbnailSize.width == 0 || thumbnailSize.height == 0 || pixelWidth == 0 || pixelHeight == 0 || (pixelWidth <= thumbnailSize.width && pixelHeight <= thumbnailSize.height)) {
|
||||
NSDictionary *options;
|
||||
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;
|
||||
options = @{kSDCGImageSourceRasterizationDPI : @(rasterizationDPI)};
|
||||
}
|
||||
imageRef = CGImageSourceCreateImageAtIndex(source, index, (__bridge CFDictionaryRef)options);
|
||||
} else {
|
||||
NSMutableDictionary *thumbnailOptions = [NSMutableDictionary dictionary];
|
||||
thumbnailOptions[(__bridge NSString *)kCGImageSourceCreateThumbnailWithTransform] = @(preserveAspectRatio);
|
||||
|
@ -179,21 +206,22 @@
|
|||
thumbnailOptions[(__bridge NSString *)kCGImageSourceThumbnailMaxPixelSize] = @(maxPixelSize);
|
||||
thumbnailOptions[(__bridge NSString *)kCGImageSourceCreateThumbnailFromImageIfAbsent] = @(YES);
|
||||
imageRef = CGImageSourceCreateThumbnailAtIndex(source, index, (__bridge CFDictionaryRef)thumbnailOptions);
|
||||
}
|
||||
if (!imageRef) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
if (thumbnailSize.width > 0 && thumbnailSize.height > 0) {
|
||||
if (preserveAspectRatio) {
|
||||
// kCGImageSourceCreateThumbnailWithTransform will apply EXIF transform as well, we should not apply twice
|
||||
exifOrientation = kCGImagePropertyOrientationUp;
|
||||
} else {
|
||||
// `CGImageSourceCreateThumbnailAtIndex` take only pixel dimension, if not `preserveAspectRatio`, we should manual scale to the target size
|
||||
if (imageRef) {
|
||||
CGImageRef scaledImageRef = [SDImageCoderHelper CGImageCreateScaled:imageRef size:thumbnailSize];
|
||||
CGImageRelease(imageRef);
|
||||
imageRef = scaledImageRef;
|
||||
}
|
||||
CGImageRef scaledImageRef = [SDImageCoderHelper CGImageCreateScaled:imageRef size:thumbnailSize];
|
||||
CGImageRelease(imageRef);
|
||||
imageRef = scaledImageRef;
|
||||
}
|
||||
}
|
||||
if (!imageRef) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
#if SD_UIKIT || SD_WATCH
|
||||
UIImageOrientation imageOrientation = [SDImageCoderHelper imageOrientationFromEXIFOrientation:exifOrientation];
|
||||
|
@ -363,7 +391,7 @@
|
|||
if (scaleFactor != nil) {
|
||||
scale = MAX([scaleFactor doubleValue], 1);
|
||||
}
|
||||
image = [SDImageIOAnimatedCoder createFrameAtIndex:0 source:_imageSource scale:scale preserveAspectRatio:_preserveAspectRatio thumbnailSize:_thumbnailSize];
|
||||
image = [self.class createFrameAtIndex:0 source:_imageSource scale:scale preserveAspectRatio:_preserveAspectRatio thumbnailSize:_thumbnailSize];
|
||||
if (image) {
|
||||
image.sd_imageFormat = self.class.imageFormat;
|
||||
}
|
||||
|
|
|
@ -195,6 +195,12 @@ typedef NS_OPTIONS(NSUInteger, SDWebImageOptions) {
|
|||
* Note if you use this when using the custom cache serializer, or using the transformer, we will also wait until the output image data written is finished.
|
||||
*/
|
||||
SDWebImageWaitStoreCache = 1 << 22,
|
||||
|
||||
/**
|
||||
* We usually don't apply transform on vector images, because vector images supports dynamically changing to any size, rasterize to a fixed size will loss details. To modify vector images, you can process the vector data at runtime (such as modifying PDF tag / SVG element).
|
||||
* Use this flag to transform them anyway.
|
||||
*/
|
||||
SDWebImageTransformVectorImage = 1 << 23,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -332,7 +332,9 @@ static id<SDImageLoader> _defaultImageLoader;
|
|||
id<SDImageTransformer> transformer = context[SDWebImageContextImageTransformer];
|
||||
id<SDWebImageCacheSerializer> cacheSerializer = context[SDWebImageContextCacheSerializer];
|
||||
|
||||
BOOL shouldTransformImage = downloadedImage && (!downloadedImage.sd_isAnimated || (options & SDWebImageTransformAnimatedImage)) && transformer;
|
||||
BOOL shouldTransformImage = downloadedImage && transformer;
|
||||
shouldTransformImage = shouldTransformImage && (!downloadedImage.sd_isAnimated || (options & SDWebImageTransformAnimatedImage));
|
||||
shouldTransformImage = shouldTransformImage && (!downloadedImage.sd_isVector || (options & SDWebImageTransformVectorImage));
|
||||
BOOL shouldCacheOriginal = downloadedImage && finished;
|
||||
BOOL waitStoreCache = SD_OPTIONS_CONTAINS(options, SDWebImageWaitStoreCache);
|
||||
|
||||
|
@ -380,7 +382,9 @@ static id<SDImageLoader> _defaultImageLoader;
|
|||
NSString *key = [self cacheKeyForURL:url context:context];
|
||||
id<SDImageTransformer> transformer = context[SDWebImageContextImageTransformer];
|
||||
id<SDWebImageCacheSerializer> cacheSerializer = context[SDWebImageContextCacheSerializer];
|
||||
BOOL shouldTransformImage = originalImage && (!originalImage.sd_isAnimated || (options & SDWebImageTransformAnimatedImage)) && transformer;
|
||||
BOOL shouldTransformImage = originalImage && transformer;
|
||||
shouldTransformImage = shouldTransformImage && (!originalImage.sd_isAnimated || (options & SDWebImageTransformAnimatedImage));
|
||||
shouldTransformImage = shouldTransformImage && (!originalImage.sd_isVector || (options & SDWebImageTransformVectorImage));
|
||||
BOOL waitStoreCache = SD_OPTIONS_CONTAINS(options, SDWebImageWaitStoreCache);
|
||||
// if available, store transformed image to cache
|
||||
if (shouldTransformImage) {
|
||||
|
|
|
@ -28,12 +28,20 @@
|
|||
|
||||
/**
|
||||
* UIKit:
|
||||
* Check the `images` array property
|
||||
* Check the `images` array property.
|
||||
* AppKit:
|
||||
* NSImage currently only support animated via GIF imageRep unlike UIImage. It will check the imageRep's frame count.
|
||||
*/
|
||||
@property (nonatomic, assign, readonly) BOOL sd_isAnimated;
|
||||
|
||||
/**
|
||||
* UIKit:
|
||||
* Check the `isSymbolImage` property. Also check the system PDF(iOS 11+) && SVG(iOS 13+) support.
|
||||
* AppKit:
|
||||
* NSImage supports PDF && SVG && EPS imageRep, check the imageRep class.
|
||||
*/
|
||||
@property (nonatomic, assign, readonly) BOOL sd_isVector;
|
||||
|
||||
/**
|
||||
* The image format represent the original compressed image data format.
|
||||
* If you don't manually specify a format, this information is retrieve from CGImage using `CGImageGetUTType`, which may return nil for non-CG based image. At this time it will return `SDImageFormatUndefined` as default value.
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#import "UIImage+Metadata.h"
|
||||
#import "NSImage+Compatibility.h"
|
||||
#import "SDInternalMacros.h"
|
||||
#import "objc/runtime.h"
|
||||
|
||||
@implementation UIImage (Metadata)
|
||||
|
@ -32,6 +33,32 @@
|
|||
return (self.images != nil);
|
||||
}
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
|
||||
- (BOOL)sd_isVector {
|
||||
if (@available(iOS 13.0, tvOS 13.0, watchOS 6.0, *)) {
|
||||
// Xcode 11 supports symbol image, keep Xcode 10 compatible currently
|
||||
SEL SymbolSelector = NSSelectorFromString(@"isSymbolImage");
|
||||
if ([self respondsToSelector:SymbolSelector] && [self performSelector:SymbolSelector]) {
|
||||
return YES;
|
||||
}
|
||||
// SVG
|
||||
SEL SVGSelector = SD_SEL_SPI(CGSVGDocument);
|
||||
if ([self respondsToSelector:SVGSelector] && [self performSelector:SVGSelector]) {
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
if (@available(iOS 11.0, tvOS 11.0, watchOS 4.0, *)) {
|
||||
// PDF
|
||||
SEL PDFSelector = SD_SEL_SPI(CGPDFPage);
|
||||
if ([self respondsToSelector:PDFSelector] && [self performSelector:PDFSelector]) {
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
#else
|
||||
|
||||
- (NSUInteger)sd_imageLoopCount {
|
||||
|
@ -61,7 +88,7 @@
|
|||
}
|
||||
|
||||
- (BOOL)sd_isAnimated {
|
||||
BOOL isGIF = NO;
|
||||
BOOL isAnimated = NO;
|
||||
NSRect imageRect = NSMakeRect(0, 0, self.size.width, self.size.height);
|
||||
NSImageRep *imageRep = [self bestRepresentationForRect:imageRect context:nil hints:nil];
|
||||
NSBitmapImageRep *bitmapImageRep;
|
||||
|
@ -70,9 +97,24 @@
|
|||
}
|
||||
if (bitmapImageRep) {
|
||||
NSUInteger frameCount = [[bitmapImageRep valueForProperty:NSImageFrameCount] unsignedIntegerValue];
|
||||
isGIF = frameCount > 1 ? YES : NO;
|
||||
isAnimated = frameCount > 1 ? YES : NO;
|
||||
}
|
||||
return isGIF;
|
||||
return isAnimated;
|
||||
}
|
||||
|
||||
- (BOOL)sd_isVector {
|
||||
NSRect imageRect = NSMakeRect(0, 0, self.size.width, self.size.height);
|
||||
NSImageRep *imageRep = [self bestRepresentationForRect:imageRect context:nil hints:nil];
|
||||
if ([imageRep isKindOfClass:[NSPDFImageRep class]]) {
|
||||
return YES;
|
||||
}
|
||||
if ([imageRep isKindOfClass:[NSEPSImageRep class]]) {
|
||||
return YES;
|
||||
}
|
||||
if ([NSStringFromClass(imageRep.class) hasSuffix:@"NSSVGImageRep"]) {
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -21,6 +21,18 @@
|
|||
#define SD_OPTIONS_CONTAINS(options, value) (((options) & (value)) == (value))
|
||||
#endif
|
||||
|
||||
#ifndef SD_CSTRING
|
||||
#define SD_CSTRING(str) #str
|
||||
#endif
|
||||
|
||||
#ifndef SD_NSSTRING
|
||||
#define SD_NSSTRING(str) @(SD_CSTRING(str))
|
||||
#endif
|
||||
|
||||
#ifndef SD_SEL_SPI
|
||||
#define SD_SEL_SPI(name) NSSelectorFromString([NSString stringWithFormat:@"_%@", SD_NSSTRING(name)])
|
||||
#endif
|
||||
|
||||
#ifndef weakify
|
||||
#define weakify(...) \
|
||||
sd_keywordify \
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
322241802272F808002429DB /* SDUtilsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3222417E2272F808002429DB /* SDUtilsTests.m */; };
|
||||
3226ECBB20754F7700FAFACF /* SDWebImageTestDownloadOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 3226ECBA20754F7700FAFACF /* SDWebImageTestDownloadOperation.m */; };
|
||||
3226ECBC20754F7700FAFACF /* SDWebImageTestDownloadOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 3226ECBA20754F7700FAFACF /* SDWebImageTestDownloadOperation.m */; };
|
||||
3234306223E2BAC800C290C8 /* TestImage.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 3234306123E2BAC800C290C8 /* TestImage.pdf */; };
|
||||
3234306323E2BAC800C290C8 /* TestImage.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 3234306123E2BAC800C290C8 /* TestImage.pdf */; };
|
||||
3234306423E2BAC800C290C8 /* TestImage.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 3234306123E2BAC800C290C8 /* TestImage.pdf */; };
|
||||
323B8E1F20862322008952BE /* SDWebImageTestLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 323B8E1E20862322008952BE /* SDWebImageTestLoader.m */; };
|
||||
323B8E2020862322008952BE /* SDWebImageTestLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 323B8E1E20862322008952BE /* SDWebImageTestLoader.m */; };
|
||||
324047442271956F007C53E1 /* TestEXIF.png in Resources */ = {isa = PBXBuildFile; fileRef = 324047432271956F007C53E1 /* TestEXIF.png */; };
|
||||
|
@ -107,6 +110,7 @@
|
|||
3222417E2272F808002429DB /* SDUtilsTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDUtilsTests.m; sourceTree = "<group>"; };
|
||||
3226ECB920754F7700FAFACF /* SDWebImageTestDownloadOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDWebImageTestDownloadOperation.h; sourceTree = "<group>"; };
|
||||
3226ECBA20754F7700FAFACF /* SDWebImageTestDownloadOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDWebImageTestDownloadOperation.m; sourceTree = "<group>"; };
|
||||
3234306123E2BAC800C290C8 /* TestImage.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = TestImage.pdf; sourceTree = "<group>"; };
|
||||
323B8E1D20862322008952BE /* SDWebImageTestLoader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDWebImageTestLoader.h; sourceTree = "<group>"; };
|
||||
323B8E1E20862322008952BE /* SDWebImageTestLoader.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDWebImageTestLoader.m; sourceTree = "<group>"; };
|
||||
324047432271956F007C53E1 /* TestEXIF.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = TestEXIF.png; sourceTree = "<group>"; };
|
||||
|
@ -238,6 +242,7 @@
|
|||
433BBBB81D7EF8260086B6E9 /* TestImage.png */,
|
||||
327A418B211D660600495442 /* TestImage.heic */,
|
||||
32905E63211D786E00460FCF /* TestImage.heif */,
|
||||
3234306123E2BAC800C290C8 /* TestImage.pdf */,
|
||||
327054E1206CEFF3006EA328 /* TestImageAnimated.apng */,
|
||||
3297A09E23374D1600814590 /* TestImageAnimated.heic */,
|
||||
);
|
||||
|
@ -443,6 +448,7 @@
|
|||
3299228B2365DC6C00EAFD97 /* TestImage.heic in Resources */,
|
||||
329922872365DC6C00EAFD97 /* TestLoopCount.gif in Resources */,
|
||||
3299228C2365DC6C00EAFD97 /* TestImage.heif in Resources */,
|
||||
3234306423E2BAC800C290C8 /* TestImage.pdf in Resources */,
|
||||
329922892365DC6C00EAFD97 /* TestImageLarge.jpg in Resources */,
|
||||
3299228A2365DC6C00EAFD97 /* TestImage.png in Resources */,
|
||||
329922842365DC6C00EAFD97 /* MonochromeTestImage.jpg in Resources */,
|
||||
|
@ -461,6 +467,7 @@
|
|||
32B99EA3203B31360017FD66 /* TestImage.gif in Resources */,
|
||||
324047452271956F007C53E1 /* TestEXIF.png in Resources */,
|
||||
32B99EA4203B31360017FD66 /* TestImage.jpg in Resources */,
|
||||
3234306323E2BAC800C290C8 /* TestImage.pdf in Resources */,
|
||||
32B99EA6203B31360017FD66 /* TestImage.png in Resources */,
|
||||
3297A0A023374D1700814590 /* TestImageAnimated.heic in Resources */,
|
||||
32B99EA2203B31360017FD66 /* MonochromeTestImage.jpg in Resources */,
|
||||
|
@ -479,6 +486,7 @@
|
|||
5F7F38AD1AE2A77A00B0E330 /* TestImage.jpg in Resources */,
|
||||
32905E64211D786E00460FCF /* TestImage.heif in Resources */,
|
||||
43828A451DA67F9900000E62 /* TestImageLarge.jpg in Resources */,
|
||||
3234306223E2BAC800C290C8 /* TestImage.pdf in Resources */,
|
||||
433BBBB71D7EF8200086B6E9 /* TestImage.gif in Resources */,
|
||||
433BBBB91D7EF8260086B6E9 /* TestImage.png in Resources */,
|
||||
3297A09F23374D1700814590 /* TestImageAnimated.heic in Resources */,
|
||||
|
|
Binary file not shown.
|
@ -156,22 +156,34 @@
|
|||
withLocalImageURL:heicURL
|
||||
supportsEncoding:supportsEncoding
|
||||
encodingFormat:SDImageFormatHEIC
|
||||
isAnimatedImage:isAnimatedImage];
|
||||
isAnimatedImage:isAnimatedImage
|
||||
isVectorImage:NO];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)test17ThatPDFWorks {
|
||||
NSURL *pdfURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"TestImage" withExtension:@"pdf"];
|
||||
[self verifyCoder:[SDImageIOCoder sharedCoder]
|
||||
withLocalImageURL:pdfURL
|
||||
supportsEncoding:NO
|
||||
encodingFormat:SDImageFormatUndefined
|
||||
isAnimatedImage:NO
|
||||
isVectorImage:YES];
|
||||
}
|
||||
|
||||
- (void)verifyCoder:(id<SDImageCoder>)coder
|
||||
withLocalImageURL:(NSURL *)imageUrl
|
||||
supportsEncoding:(BOOL)supportsEncoding
|
||||
isAnimatedImage:(BOOL)isAnimated {
|
||||
[self verifyCoder:coder withLocalImageURL:imageUrl supportsEncoding:supportsEncoding encodingFormat:SDImageFormatUndefined isAnimatedImage:isAnimated];
|
||||
[self verifyCoder:coder withLocalImageURL:imageUrl supportsEncoding:supportsEncoding encodingFormat:SDImageFormatUndefined isAnimatedImage:isAnimated isVectorImage:NO];
|
||||
}
|
||||
|
||||
- (void)verifyCoder:(id<SDImageCoder>)coder
|
||||
withLocalImageURL:(NSURL *)imageUrl
|
||||
supportsEncoding:(BOOL)supportsEncoding
|
||||
encodingFormat:(SDImageFormat)encodingFormat
|
||||
isAnimatedImage:(BOOL)isAnimated {
|
||||
isAnimatedImage:(BOOL)isAnimated
|
||||
isVectorImage:(BOOL)isVector {
|
||||
NSData *inputImageData = [NSData dataWithContentsOfURL:imageUrl];
|
||||
expect(inputImageData).toNot.beNil();
|
||||
SDImageFormat inputImageFormat = [NSData sd_imageFormatForImageData:inputImageData];
|
||||
|
@ -204,7 +216,18 @@ withLocalImageURL:(NSURL *)imageUrl
|
|||
CGFloat pixelHeight = inputImage.size.height;
|
||||
expect(pixelWidth).beGreaterThan(0);
|
||||
expect(pixelHeight).beGreaterThan(0);
|
||||
// check thumnail with scratch
|
||||
// check vector format supports thumbnail with screen size
|
||||
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);
|
||||
}
|
||||
|
||||
// check thumbnail with scratch
|
||||
CGFloat thumbnailWidth = 50;
|
||||
CGFloat thumbnailHeight = 50;
|
||||
UIImage *thumbImage = [coder decodedImageWithData:inputImageData options:@{
|
||||
|
@ -213,7 +236,7 @@ withLocalImageURL:(NSURL *)imageUrl
|
|||
}];
|
||||
expect(thumbImage).toNot.beNil();
|
||||
expect(thumbImage.size).equal(CGSizeMake(thumbnailWidth, thumbnailHeight));
|
||||
// check thumnail with aspect ratio limit
|
||||
// check thumbnail with aspect ratio limit
|
||||
thumbImage = [coder decodedImageWithData:inputImageData options:@{
|
||||
SDImageCoderDecodeThumbnailPixelSize : @(CGSizeMake(thumbnailWidth, thumbnailHeight)),
|
||||
SDImageCoderDecodePreserveAspectRatio : @(YES)
|
||||
|
|
Loading…
Reference in New Issue