C# 在asp.net core c中用纹理替换颜色#
自从System.net core上没有绘图功能以来,我一直在一个名为ImageSharp的图像处理器上进行实验,System.Drawing可能会有它的问题 我想用图像中的特定纹理填充空白。下面的代码正在运行,但速度非常慢 因为这是我第一次处理图像,我真的不知道最有效的方法是什么 用纹理填充空白的最佳有效方法是什么 因此: 为此:C# 在asp.net core c中用纹理替换颜色#,c#,image-processing,graphics,asp.net-core,imagesharp,C#,Image Processing,Graphics,Asp.net Core,Imagesharp,自从System.net core上没有绘图功能以来,我一直在一个名为ImageSharp的图像处理器上进行实验,System.Drawing可能会有它的问题 我想用图像中的特定纹理填充空白。下面的代码正在运行,但速度非常慢 因为这是我第一次处理图像,我真的不知道最有效的方法是什么 用纹理填充空白的最佳有效方法是什么 因此: 为此: public void CreateImage() { var webRoot=_env.WebRootPath; var ImgSrc=“\\Images\\
public void CreateImage()
{
var webRoot=_env.WebRootPath;
var ImgSrc=“\\Images\\SampleImage.png”;
var TextureURL=“\\Images\\Starsinthesky.jpg”;
var file=webRoot+ImgSrc;
var texture=webRoot+TextureURL;
var myPath=Path.Combine(webRoot,ImgSrc);
字节[]img;
使用(Image=Image.Load(文件))
{
HashSet textureArr=getRGBaBytes(纹理,图像);
用于(int h=0;h tex.宽度| | sample.高度>tex.高度)
{
抛出新异常(“纹理图像尺寸必须大于或等于样本图像”);
}
HashSet myTexture=新HashSet();
对于(inth=0;h我开发了一个小的控制台应用程序来演示实现您想要的东西是多么简单,但首先我将解释为什么您的方法很慢
getRGBaBytes
不是必需的。您实际上是在两个图像之间循环,并为纹理图像中的每个像素创建一个类。这需要大量内存分配
在每个像素操作中都有一个Linq查询。Where
和First
。同样,为图像中的每个像素分配大量内存。不需要这样做
每次从十六进制值解析时,您都要与一个新的Rgba32
struct进行比较,这会很慢。这可以使用staticRgba32.White
struct来完成
static void Main(字符串[]args)
{
System.IO.Directory.CreateDirectory(“输出”);
使用(var img=Image.Load(“LPUVf.png”))
使用(var texture=Image.Load(“stars.jpg”))
{
if(img.Width>texture.Width | | img.Height>texture.Height)
{
抛出新的InvalidOperationException(“图像尺寸必须小于或等于纹理尺寸!”);
}
对于(int y=0;y
这是我的示例的输出。(我想我可能实际使用了相同的星景图像:)。您可以通过测试每个Rgba32
组件是否在255
范围内来改进和减少任何剩余的白色区域,但我将把这留给您
p.S ImageSharp.Drawing包包含可以将纹理绘制到多边形的方法。理论上,如果您知道每个复合零件的尺寸,您可以从头开始创建新图像
更新:
我忍不住写了一些代码来减少剩余像素
static void Main(string[] args)
{
System.IO.Directory.CreateDirectory("output");
const int min = 128; // Grey midpoint
using (var img = Image.Load("LPUVf.png"))
using (var texture = Image.Load("stars.jpg"))
{
if (img.Width > texture.Width || img.Height > texture.Height)
{
throw new InvalidOperationException("Image dimensions must be less than or equal to texture dimensions!");
}
for (int y = 0; y < img.Height; y++)
{
for (int x = 0; x < img.Width; x++)
{
var pixel = img[x, y];
if (pixel.R >= min && pixel.G >= min && pixel.B >= min && pixel.A >= min)
{
img[x, y] = texture[x, y];
}
}
}
img.Save("output/LBUVf.png");
}
}
static void Main(字符串[]args)
{
System.IO.Directory.CreateDirectory(“输出”);
常量int min=128;//灰色中点
使用(var img=Image.Load(“LPUVf.png”))
使用(var texture=Image.Load(“stars.jpg”))
{
if(img.Width>texture.Width | | img.Height>texture.Height)
{
抛出新的InvalidOperationException(“图像尺寸必须小于或等于纹理尺寸!”);
}
对于(int y=0;y=min&&pixel.G>=min&&pixel.B>=min&&pixel.A>=min)
{
img[x,y]=纹理[x,y];
}
}
}
img.Save(“output/LBUVf.png”);
}
}
正如你所看到的那样,这要好多了
当您创建纹理集合时,为什么不使用哈希集
呢?您基本上已经在使用二维数组了。这应该会有助于您的性能。我本来打算制作一个测试程序并测试它,但我无法在LinqPad中运行它,抱歉。另一件事可能会发生帮助是提升这一行Rgba32.FromHex(“#ffffff”)
到双嵌套循环之外。优化器可能会注意到它是一个常量,只会执行一次创建,但如果没有,则您将为图像中的每个像素创建相同的颜色,以便检查它是否为白色。已尝试并测试过。Miles better:D非常感谢您花时间添加代码以删除t他锯齿状的边缘不用担心,很乐意帮忙:)
static void Main(string[] args)
{
System.IO.Directory.CreateDirectory("output");
const int min = 128; // Grey midpoint
using (var img = Image.Load("LPUVf.png"))
using (var texture = Image.Load("stars.jpg"))
{
if (img.Width > texture.Width || img.Height > texture.Height)
{
throw new InvalidOperationException("Image dimensions must be less than or equal to texture dimensions!");
}
for (int y = 0; y < img.Height; y++)
{
for (int x = 0; x < img.Width; x++)
{
var pixel = img[x, y];
if (pixel.R >= min && pixel.G >= min && pixel.B >= min && pixel.A >= min)
{
img[x, y] = texture[x, y];
}
}
}
img.Save("output/LBUVf.png");
}
}