簡體   English   中英

unity texture2d EncodeToJPG透明黑色

[英]unity texture2d EncodeToJPG transparent black

我有一個紋理用戶繪制(在移動設備上),我想將其編碼為jpg,以便用戶可以共享,但我發現轉換部分將在編碼的jpg中為黑色:

在此輸入圖像描述

雖然我希望jpg是這樣的: 在此輸入圖像描述

但我沒有找到任何重寫的texture2d.EncodeToJPG()方法來做到這一點。

有任何想法嗎?

注意

鳥的翅膀是專門為Color.white繪制的,所以在編碼的jpg中它可能是白色的。

現在接近

我終於通過以下方式完成了這項工作:

 Color32[] pixels = text.GetPixels32();
 Color blackTransparent = Color.black;
 blackTransparent.a = 0;
 for(int i = 0;i < pixels.Length; i++)
 {
    if(pixels[i] == blackTransparent)
    {
            pixels[i] = Color.white;
     }
  }
  text.SetPixels32(pixels);
  text.Apply();

但這將遍歷紋理的所有像素,如果有人有更好的方法,請告訴我們。

這種方法有問題:

我們發現使用上面的代碼在jpg上會有一些邊緣(當遇到黑線時),可能需要一些圖形處理知識才能解決這個問題? 在此輸入圖像描述

這是我們如何將圖像加載到texture2d(根據評論的要求)

  Texture2D text = new Texture2D(1, 1, TextureFormat.PVRTC_RGBA4, false);
  byte[] imagebytes = null;
  string path = "image/path/sample.png";
  if (System.IO.File.Exists(path))
  {
      Debug.Log(" really load file from " + path);
      imagebytes = System.IO.File.ReadAllBytes(path);
  }
  text.LoadImage(imagebytes, false);

您可以嘗試編碼為PNG。 JPG無法呈現透明度。

就像 :

texture2d.EncodeToPNG();

在此查找完整的文檔

如果應用程序在Microsoft OS上運行,您也可以使用轉換為jpg

對於您的第一個問題編輯,詢問如何改進循環遍歷所有像素的代碼,您可以。 只需用for (int i = 0; i < pixels.Length; i += 4)替換for(int i = 0;i < pixels.Length; i++) for (int i = 0; i < pixels.Length; i += 4)然后訪問i+0i+3內的每個索引環。 循環速度快約4倍

Color32[] pixels = text.GetPixels32();
Color blackTransparent = Color.black;
Color overwriteColor = Color.white;

blackTransparent.a = 0;
for (int i = 0; i < pixels.Length; i += 4)
{
    if (pixels[i] == blackTransparent)
        pixels[i] = overwriteColor;


    if (pixels[i + 1] == blackTransparent)
        pixels[i + 1] = overwriteColor;


    if (pixels[i + 2] == blackTransparent)
        pixels[i + 2] = overwriteColor;


    if (pixels[i + 3] == blackTransparent)
        pixels[i + 3] = overwriteColor;
}
text.SetPixels32(pixels);
text.Apply(true);

雖然,這兩個代碼都會遇到與第二次編輯中提到的相同的鋸齒狀線問題。

在此輸入圖像描述



要修復它,請不要將像素直接與==符號進行比較。 使用一個讓您使用閾值來比較顏色而不僅僅是數字的函數。 是我用來比較Unity中RGB顏色的功能,我建議你開始使用它。

然后,您必須手動檢查alpha是低於還是等於某個值。 90的值似乎對此有用。

這是腳本的樣子:

Color32[] pixels = text.GetPixels32();
Color blackTransparent = Color.black;

for (int i = 0; i < pixels.Length; i += 4)
{
    checkPixel(ref pixels[i], blackTransparent, Color.white, 600);
    checkPixel(ref pixels[i + 1], blackTransparent, Color.white, 600);
    checkPixel(ref pixels[i + 2], blackTransparent, Color.white, 600);
    checkPixel(ref pixels[i + 3], blackTransparent, Color.white, 600);
}
text.SetPixels32(pixels);
text.Apply();

函數checkPixelColourDistance函數:

void checkPixel(ref Color32 pixel1, Color32 pixel2, Color32 newColor, int threshold)
{
    if (ColourDistance(pixel1, pixel2) <= threshold)
    {
        if (pixel1.a <= 90)
        {
            pixel1 = Color.white;
        }
    }
}

private static double ColourDistance(Color32 c1, Color32 c2)
{
    double rmean = (c1.r + c2.r) / 2;

    int r = c1.r - c2.r;
    int g = c1.g - c2.g;
    int b = c1.b - c2.b;
    double weightR = 2 + rmean / 256;
    double weightG = 4.0;
    double weightB = 2 + (255 - rmean) / 256;
    return Math.Sqrt(weightR * r * r + weightG * g * g + weightB * b * b);
}

這就是結果:

在此輸入圖像描述

它仍然可以改進。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM