将三维字节数组转换为单字节数组

本文关键字:数组 字节 单字节 转换 三维 字节数 | 更新日期: 2023-09-27 18:36:04

我有一个三维字节数组。

三维数组表示 jpeg 图像。每个通道/阵列代表RGB频谱的一部分。

我对保留黑色像素不感兴趣。黑色像素由以下非典型排列表示:

myarray[0,0,0] =0;
myarray[0,0,1] =0;
myarray[0,0,2] =0;

因此,我已通过执行此byte[] AFlatArray = new byte[width x height x 3]然后将此 3d 数组展平为一维数组,然后分配相应的坐标值。

但就像我说的,我不想要黑色像素。因此,此数组必须仅包含具有 x,y 坐标的彩色像素。我想要的结果是重新表示仅包含非黑色像素的 i 维字节数组中的图像。我该怎么做?

由于xy坐标系,看起来我还必须存储黑色像素。我尝试写入二进制文件,但由于 jpeg 文件被压缩,该文件的大小大于 jpeg 文件。


我需要一个单字节数组,因为我有一个具有红绿蓝分量的图像。我想存储 2 张图像之间的差异。所以,这是一个 3 暗淡的阵列。由于并非所有像素都会不同,因此我只想存储差异。但是,即使展平化大小仍然大于图像的字节大小(因为它是 jpeg 并经过压缩)。

我正在使用emgu图像框架。当您枚举图像的数据时,它可以为您提供 3 个通道,每个通道由字节数组中的一个维度表示。我正在使用的 3 个通道是 (R)ed、(G)reen 和 (B)lue。我可以在HSL或HSV(等)的色彩空间中工作,然后我可以使用3个通道的色相,饱和度和亮度。

将三维字节数组转换为单字节数组

通过将三个维度相乘来计算总大小,分配结果数组,并使用三个嵌套循环 - 每个维度一个。为输出数组中的当前位置创建一个计数器;当您将项目放入输出数组时,递增该计数器 - 如下所示:

byte[,,] threeD = new byte[X,Y,Z];
byte[] res = new byte[X*Y*Z];
int pos = 0;
for (int x = 0 ; x != X ; x++)
    for (int y = 0 ; y != Y ; y++)
        for (int z = 0 ; z != Z ; z++)
            res[pos++] = threeD[x,y,z];

如果它不是交错数组:

byte[] newArray = new byte[oldArray.Length];
for(int i = 0; i < oldArray.GetLength(0); i++) {
    for(int k = 0; k < oldArray.GetLength(1); k++) {
        for(int j = 0; j < oldArray.GetLength(2); j++) {
            int index = i * oldArray.GetLength(1) * 
                oldArray.GetLength(2) + k * oldArray.GetLength(2) + j;
            newArray[index] = oldArray[i, k, j];
        }
    }
}

或者,在单个循环中:

   byte[] newArray = new byte[oldArray.Length];
   for (int i = 0; i < oldArray.Length; i++) {
       int ind3 = i % oldArray.GetLength(2);
       int ind2 = i / oldArray.GetLength(2) % oldArray.GetLength(1);
       int ind1 = i / (oldArray.GetLength(1) * oldArray.GetLength(2));
       newArray[i] = oldArray[ind1, ind2, ind3];
   }

如果它是一个锯齿状数组,那么你将不知道 3D 数组中元素的确切总数,在这种情况下,我会使用一个列表,在将元素添加到列表中的同时遍历三个维度,然后使用 List.ToArray() 将列表转换为 1D 数组。