ibireme/YYImage

修复图片方向后,图片乱码

rakuyoMo opened this issue · 1 comments

这个问题和以下两个 issues 类似,目前只在 iOS 12 的设备上复现过,iOS 12 以下的设备没有该问题。

#55 (comment) #5 (comment)

这个问题具体来说,是对 YYImage 对象调用 yy_imageDataRepresentation 方法后,出现图片乱码的问题,如下图所示。

_yy_dataRepresentationForSystem 方法中的 修复图片方向的相关代码(2845-2851 行,如下所示)注释后,图片不再乱码。

if (self.imageOrientation != UIImageOrientationUp) {
    CGImageRef rotated = YYCGImageCreateCopyWithOrientation(imageRef, self.imageOrientation, bitmapInfo | alphaInfo);
    if (rotated) {
        CFRelease(imageRef);
        imageRef = rotated;
    }
}

推测为 YYCGImageCreateCopyWithOrientation 方法内部某些代码与 iOS 12 不兼容?

------------------------ English ------------------------

This issue is similar to the following two issues, which are currently only reproduced on iOS 12 devices, and devices with iOS 12 or lower do not have this issue.

#55 (comment) #5 (comment)

Specifically, this problem occurs when the yy_imageDataRepresentation method is called on the YYImage object, and the image is garbled, as shown in the following figure.

After commenting the relevant code (2845-2851 lines, as shown below) in the _yy_dataRepresentationForSystem method, the image is no longer garbled.

if (self.imageOrientation != UIImageOrientationUp) {
    CGImageRef rotated = YYCGImageCreateCopyWithOrientation(imageRef, self.imageOrientation, bitmapInfo | alphaInfo);
    if (rotated) {
        CFRelease(imageRef);
        imageRef = rotated;
    }
}

Is it speculated that some code inside the YYCGImageCreateCopyWithOrientation method is not compatible with iOS 12?

最终我采用 “手动修正图片,之后再转为 NSData 对象” 的方法,解决了这个问题。

相关代码如下:

NSData *imageData = hasAnimatedImageData ? image.animatedImageData : [YYImageEncoder encodeImage:[image mbc_fixOrientation] type:imageType quality:0.9];

修正图片方向的代码如下(来源自互联网):

- (UIImage *)mbc_fixOrientation {
    
    // No-op if the orientation is already correct
    if (self.imageOrientation == UIImageOrientationUp) {
        return self;
    }
    
    // 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 (self.imageOrientation) {
        case UIImageOrientationDown:
        case UIImageOrientationDownMirrored:
            transform = CGAffineTransformTranslate(transform, self.size.width, self.size.height);
            transform = CGAffineTransformRotate(transform, M_PI);
            break;
            
        case UIImageOrientationLeft:
        case UIImageOrientationLeftMirrored:
            transform = CGAffineTransformTranslate(transform, self.size.width, 0);
            transform = CGAffineTransformRotate(transform, M_PI_2);
            break;
            
        case UIImageOrientationRight:
        case UIImageOrientationRightMirrored:
            transform = CGAffineTransformTranslate(transform, 0, self.size.height);
            transform = CGAffineTransformRotate(transform, -M_PI_2);
            break;
        default:
            break;
    }
    
    switch (self.imageOrientation) {
        case UIImageOrientationUpMirrored:
        case UIImageOrientationDownMirrored:
            transform = CGAffineTransformTranslate(transform, self.size.width, 0);
            transform = CGAffineTransformScale(transform, -1, 1);
            break;
            
        case UIImageOrientationLeftMirrored:
        case UIImageOrientationRightMirrored:
            transform = CGAffineTransformTranslate(transform, self.size.height, 0);
            transform = CGAffineTransformScale(transform, -1, 1);
            break;
        default:
            break;
    }
    
    // Now we draw the underlying CGImage into a new context, applying the transform
    // calculated above.
    CGContextRef ctx = CGBitmapContextCreate(NULL,
                                             self.size.width,
                                             self.size.height,
                                             CGImageGetBitsPerComponent(self.CGImage), 0,
                                             CGImageGetColorSpace(self.CGImage),
                                             CGImageGetBitmapInfo(self.CGImage));
    
    CGContextConcatCTM(ctx, transform);
    switch (self.imageOrientation) {
        case UIImageOrientationLeft:
        case UIImageOrientationLeftMirrored:
        case UIImageOrientationRight:
        case UIImageOrientationRightMirrored:
            // Grr...
            CGContextDrawImage(ctx, CGRectMake(0,0,self.size.height,self.size.width), self.CGImage);
            break;
            
        default:
            CGContextDrawImage(ctx, CGRectMake(0,0,self.size.width,self.size.height), self.CGImage);
            break;
    }
    
    // And now we just create a new UIImage from the drawing context
    CGImageRef cgimg = CGBitmapContextCreateImage(ctx);
    UIImage *img = [UIImage imageWithCGImage:cgimg];
    CGContextRelease(ctx);
    CGImageRelease(cgimg);
    return img;
}