Flutter+Metal实现图像处理详细流程

 更新时间:2022年06月18日 09:25:00   作者:handyTool  
Flutter使用CVPixelBuffer和iOS交互,我们可以直接使用CVPixelBuffer创建MTLTexture,然后将MTLTexture设置为渲染目标,这篇文章主要介绍了Flutter+Metal实现图像处理,需要的朋友可以参考下

背景

在之前自制的图像处理App中,使用了OpenGL处理图片,这次使用Metal替代OpenGL,来达到更好的性能,顺便熟悉一下Metal的渲染流程

基本思路

Flutter使用CVPixelBuffer和iOS交互,我们可以直接使用CVPixelBuffer创建MTLTexture,然后将MTLTexture设置为渲染目标。这样Metal框架可以直接将渲染结果写入CVPixelBuffer,达到更加高效的目的。

Metal环境设置

主要初始化DevicePipelineStateCommandQueue三个对象。我们需要依赖Device分配各种Metal资源,PipelineState管理着渲染流水线的各个环节的配置,比如vertex shader,fragment shader,输出像素格式等。CommandQueue用于管理执行的绘制命令。

_device = MTLCreateSystemDefaultDevice();
id<MTLLibrary> lib = [_device newDefaultLibrary];
id<MTLFunction> vertexFunc = [lib newFunctionWithName:vertexFuncName];
id<MTLFunction> fragFunc = [lib newFunctionWithName:fragFuncName];
MTLRenderPipelineDescriptor *renderPipelineDesc = [MTLRenderPipelineDescriptor new];
renderPipelineDesc.vertexFunction = vertexFunc;
renderPipelineDesc.fragmentFunction = fragFunc;
renderPipelineDesc.colorAttachments[0].pixelFormat = MTLPixelFormatBGRA8Unorm;
_pipelineState = [_device newRenderPipelineStateWithDescriptor:renderPipelineDesc error:nil];
_commandQueue = [_device newCommandQueue];

从CVPixelBuffer创建MTLTexture纹理

首先创建一个CVPixelBuffer对象

NSDictionary *pixelAttributes = @{( id )kCVPixelBufferIOSurfacePropertiesKey : @{}};
CVPixelBufferCreate(
            kCFAllocatorDefault,
                    imageWidth,
                    imageHeight,
            kCVPixelFormatType_32BGRA,
                    (__bridge CFDictionaryRef)pixelAttributes,
                    &_renderTargetPixelBuffer);

利用CVMetalTextureCacheCreateTextureFromImageCVPixelBuffer创建MTLTexture

CVReturn ret = CVMetalTextureCacheCreate(kCFAllocatorDefault, nil, _mtContext.device, nil, &_textureCache);
CVMetalTextureRef renderTargetMetalTextureRef;
ret = CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault, _textureCache, _renderTargetPixelBuffer, nil, MTLPixelFormatBGRA8Unorm, imageWidth, imageHeight, 0, &renderTargetMetalTextureRef);
id<MTLTexture> mtlTexture = CVMetalTextureGetTexture(renderTargetMetalTextureRef);

渲染到纹理

CommandQueue获得一个CommandBuffer,用于保存需要执行的绘制命令

_activeCmdBuffer = [_commandQueue commandBuffer];

创建MTLRenderPassDescriptor设置本次绘制的相关配置,比如绘制到哪里,这里指定通过CVPixelBuffer创建出来的MTLTexture,是否清除当前内容,清除的颜色

MTLRenderPassDescriptor *renderPassDesc = [MTLRenderPassDescriptor new];
renderPassDesc.colorAttachments[0].texture = target;
renderPassDesc.colorAttachments[0].loadAction = MTLLoadActionClear;
renderPassDesc.colorAttachments[0].clearColor = MTLClearColorMake(0, 0, 0, 1);

通过CommandBufferMTLRenderPassDescriptor创建一个MTLRenderCommandEncoder

_activeEncoder = [_activeCmdBuffer renderCommandEncoderWithDescriptor:renderPassDesc];

指定MTLRenderCommandEncoder所在的PipelineState

[_activeEncoder setRenderPipelineState:_pipelineState];

使用MTLRenderCommandEncoder绑定BufferTexture,在Metal里,Uniform和Vertex Buffer 都是通过MTLBuffer绑定到Shader中

[_activeEncoder setVertexBuffer:vertexBuffer offset:0 atIndex:0];
[_activeEncoder setFragmentBuffer:uniformBuffer offset:0 atIndex:0];
[_activeEncoder setFragmentBuffer:texture offset:0 atIndex:0];

绘制图形

[_activeEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:vertexCount instanceCount:1];

显式的结束MTLRenderCommandEncoder

[_activeEncoder endEncoding];

提交CommandBuffer

[_activeCmdBuffer commit];

等待绘制结束,如果你想要异步等待,需要在[_activeCmdBuffer commit]之前设置completedHandler

// 同步等待
[_activeCmdBuffer waitUntilCompleted];
// 异步等待
[_activeCmdBuffer addCompletedHandler:^(id<MTLCommandBuffer> _Nonnull buf) {
}];

到此绘制的内容就已经在CVPixelBuffer中了,再将CVPixelBuffer提交给Flutter显示即可。

到此这篇关于Flutter+Metal实现图像处理的文章就介绍到这了,更多相关Flutter图像处理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Android中注解处理器APT用法示例

    Android中注解处理器APT用法示例

    APT全称Annotation Processing Tool,即注解处理器,APT是一种处理注释的工具, 它对源代码文件进行检测找出其中的注解,并使用注解进行额外的处理,给我们自动生成代码,简化使用,很多流行框架都使用到了APT技术,如 ButterKnife,Retrofit,Arouter,EventBus 等等
    2023-12-12
  • Android编程实现自定义title功能示例

    Android编程实现自定义title功能示例

    这篇文章主要介绍了Android编程实现自定义title功能,结合具体实例形式分析了Android自定义title的具体实现步骤与相关操作技巧,需要的朋友可以参考下
    2017-03-03
  • Android ListView分页简单实现

    Android ListView分页简单实现

    这篇文章主要介绍了Android ListView分页简单实现的相关资料,需要的朋友可以参考下
    2017-06-06
  • Android实现简易的柱状图和曲线图表实例代码

    Android实现简易的柱状图和曲线图表实例代码

    柱状图是统计图表中经常用到的一种图表,比如降雨量之类的统计展示。这篇文章主要给大家介绍了关于利用Android如何实现简易的柱状图和曲线图表的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下。
    2017-12-12
  • php 异步调用方法实现示例

    php 异步调用方法实现示例

    客户端与服务器端是通过HTTP协议进行连接通讯,客户端发起请求,服务器端接收到请求后执行处理,并返回处理结果
    2014-01-01
  • android判断一个Activity是否处于栈顶的实例

    android判断一个Activity是否处于栈顶的实例

    下面小编就为大家分享一篇android判断一个Activity是否处于栈顶的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-03-03
  • 安卓(android)怎么实现下拉刷新

    安卓(android)怎么实现下拉刷新

    这里我们将采取的方案是使用组合View的方式,先自定义一个布局继承自LinearLayout,然后在这个布局中加入下拉头和ListView这两个子元素,并让这两个子元素纵向排列。对安卓(android)怎么实现下拉刷新的相关知识感兴趣的朋友一起学习吧
    2016-04-04
  • Android多点触控实现图片自由缩放

    Android多点触控实现图片自由缩放

    这篇文章主要为大家详细介绍了Android多点触控实现图片自由缩放,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-12-12
  • Android 6.0权限请求相关及权限分组方法

    Android 6.0权限请求相关及权限分组方法

    今天小编就为大家分享一篇Android 6.0权限请求相关及权限分组方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-08-08
  • 将替代ListView的RecyclerView 的使用详解(一)

    将替代ListView的RecyclerView 的使用详解(一)

    这篇文章主要介绍了将替代ListView的RecyclerView 的使用详解(一)的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2016-07-07

最新评论