C# 如何从颜色的原始字节数组中获取部分图像?

C# 如何从颜色的原始字节数组中获取部分图像?,c#,unity3d,C#,Unity3d,所以我想从颜色的字节数组中获取部分图像。该图像为64x64像素的unity徽标。我想抓取图像的三分之一(Unity徽标)。如何遍历字节数组以获得此图像 假设每个字节都是一个像素(这仅适用于8位深度图像),字节0-63是第一行,64-127是第二行,以此类推 也就是说,要根据像素在图像本身中的二维坐标找出像素在一维数组中的位置,您需要 int oneDimPos = (y*64) + x; 如果每个像素为3字节(24位颜色深度),则从二维坐标到一维坐标的转换为: int oneDimPos

所以我想从颜色的字节数组中获取部分图像。该图像为64x64像素的unity徽标。我想抓取图像的三分之一(Unity徽标)。如何遍历字节数组以获得此图像


假设每个字节都是一个像素(这仅适用于8位深度图像),字节0-63是第一行,64-127是第二行,以此类推

也就是说,要根据像素在图像本身中的二维坐标找出像素在一维数组中的位置,您需要

int oneDimPos = (y*64) + x;
如果每个像素为3字节(24位颜色深度),则从二维坐标到一维坐标的转换为:

int oneDimPos = (y * 64 * 3) + (x * 3);
(因此,最通用的公式是:

int oneDimPos = (y * imageWidth * colorDepth) + (x * colorDepth);
您需要记住这一点,并相应地调整代码。或者更好的是,使用这个最通用的版本,并从用作源的资源中实际读取图像宽度及其颜色深度

注意:如果图像不是每像素8位,那么这个等式自然只会给出属于该像素的第一个起始位,并且您仍然需要注意实际读取属于该像素的其他位

为了简单起见,我将在假设8位颜色深度的情况下完成答案,这样您不仅可以复制粘贴答案,还必须理解答案,并根据您的具体需要重新塑造它;) )

这意味着您现在可以对x和y执行经典的两个嵌套循环:

List<byte> result = new List(); //i'm going to use list so i can just .Add each byte instead of having to calculate and allocate the final size in advance, and having to mess around with recalculating the index from the source array into the destination one, because i'm lazy
for(int x=0; x < 22; x++){ //no way for you to grab precise third since that boundary is in the middle of a pixel for an image 64pixels wide
  for(int y = 0; y < 64; y++){ //we go all the way to the bottom
    result.Add(sourceAsset.bytes[(y*64) + x]);
  }
}

//now just convert the list to actual byte array
byte[] resultBytes = result.ToArray();
列表结果=新列表()//我将使用list,这样我就可以添加每个字节,而不必提前计算和分配最终大小,还要重新计算从源数组到目标数组的索引,因为我很懒
对于(int x=0;x<22;x++){//没有方法抓取精确的第三,因为该边界位于图像64像素宽的像素的中间。
对于(inty=0;y<64;y++){//我们一直到底
添加(sourceAsset.bytes[(y*64)+x]);
}
}
//现在只需将列表转换为实际的字节数组
byte[]resultBytes=result.ToArray();

我的原始问题与问题不完全相同。我想通过一个每个人都可以查看的字节数组来简化它。Unity网站上的字节数组和我得到的不完全一样

因此,我有3 x 1080p的纵向屏幕(1080 x 1920像素),带有RGBA通道。我抓取了一张截图,得到了一个大小为24883200字节的数组

注:3*宽度(1080)*高度(1920)*通道(4)=24883200

    byte[] colors = new byte[24883200]; // Screenshot of 3x1080p screen.
    byte[] leftThird = new byte[colors.Length / 3];
    Array.Copy(colors, 0, leftThird, 0, colors.Length / 3); // Grab the first third of array
这是一个问题,因为颜色数组是从上到下、从左到右读取的。因此,您应该读取3 x 1080 x 4通道的一部分

    int width = 1080 * 4; // 4 channels of colors (RGBA)
    int fullWidth = width * 3; // Three screens
    int height = 1920;
    byte[] leftScreen = new byte[screenShotByteArray.Length / 3];
    for(int i = 0; i < height; i++)
    {
        Array.Copy(screenShotByteArray, (i * fullWidth) + (offset * 4), leftScreen, i * width, width);
    }
int-width=1080*4;//4个颜色通道(RGBA)
int fullWidth=width*3;//三屏
整数高度=1920;
byte[]leftScreen=新字节[screenShotByteArray.Length/3];
对于(int i=0;i
您将使用2作为循环。。。你试过什么?你确定是生的吗?该方法的文档中谈到了JPG和PNG。@John_,我还没有验证,但我希望Unity在导入资产时已经进行了自己的转换,我还希望在将资产拖动到TextAsset类型字段时,也就是说,无论原始文件的格式是什么,当您从TextAsset类型变量中提取字节时,在那个阶段很可能是原始字节。。。文档中的整页都是。。。有点奇怪,好像在使用黑客,但是。。。好。。。看起来像是unity允许并使之生效的那种黑客行为。看起来你是对的。遗憾的是,这个例子不适用。我处理的最初问题是,我有一个3240x120像素的颜色字节数组,有4个颜色通道。原始:字节[]颜色=新字节[]{/*某些颜色*/};//这是我从游戏摄像机中获取的完整的颜色字节数组。字节[]leftThird=新字节[colors.length/3];复制(颜色,0,leftThird,0,leftThird.length);//这是一个奇怪的图像。修复:用于(int row=0;row1d坐标转换,而修复程序正是根据我给出的答案和解释进行的。所以我不明白我的答案是怎么回事。