无法使用MTKTextureLoader将大型jpeg加载到MTLTexture中

时间:2019-02-15 13:40:08

标签: metal core-image metalkit

我正在尝试将大图像加载到MTLTexture中,并且可以处理4000x6000图像。但是,当我尝试使用6000x8000时,它不能。

func setTexture(device:MTLDevice,imageName:String)-> MTLTexture? {         让textureLoader = MTKTextureLoader(设备:设备)

public partial class DrawAndSharePage : Rg.Plugins.Popup.Pages.PopupPage
{
    Dictionary<long, SKPath> inProgressPaths = new Dictionary<long, SKPath>();
    List<SKPath> completedPaths = new List<SKPath>();

    SKPaint paint = new SKPaint
    {
        Style = SKPaintStyle.Stroke,
        Color = SKColors.Blue,
        StrokeWidth = 10,
        StrokeCap = SKStrokeCap.Round,
        StrokeJoin = SKStrokeJoin.Round
    };

    public DrawAndSharePage()
    {
        BackgroundColor = new Color(0, 0, 0, 0.1);
        InitializeComponent();
    }

    private async void BtnClose_Clicked(object sender, System.EventArgs e)
    {
        await Rg.Plugins.Popup.Services.PopupNavigation.Instance.PopAllAsync();
    }

    void OnTouchEffectAction(object sender, TouchActionEventArgs args)
    {
        switch (args.Type)
        {
            case TouchActionType.Pressed:
                if (!inProgressPaths.ContainsKey(args.Id))
                {
                    SKPath path = new SKPath();
                    path.MoveTo(ConvertToPixel(args.Location));
                    inProgressPaths.Add(args.Id, path);
                    canvasView.InvalidateSurface();
                }
                break;

            case TouchActionType.Moved:
                if (inProgressPaths.ContainsKey(args.Id))
                {
                    SKPath path = inProgressPaths[args.Id];
                    path.LineTo(ConvertToPixel(args.Location));
                    canvasView.InvalidateSurface();
                }
                break;

            case TouchActionType.Released:
                if (inProgressPaths.ContainsKey(args.Id))
                {
                    completedPaths.Add(inProgressPaths[args.Id]);
                    inProgressPaths.Remove(args.Id);
                    canvasView.InvalidateSurface();
                }
                break;

            case TouchActionType.Cancelled:
                if (inProgressPaths.ContainsKey(args.Id))
                {
                    inProgressPaths.Remove(args.Id);
                    canvasView.InvalidateSurface();
                }
                break;
        }
    }

    void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
    {
        SKCanvas canvas = args.Surface.Canvas;
        canvas.Clear();

        foreach (SKPath path in completedPaths)
        {
            canvas.DrawPath(path, paint);
        }

        foreach (SKPath path in inProgressPaths.Values)
        {
            canvas.DrawPath(path, paint);
        }
    }

    SKPoint ConvertToPixel(Point pt)
    {
        return new SKPoint((float)(canvasView.CanvasSize.Width * pt.X / canvasView.Width),
                           (float)(canvasView.CanvasSize.Height * pt.Y / canvasView.Height));
    }

    private void OnTouchEffectAction(object sender, object args)
    {

    }
}

相当基本的代码。我正在具有A9芯片,GPU系列3的iPad Pro中运行它。它应该处理这么大的纹理。如果不接受此大小,是否应该以某种方式手动对其进行平铺?在那种情况下,最好的方法是:使用MTLRegionMake复制字节,在Core Image或Core Graphics上下文中切片...

感谢您的帮助

2 个答案:

答案 0 :(得分:0)

我之前遇到过这个问题,纹理会加载到一个设备上,而不是另一个上。我认为这是纹理加载器的错误。

您可以使用CGImage和CGContext手动加载纹理,将图像绘制到上下文中。创建一个MTLTexture缓冲区,然后使用MTLRegion将字节从CGContext复制到纹理中。

这并非万无一失,您必须确保对金属缓冲区使用正确的像素格式,否则会得到奇怪的结果,因此您可以为要导入的一种特定格式的图像编写代码,或者执行很多操作检查。苹果公司的Basic Texturing example展示了如何在使用MTLRegion将字节写入纹理之前更改颜色顺序。

答案 1 :(得分:0)

在您提出有用的意见之后,我决定手动将其加载到CGContext并复制到MTLTexture。我在下面添加解决方案代码。不应在每次创建纹理时都创建上下文,最好将其放置在函数之外并保持重用。

UIView