Как вызвать PaintSurface дважды в формах Skiasharp Xamarin - PullRequest
0 голосов
/ 09 ноября 2018

Я делаю проект, в котором я могу изменить фильтр изображения. Я использую 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

1 Ответ

0 голосов
/ 09 ноября 2018

Надеюсь, я правильно понял, вы используете несколько SKCanvasViews и в зависимости от того, какой «режим» пользователь выбирает в вашем приложении, вы активируете соответствующую поверхность?

Я бы не рекомендовал это. Даже если это ~ работает ~, это может очень быстро запутать.

Мой подход к вашей проблеме - переписать представление следующим образом:

Создайте перечисление, содержащее имена ваших фильтров и другую запись для «none», например,

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

Затем создайте свойство типа этого перечисления на своей странице.

Filters currentFilter = Filters.None;

Теперь вместо того, чтобы копировать код рендеринга 4 раза, вы можете изменить основной метод PaintSurface на что-то вроде:

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();

поэтому поверхность будет перерисована, а затем сохранено изображение.

...