如何使用任何像素着色语言创建 Photoshop Stamp 滤镜模拟?

发布于 2024-08-23 07:20:26 字数 61 浏览 5 评论 0原文

如何使用任何像素着色语言创建 Photoshop Stamp 滤镜模拟? (我至少需要过滤算法......)

How to create Photoshop Stamp filter analog in any pixel shading language? (I need at least filter algorithm...)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

愚人国度 2024-08-30 07:20:26

我查看了 Photoshop 中的图章滤镜,它看起来像是一个阈值和一个强模糊加在一起。

我使用了 Devnet 上的 Pixel Bender 基础知识文章 找到的 Horizo​​ntalGaussianBlur 内核
只是增加了一个便宜的门槛。这是我的内核的样子:

<languageVersion : 1.0;>

kernel stamp
<   namespace : "toMaterial";
    vendor : "George Profenza";
    version : 1;
    description : "Attempt to simulate Photoshop Stamp Filter. Original blur code: http://www.adobe.com/devnet/flash/articles/pixel_bender_basics_05.html";
>
{
    input image4 src;
    output pixel4 dst;

    parameter float threshold<
        minValue: 0.0;
        defaultValue:0.5;
        maxValue:1.0;
    >;
    parameter int radius
    <
        minValue : 1;
        maxValue : 6;
        defaultValue : 6;
    >;

    void
    evaluatePixel()
    {
        pixel4 center, band1, band2, band3, band4, band5, band6;
        float2 pos = outCoord();

        //Sample image in bands
        if(radius > 5) {
            pixel4 left  = dst;
            pixel4 right = dst;
            left.x -= 6.0;
            right.x += 6.0;
            band6 = left+right;
        }
        if(radius > 4) {
            pixel4 left  = dst;
            pixel4 right = dst;
            left.x -= 5.0;
            right.x += 5.0;
            band5 = left+right;
        }
        if(radius > 3) {
            pixel4 left  = dst;
            pixel4 right = dst;
            left.x -= 4.0;
            right.x += 4.0;
            band4 = left+right;
        }
        if(radius > 2) {
            pixel4 left  = dst;
            pixel4 right = dst;
            left.x -= 3.0;
            right.x += 3.0;
            band3 = left+right;
        }
        if(radius > 1) {
            pixel4 left  = dst;
            pixel4 right = dst;
            left.x -= 2.0;
            right.x += 2.0;
            band2 = left+right;
        }
        pixel4 left  = dst;
        pixel4 right = dst;
        left.x -= 1.0;
        right.x += 1.0;
        band1 = left+right;

        dst = sampleNearest(src,pos);
        //quick'n'dirty grayscale
        dst.rgb = float3(dst.r + dst.g + dst.b) * 0.333333333;
        //threshold
        if(dst.r < threshold) dst.r = 0.0; else dst.r = 1.0;
        if(dst.g < threshold) dst.g = 0.0; else dst.g = 1.0;
        if(dst.b < threshold) dst.b = 0.0; else dst.b = 1.0;

        center = dst;

        //Apply weights and compute resulting pixel
       if( radius == 6 )
       {
            dst = (band6 + (band5 * 12.0) + (band4 * 66.0) + (band3 * 220.0) + (band2 * 495.0) + (band1 * 792.0) + (center * 924.0)) * 0.000244140625;//4096.0;
       }
       if( radius == 5 )
       {
            dst = (band5 + (band4 * 10.0) + (band3 * 45.0) + (band2 * 120.0) + (band1 * 210.0) + (center * 252.0)) * 0.0009765625;//1024.0;
       }       
       if( radius == 4 )
       {
            dst = (band4 + (band3 * 8.0) + (band2 * 28.0) + (band1 * 56.0) + (center * 70.0)) * 0.00390625;//256.0;
       }
       if( radius == 3 )
       {
            dst = (band3 + (band2 * 6.0) + (band1 * 15.0) + (center * 20.0)) * 0.015625;//64.0;
       }
       if( radius == 2 )
       {
            dst = (band2 + (band1 * 4.0) + (center * 6.0)) * 0.0625;//16.0
       }
       if( radius == 1 )
       {
            dst = (band1 + (center * 2.0)) * 0.25;//4.0
       }

    }
}

