2017-12-12 14 views
1

ImageSharp라는 이미지 프로세서를 사용해 본 적이 있는데, asp.net 코어에서 System.Drawing을 사용할 수 없으며 System.Drawing이 불행을 겪을 수 있기 때문입니다.asp.net 코어에서 텍스처로 색상 바꾸기 C#

공백을 이미지의 특정 텍스처로 채우고 싶습니다. 아래의 코드는 작동하지만 고통스럽게 느립니다.

이미지를 처음 처리하기 때문에이 작업을 수행하는 가장 효율적인 방법이 무엇인지 알 수 없습니다.

공백을 텍스처로 채우는 가장 효과적이고 효율적인 방법은 무엇입니까? 이에 Doughnut

:이 결과

Sparkly Doughnut

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

     byte[] img; 

     using (Image<Rgba32> image = Image.Load(file)) 
     { 
      HashSet<Texture> textureArr = getRGBaBytes(texture, image); 
      for (int h = 0; h <= image.Height; h++) 
      { 
       for(int w = 0; w <= image.Width; w++) 
       { 
        if(image[w,h] == Rgba32.FromHex("#ffffff")) 
        { 
         image[w, h] = textureArr.Where(t => t.x == w && t.y == h).First().color; 
        } 
       } 
      } 
      image.Save("NewImage.png"); 
     } 
    } 

    public HashSet<Texture> getRGBaBytes(string textureURL, Image<Rgba32> sample) 
    { 

     using (Image<Rgba32> tex = Image.Load(textureURL)) 
     { 
      int bitsizelimit = int.MaxValue;  
      if (sample.Width > tex.Width || sample.Height > tex.Height) 
      { 
       throw new Exception("Texture image dimensions must be greater or equal to sample image"); 
      } 

      HashSet<Texture> myTexture = new HashSet<Texture>(); 
      for (int h = 0; h <= sample.Height; h++) 
      { 
       for (int w = 0; w <= sample.Width; w++) 
       { 
        System.Diagnostics.Debug.WriteLine($"{tex[w,h].ToHex()} at x:{w} y:{h}"); 
        myTexture.Add(new Texture { color = tex[w, h], x = w, y = h }); 
       } 
      } 
      return myTexture; 
     } 
    } 

    public class Texture 
    { 
     public Rgba32 color { get; set; } 
     public int x { get; set; } 
     public int y { get; set; } 
    } 
+0

, 당신은 기본적으로 이미로 사용하고 있습니다. 그것은 당신의 성과에 도움이 될 것입니다. 나는 테스트 프로그램을 만들고 이것을 테스트하려고했지만, LinqPad에서 실행할 수는 없다. 미안하다. – pstrjds

+0

또 다른 한 가지는'Rgba32.FromHex ("# ffffff")'행을 이중 중첩 루프 밖으로 승격시키는 것입니다.최적화 프로그램은 상수이고 한 번만 생성을 수행하지만 그렇지 않은 경우에는 이미지의 모든 픽셀에 대해 동일한 색상을 생성하므로 흰색인지 여부를 확인할 수 있습니다. – pstrjds

답변

2
내가 당신이 원하는 것을 달성하는 방법을 간단하게 보여주기 위해 작은 콘솔 응용 프로그램을 노크하지만 처음에는 이유를 설명 할 것이다

접근 방식이 느립니다.

  1. getRGBaBytes은 필요하지 않습니다. 기본적으로 두 이미지를 반복하고 질감이있는 이미지의 각 픽셀에 대한 클래스를 만듭니다. 그것은 많은 메모리 할당입니다!
  2. 각 픽셀 작업 내에 Linq 쿼리가 있습니다. WhereFirst. 이미지의 각 픽셀에 대한 대량의 메모리 할당. 이럴 필요가 없습니다.
  3. 속도가 느린 16 진수 값에서 구문 분석 할 때마다 새로운 Rgba32 구조체와 비교를 수행하고 있습니다. 대신 static Rgba32.White 구조체를 사용하여이 작업을 수행 할 수 있습니다.
static void Main(string[] args) 
{ 
    System.IO.Directory.CreateDirectory("output"); 
    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 == Rgba32.White) 
       { 
        img[x, y] = texture[x, y]; 
       } 
      } 
     } 

     img.Save("output/LBUVf.png"); 
    } 
} 

은 여기 내 샘플의 출력입니다. (나는 실제로 같은 별 모양 이미지를 사용했을 것입니다 :)) 각 Rgba32 구성 요소가 255 범위 내에 있는지 테스트하여 남은 흰색 영역을 개선하고 줄일 수 있지만 그만 두겠습니다.

Sample output

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"); 
    } 
} 

매우 잘 볼 수 있습니다. 대신 그냥 두 차원 배열을 사용하지 왜`Texture` 모음을 만들 때 'HashSet`를 사용

Updated sample with better result

+1

시도하고 테스트했습니다. 더 나은 마일 : D 그리고 지그재그 모양의 가장자리를 제거하는 코드를 추가 할 시간을 주셔서 감사합니다. – CyanideHavik

+0

걱정하지 마세요, 도와 드리겠습니다. :) –