Update the correct byte alignment and check with 8 * 4 bytes
The sd_isDecoded default value only check once
This commit is contained in:
parent
06589dbcc4
commit
f6ca661537
|
@ -79,6 +79,13 @@ static inline size_t SDByteAlign(size_t size, size_t alignment) {
|
|||
*/
|
||||
+ (CGBitmapInfo)preferredBitmapInfo:(BOOL)containsAlpha;
|
||||
|
||||
/**
|
||||
Check whether CGImage is hardware supported to rendering on screen, without the trigger of `CA::Render::copy_image`
|
||||
You can debug the copied image by using Xcode's `Color Copied Image`, the copied image will turn Cyan and occupy double RAM for bitmap buffer.
|
||||
Typically, when the CGImage's using the method above (`colorspace` / `byteAlignment` / `bitmapInfo`) can render withtout the copy.
|
||||
*/
|
||||
+ (BOOL)CGImageIsHardwareSupported:(_Nonnull CGImageRef)cgImage;
|
||||
|
||||
/**
|
||||
Check whether CGImage contains alpha channel.
|
||||
|
||||
|
|
|
@ -17,8 +17,11 @@
|
|||
#import "SDInternalMacros.h"
|
||||
#import "SDGraphicsImageRenderer.h"
|
||||
#import "SDInternalMacros.h"
|
||||
#import "SDDeviceHelper.h"
|
||||
#import <Accelerate/Accelerate.h>
|
||||
|
||||
#define kCGColorSpaceDeviceRGB @"kCGColorSpaceDeviceRGB"
|
||||
|
||||
#if SD_UIKIT
|
||||
static inline UIImage *SDImageDecodeUIKit(UIImage *image) {
|
||||
// See: https://developer.apple.com/documentation/uikit/uiimage/3750834-imagebypreparingfordisplay
|
||||
|
@ -296,13 +299,10 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
|
|||
}
|
||||
|
||||
+ (size_t)preferredByteAlignment {
|
||||
// Actually the page size of system
|
||||
static int __pageSize = 0;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
__pageSize = getpagesize();
|
||||
});
|
||||
return __pageSize;
|
||||
// https://github.com/path/FastImageCache#byte-alignment
|
||||
// A properly aligned bytes-per-row value must be a multiple of 8 pixels × bytes per pixel.
|
||||
// return [SDDeviceHelper cacheLineSize]; // Seems not the CPU cache line size
|
||||
return 32;
|
||||
}
|
||||
|
||||
+ (CGBitmapInfo)preferredBitmapInfo:(BOOL)containsAlpha {
|
||||
|
@ -315,6 +315,36 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
|
|||
return CGImageGetBitmapInfo(cgImage);
|
||||
}
|
||||
|
||||
+ (BOOL)CGImageIsHardwareSupported:(CGImageRef)cgImage {
|
||||
BOOL supported = YES;
|
||||
// 1. Check byte alignment
|
||||
size_t bytesPerRow = CGImageGetBytesPerRow(cgImage);
|
||||
if (SDByteAlign(bytesPerRow, [SDImageCoderHelper preferredByteAlignment]) == bytesPerRow) {
|
||||
// byte aligned, OK
|
||||
supported &= YES;
|
||||
} else {
|
||||
// not aligned
|
||||
supported &= NO;
|
||||
}
|
||||
if (!supported) return supported;
|
||||
|
||||
// 2. Check color space
|
||||
if (@available(iOS 10.0, tvOS 10.0, macOS 10.6, watchOS 3.0, *)) {
|
||||
CGColorSpaceRef colorspace = CGImageGetColorSpace(cgImage);
|
||||
NSString *colorspaceName = (__bridge_transfer NSString *)CGColorSpaceCopyName(colorspace);
|
||||
// Seems sRGB/deviceRGB always supported, P3 not always
|
||||
if ([colorspaceName isEqualToString:(__bridge NSString *)kCGColorSpaceSRGB] || [colorspaceName isEqualToString:kCGColorSpaceDeviceRGB]) {
|
||||
supported &= YES;
|
||||
} else {
|
||||
supported &= NO;
|
||||
}
|
||||
return supported;
|
||||
} else {
|
||||
// Fallback on earlier versions
|
||||
return supported;
|
||||
}
|
||||
}
|
||||
|
||||
+ (BOOL)CGImageContainsAlpha:(CGImageRef)cgImage {
|
||||
if (!cgImage) {
|
||||
return NO;
|
||||
|
|
|
@ -20,25 +20,22 @@
|
|||
} else {
|
||||
// Assume only CGImage based can use lazy decoding
|
||||
CGImageRef cgImage = self.CGImage;
|
||||
if (!cgImage) {
|
||||
// Assume others as non-decoded
|
||||
return NO;
|
||||
}
|
||||
CFStringRef uttype = CGImageGetUTType(self.CGImage);
|
||||
if (uttype) {
|
||||
// Only ImageIO can set `com.apple.ImageIO.imageSourceTypeIdentifier`
|
||||
return NO;
|
||||
} else {
|
||||
// Now, let's check if the CGImage is byte-aligned (not aligned will cause extra copy)
|
||||
size_t bytesPerRow = CGImageGetBytesPerRow(cgImage);
|
||||
if (SDByteAlign(bytesPerRow, [SDImageCoderHelper preferredByteAlignment]) == bytesPerRow) {
|
||||
// byte aligned, OK
|
||||
return YES;
|
||||
BOOL isDecoded;
|
||||
if (cgImage) {
|
||||
CFStringRef uttype = CGImageGetUTType(self.CGImage);
|
||||
if (uttype) {
|
||||
// Only ImageIO can set `com.apple.ImageIO.imageSourceTypeIdentifier`
|
||||
isDecoded = NO;
|
||||
} else {
|
||||
// not aligned, still need force-decode
|
||||
return NO;
|
||||
// Now, let's check if the CGImage is hardware supported (not byte-aligned will cause extra copy)
|
||||
isDecoded = [SDImageCoderHelper CGImageIsHardwareSupported:cgImage];
|
||||
}
|
||||
} else {
|
||||
// Assume others as non-decoded
|
||||
isDecoded = NO;
|
||||
}
|
||||
objc_setAssociatedObject(self, @selector(sd_isDecoded), @(isDecoded), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
return isDecoded;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,5 +14,6 @@
|
|||
|
||||
+ (NSUInteger)totalMemory;
|
||||
+ (NSUInteger)freeMemory;
|
||||
+ (size_t)cacheLineSize;
|
||||
|
||||
@end
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#import "SDDeviceHelper.h"
|
||||
#import <mach/mach.h>
|
||||
#import <sys/sysctl.h>
|
||||
|
||||
@implementation SDDeviceHelper
|
||||
|
||||
|
@ -29,4 +30,18 @@
|
|||
return vm_stat.free_count * page_size;
|
||||
}
|
||||
|
||||
+ (size_t)cacheLineSize {
|
||||
size_t size;
|
||||
sysctlbyname("hw.cachelinesize", NULL, &size, NULL, 0);
|
||||
char *info = malloc(size);
|
||||
sysctlbyname("hw.cachelinesize", info, &size, NULL, 0);
|
||||
if (strlen(info)) {
|
||||
// hardcode
|
||||
return 64;
|
||||
}
|
||||
char *end;
|
||||
long result = strtol(info, &end, 10);
|
||||
return result;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
Loading…
Reference in New Issue