485929fd创建于 2019年4月3日历史提交
#import "FlutterNativeImagePlugin.h"
#import <UIKit/UIKit.h>
#import "UIImage+Resize.h"

@implementation FlutterNativeImagePlugin
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
    FlutterMethodChannel* channel = [FlutterMethodChannel
                                     methodChannelWithName:@"flutter_native_image"
                                     binaryMessenger:[registrar messenger]];
    FlutterNativeImagePlugin* instance = [[FlutterNativeImagePlugin alloc] init];
    [registrar addMethodCallDelegate:instance channel:channel];
}

- (UIImage *)normalizedImage:(UIImage *)image {
  if (image.imageOrientation == UIImageOrientationUp) return image;

  UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale);
  [image drawInRect:(CGRect){0, 0, image.size}];
  UIImage *normalizedImage = UIGraphicsGetImageFromCurrentImageContext();
  UIGraphicsEndImageContext();
  return normalizedImage;
}

- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
    NSDictionary *_arguments;
    
    if ([@"getPlatformVersion" isEqualToString:call.method]) {
        result([@"iOS " stringByAppendingString:[[UIDevice currentDevice] systemVersion]]);
    }
    else if ([@"compressImage" isEqualToString:call.method]) {
        _arguments = call.arguments;
        
        NSString *fileExtension = @"_compressed.jpg";
        
        int qualityArgument = [[_arguments objectForKey:@"quality"] intValue];
        int percentageArgument = [[_arguments objectForKey:@"percentage"] intValue];
        int widthArgument = [[_arguments objectForKey:@"targetWidth"] intValue];
        int heightArgument = [[_arguments objectForKey:@"targetHeight"] intValue];
        NSString *fileArgument = [_arguments objectForKey:@"file"];
        NSURL *uncompressedFileUrl = [NSURL URLWithString:fileArgument];
        
        NSString *fileName = [[fileArgument lastPathComponent] stringByDeletingPathExtension];
        NSString *uuid = [[NSUUID UUID] UUIDString];
        NSString *tempFileName =  [NSString stringWithFormat:@"%@%@%@", fileName, uuid, fileExtension];
        NSString *finalFileName = [NSTemporaryDirectory() stringByAppendingPathComponent:tempFileName];
        
        NSString *path = [uncompressedFileUrl path];
        NSData *data = [[NSFileManager defaultManager] contentsAtPath:path];
        
        UIImage *img = [[UIImage alloc] initWithData:data];

        CGFloat newWidth = (widthArgument == 0 ? (img.size.width / 100 * percentageArgument) : widthArgument);
        CGFloat newHeight = (heightArgument == 0 ? (img.size.height / 100 * percentageArgument) : heightArgument);
        
        CGSize newSize = CGSizeMake(newWidth, newHeight);
        
        UIImage *resizedImage = [img resizedImage:newSize interpolationQuality:kCGInterpolationHigh];
        resizedImage = [self normalizedImage:resizedImage];
        NSData *imageData = UIImageJPEGRepresentation(resizedImage, qualityArgument / 100.0);

        if ([[NSFileManager defaultManager] createFileAtPath:finalFileName contents:imageData attributes:nil]) {
            result(finalFileName);
        } else {
            result([FlutterError errorWithCode:@"create_error"
                                       message:@"Temporary file could not be created"
                                       details:nil]);
        }
        
        result(finalFileName);
        return;
    } 
    else if ([@"getImageProperties" isEqualToString:call.method]) {
        _arguments = call.arguments;
        
        NSString *fileArgument = [_arguments objectForKey:@"file"];
        NSURL *uncompressedFileUrl = [NSURL URLWithString:fileArgument];
        NSString *fileName = [[fileArgument lastPathComponent] stringByDeletingPathExtension];

        NSString *path = [uncompressedFileUrl path];
        NSData *data = [[NSFileManager defaultManager] contentsAtPath:path];

        UIImage *img = [[UIImage alloc] initWithData:data];
        
        // Class ALAsset that provides a way to get EXIF attributes has been deprecated since iOS 8+,
        // but the replacing class PHAsset does not have a way to obtain image orientation.
        // For the purposes of FlutterNativeImagePlgin it's ok to leave it as undefined, as
        // all images captured/stored on iOS effectively have "normal" orientation so
        // it should not affect image crop/resize operations.
        int orientation = 0; // undefined orientation
        NSDictionary *dict = @{ @"width" : @(lroundf(img.size.width)),
                                @"height" : @(lroundf(img.size.height)),
                                @"orientation": @((NSInteger)orientation)};

        result(dict);
        return;
    }
    else if([@"cropImage" isEqualToString:call.method]) {
    	_arguments = call.arguments;

	NSString *fileExtension = @"_cropped.jpg";

    	NSString *fileArgument = [_arguments objectForKey:@"file"];
    	NSURL *uncompressedFileUrl = [NSURL URLWithString:fileArgument];
    	int originX = [[_arguments objectForKey:@"originX"] intValue];
    	int originY = [[_arguments objectForKey:@"originY"] intValue];
    	int width = [[_arguments objectForKey:@"width"] intValue];
    	int height = [[_arguments objectForKey:@"height"] intValue];

        NSString *fileName = [[fileArgument lastPathComponent] stringByDeletingPathExtension];   
        NSString *uuid = [[NSUUID UUID] UUIDString];
        NSString *tempFileName =  [NSString stringWithFormat:@"%@%@%@", fileName, uuid, fileExtension];
        NSString *finalFileName = [NSTemporaryDirectory() stringByAppendingPathComponent:tempFileName];
        
        NSString *path = [uncompressedFileUrl path];
        NSData *data = [[NSFileManager defaultManager] contentsAtPath:path];
        
        UIImage *img = [[UIImage alloc] initWithData:data];
        img = [self normalizedImage:img];

        if(originX<0 || originY<0 
        	|| originX>img.size.width || originY>img.size.height 
        	|| originX+width>img.size.width || originY+height>img.size.height) {
        	result([FlutterError errorWithCode:@"bounds_error"
                                        message:@"Bounds are outside of the dimensions of the source image"
                                        details:nil]);
        }

		CGRect cropRect = CGRectMake(originX, originY, width, height);
		CGImageRef imageRef = CGImageCreateWithImageInRect([img CGImage], cropRect);
		UIImage *croppedImg = [UIImage imageWithCGImage:imageRef];
		CGImageRelease(imageRef);

		NSData *imageData = UIImageJPEGRepresentation(croppedImg, 1.0);

        if ([[NSFileManager defaultManager] createFileAtPath:finalFileName contents:imageData attributes:nil]) {
            result(finalFileName);
        } else {
            result([FlutterError errorWithCode:@"create_error"
                                        message:@"Temporary file could not be created"
                                        details:nil]);
        }

        result(finalFileName);
        return;
    }
    else {
        result(FlutterMethodNotImplemented);
    }
}
@end