Support use url.path or custom UTI hint passed to ImageIO, solve the TIFF/NEF/SRW raw image decoding with wrong size
This is because file extension will cause ImageIO use different codec, which does not support all of them without context
This commit is contained in:
parent
9248fe561a
commit
b1b16a17b3
|
@ -73,6 +73,7 @@
|
|||
@"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",
|
||||
@"https://res.cloudinary.com/dwpjzbyux/raw/upload/v1666474070/RawDemo/raw_vebed5.NEF",
|
||||
@"http://via.placeholder.com/200x200.jpg",
|
||||
nil];
|
||||
|
||||
|
|
|
@ -28,12 +28,16 @@ SDImageCoderOptions * _Nonnull SDGetDecodeOptionsFromContext(SDWebImageContext *
|
|||
if (context[SDWebImageContextImageThumbnailPixelSize]) {
|
||||
thumbnailSizeValue = context[SDWebImageContextImageThumbnailPixelSize];
|
||||
}
|
||||
NSString *typeIdentifierHint = context[SDWebImageContextImageTypeIdentifierHint];
|
||||
NSString *fileExtensionHint = cacheKey.pathExtension; // without dot
|
||||
|
||||
SDImageCoderMutableOptions *mutableCoderOptions = [NSMutableDictionary dictionaryWithCapacity:2];
|
||||
SDImageCoderMutableOptions *mutableCoderOptions = [NSMutableDictionary dictionaryWithCapacity:6];
|
||||
mutableCoderOptions[SDImageCoderDecodeFirstFrameOnly] = @(decodeFirstFrame);
|
||||
mutableCoderOptions[SDImageCoderDecodeScaleFactor] = @(scale);
|
||||
mutableCoderOptions[SDImageCoderDecodePreserveAspectRatio] = preserveAspectRatioValue;
|
||||
mutableCoderOptions[SDImageCoderDecodeThumbnailPixelSize] = thumbnailSizeValue;
|
||||
mutableCoderOptions[SDImageCoderDecodeTypeIdentifierHint] = typeIdentifierHint;
|
||||
mutableCoderOptions[SDImageCoderDecodeFileExtensionHint] = fileExtensionHint;
|
||||
mutableCoderOptions[SDImageCoderWebImageContext] = context;
|
||||
SDImageCoderOptions *coderOptions = [mutableCoderOptions copy];
|
||||
|
||||
|
|
|
@ -44,6 +44,22 @@ FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderDecodePreserveAs
|
|||
*/
|
||||
FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderDecodeThumbnailPixelSize;
|
||||
|
||||
/**
|
||||
A NSString value indicating the source image's file extension. Example: "jpg", "nef", "tif", don't prefix the dot
|
||||
Some image file format share the same data structure but has different tag explanation, like TIFF and NEF/SRW, see https://en.wikipedia.org/wiki/TIFF
|
||||
Changing the file extension cause the different image result. The coder (like ImageIO) may use file extension to choose the correct parser
|
||||
@note However, different UTType may share the same file extension, like `public.jpeg` and `public.jpeg-2000` both use `.jpg`. If you want detail control, use `TypeIdentifierHint` below
|
||||
*/
|
||||
FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderDecodeFileExtensionHint;
|
||||
|
||||
/**
|
||||
A NSString value (UTI) indicating the source image's file extension. Example: "public.jpeg-2000", "com.nikon.raw-image", "public.tiff"
|
||||
Some image file format share the same data structure but has different tag explanation, like TIFF and NEF/SRW, see https://en.wikipedia.org/wiki/TIFF
|
||||
Changing the file extension cause the different image result. The coder (like ImageIO) may use file extension to choose the correct parser
|
||||
@note If you provide `TypeIdentifierHint`, the `FileExtensionHint` option above will be ignored (because UTType has high priority)
|
||||
@note If you really don't want any hint which effect the image result, pass `NSNull.null` instead
|
||||
*/
|
||||
FOUNDATION_EXPORT SDImageCoderOption _Nonnull const SDImageCoderDecodeTypeIdentifierHint;
|
||||
|
||||
// These options are for image encoding
|
||||
/**
|
||||
|
|
|
@ -12,6 +12,8 @@ SDImageCoderOption const SDImageCoderDecodeFirstFrameOnly = @"decodeFirstFrameOn
|
|||
SDImageCoderOption const SDImageCoderDecodeScaleFactor = @"decodeScaleFactor";
|
||||
SDImageCoderOption const SDImageCoderDecodePreserveAspectRatio = @"decodePreserveAspectRatio";
|
||||
SDImageCoderOption const SDImageCoderDecodeThumbnailPixelSize = @"decodeThumbnailPixelSize";
|
||||
SDImageCoderOption const SDImageCoderDecodeFileExtensionHint = @"decodeFileExtensionHint";
|
||||
SDImageCoderOption const SDImageCoderDecodeTypeIdentifierHint = @"decodeTypeIdentifierHint";
|
||||
|
||||
SDImageCoderOption const SDImageCoderEncodeFirstFrameOnly = @"encodeFirstFrameOnly";
|
||||
SDImageCoderOption const SDImageCoderEncodeCompressionQuality = @"encodeCompressionQuality";
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <ImageIO/ImageIO.h>
|
||||
#import "SDImageCoder.h"
|
||||
|
||||
/**
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
#import "UIImage+ForceDecode.h"
|
||||
#import "SDInternalMacros.h"
|
||||
|
||||
#import <ImageIO/ImageIO.h>
|
||||
#import <CoreServices/CoreServices.h>
|
||||
|
||||
// Specify DPI for vector format in CGImageSource, like PDF
|
||||
static NSString * kSDCGImageSourceRasterizationDPI = @"kCGImageSourceRasterizationDPI";
|
||||
// Specify File Size for lossy format encoding, like JPEG
|
||||
|
@ -320,10 +323,31 @@ static NSString * kSDCGImageDestinationRequestedFileSize = @"kCGImageDestination
|
|||
}
|
||||
#endif
|
||||
|
||||
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
|
||||
NSString *typeIdentifierHint = options[SDImageCoderDecodeTypeIdentifierHint];
|
||||
if (!typeIdentifierHint) {
|
||||
// Check file extension and convert to UTI, from: https://stackoverflow.com/questions/1506251/getting-an-uniform-type-identifier-for-a-given-extension
|
||||
NSString *fileExtensionHint = options[SDImageCoderDecodeFileExtensionHint];
|
||||
if (fileExtensionHint) {
|
||||
typeIdentifierHint = (__bridge_transfer NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)fileExtensionHint, NULL);
|
||||
}
|
||||
} else if ([typeIdentifierHint isEqual:NSNull.null]) {
|
||||
// Hack if user don't want to imply file extension
|
||||
typeIdentifierHint = nil;
|
||||
}
|
||||
|
||||
NSDictionary *creatingOptions = nil;
|
||||
if (typeIdentifierHint) {
|
||||
creatingOptions = @{(__bridge NSString *)kCGImageSourceTypeIdentifierHint : typeIdentifierHint};
|
||||
}
|
||||
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, (__bridge CFDictionaryRef)creatingOptions);
|
||||
if (!source) {
|
||||
// Try again without UTType hint, the call site from user may provide the wrong UTType
|
||||
source = CGImageSourceCreateWithData((__bridge CFDataRef)data, (__bridge CFDictionaryRef)creatingOptions);
|
||||
}
|
||||
if (!source) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
size_t count = CGImageSourceGetCount(source);
|
||||
UIImage *animatedImage;
|
||||
|
||||
|
|
|
@ -9,10 +9,12 @@
|
|||
#import "SDImageIOCoder.h"
|
||||
#import "SDImageCoderHelper.h"
|
||||
#import "NSImage+Compatibility.h"
|
||||
#import <ImageIO/ImageIO.h>
|
||||
#import "UIImage+Metadata.h"
|
||||
#import "SDImageIOAnimatedCoderInternal.h"
|
||||
|
||||
#import <ImageIO/ImageIO.h>
|
||||
#import <CoreServices/CoreServices.h>
|
||||
|
||||
// Specify DPI for vector format in CGImageSource, like PDF
|
||||
static NSString * kSDCGImageSourceRasterizationDPI = @"kCGImageSourceRasterizationDPI";
|
||||
// Specify File Size for lossy format encoding, like JPEG
|
||||
|
@ -110,7 +112,27 @@ static NSString * kSDCGImageDestinationRequestedFileSize = @"kCGImageDestination
|
|||
preserveAspectRatio = preserveAspectRatioValue.boolValue;
|
||||
}
|
||||
|
||||
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
|
||||
NSString *typeIdentifierHint = options[SDImageCoderDecodeTypeIdentifierHint];
|
||||
if (!typeIdentifierHint) {
|
||||
// Check file extension and convert to UTI, from: https://stackoverflow.com/questions/1506251/getting-an-uniform-type-identifier-for-a-given-extension
|
||||
NSString *fileExtensionHint = options[SDImageCoderDecodeFileExtensionHint];
|
||||
if (fileExtensionHint) {
|
||||
typeIdentifierHint = (__bridge_transfer NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)fileExtensionHint, NULL);
|
||||
}
|
||||
} else if ([typeIdentifierHint isEqual:NSNull.null]) {
|
||||
// Hack if user don't want to imply file extension
|
||||
typeIdentifierHint = nil;
|
||||
}
|
||||
|
||||
NSDictionary *creatingOptions = nil;
|
||||
if (typeIdentifierHint) {
|
||||
creatingOptions = @{(__bridge NSString *)kCGImageSourceTypeIdentifierHint : typeIdentifierHint};
|
||||
}
|
||||
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, (__bridge CFDictionaryRef)creatingOptions);
|
||||
if (!source) {
|
||||
// Try again without UTType hint, the call site from user may provide the wrong UTType
|
||||
source = CGImageSourceCreateWithData((__bridge CFDataRef)data, (__bridge CFDictionaryRef)creatingOptions);
|
||||
}
|
||||
if (!source) {
|
||||
return nil;
|
||||
}
|
||||
|
|
|
@ -262,6 +262,15 @@ FOUNDATION_EXPORT SDWebImageContextOption _Nonnull const SDWebImageContextImageP
|
|||
*/
|
||||
FOUNDATION_EXPORT SDWebImageContextOption _Nonnull const SDWebImageContextImageThumbnailPixelSize;
|
||||
|
||||
/**
|
||||
A NSString value (UTI) indicating the source image's file extension. Example: "public.jpeg-2000", "com.nikon.raw-image", "public.tiff"
|
||||
Some image file format share the same data structure but has different tag explanation, like TIFF and NEF/SRW, see https://en.wikipedia.org/wiki/TIFF
|
||||
Changing the file extension cause the different image result. The coder (like ImageIO) may use file extension to choose the correct parser
|
||||
@note If you don't provide this option, we will use the `URL.path` as file extension to calculate the UTI hint
|
||||
@note If you really don't want any hint which effect the image result, pass `NSNull.null` instead
|
||||
*/
|
||||
FOUNDATION_EXPORT SDWebImageContextOption _Nonnull const SDWebImageContextImageTypeIdentifierHint;
|
||||
|
||||
/**
|
||||
A SDImageCacheType raw value which specify the source of cache to query. Specify `SDImageCacheTypeDisk` to query from disk cache only; `SDImageCacheTypeMemory` to query from memory only. And `SDImageCacheTypeAll` to query from both memory cache and disk cache. Specify `SDImageCacheTypeNone` is invalid and totally ignore the cache query.
|
||||
If not provide or the value is invalid, we will use `SDImageCacheTypeAll`. (NSNumber)
|
||||
|
|
|
@ -134,6 +134,7 @@ SDWebImageContextOption const SDWebImageContextImageTransformer = @"imageTransfo
|
|||
SDWebImageContextOption const SDWebImageContextImageScaleFactor = @"imageScaleFactor";
|
||||
SDWebImageContextOption const SDWebImageContextImagePreserveAspectRatio = @"imagePreserveAspectRatio";
|
||||
SDWebImageContextOption const SDWebImageContextImageThumbnailPixelSize = @"imageThumbnailPixelSize";
|
||||
SDWebImageContextOption const SDWebImageContextImageTypeIdentifierHint = @"imageTypeIdentifierHint";
|
||||
SDWebImageContextOption const SDWebImageContextQueryCacheType = @"queryCacheType";
|
||||
SDWebImageContextOption const SDWebImageContextStoreCacheType = @"storeCacheType";
|
||||
SDWebImageContextOption const SDWebImageContextOriginalQueryCacheType = @"originalQueryCacheType";
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <ImageIO/ImageIO.h>
|
||||
#import "SDImageIOAnimatedCoder.h"
|
||||
|
||||
// AVFileTypeHEIC/AVFileTypeHEIF is defined in AVFoundation via iOS 11, we use this without import AVFoundation
|
||||
|
|
Loading…
Reference in New Issue