Unity3D-通过调用iOS原生代码将图片进行高斯模糊

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/pz789as/article/details/89949056

之前一直想使用Shader去做高斯模糊特效,后面发现图片过大的话,效率真的是相当的不理想。

后来在网上看到说iOS本身是有将图片处理成高斯模糊的功能的,想想也确实,苹果设备的背景经常会出现模糊特效,那他们的算法应该很快速的,于是突发奇想,如果将要做模糊处理的图片,传到原生端然后处理成模糊图片之后,再传回来使用,不就可以达到这个目的了么!

首先要知道这个的局限性,不能实时的去做,这是什么意思呢,如果截图这一下也是会有一点卡的,如果实时处理的话,肯定会不流畅。

还有一个,图片的格式,不能是Unity的压缩格式,因为我没法解压缩图片,那穿过去的图片就没法生成正常图片了。

最后,图片要是可读写的,否则拿不到图片的二进制数据,也没法做;

那么怎么做呢,关于Unity桥接原生的我在之前的文章说过了,可以参考这里:Unity和iOS互通

原生代码:

- (void) imageToBlurImage:(NSString *)media radius:(float)radius {
    if(media.length != 0) {// 1、创建输入图像,CIImage类型,这里使用从外部传过来的图片。
        NSData *imageData = [[NSData alloc]initWithBase64EncodedString:media options:0];
        CIImage* inputImage = [CIImage imageWithData:imageData];
        
        // 2、构建一个滤镜图表
//        CIColor* sepiaColor = [CIColor colorWithRed:0.76 green:0.65 blue:0.54];
//        // 2.1 先构建一个 CIColorMonochrome 滤镜,并配置输入图像与滤镜参数
//        CIFilter* monochromeFilter = [CIFilter filterWithName:@"CIColorMonochrome" withInputParameters:@{@"inputColor":sepiaColor,@"inputIntensity":@1.0}];
//        [monochromeFilter setValue:inputImage forKey:@"inputImage"];
//        // 2.2 先构建一个 CIVignette 滤镜
//        CIFilter* vignetteFilter = [CIFilter filterWithName:@"CIVignette" withInputParameters:@{@"inputRadius":@1.0, @"inputIntensity":@1.0}];
//        [vignetteFilter setValue:monochromeFilter.outputImage forKey:@"inputImage"];
        NSNumber* numRad = [NSNumber numberWithFloat:radius];
        CIFilter* gaussianFilter = [CIFilter filterWithName:@"CIGaussianBlur" withInputParameters:@{@"inputRadius":numRad}];
        [gaussianFilter setValue:inputImage forKey:@"inputImage"];
        
        // 3、得到一个滤镜处理后的图片,并转换至 UIImage
        // 创建一个 CIContext
        CIContext* ciContext = [CIContext contextWithOptions:nil];
        // 将 CIImage 过渡到 CGImageRef 类型
        CGImageRef cgImage = [ciContext createCGImage:gaussianFilter.outputImage fromRect:inputImage.extent];
        // 最后转换为 UIImage 类型
        UIImage* uiImage = [UIImage imageWithCGImage:cgImage];
        
        // 将得到的图片转化成图片数据,通过SendMessage传送到Unity端
        NSData *imgData = UIImagePNGRepresentation(uiImage);
        NSString *_encodeImageStr = [imgData base64EncodedStringWithOptions:NSDataBase64DecodingIgnoreUnknownCharacters];
        if (_encodeImageStr == nil){
            UnitySendMessage( "GJCNativeShare", "ToBlurImageFailed", [GJC_DataConvertor NSStringToChar:@"iamge change error! the image format is not support!"]);
        }else{
            UnitySendMessage( "GJCNativeShare", "ToBlurImageSuccess", _encodeImageStr.UTF8String);
        }
    }else{
        UnitySendMessage( "GJCNativeShare", "ToBlurImageFailed", [GJC_DataConvertor NSStringToChar:@"iamge data is null!"]);
    }
}
extern "C" {
    void _GJC_ToBlurImage(char* encodedMedia, float radius){
        NSString *media = [GJC_DataConvertor charToNSString:encodedMedia];
        [[GJCSocialShare sharedInstance] imageToBlurImage:media radius:radius];
    }
}

然后Unity这边:

[DllImport ("__Internal")]
	private static extern bool _GJC_ToBlurImage(string encodedMedia, float radius);
/// <summary>
	/// 调用原生的高斯模糊处理,传递一张图片过去,得到处理之后的图片
	/// </summary>
	/// <param name="texture">分享的图片</param>
	public void TextureToBlur(Texture2D texture, float radius) {
		Debug.Log("TextureToBlur");
		#if UNITY_IPHONE && !UNITY_EDITOR
			if(texture != null) {
				Debug.Log("TextureToBlur: Texture");
				string bytesString = System.Convert.ToBase64String (texture.EncodeToPNG());
				// string bytesString = System.Convert.ToBase64String (texture.GetRawTextureData());
				_GJC_ToBlurImage(bytesString, radius);
			}else{
				ToBlurImageFailed("texture is null!");
			}
		#else
			// string bytesString = System.Convert.ToBase64String (texture.EncodeToEXR());
			// Texture2D newTexture = new Texture2D(1,1);
			// newTexture.LoadRawTextureData(texture.GetRawTextureData());
			// string bytesString = System.Convert.ToBase64String (texture.EncodeToPNG());
			ToBlurImageFailed("this platform is not support!");
		#endif
	}

从原生的回调:

/// <summary>
	/// 图片转换成Blur效果之后,回调的结果
	/// </summary>
	/// <param name="base64">Base64.</param>
	private void ToBlurImageSuccess(string base64)	  
	{
		Debug.Log ("Native To ToBlurImageSuccess");
		if(onToBlurImage != null)
		{
			onToBlurImage("Success", base64);
		}
	}
	private void ToBlurImageFailed(string error){
		Debug.Log ("Native To ToBlurImageFailed: " + error);
		if(onToBlurImage != null)
		{
			onToBlurImage("Failed", error);
		}
	}

将iOS传递过来的数据,转换成图片

/// <summary>
	/// 将ios传过的string转成u3d中的texture
	/// </summary>
	/// <param name="base64"></param>
	/// <returns></returns>
	public static Texture2D Base64StringToTexture2D(string base64)
	{
		Debug.Log ("Run Base64StringToTexture2d");
		Texture2D tex = new Texture2D(1,1);
		try
		{			
			byte[] bytes = System.Convert.FromBase64String(base64);
			tex.LoadImage(bytes);
			tex.hideFlags = HideFlags.DontSave;
			tex.filterMode = FilterMode.Point;
			tex.wrapMode = TextureWrapMode.Clamp;
		}
		catch(System.Exception ex)
		{
			Debug.Log ("Create Texture2D Failed!!");
			Debug.LogError(ex.Message);
		}
		return tex;
	}

自己使用了之后,速度还是蛮快的,目前这个用在一些固定大背景模糊的位置,实时的话,还是想想如何优化Shader去做吧。

猜你喜欢

转载自blog.csdn.net/pz789as/article/details/89949056
今日推荐