XNA C中的颜色替换#

Jac*_*ack 7 c# xna

我使用加载我的纹理

Texture2D.FromFile()
Run Code Online (Sandbox Code Playgroud)

然后用它们画出来

spriteBatch.Draw()
Run Code Online (Sandbox Code Playgroud)

但重点是:我想将图像的某些颜色更改为另一种颜色.所以我的问题:

  1. 如何将图像的单色更改为另一种颜色(例如蓝色到红色).

  2. 事实上,我真正想做的是将一组颜色改为另一组颜色.例如红色和类似色调,红色到蓝色,类似色调,蓝色.例如,您可以在Corel PHOTO-PAINT("替换颜色")中执行此操作.

请记住,我是XNA的初学者.最好的问候,杰克

编辑:

伙计们,非常感谢您的帮助.Callum的回答确实非常有用.但我想知道是否有内置函数来解决我的第二个问题,因为编写自己的函数可能非常耗时.我认为,这种功能可能非常有用.就像是:

color.SetNewColor(Color color_from, Color color_to, int range)
Run Code Online (Sandbox Code Playgroud)

正如我之前所说的那样,这种功能是用Corel PHOTO-PAINT构建的.为了更好地解释它,这里是我正在谈论的例子:

链接文字

所以,我只设置color_from,color_to和range.我认为它的作用是这样的:它检查图像的每种颜色,如果它在color_from的范围内,它会在color_to的色调中变为足够的颜色.

Cal*_*ers 11

我猜你的意思是改变个别像素?在这种情况下,使用类的GetData()SetData()方法Texture2D.


例如,您可以通过执行以下操作获取包含各个像素颜色的数组:

// Assume you have a Texture2D called texture

Color[] data = new Color[texture.Width * texture.Height];
texutre.GetData(data);

// You now have a packed array of Colors. 
// So, change the 3rd pixel from the right which is the 4th pixel from the top do:

data[4*texture.Width+3] = Color.Red;

// Once you have finished changing data, set it back to the texture:

texture.SetData(data);
Run Code Online (Sandbox Code Playgroud)

请注意,您可以使用其他重载GetData()来仅选择一个部分.


因此,要将指定颜色的每个像素替换为另一种颜色:

// Assume you have a Texture2D called texture, Colors called colorFrom, colorTo

Color[] data = new Color[texture.Width * texture.Height];
texutre.GetData(data);

for(int i = 0; i < data.Length; i++)
    if(data[i] == colorFrom)
        data[i] = colorTo;

texture.SetData(data);
Run Code Online (Sandbox Code Playgroud)

要查看色调是否相似,请尝试以下方法:

private bool IsSimilar(Color original, Color test, int redDelta, int blueDelta, int greenDelta)
{
    return Math.Abs(original.R - test.R) < redDelta && Math.Abs(original.G - test.G) < greenDelta && Math.Abs(original.B - test.B) < blueDelta;
}
Run Code Online (Sandbox Code Playgroud)

其中*delta是您要接受的每个颜色通道的更改容差.


要回答您的编辑,没有内置功能,但您可以使用上述两个部分的混合思路:

Color[] data = new Color[texture.Width * texture.Height];
texutre.GetData(data);

for(int i = 0; i < data.Length; i++)
    if(IsSimilar(data[i], colorFrom, range, range, range))
        data[i] = colorTo;

texture.SetData(data);
Run Code Online (Sandbox Code Playgroud)


Jas*_*aat 6

使用 GetData 和 SetData 在 GPU 和 CPU 之间移动数据是一项昂贵的操作。如果颜色数量有限,您可以在渲染到屏幕时使用像素着色器效果。您可以将效果传递给 SpriteBatch.Begin:

sampler2D input : register(s0);

/// <summary>The color used to tint the input.</summary>
/// <defaultValue>White</defaultValue>
float4 FromColor : register(C0);

/// <summary>The color used to tint the input.</summary>
/// <defaultValue>Red</defaultValue>
float4 ToColor : register(C1);

/// <summary>Explain the purpose of this variable.</summary>
/// <minValue>05/minValue>
/// <maxValue>10</maxValue>
/// <defaultValue>3.5</defaultValue>
float4 main(float2 uv : TEXCOORD) : COLOR 
{ 
    float4 Color; 
    Color= tex2D(input , uv.xy); 
    if (Color.r == FromColor.r && Color.g == FromColor.g && Color.b == FromColor.b)
        return ToColor;
    return Color; 
}

technique Technique1
{
    pass Pass1
    {
        PixelShader = compile ps_2_0 main();
    }
}
Run Code Online (Sandbox Code Playgroud)

在 LoadContent 方法中创建效果:

colorSwapEffect = Content.Load<Effect>(@"Effects\ColorSwap");
colorSwapEffect.Parameters["FromColor"].SetValue(Color.White);
colorSwapEffect.Parameters["ToColor"].SetValue(Color.Red);
Run Code Online (Sandbox Code Playgroud)

并将效果传递给您对 SpriteBatch.Begin() 的调用:

sprite.Begin(0, BlendState.Opaque, SamplerState.PointWrap, 
    DepthStencilState.Default, RasterizerState.CullNone, colorSwapEffect);
Run Code Online (Sandbox Code Playgroud)

对于您真正想做的事情,您可以更轻松地交换红色和蓝色通道。将像素着色器的 main() 函数更改为此,交换 b(蓝色)和 r(红色):

float4 main(float2 uv : TEXCOORD) : COLOR 
{ 
    float4 Color;
    Color= tex2D(input , uv.xy);
    return float4(Color.b, Color.g, Color.r, Color.a);
}
Run Code Online (Sandbox Code Playgroud)