简体   繁体   中英

How do I get a partial image from a raw byte array of colors?

So I want to grab a partial image from a byte array of colors. The image is a unity logo that is 64x64 pixels. I want to grab a third of the image (Unity Logo). How would I traverse the byte array to get this image?

统一标志

Unity 标志之三

Unity Byte Array

assuming each byte is a single pixel (which is only true for 8-bit depth images), the bytes 0-63 are the first row, 64-127 are the second row, etc etc.

meaning that to find out the position of a pixel in the one-dimensional array, based on its two-dimensional coordinates in the image itself, you do

int oneDimPos = (y*64) + x;

if each pixel were 3 bytes (24-bit color depth), the conversion from 2dimensional to 1dimensional coordinates would be:

int oneDimPos = (y * 64 * 3) + (x * 3);

(so the most generic equation is:

int oneDimPos = (y * imageWidth * colorDepth) + (x * colorDepth);

and you need to keep this in mind and adjust the code accordingly. or even better, use this most generic version, and actually read the image width and its color depth from the asset you're using as source.

BEWARE: if the image is anything else than 8bits per pixel, this equation will, naturally, only give you the first, starting bit belonging to that pixel, and you still need to take care to actually also read the other ones that belong to that pixel

i'm gonna finish the answer assuming 8bit color depth, for simplicity, as well as so that you can't just copypaste the answer, but also have to understand it and re-shape it according to your specific needs ;) )

meaning you can now do classic two nested loops for x and 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();

The original issue that I was having was not exactly the same as the question. I wanted to simplify it by having a byte array that everyone could take a look at. The byte array from Unity's website wasn't exactly what I was getting.

So I have 3 x 1080p portrait screen (1080 x 1920 pixels) with RGBA channels. I grabbed a screenshot from this and got a 24,883,200 size byte array.

Note, 3 * width(1080) * height(1920) * channels(4) = 24,883,200.

    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

This is an issue because the colors array is read from top to bottom, left to right. So instead, you should read a portion of the 3 x 1080 x 4 channels.

    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);
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM