Add helper method in coder helper to create decoded CGImage to specify orientation. The existing method just call with Up orientation
This commit is contained in:
parent
b9ec481edf
commit
acbdb8c374
|
@ -61,12 +61,23 @@
|
||||||
/**
|
/**
|
||||||
Create a decoded image by the provided image. This follows The Create Rule and you are response to call release after usage.
|
Create a decoded image by the provided image. This follows The Create Rule and you are response to call release after usage.
|
||||||
It will detect whether image contains alpha channel, then create a new bitmap context with the same size of image, and draw it. This can ensure that the image do not need extra decoding after been set to the imageView.
|
It will detect whether image contains alpha channel, then create a new bitmap context with the same size of image, and draw it. This can ensure that the image do not need extra decoding after been set to the imageView.
|
||||||
|
@note This actually call `imageRefCreateDecoded:orientation` with the Up orientation.
|
||||||
|
|
||||||
@param imageRef The CGImage
|
@param imageRef The CGImage
|
||||||
@return A new created decoded image
|
@return A new created decoded image
|
||||||
*/
|
*/
|
||||||
+ (CGImageRef _Nullable)imageRefCreateDecoded:(_Nonnull CGImageRef)imageRef CF_RETURNS_RETAINED;
|
+ (CGImageRef _Nullable)imageRefCreateDecoded:(_Nonnull CGImageRef)imageRef CF_RETURNS_RETAINED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Create a decoded image by the provided image. This follows The Create Rule and you are response to call release after usage.
|
||||||
|
It will detect whether image contains alpha channel, then create a new bitmap context with the same size of image, and draw it. This can ensure that the image do not need extra decoding after been set to the imageView.
|
||||||
|
|
||||||
|
@param imageRef The CGImage
|
||||||
|
@param orientation The image orientation.
|
||||||
|
@return A new created decoded image
|
||||||
|
*/
|
||||||
|
+ (CGImageRef _Nullable)imageRefCreateDecoded:(_Nonnull CGImageRef)imageRef orientation:(CGImagePropertyOrientation)orientation CF_RETURNS_RETAINED;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Return the decoded image by the provided image. This one unlike `imageRefCreateDecoded:`, will not decode the image which contains alpha channel or animated image
|
Return the decoded image by the provided image. This one unlike `imageRefCreateDecoded:`, will not decode the image which contains alpha channel or animated image
|
||||||
@param image The image to be decoded
|
@param image The image to be decoded
|
||||||
|
|
|
@ -248,13 +248,16 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (CGImageRef)imageRefCreateDecoded:(CGImageRef)imageRef {
|
+ (CGImageRef)imageRefCreateDecoded:(CGImageRef)imageRef {
|
||||||
|
return [self imageRefCreateDecoded:imageRef orientation:kCGImagePropertyOrientationUp];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (CGImageRef)imageRefCreateDecoded:(CGImageRef)imageRef orientation:(CGImagePropertyOrientation)orientation {
|
||||||
if (!imageRef) {
|
if (!imageRef) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
size_t width = CGImageGetWidth(imageRef);
|
size_t width = CGImageGetWidth(imageRef);
|
||||||
size_t height = CGImageGetHeight(imageRef);
|
size_t height = CGImageGetHeight(imageRef);
|
||||||
if (width == 0 || height == 0) return NULL;
|
if (width == 0 || height == 0) return NULL;
|
||||||
CGRect rect = CGRectMake(0, 0, width, height);
|
|
||||||
BOOL hasAlpha = [self imageRefContainsAlpha:imageRef];
|
BOOL hasAlpha = [self imageRefContainsAlpha:imageRef];
|
||||||
// iOS prefer BGRA8888 (premultiplied) or BGRX8888 bitmapInfo for screen rendering, which is same as `UIGraphicsBeginImageContext()` or `- [CALayer drawInContext:]`
|
// iOS prefer BGRA8888 (premultiplied) or BGRX8888 bitmapInfo for screen rendering, which is same as `UIGraphicsBeginImageContext()` or `- [CALayer drawInContext:]`
|
||||||
// Through you can use any supported bitmapInfo (see: https://developer.apple.com/library/content/documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_context/dq_context.html#//apple_ref/doc/uid/TP30001066-CH203-BCIBHHBB ) and let Core Graphics reorder it when you call `CGContextDrawImage`
|
// Through you can use any supported bitmapInfo (see: https://developer.apple.com/library/content/documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_context/dq_context.html#//apple_ref/doc/uid/TP30001066-CH203-BCIBHHBB ) and let Core Graphics reorder it when you call `CGContextDrawImage`
|
||||||
|
@ -265,6 +268,25 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
|
||||||
if (!context) {
|
if (!context) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply transform
|
||||||
|
CGAffineTransform transform = SDCGContextTransformFromOrientation(orientation, CGSizeMake(width, height));
|
||||||
|
CGRect rect;
|
||||||
|
switch (orientation) {
|
||||||
|
case kCGImagePropertyOrientationLeft:
|
||||||
|
case kCGImagePropertyOrientationLeftMirrored:
|
||||||
|
case kCGImagePropertyOrientationRight:
|
||||||
|
case kCGImagePropertyOrientationRightMirrored: {
|
||||||
|
// These orientation should swap width & height
|
||||||
|
rect = CGRectMake(0, 0, height, width);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: {
|
||||||
|
rect = CGRectMake(0, 0, width, height);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
CGContextConcatCTM(context, transform);
|
||||||
CGContextDrawImage(context, rect, imageRef);
|
CGContextDrawImage(context, rect, imageRef);
|
||||||
CGImageRef newImageRef = CGBitmapContextCreateImage(context);
|
CGImageRef newImageRef = CGBitmapContextCreateImage(context);
|
||||||
CGContextRelease(context);
|
CGContextRelease(context);
|
||||||
|
@ -546,7 +568,60 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
|
||||||
|
|
||||||
return shouldScaleDown;
|
return shouldScaleDown;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static CGAffineTransform SDCGContextTransformFromOrientation(CGImagePropertyOrientation orientation, CGSize size) {
|
||||||
|
// Inspiration from @libfeihu
|
||||||
|
// We need to calculate the proper transformation to make the image upright.
|
||||||
|
// We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
|
||||||
|
CGAffineTransform transform = CGAffineTransformIdentity;
|
||||||
|
|
||||||
|
switch (orientation) {
|
||||||
|
case kCGImagePropertyOrientationDown:
|
||||||
|
case kCGImagePropertyOrientationDownMirrored:
|
||||||
|
transform = CGAffineTransformTranslate(transform, size.width, size.height);
|
||||||
|
transform = CGAffineTransformRotate(transform, M_PI);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kCGImagePropertyOrientationLeft:
|
||||||
|
case kCGImagePropertyOrientationLeftMirrored:
|
||||||
|
transform = CGAffineTransformTranslate(transform, size.width, 0);
|
||||||
|
transform = CGAffineTransformRotate(transform, M_PI_2);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kCGImagePropertyOrientationRight:
|
||||||
|
case kCGImagePropertyOrientationRightMirrored:
|
||||||
|
transform = CGAffineTransformTranslate(transform, 0, size.height);
|
||||||
|
transform = CGAffineTransformRotate(transform, -M_PI_2);
|
||||||
|
break;
|
||||||
|
case kCGImagePropertyOrientationUp:
|
||||||
|
case kCGImagePropertyOrientationUpMirrored:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (orientation) {
|
||||||
|
case kCGImagePropertyOrientationUpMirrored:
|
||||||
|
case kCGImagePropertyOrientationDownMirrored:
|
||||||
|
transform = CGAffineTransformTranslate(transform, size.width, 0);
|
||||||
|
transform = CGAffineTransformScale(transform, -1, 1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kCGImagePropertyOrientationLeftMirrored:
|
||||||
|
case kCGImagePropertyOrientationRightMirrored:
|
||||||
|
transform = CGAffineTransformTranslate(transform, size.height, 0);
|
||||||
|
transform = CGAffineTransformScale(transform, -1, 1);
|
||||||
|
break;
|
||||||
|
case kCGImagePropertyOrientationUp:
|
||||||
|
case kCGImagePropertyOrientationDown:
|
||||||
|
case kCGImagePropertyOrientationLeft:
|
||||||
|
case kCGImagePropertyOrientationRight:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if SD_UIKIT || SD_WATCH
|
||||||
static NSUInteger gcd(NSUInteger a, NSUInteger b) {
|
static NSUInteger gcd(NSUInteger a, NSUInteger b) {
|
||||||
NSUInteger c;
|
NSUInteger c;
|
||||||
while (a != 0) {
|
while (a != 0) {
|
||||||
|
|
Loading…
Reference in New Issue