这远非完美,这是我现在可以快速破解的。这应该
不过给你一些想法。

更新:

这是使用适当灰度的更新版本,高斯模糊代码主要来自Pixel Bender 指南

<languageVersion : 1.0;>

kernel Stamp
<   namespace : "gp";
    vendor : "George Profenza";
    version : 1;
    description : "Attempt to do a filter similar to Photoshop's Stamp Filter, blur code mostly from the guide: http://www.adobe.com/go/pixelbender_devguide";
>
{
    input image4 source;
    output pixel4 result;

    parameter int blur<
        minValue:1;
        defaultValue:3;
        maxValue:8;
    >;
    parameter float threshold<
        minValue:0.0;
        maxValue:1.0;
        defaultValue:0.5;
    >;

    void
    evaluatePixel()
    {
        //blur
        const float sigma = 2.0;
        float c = 1.0 / ( sqrt(2.0 * 3.1415926535 ) * sigma );
        float ec = 2.0 * sigma * sigma;
        float weight0 = exp( -( 0.0 * 0.0 ) / ec ) * c;
        float weight1 = exp( -( 1.0 * 1.0 ) / ec ) * c;
        if(blur > 1) float weight2 = exp( -( 2.0 * 2.0 ) / ec ) * c;
        if(blur > 2) float weight3 = exp( -( 3.0 * 3.0 ) / ec ) * c;
        if(blur > 3) float weight4 = exp( -( 4.0 * 4.0 ) / ec ) * c;
        if(blur > 4) float weight5 = exp( -( 5.0 * 5.0 ) / ec ) * c;
        if(blur > 5) float weight6 = exp( -( 6.0 * 6.0 ) / ec ) * c;
        if(blur > 6) float weight7 = exp( -( 7.0 * 7.0 ) / ec ) * c;
        if(blur > 7) float weight8 = exp( -( 8.0 * 7.0 ) / ec ) * c;

        float4 acc = float4( 0.0 );

        acc += sampleNearest( source, outCoord() ) * weight0;
        acc += sampleNearest( source, outCoord() + float2( 1.0, 0.0 ) ) * weight1;
        acc += sampleNearest( source, outCoord() + float2( -1.0, 0.0 ) ) * weight1;
        if(blur > 1) {
            acc += sampleNearest( source, outCoord() + float2( 2.0, 0.0 ) ) * weight2;
            acc += sampleNearest( source, outCoord() + float2( -2.0, 0.0 ) ) * weight2;
        }
        if(blur > 2) {
            acc += sampleNearest( source, outCoord() + float2( 3.0, 0.0 ) ) * weight3;
            acc += sampleNearest( source, outCoord() + float2( -3.0, 0.0 ) ) * weight3;
        }
        if(blur > 3) {
            acc += sampleNearest( source, outCoord() + float2( 4.0, 0.0 ) ) * weight4;
            acc += sampleNearest( source, outCoord() + float2( -4.0, 0.0 ) ) * weight4;
        }
        if(blur > 4) {
            acc += sampleNearest( source, outCoord() + float2( 5.0, 0.0 ) ) * weight5;
            acc += sampleNearest( source, outCoord() + float2( -5.0, 0.0 ) ) * weight5;
        }
        if(blur > 5) {
            acc += sampleNearest( source, outCoord() + float2( 6.0, 0.0 ) ) * weight6;
            acc += sampleNearest( source, outCoord() + float2( -6.0, 0.0 ) ) * weight6;
        }
        if(blur > 6) {
            acc += sampleNearest( source, outCoord() + float2( 7.0, 0.0 ) ) * weight7;
            acc += sampleNearest( source, outCoord() + float2( -7.0, 0.0 ) ) * weight7;
        }
        if(blur > 7) {
            acc += sampleNearest( source, outCoord() + float2( 8.0, 0.0 ) ) * weight8;
            acc += sampleNearest( source, outCoord() + float2( -8.0, 0.0 ) ) * weight8;
        }
        //grayscale
        float luma = 0.299 * acc.r + 0.587 * acc.g + 0.114 * acc.b;
        acc = float4(luma,luma,luma,1.0);
        //threshold
        if(acc.r < threshold) acc.r = 0.0; else acc.r = 1.0;
        if(acc.g < threshold) acc.g = 0.0; else acc.g = 1.0;
        if(acc.b < threshold) acc.b = 0.0; else acc.b = 1.0;

        result = acc;
    }
}

