【问题标题】:How to call PaintSurface twice in skiasharp xamarin forms如何在skiasharp xamarin表单中调用PaintSurface两次
【发布时间】:2019-04-12 16:44:59
【问题描述】:

我正在做一个可以更改图像过滤器的项目。我正在使用skiasharp 来更改图像的过滤器。它类似于 CamScanner 应用程序。但是,当我先将滤镜更改为灰度,然后变亮,然后是棕褐色,然后再次返回灰度时,我点击保存,我得到了棕褐色的图像。我知道最后生成的数据是棕褐色的,因此它正在保存该数据。但是,如果我想更改 3 次以上,它就行不通了。请帮帮我。这是我的编码。

  <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 xmlns:skia="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms"
                 BackgroundColor="Black"
                 x:Class="JC.EditPage">
        <ContentPage.Content>

            <StackLayout Padding="10,10,10,10" Orientation="Vertical">


                <Image x:Name="imageView" HeightRequest="450"
                       HorizontalOptions="FillAndExpand"
                       VerticalOptions="CenterAndExpand" IsVisible="True"/>

                <StackLayout x:Name="canvasStackView" IsVisible="False">
                    <skia:SKCanvasView HeightRequest="450" PaintSurface="OnCanvasViewPaintSurface" VerticalOptions="CenterAndExpand" HorizontalOptions="FillAndExpand"/>
                </StackLayout>

                <StackLayout x:Name="canvasLightenStackView" IsVisible="False">
                    <skia:SKCanvasView HeightRequest="450" PaintSurface="OnCanvasViewPaintSurfaceLighten" VerticalOptions="CenterAndExpand" HorizontalOptions="FillAndExpand"/>
                </StackLayout>

                <StackLayout x:Name="canvasSepiaStackView" IsVisible="False">
                    <skia:SKCanvasView HeightRequest="450" PaintSurface="OnCanvasViewPaintSurfaceSepia" VerticalOptions="CenterAndExpand" HorizontalOptions="FillAndExpand"/>
                </StackLayout>

      <ScrollView Orientation="Horizontal" HorizontalScrollBarVisibility="Never">
                    <StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand" VerticalOptions="EndAndExpand" x:Name="filterStack" IsVisible="True">
                        <StackLayout WidthRequest="100" HeightRequest="70" BackgroundColor="White">
                            <Label Text="Original" FontFamily="Bold" Font="14" TextColor="Black" VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand"/>
                            <StackLayout.GestureRecognizers>
                                <TapGestureRecognizer Tapped="Original_Tapped">
                                </TapGestureRecognizer>
                            </StackLayout.GestureRecognizers>
                        </StackLayout>

                        <StackLayout WidthRequest="100" HeightRequest="70" BackgroundColor="White" >
                            <Label Text="Grayscale" FontFamily="Bold" Font="14" TextColor="Black" VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand"/>
                            <StackLayout.GestureRecognizers>
                                <TapGestureRecognizer Tapped="Grayscale_Tapped">
                                </TapGestureRecognizer>
                            </StackLayout.GestureRecognizers>
                        </StackLayout>

                        <StackLayout WidthRequest="100" HeightRequest="70" BackgroundColor="White">
                            <Label Text="Lighten" FontFamily="Bold" Font="14" TextColor="Black" VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand"/>
                            <StackLayout.GestureRecognizers>
                                <TapGestureRecognizer Tapped="Lighten_Tapped">
                                </TapGestureRecognizer>
                            </StackLayout.GestureRecognizers>
                        </StackLayout>

                        <StackLayout WidthRequest="100" HeightRequest="70" BackgroundColor="White" >
                            <Label Text="Sepia" FontFamily="Bold" Font="14" TextColor="Black" VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand"/>
                            <StackLayout.GestureRecognizers>
                                <TapGestureRecognizer Tapped="Speia_Tapped">
                                </TapGestureRecognizer>
                            </StackLayout.GestureRecognizers>
                        </StackLayout>
                    </StackLayout>
                </ScrollView>

                <StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand" VerticalOptions="EndAndExpand" BackgroundColor="White">
                    <Image Source="goback.png" HorizontalOptions="StartAndExpand">
                        <Image.GestureRecognizers>
                            <TapGestureRecognizer Tapped="goback_Tapped"/>
                        </Image.GestureRecognizers>
                    </Image>

                    <Image Source="tick.png" HorizontalOptions="EndAndExpand">
                        <Image.GestureRecognizers>
                            <TapGestureRecognizer Tapped="Save_Tapped"/>
                        </Image.GestureRecognizers>
                    </Image>
                </StackLayout>
            </StackLayout>
        </ContentPage.Content>
    </ContentPage>

