首页 文章

unity texture2d EncodeToJPG透明黑色

提问于
浏览
1

我有一个纹理用户绘制(在移动设备上),我想将其编码为jpg,以便用户可以共享,但我发现转换部分将在编码的jpg中为黑色:

enter image description here

虽然我希望jpg是这样的:
enter image description here

但我没有找到任何重写方法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上会有一些边缘(当遇到黑线时),可能需要一些图形处理知识才能解决这个问题?
enter image description here

以下是我们如何将图像加载到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);

2 回答

  • 1

    对于您的第一个问题编辑,询问如何改进循环遍历所有像素的代码,您可以 . 只需将 for(int i = 0;i < pixels.Length; i++) 替换为 for (int i = 0; i < pixels.Length; i += 4) ,然后在循环内访问 i+0 中的每个索引到 i+3 . 循环速度约为 4x .

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

    虽然,这两个代码都会遇到与第二次编辑中提到的相同的锯齿状线问题 .

    enter image description here



    要修复它,请不要将像素直接与 == 符号进行比较 . 使用一个让您使用阈值来比较颜色而不仅仅是数字的函数 . This是我用来比较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);
    }
    

    这就是结果:

    enter image description here

    它仍然可以改进 .

  • 2

    您可以尝试编码为PNG . JPG无法呈现透明度 .

    就像 :

    texture2d.EncodeToPNG();
    

    Find complete doc here

    如果应用程序在Microsoft OS上运行,您也可以使用this转换为jpg

相关问题