注意:我在模糊后应用了阈值,因此结果并不完全是图章过滤器,但很接近。

哈特哈,
乔治

I've look at the Stamp Filter in Photoshop and it looks like a Threshold and a strong Blur added together.

I've used the HorizontalGaussianBlur kernel found Pixel Bender Basics Article on Devnet
and just added a cheap threshold. Here is how my kernel looks like:

<languageVersion : 1.0;>

kernel stamp
<   namespace : "toMaterial";
    vendor : "George Profenza";
    version : 1;
    description : "Attempt to simulate Photoshop Stamp Filter. Original blur code: http://www.adobe.com/devnet/flash/articles/pixel_bender_basics_05.html";
>
{
    input image4 src;
    output pixel4 dst;

    parameter float threshold<
        minValue: 0.0;
        defaultValue:0.5;
        maxValue:1.0;
    >;
    parameter int radius
    <
        minValue : 1;
        maxValue : 6;
        defaultValue : 6;
    >;

    void
    evaluatePixel()
    {
        pixel4 center, band1, band2, band3, band4, band5, band6;
        float2 pos = outCoord();

        //Sample image in bands
        if(radius > 5) {
            pixel4 left  = dst;
            pixel4 right = dst;
            left.x -= 6.0;
            right.x += 6.0;
            band6 = left+right;
        }
        if(radius > 4) {
            pixel4 left  = dst;
            pixel4 right = dst;
            left.x -= 5.0;
            right.x += 5.0;
            band5 = left+right;
        }
        if(radius > 3) {
            pixel4 left  = dst;
            pixel4 right = dst;
            left.x -= 4.0;
            right.x += 4.0;
            band4 = left+right;
        }
        if(radius > 2) {
            pixel4 left  = dst;
            pixel4 right = dst;
            left.x -= 3.0;
            right.x += 3.0;
            band3 = left+right;
        }
        if(radius > 1) {
            pixel4 left  = dst;
            pixel4 right = dst;
            left.x -= 2.0;
            right.x += 2.0;
            band2 = left+right;
        }
        pixel4 left  = dst;
        pixel4 right = dst;
        left.x -= 1.0;
        right.x += 1.0;
        band1 = left+right;

        dst = sampleNearest(src,pos);
        //quick'n'dirty grayscale
        dst.rgb = float3(dst.r + dst.g + dst.b) * 0.333333333;
        //threshold
        if(dst.r < threshold) dst.r = 0.0; else dst.r = 1.0;
        if(dst.g < threshold) dst.g = 0.0; else dst.g = 1.0;
        if(dst.b < threshold) dst.b = 0.0; else dst.b = 1.0;

        center = dst;

        //Apply weights and compute resulting pixel
       if( radius == 6 )
       {
            dst = (band6 + (band5 * 12.0) + (band4 * 66.0) + (band3 * 220.0) + (band2 * 495.0) + (band1 * 792.0) + (center * 924.0)) * 0.000244140625;//4096.0;
       }
       if( radius == 5 )
       {
            dst = (band5 + (band4 * 10.0) + (band3 * 45.0) + (band2 * 120.0) + (band1 * 210.0) + (center * 252.0)) * 0.0009765625;//1024.0;
       }       
       if( radius == 4 )
       {
            dst = (band4 + (band3 * 8.0) + (band2 * 28.0) + (band1 * 56.0) + (center * 70.0)) * 0.00390625;//256.0;
       }
       if( radius == 3 )
       {
            dst = (band3 + (band2 * 6.0) + (band1 * 15.0) + (center * 20.0)) * 0.015625;//64.0;
       }
       if( radius == 2 )
       {
            dst = (band2 + (band1 * 4.0) + (center * 6.0)) * 0.0625;//16.0
       }
       if( radius == 1 )
       {
            dst = (band1 + (center * 2.0)) * 0.25;//4.0
       }

    }
}

This is far from perfect, it is what I could hack quickly at this hour. This should
give you some ideas though.

UPDATE:

Here is an updated version using proper grayscale and the Gaussian Blur code is mostly from the Pixel Bender Guide.

<languageVersion : 1.0;>

kernel Stamp
<   namespace : "gp";
    vendor : "George Profenza";
    version : 1;
    description : "Attempt to do a filter similar to Photoshop's Stamp Filter, blur code mostly from the guide: http://www.adobe.com/go/pixelbender_devguide";
>
{
    input image4 source;
    output pixel4 result;

    parameter int blur<
        minValue:1;
        defaultValue:3;
        maxValue:8;
    >;
    parameter float threshold<
        minValue:0.0;
        maxValue:1.0;
        defaultValue:0.5;
    >;

    void
    evaluatePixel()
    {
        //blur
        const float sigma = 2.0;
        float c = 1.0 / ( sqrt(2.0 * 3.1415926535 ) * sigma );
        float ec = 2.0 * sigma * sigma;
        float weight0 = exp( -( 0.0 * 0.0 ) / ec ) * c;
        float weight1 = exp( -( 1.0 * 1.0 ) / ec ) * c;
        if(blur > 1) float weight2 = exp( -( 2.0 * 2.0 ) / ec ) * c;
        if(blur > 2) float weight3 = exp( -( 3.0 * 3.0 ) / ec ) * c;
        if(blur > 3) float weight4 = exp( -( 4.0 * 4.0 ) / ec ) * c;
        if(blur > 4) float weight5 = exp( -( 5.0 * 5.0 ) / ec ) * c;
        if(blur > 5) float weight6 = exp( -( 6.0 * 6.0 ) / ec ) * c;
        if(blur > 6) float weight7 = exp( -( 7.0 * 7.0 ) / ec ) * c;
        if(blur > 7) float weight8 = exp( -( 8.0 * 7.0 ) / ec ) * c;

        float4 acc = float4( 0.0 );

        acc += sampleNearest( source, outCoord() ) * weight0;
        acc += sampleNearest( source, outCoord() + float2( 1.0, 0.0 ) ) * weight1;
        acc += sampleNearest( source, outCoord() + float2( -1.0, 0.0 ) ) * weight1;
        if(blur > 1) {
            acc += sampleNearest( source, outCoord() + float2( 2.0, 0.0 ) ) * weight2;
            acc += sampleNearest( source, outCoord() + float2( -2.0, 0.0 ) ) * weight2;
        }
        if(blur > 2) {
            acc += sampleNearest( source, outCoord() + float2( 3.0, 0.0 ) ) * weight3;
            acc += sampleNearest( source, outCoord() + float2( -3.0, 0.0 ) ) * weight3;
        }
        if(blur > 3) {
            acc += sampleNearest( source, outCoord() + float2( 4.0, 0.0 ) ) * weight4;
            acc += sampleNearest( source, outCoord() + float2( -4.0, 0.0 ) ) * weight4;
        }
        if(blur > 4) {
            acc += sampleNearest( source, outCoord() + float2( 5.0, 0.0 ) ) * weight5;
            acc += sampleNearest( source, outCoord() + float2( -5.0, 0.0 ) ) * weight5;
        }
        if(blur > 5) {
            acc += sampleNearest( source, outCoord() + float2( 6.0, 0.0 ) ) * weight6;
            acc += sampleNearest( source, outCoord() + float2( -6.0, 0.0 ) ) * weight6;
        }
        if(blur > 6) {
            acc += sampleNearest( source, outCoord() + float2( 7.0, 0.0 ) ) * weight7;
            acc += sampleNearest( source, outCoord() + float2( -7.0, 0.0 ) ) * weight7;
        }
        if(blur > 7) {
            acc += sampleNearest( source, outCoord() + float2( 8.0, 0.0 ) ) * weight8;
            acc += sampleNearest( source, outCoord() + float2( -8.0, 0.0 ) ) * weight8;
        }
        //grayscale
        float luma = 0.299 * acc.r + 0.587 * acc.g + 0.114 * acc.b;
        acc = float4(luma,luma,luma,1.0);
        //threshold
        if(acc.r < threshold) acc.r = 0.0; else acc.r = 1.0;
        if(acc.g < threshold) acc.g = 0.0; else acc.g = 1.0;
        if(acc.b < threshold) acc.b = 0.0; else acc.b = 1.0;

        result = acc;
    }
}

Note: I applied the threshold after the blur, so the result is not exactly a Stamp Filter but close.

HTH,
George

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文