这是我的 XAML.CS 文件 -

  private async void Grayscale_Tapped(object sender, EventArgs e)
    {
        DependencyService.Get<IProgressInterface>().ShowLoader("Please wait...");



        adjust = false;
        canvasEditStackView.IsVisible = false;
        canvasSepiaStackView.IsVisible = false;
        canvasLightenStackView.IsVisible = false;
        imageView.IsVisible = false;
        canvasStackView.IsVisible = true;
        filterStack.IsVisible = true;
        original = false;

        byte[] tempArray = await StorageHelper.LoadImage(image, path);

       canvasView = new SKCanvasView();
       canvasView.PaintSurface += OnCanvasViewPaintSurface;

        using (Stream stream = new MemoryStream(tempArray))
        {
            if (stream != null)
            {
                libraryBitmap = SKBitmap.Decode(stream);
                canvasView.InvalidateSurface();
            }
        }
        DependencyService.Get<IProgressInterface>().DismissLoader();
    }

    void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
    {
        Console.WriteLine("Hits");
        DependencyService.Get<IProgressInterface>().ShowLoader("Please wait...");

        SKImageInfo info = args.Info;
        SKSurface surface = args.Surface;
        SKCanvas canvas = surface.Canvas;

        canvas.Clear();

        using (SKPaint paint = new SKPaint())
        {

            paint.ColorFilter =
                SKColorFilter.CreateColorMatrix(new float[]
                {
                0.21f, 0.72f, 0.07f, 0, 0,
                0.21f, 0.72f, 0.07f, 0, 0,
                0.21f, 0.72f, 0.07f, 0, 0,
                0,     0,     0,     1, 0
                });

            canvas.DrawBitmap(libraryBitmap, info.Rect, BitmapStretch.Uniform, paint: paint);
            DependencyService.Get<IProgressInterface>().DismissLoader();
        }
        var snap = surface.Snapshot();
        SKData data = snap.Encode();
        saveData = data;

    }

    private async void Lighten_Tapped(object sender, EventArgs e)
    {
        DependencyService.Get<IProgressInterface>().ShowLoader("Please wait...");


        adjust = false;
        imageView.IsVisible = false;
        canvasEditStackView.IsVisible = false;
        canvasStackView.IsVisible = false;
        canvasSepiaStackView.IsVisible = false;
        canvasLightenStackView.IsVisible = true;
        filterStack.IsVisible = true;
        original = false;

        byte[] tempArray = await StorageHelper.LoadImage(image, path);

        canvasView = new SKCanvasView();
        canvasView.PaintSurface += OnCanvasViewPaintSurfaceLighten;

        using (Stream stream = new MemoryStream(tempArray))
        {
            if (stream != null)
            {
                libraryBitmap = SKBitmap.Decode(stream);
                canvasView.InvalidateSurface();
            }
        }
        DependencyService.Get<IProgressInterface>().DismissLoader();

    }

    void OnCanvasViewPaintSurfaceLighten(object sender, SKPaintSurfaceEventArgs args)
    {
        DependencyService.Get<IProgressInterface>().ShowLoader("Please wait...");
        SKImageInfo info = args.Info;
        SKSurface surface = args.Surface;
        SKCanvas canvas = surface.Canvas;

        canvas.Clear();

        using (SKPaint paint = new SKPaint())
        {
            paint.ColorFilter =
                SKColorFilter.CreateColorMatrix(new float[]
                {
                0.75f, 0.25f, 0.25f, 0, 0,
                0.25f, 0.75f, 0.25f, 0, 0,
                0.25f, 0.25f, 0.75f, 0, 0,
                0, 0, 0, 1, 0
                });
            canvas.DrawBitmap(libraryBitmap, info.Rect, BitmapStretch.Uniform, paint: paint);
            DependencyService.Get<IProgressInterface>().DismissLoader();
        }
        var snap = surface.Snapshot();
        SKData data = snap.Encode();
        saveData = data;

    }

    public async void Speia_Tapped(object sender, EventArgs e)
    {

        DependencyService.Get<IProgressInterface>().ShowLoader("Please wait...");



        adjust = false;
        imageView.IsVisible = false;
        canvasEditStackView.IsVisible = false;
        canvasStackView.IsVisible = false;
        canvasLightenStackView.IsVisible = false;
        canvasSepiaStackView.IsVisible = true;
        filterStack.IsVisible = true;
        original = false;

        byte[] tempArray = await StorageHelper.LoadImage(image, path);

        canvasView = new SKCanvasView();
        canvasView.PaintSurface += OnCanvasViewPaintSurfaceSepia;

        using (Stream stream = new MemoryStream(tempArray))
        {
            if (stream != null)
            {
                libraryBitmap = SKBitmap.Decode(stream);
                canvasView.InvalidateSurface();

            }
        }
        DependencyService.Get<IProgressInterface>().DismissLoader();
    }

    void OnCanvasViewPaintSurfaceSepia(object sender, SKPaintSurfaceEventArgs args)
    {
        DependencyService.Get<IProgressInterface>().ShowLoader("Please wait...");
        SKImageInfo info = args.Info;
        SKSurface surface = args.Surface;
        SKCanvas canvas = surface.Canvas;

        canvas.Clear();
        using (SKPaint paint = new SKPaint())
        {
            paint.ColorFilter =
                SKColorFilter.CreateColorMatrix(new float[]
                {
                  1, 0,   0, 0, 0,
                  0, 1,   0, 0, 0,
                  0, 0, 0.8f, 0, 0,
                  0, 0,   0, 1, 0
                });
            canvas.DrawBitmap(libraryBitmap, info.Rect, BitmapStretch.Uniform, paint: paint);
            DependencyService.Get<IProgressInterface>().DismissLoader();
        }
        var snap = surface.Snapshot();
        SKData data = snap.Encode();
        saveData = data;
    }

