Поддерживает ли UWP Composition Api замену цвета?

Я пытался найти примеры, связанные с заменой цвета, вот пример использования Photoshop, который может взять, например, синий оттенок и заменить его на красный оттенок:

ПЕРЕД:  введите описание изображения здесь

ПОСЛЕ:  введите описание изображения здесь

Возможно ли это с помощью Composition Effects в последней версии Composition Api?

Я видел примеры, связанные с вращением оттенка, температурой и оттенком:

https://xamlbrewer.wordpress.com/2016/04/08/uwp-composition-effects-hue-rotation/

https://xamlbrewer.wordpress.com/2016/04/19/uwp-composition-effects-temperature-and-tint/

Но мне интересно, может ли api использовать эффекты для переключения цветового диапазона в изображении?


person Maximus    schedule 01.12.2017    source источник
comment
Вот ColorMatrixEffect, упомянутый Johhny для тех, кто хочет дополнительно изучить такую ​​функцию: microsoft noreferrer. github.io/Win2D/html/ Я также наткнулся на блог, который использует эффекты для изменения оттенка / температуры изображения. Это не совсем то, что я хотел, но он близок, и я могу его использовать. blog.robmikh.com/uwp/composition/ 2016/04/21 /   -  person Maximus    schedule 18.01.2018


Ответы (1)


У меня есть решение, которое может тебе понравиться. Пример выглядит так:

введите описание изображения здесь

Для этого я использовал 3 эффекта в цепочке: PixelShaderEffect, GaussianBlurEffect и BlendEffect из Win2d API.

XAML имеет CanvasAnimatedControl для рисования результата, а также некоторые вспомогательные средства, такие как source (цвет, который мы хотим заменить) и заменять средства выбора цвета и ползунок порогового значения.

<Grid>
    <xaml:CanvasAnimatedControl x:Name="AnimatedControl"
                            CreateResources="AnimatedControl_OnCreateResources"
                            Draw="AnimatedControl_OnDraw"/>

    <StackPanel HorizontalAlignment="Left" VerticalAlignment="Bottom">
        <TextBlock Text="Source Color" FontSize="32" Foreground="White" TextAlignment="Center"/>

        <ColorSpectrum Width="256" Height="256" ColorChanged="ColorSpectrum_OnColorChanged"/>
    </StackPanel>

    <StackPanel HorizontalAlignment="Right" VerticalAlignment="Bottom">
        <TextBlock Text="Replace Color" FontSize="32" Foreground="White" TextAlignment="Center"/>

        <ColorSpectrum Width="256" Height="256" ColorChanged="ColorSpectrum_OnColorChanged1"/>
    </StackPanel>

    <Slider Width="512" ValueChanged="RangeBase_OnValueChanged" VerticalAlignment="Center"/>
</Grid>

Код позади:

    private PixelShaderEffect _textureShader;
    private GaussianBlurEffect _blur;
    private BlendEffect _blend;

    private void AnimatedControl_OnCreateResources(CanvasAnimatedControl sender, CanvasCreateResourcesEventArgs args)
    {
        args.TrackAsyncAction(CreateResourcesAsync(sender).AsAsyncAction());
    }

    private async Task CreateResourcesAsync(CanvasAnimatedControl sender)
    {
        var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/Shaders/TextureTest.bin"));
        var buffer = await FileIO.ReadBufferAsync(file);

        var sourceImage = await CanvasBitmap.LoadAsync(sender, new Uri("ms-appx:///Assets/image.jpg"));

        _textureShader = new PixelShaderEffect(buffer.ToArray())
        {
            Source1 = sourceImage
        };

        _blur = new GaussianBlurEffect
        {
            BlurAmount = 4,
            Source = _textureShader
        };

        _blend = new BlendEffect
        {
            Foreground = _blur,
            Background = sourceImage,
            Mode = BlendEffectMode.Color
        };
    }

    private void AnimatedControl_OnDraw(ICanvasAnimatedControl sender, CanvasAnimatedDrawEventArgs args)
    {
        args.DrawingSession.DrawImage(_blend);
    }

    private void RangeBase_OnValueChanged(object sender, RangeBaseValueChangedEventArgs e)
    {
        _textureShader.Properties["threshold"] = (float)e.NewValue / 100;
    }

    private void ColorSpectrum_OnColorChanged(ColorSpectrum sender, ColorChangedEventArgs args)
    {
        _textureShader.Properties["sourceColor"] = new Vector3((float)args.NewColor.R / 255, (float)args.NewColor.G / 255, (float)args.NewColor.B / 255);
    }

    private void ColorSpectrum_OnColorChanged1(ColorSpectrum sender, ColorChangedEventArgs args)
    {
        _textureShader.Properties["replaceColor"] = new Vector3((float)args.NewColor.R / 255, (float)args.NewColor.G / 255, (float)args.NewColor.B / 255);
    }

