unity-game-engine - 来自 byte[] 数组的位图

标签 unity-game-engine bitmap arrays

我想从字节[]创建位图。我的问题是我无法在 Unity 中使用 BitmapSource,如果我使用 MemoryStream Unity 会出现错误。

我尝试过这个:

  Bitmap bitmap = new Bitmap(512, 424);

  var data = bitmap.LockBits(new Rectangle(Point.Empty, bitmap.Size),
  ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);

  Marshal.Copy(arrayData, 0, data.Scan0, arrayData.Length);

  bitmap.UnlockBits(data);

它有效,但我得到的位图方向错误。有人可以解释一下原因并为我找到解决方案吗?

最佳答案

这可以是两件事,也可以结合起来:choice of coordinate system ,和 Endianness

有一个约定(我相信是通用的)从左到右列出像素,但没有关于垂直方向。虽然某些程序和 API 的 Y 坐标在底部为零并向上增加,但其他程序和 API 的做法恰恰相反。我不知道你从哪里得到byte[],但是一些API允许你在写入、读取或使用纹理时配置像素方向。否则,您必须手动重新排列行。

这同样适用于字节序; ARGB 有时表示蓝色是最后一个字节,有时表示第一个字节。某些类,如 BitConverter也有内置解决方案。

Unity 使用大端bottom-up纹理。事实上,Unity handles lots of this stuff under the hood ,并且在导入位图文件时必须重新排序行并翻转字节。 Unity还提供了类似LoadImage的方法和 EncodeToPNG可以解决这两个问题。

为了说明 byte[] 发生的情况,此示例代码以三种不同的方式保存同一图像(但您需要将它们导入为 Truecolor 才能看到它们在 Unity 中正确):

using UnityEngine;
using UnityEditor;
using System.Drawing;
using System.Drawing.Imaging;

public class CreateTexture2D : MonoBehaviour {

    public void Start () {

        int texWidth = 4, texHeight = 4;

        // Raw 4x4 bitmap data, in bottom-up big-endian ARGB byte order. It's transparent black for the most part.
        byte[] rawBitmap = new byte[] {

            // Red corner (bottom-left) is written first
            255,255,0,0,  0,0,0,0,      0,0,0,0,      0,0,0,0,
            0,0,0,0,      0,0,0,0,      0,0,0,0,      0,0,0,0,
            0,0,0,0,      0,0,0,0,      0,0,0,0,      0,0,0,0,
            255,0,0,255,  255,0,0,255,  255,0,0,255,  255,0,0,255
            //Blue border (top) is the last "row" of the array
        };

        // We create a Texture2D from the rawBitmap
        Texture2D texture = new Texture2D(texWidth, texHeight, TextureFormat.ARGB32, false);
        texture.LoadRawTextureData(rawBitmap);
        texture.Apply();

        // 1.- We save it directly as a Unity asset (btw, this is useful if you only use it inside Unity)
        UnityEditor.AssetDatabase.CreateAsset(texture, "Assets/TextureAsset.asset");

        // 2.- We save the texture to a file, but letting Unity handle formatting
        byte[] textureAsPNG = texture.EncodeToPNG();
        System.IO.File.WriteAllBytes(Application.dataPath + "/EncodedByUnity.png", textureAsPNG);

        // 3.- Rearrange the rawBitmap manually into a top-down small-endian ARGB byte order. Then write to a Bitmap, and save to disk.
        // Bonus: This permutation is it's own inverse, so it works both ways.
        byte[] rearrangedBM = new byte[rawBitmap.Length];
        for (int row = 0; row < texHeight; row++)
            for (int col = 0; col < texWidth; col++)
                for (int i = 0; i < 4; i++)
                    rearrangedBM[row * 4 * texWidth + 4 * col + i] = rawBitmap[(texHeight - 1 - row) * 4 * texWidth + 4 * col + (3 - i)];

        Bitmap bitmap = new Bitmap(texWidth, texHeight, PixelFormat.Format32bppArgb);
        var data = bitmap.LockBits(new Rectangle(0, 0, texWidth, texHeight), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
        System.Runtime.InteropServices.Marshal.Copy(rearrangedBM, 0, data.Scan0, rearrangedBM.Length);
        bitmap.UnlockBits(data);
        bitmap.Save(Application.dataPath + "/SavedBitmap.png", ImageFormat.Png);
    }
}

关于unity-game-engine - 来自 byte[] 数组的位图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30423737/

相关文章:

c# - Visual Studio 2019 忽略选项卡首选项

unity-game-engine - 我们如何为 linerenderer 设置白色

android - 回收位图不释放内存

c++ - "Enlarging"一个二维数组 (m,n)

java - 如何在 Java 中为 MaxHeapPriorityQueue 编写 sortRemove 方法?

javascript - JS : update the data in a specific object by key

android - 为 android unity 构建时出现这些奇怪的 xcode/iOS 错误

android - 如何与Unity一起存储简单的数据?

android - 我无法将我的位图保存到 Android 中的图库中?

android - 图像保存到 SD 卡覆盖现有文件