这是我的保存命令。

 if (original == true)
            {
                var editPref = DependencyService.Get<IUserPreferences>();
                editPref.SaveString("edit", "false");

                await Navigation.PushModalAsync(new desiredLocationStoragePage(path));
            }
            else
            {
                var editPref = DependencyService.Get<IUserPreferences>();
                editPref.SaveString("edit", "true");
                string saveName = fileName;
                using (var stream = File.OpenWrite(saveName))
                {
                    saveData.SaveTo(stream);
                }
                await Navigation.PushModalAsync(new desiredLocationStoragePage(fileName));

            }



   please help me out guys I am quite stuck after this phase

【问题讨论】:

    标签: xamarin xamarin.forms xamarin.ios xamarin.android skiasharp


    【解决方案1】:

    希望我没看错,您正在使用多个 SKCanvasViews,并且根据用户在您的应用中选择的“模式”,您激活相应的表面?

    我不建议这样做。即使它〜有点〜工作,它可能会很快变得混乱。

    我对您的问题的处理方法是按以下方式重写视图:

    创建一个包含过滤器名称和另一个“无”条目的枚举,例如

    public enum Filters
    {
        None = 0,
        Grayscale = 1,
        Lighten = 2,
        Sepia = 4
    } 
    

    然后在您的页面中创建此枚举类型的属性。

    Filters currentFilter = Filters.None;
    

    现在,您可以将主 PaintSurface 方法更改为类似以下内容,而不是复制您的渲染代码 4 次:

    void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
    {
        Console.WriteLine("Hits");
        DependencyService.Get<IProgressInterface>().ShowLoader("Please wait...");
    
        SKImageInfo info = args.Info;
        SKSurface surface = args.Surface;
        SKCanvas canvas = surface.Canvas;
    
        canvas.Clear();
    
    
    
        using (SKPaint paint = new SKPaint())
        {
            // check if currentFilter is set to Filters.None
            if( (currentFilter & Filters.None) == Filters.None )
            {
                paint.ColorFilter =
                    SKColorFilter.CreateColorMatrix(new float[]
                    {
                        0.21f, 0.72f, 0.07f, 0, 0,
                        0.21f, 0.72f, 0.07f, 0, 0,
                        0.21f, 0.72f, 0.07f, 0, 0,
                        0,     0,     0,     1, 0
                    });
            }
            // check if currentFilter is set to Filters.Lighten
            else if ( (currentFilter & Filters.Lighten) == Filters.Lighten)
            {
                paint.ColorFilter =
                    SKColorFilter.CreateColorMatrix(new float[]
                    {
                        0.75f, 0.25f, 0.25f, 0, 0,
                        0.25f, 0.75f, 0.25f, 0, 0,
                        0.25f, 0.25f, 0.75f, 0, 0,
                        0, 0, 0, 1, 0
                });
            }
    
            /*
                ... proceed with other filters accordingly ....
            */
    
            canvas.DrawBitmap(libraryBitmap, info.Rect, BitmapStretch.Uniform, paint: paint);
            DependencyService.Get<IProgressInterface>().DismissLoader();
        }
        var snap = surface.Snapshot();
        SKData data = snap.Encode();
        saveData = data;
    
    }
    

    因此,当您点击 SetFilterButton 时,您只需将页面的 customFilter 属性设置为相应的过滤器并调用

    canvasView.InvalidateSurface();
    

    所以表面将被重绘,然后保存图像。

    【讨论】:

    • 哇,我怎么没想到。非常感谢@markus,我将立即实施。
    • 我尝试实现,但 canvasView 不会根据模式发生变化。我认为问题出在canvasView.InvalidateSurface(); 我尝试在 onclick 方法中的任何地方使用它。但它似乎并没有重绘一个新的表面。它需要旧的。就像我先点击 speia 一样,它会变成棕褐色,但之后如果我点击灰度,它仍然需要棕褐色。我将控制台放在 onpaintsurface 方法上,在第一种模式后单击任何内容后它都没有命中......希望你能理解。
    • 再次查看您的函数后,我注意到 canvasView 是在您点击的方法中创建的,而没有添加到屏幕上的任何位置。所以基本上你的画布视图存在于内存中的某个地方,但从不在屏幕上,因此永远不会绘制任何东西。但是,这应该很容易解决。在您的 xaml 中,给(希望只有)SKCanvasView 属性“x:Name="CanvasView"。现在您可以在您的按钮点击方法中调用 CanvasView.InvalidateSurface()。
    • 我真的不知道该怎么感谢你。愿上帝保佑你。它像美女一样工作。
    猜你喜欢
    • 1970-01-01
    • 2018-09-27
    • 2020-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-19
    相关资源
    最近更新 更多