Mat Mat - 1 day ago 3
C# Question

Get grayscale Image height without considering white pixels

I have grayscale pictures of an

ArrayList<System.Windows.Controls.Image>
laid out horizontally on a
Canvas
. Their
ImageSource
are of type
System.Windows.Media.Imaging.BitmapImage
.

Is there a way to measure in pixels the height of each
Image
without considering white, non-transparent pixels Outside the colored part ?

Lets say I have an
Image
of height
10
, in which the whole top half is white and the bottom half is black; I would need to get
5
as it's height. In the same way, if that
Image
had the top third black, middle third white and bottom third black, the height would be
10
.

Here's a drawing that shows the desired heights (in blue) of 3 images:

Example picture

I am willing to use another type for the images, but it Must be possible to either get from a
byte[]
array to that type, or to convert
Image
to it.

I have read the docs on
Image
,
ImageSource
and
Visual
, but I really have no clue where to start.

Answer

Accessing pixel data from a BitmapImage is a bit of a hassle, but you can construct a WriteableBitmap from the BitmapImage object which is much easier (not to mention more efficient).

WriteableBitmap bmp = new WriteableBitmap(img.Source as BitmapImage);
bmp.Lock();

unsafe
{
    int width = bmp.PixelWidth;
    int height = bmp.PixelHeight;
    byte* ptr = (byte*)bmp.BackBuffer;
    int stride = bmp.BackBufferStride;
    int bpp = 4; // Assuming Bgra image format

    int hms;
    for (int y = 0; y < height; y++)
    {
        hms = y * stride;
        for (int x = 0; x < width; x++)
        {
            int idx = hms + (x * bpp);

            byte b = ptr[idx];
            byte g = ptr[idx + 1];
            byte r = ptr[idx + 2];
            byte a = ptr[idx + 3];

            // Construct your histogram
        }
    }
}

bmp.Unlock();

From here, you can construct a histogram from the pixel data, and analyze that histogram to find the boundaries of the non-white pixels in the images.

EDIT: Here's a Silverlight version of the same thing (untested):

WriteableBitmap bmp = new WriteableBitmap(img.Source as BitmapImage);
int width = bmp.PixelWidth;
int height = bmp.PixelHeight;

for (int y = 0; y < height; y++)
{
    for (int x = 0; x < width; x++)
    {
        int pixel = bmp.Pixels[y * width + x];
        // Do your stuff
    }
}
Comments