unity3d - 如何为 png 复制 Texture2d.LoadImage 以获得 RGB32 格式(现在获得 ARGB32)
问题描述
我正在尝试提高用于将 png 转换为灰度的代码的性能。
我通过 Json 加载图像,转换为纹理,然后在运行时通过每个像素进行灰度化并使用GetPixels32/SetPixels32
. 对于我拥有的许多图像,内存使用量太高,所以我想使用更高效GetRawTextureData
的 .
然而LoadImage
,返回一个ARGB32 texture2d
似乎搞砸了,然后在GetRawTextureData
(RGB32)中使用。
这很令人困惑,因为在 Unity 2019.2 上带有 LoadImage 的 png 应该返回RGBA32,但对我来说,它返回的是ARGB32,这是 LoadImage 旧版 Unity 5.3 会返回的 - 不确定是否存在错误或文档错误。
Texture2D thisTexture = new Texture2D(1, 1, TextureFormat.RGBA32, false);
byte[] t = Convert.FromBase64String(imageString);//png image in string format
thisTexture.LoadImage(t);//Using Unity2019.2.2 result is ARGB32
当我将图像转换为灰度时,我得到一个淡黄色的图像,我认为这是GetRawTextureData
因为RGB32但LoadImage
返回ARGB32。
如何复制LoadImage
获得RGB32的过程?
//convert texture
graph = thisTexture;
grayImg = new Texture2D(graph.width, graph.height, graph.format, false);
Debug.Log("grayImg format " + grayImg.format + " graph format " + graph.format);
Graphics.CopyTexture(graph, grayImg);
var data = grayImg.GetRawTextureData<Color32>();
int index = 0;
Color32 pixel;
for (int x = 0; x < grayImg.width; x++)
{
for (int y = 0; y < grayImg.height; y++)
{
pixel = data[index];
int p = ((256 * 256 + pixel.r) * 256 + pixel.b) * 256 + pixel.g;
int b = p % 256;
p = Mathf.FloorToInt(p / 256);
int g = p % 256;
p = Mathf.FloorToInt(p / 256);
int r = p % 256;
byte l = (byte) ((pixel.r ) + pixel.g + pixel.b);
Color32 c = new Color32(pixel.r, pixel.g, pixel.b, 1);
data[index++] = c;
}
}
// upload to the GPU
grayImg.Apply(false);
使用 LoadRawTextureData 修改代码:
Texture2D thisTexture = new Texture2D(1, 1, TextureFormat.RGBA32, false);
byte[] t = Convert.FromBase64String(imageString);//png image in string format
thisTexture.LoadRawTextureData(t);//results in RGBA32 (Note: using either thisTexture.LoadImage(t); or thisTexture.LoadRawTextureData(t); when using LoadRawTextureData to set the pixels on the grayscale, the texture continues to be yellowish.
thisTexture.Apply();
解决方案
这不是 GetRawTextureData 应该使用的方式 - 它重新调整 NativeArray 并且当与普通数组错误时非常慢。有关这方面的示例,请查看此 RawTextureDataProcessingExamples 存储库。特别是这个GrayscaleRGBA32Job文件:
using Unity.Mathematics;
using Unity.Collections;
[Unity.Burst.BurstCompile]
public struct GrayscaleRGBA32Job : Unity.Jobs.IJobParallelFor
{
public NativeArray<RGBA32> data;
void Unity.Jobs.IJobParallelFor.Execute ( int i )
{
var color = data[i];
float product = math.mul( new float3{ x=color.R , y=color.G , z=color.B } , new float3{ x=0.3f , y=0.59f , z=0.11f } );
byte b = (byte)product;
data[i] = new RGBA32{ R=b , G=b , B=b , A=color.A };
}
}
如果需要,可以在此处交换通道字节。这就是你申请这份工作的方式:
var rawdata = tex.GetRawTextureData<RGBA32>();
new GrayscaleRGBA32Job { data = tex.GetRawTextureData<RGBA32>() }
.Schedule( rawdata.Length , tex.width ).Complete();
tex.Apply();
而已。基于此,您还可以编写一个将 RGBA32 rawData 作为输入并将其直接输出到灰度纹理的 R8 rawData 的作业(无需复制,并且内存占用更小)。
推荐阅读
- python - 从.txt文件python读取列表
- java - 使用Java基于迭代从字符串数组中查找日期
- python - SciKit-Learn GridSearchCV 的 n_jobs 参数不适用于 Keras
- php - 将带有图像的数据插入数据库
- ios - 如何以编程方式隐藏键盘剪贴板?
- java - 我没有在 REST api 中获得嵌套资源的不同 ID
- javascript - 执行删除操作后如何自动刷新页面
- image - 将未压缩的 TIF 文件转换为具有压缩 LZW 和 ZIP 的 TIF 文件
- python - 如何从 github 安装 deepplantphenomics python 包?
- java - E/RecyclerView:没有附加适配器;跳过布局 Android Studio RecyclerView