简体   繁体   中英

Get pixel data from image UWP

I'm writing a simple tool, the user can select an image and it should list all the colors found in the picture.

Now, I'm facing 2 main issues, one is that it's slow because I'm looping through all the pixels in an image. Second, I'm getting unexpected results.

First thing's first, the code:

    public static async Task<List<ImageColor>> GetImageColorsAsync(StorageFile image)
    {
        List<ImageColor> colors = new List<ImageColor>();

        var imagestream = await image.OpenStreamForReadAsync(); // Convert image to stream
        var imageDecoder = await BitmapDecoder.CreateAsync(imagestream.AsRandomAccessStream()); // decode stream
        var imagePixelData = await imageDecoder.GetPixelDataAsync(); // get information about pixels
        var bytes = imagePixelData.DetachPixelData(); // get pixel data

        for (int x = 0; x < imageDecoder.PixelWidth; x++)
        {
            for (int y = 0; y < imageDecoder.PixelHeight; y++)
            {
                var location = (y * (int)imageDecoder.PixelWidth + x) * 3; // Navigate to corresponding coordinates
                var color = Color.FromArgb(0, bytes[location + 0], bytes[location + 1], bytes[location + 2]); // Filter Red Green Blue and convert this to Argb

                // find if color already exsists from its hex code
                string hex = color.ToString();
                var prevColor = colors.FirstOrDefault(a => a.ColorCodeHex == hex);

                if (colors.Count == 0 || prevColor == null)
                {
                    // new color
                    ImageColor imgColor = new ImageColor()
                    {
                        R = color.R,
                        G = color.G,
                        B = color.B,
                        ColorCodeHex = hex,
                        Occurence = 1
                    };

                    colors.Add(imgColor);
                }
                else
                {
                    // exsisting color
                    prevColor.Occurence++;
                }
            }
        }


        return colors;
    }

Now, do I really need to go through every single pixel?

And, what I did was test this function using a black image (completely black) and what I got was that there are 4 colors in that picture: black, red, green and blue.

Also, when testing using an image which was just a screenshot of some text (so the colors black, white and maybe some yellow were present) the result was huge (almost 1000+ colors) so there is clearly something wrong with my method

Now the lines where I find the location and color are not mine, I found them online and I can't really verify that this is how you should do it.

Any help guys?

First, I don't have a UWP app at hand, but I think your correctness problem is because you ignore the stride. This number is the amount of bytes that the system uses to represent a row, which is not 3*width*y, but usually more in order to align row data to a fixed grid.

Second, are you really sure you have a 3 channel image and not 4 (ARGB)? The fourth channel would at least explain why you see non-zero values in a black picture, especially because you see (#ff0000, #00ff00 and #0000ff), so you are getting ff at locations you don't expect.

Third, performance-wise, it would be a wise decision to use a dictionary or hashset instead of a list.

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