【问题标题】:unity texture2d EncodeToJPG transparent blackunity texture2d EncodeToJPG 透明黑色
【发布时间】:2017-05-10 09:01:10
【问题描述】:

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

【问题讨论】:

  • 您可以改进该代码。您是在调用 texture2d.EncodeToJPG() 之后还是之前运行该代码?
  • @Programmer 我在texture2d.EncodeToJPG()之前运行该代码
  • 好的。我会给出一个答案来改进它。
  • 我注意到您修改了您的问题以添加有关代码问题的信息....原始图像的来源是什么?原始格式是什么?
  • @Programmer 原始图片是 png 并且你在云端找到它here

标签: c# unity3d jpeg transparency


【解决方案1】:

对于您的第一个问题编辑,询问如何改进循环通过所有像素的代码,您可以。只需将for(int i = 0;i &lt; pixels.Length; i++) 替换为for (int i = 0; i &lt; 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);

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



要解决此问题,请勿将像素直接与== 符号进行比较。使用一个函数,让您使用阈值来比较颜色而不仅仅是数字。 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);
}

结果如下:

还有待改进。

【讨论】:

  • 在尝试之前接受作为答案:D。非常感谢您的努力。
  • 大声笑没问题,但如果有请告诉我。
  • 但是你能提示一下为什么你给出的循环比我给出的原始循环快 4X 倍吗?好像一圈比较了4次。
  • 答案的第一行。它不是在做for(int i = 0;i &lt; pixels.Length; i++),而是在做for (int i = 0; i &lt; pixels.Length; i += 4)。提示 i += 4 而不是 i++
  • 这允许它跳过像素中的每 4 个索引。它通过执行i+0i+1i+2i+3 而不是for 循环来补偿那些丢失的4 个索引循环。请注意,i+0 不是必需的,因为这将一事无成。它也可以只是i。在图形内容中循环像素的一种棘手方法。这也可以通过使用指针或 C++ 来改进。
【解决方案2】:

你可以尝试编码成PNG。 JPG 无法呈现透明度。

就像:

texture2d.EncodeToPNG();

Find complete doc here

如果应用在 Microsoft 操作系统上运行,您还可以使用 this 转换为 jpg

【讨论】:

  • 您好,感谢回答第三方共享SDK只接受jpg文件
  • 在c#中你可以做你想做的事
  • 谢谢,谢谢,你应该把链接放在你的答案中,我会试试的
  • 如果您使用它,那么使用 Unity 将毫无意义,因为该站点上使用的 API 无法在移动设备上运行。我只会在 Windows 上工作。
猜你喜欢
  • 2011-12-20
  • 2016-06-09
  • 2012-06-25
  • 1970-01-01
  • 2016-06-14
  • 1970-01-01
  • 2017-06-04
  • 2020-04-14
  • 1970-01-01
相关资源
最近更新 更多