c# - unity texture2d EncodeToJPG 透明黑色

标签 c# unity3d jpeg transparency

我有一个纹理用户绘制(在移动设备上),我想将其编码为 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);

最佳答案

对于您的第一个问题编辑,询问如何改进循环遍历所有像素的代码,您可以。只需替换 for(int i = 0;i < pixels.Length; i++)for (int i = 0; i < pixels.Length; i += 4)然后从 i+0 访问每个索引至 i+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);

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

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

还有待改进。

关于c# - unity texture2d EncodeToJPG 透明黑色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43887913/

相关文章:

unity3d - 根据 Horizo​​ntalLayoutGroup 等,更正 Unity3D 中的 'FlowLayoutGroup'

matlab - OpenCV 与 Matlab : Different Values on pixels with imread

c# - 我可以在 ConcurrentBag 上使用普通的 foreach 吗?

c# - 如何调试从 TeamCity 部署的 nuget 包?

c# - 有没有办法使用反射在结构实例上设置属性?

linux - 我可以在Ubuntu 19.04上运行Unity Game引擎而不损失效率吗?

debugging - 在 Emacs 中使用 Mono 软调试器

c# - 在使用 Task.Run() 创建的任务上调用 await

ios - 无需重新压缩即可从用户图库保存/获取 JPEG

php - 如何将数据库中的图像调成每行10张图像?