И самое интересное - это пиксельный шейдер:

#define D2D_INPUT_COUNT 1
#define D2D_INPUT0_SIMPLE

#include "d2d1effecthelpers.hlsli"

float3 sourceColor;
float3 replaceColor;
float threshold;

D2D_PS_ENTRY(main)
{
    float3 color = D2DGetInput(0).rgb;

    if (abs(color.r - sourceColor.r) < threshold && abs(color.g - sourceColor.g) < threshold && abs(color.b - sourceColor.b) < threshold) 
    {
        float3 newColor = color - sourceColor + replaceColor;
        return float4(newColor.r, newColor.g, newColor.b, 1);
    }
    else 
    {
        return float4(0, 0, 0, 0);
    }
}

Чтобы скомпилировать его, вам следует совершить экскурсию здесь: https://github.com/Microsoft/Win2D-Samples/tree/master/ExampleGallery/Shared/Shaders

Там есть cmd-файл, который компилирует ваши шейдеры hlsl. Если вам нужна помощь - прокомментируйте. Повеселись!

person Jet Chopper    schedule 31.01.2018
comment
Вот это да!! Это удивительно!!! Спасибо за подробное объяснение! Я бы никогда этого не понял. - person Maximus; 31.01.2018
comment
Из любопытства, почему задействован эффект размытия, если на выходе нет размытия. - person Maximus; 31.01.2018
comment
Без размытия результат был бы слишком пиксельным. Вы можете установить BlurAmount = 0, чтобы увидеть разницу. - person Jet Chopper; 31.01.2018
comment
Чоппер, быстрый вопрос, так как я никогда не работал с Win2D. Где связь между кодом и шейдером HSLS? Я не вижу ссылок на это в коде программной части. - person Maximus; 01.02.2018
comment
Когда вы компилируете шейдер hlsl, вы получаете двоичный файл, в моем случае это TextureTest.bin (мой шейдер называется TextureTest.hlsl). Не забудьте включить этот файл в свой проект и выбрать действие сборки как Content в его свойствах. - person Jet Chopper; 01.02.2018
comment
Привет снова, Джет, шейдер работает очень хорошо, и мне удалось правильно растянуть изображение. Если я хочу сделать еще один шаг, например, разрешить замену 2 или 3 цветов одновременно, я предполагаю, что мне придется установить Source2 и Source3 для PixelShader и изменить файл hlsl, чтобы иметь больше входов? Кроме того, глядя на код hlsl, я бы также добавил sourceColor2, replacecolor2 и т. Д. - person Maximus; 02.02.2018
comment
Да, Win2d PixelShaderEffect поддерживает до 8 входов текстур и множество свойств. Вы можете изменять шейдер по своему усмотрению, просто следуя тому же алгоритму - person Jet Chopper; 02.02.2018
comment
По шаблону застрял на возвращаемом значении. Я сделал проблему, но никто не понял ее. Я решил, что вы можете получить больше очков, если знаете ответ :) stackoverflow.com/questions/48598891/ - person Maximus; 07.02.2018