Main Site Documentation

Bitmap processing in RLP


#1

Hi,

Please consider the following code sample:

public static class StringExtender
{
    public static byte[] GetLedBitmapBytes(this string text, Font font, int width, int height, int x = 0, int y = 0)
    {
        byte[] data = new byte[width * height];
        using (var bitmap = new Bitmap(width, height))
        {
            bitmap.DrawText(text, font, Color.White, x, y);
            bitmap.Flush();
            data = bitmap.GetLedBitmapBytes();
        }
        return data;
    }
}

And

public static byte[] GetLedBitmapBytes(this Bitmap bitmap)
{
    int threshold = 127;
    int index = 0;
    int dimensions = bitmap.Height * bitmap.Width;

    byte[] data = new byte[dimensions / 8];

    for (int horizontalLine = 0; horizontalLine < bitmap.Height / 16; horizontalLine++)
        for (int column = 0; column < bitmap.Width / 8; column++)
            for (int row = horizontalLine * 16; row < 16 * horizontalLine + 16; row++)
                for (int x = 0; x < 8; x++)
                {
                    var c = bitmap.GetPixel(column * 8 + x, row);
                    var r = ColorUtility.GetRValue(c);
                    var g = ColorUtility.GetGValue(c);
                    var b = ColorUtility.GetBValue(c);
                    int luminance = (int)(r * 0.3 + g * 0.59 + b * 0.11);

                    if (luminance > threshold)
                        data.SetBit(index);

                    index++;
                }

    return data; 
}

This is an example of bitmap processing I need to do very frequently
and at a high speed. Of course when I wrote this stuff for the desktop framework I didn’t have to worry about speed issues or anything.

But on an embedded device it’s a completely different story.

The code takes a string, converts it to a bitmap and then converts
the bitmap to a byte[] that is sent to an LED panel which then displays it.

The data is created on the managed side, and send to the device on the native side (rlp).

The bitmap operations are the bottleneck here,
and the example is just a very very very simple example of what we really need. So I’m thinking there is no way this will ever be fast enough for let’s say: making text scroll. As I need to redraw the bitmap every time.

(I can send data to the panel at extremely high speed using RLP, but
compared to that the bitmap code takes an eternity to process)

So I’m wondering…
How to embedded device developers normally deal with bitmaps?
Are there C libraries we can use, or other resources that might help ?


#2

The bitmap is just a 2d array of pixels. You can completely write a RLPBitmap class to fit your own needs. It is easier to implement vs trying to understand someone’s code since this is really simple


#3

Yes,
But functions such as DrawText, Drawing an image within an image, seem rather difficult to me, which is one of the reasons I like to use .NET in the first place… but it might solve part of the problem :slight_smile:

Oh btw Gus, I heard your .NET Rocks Episode, that was awesome,
think I will have to mail Carl & Frank, tell them you are to modest :slight_smile:
You’re like the John Skeet of TinyCLR :stuck_out_tongue:


#4

There is a method in Bitmap class to return a byte array. So, do all bitmap on NETMF as usual but then pass on the byte array to your RLP method that does the specific work. You get the best of both world :slight_smile:

…thanks for the kind words. We can always use an extra referral and recommendation :slight_smile:


#5

@ 7 you’ll need to write a BMP header to cast it back into a bitmap on the managed side see http://www.microframework.nl/2009/09/21/native-code-on-chipworkx-using-rlp/ for an example. Text writing isn’t too incredibly difficult either see Pyxis 1 http://www.skewworks.com/products/Pyxis%20OS for some sample code; it’s written for the Arduino but can be adapted fairly easily.


#6

Hi,

Skewworks I’ll look into that thnx.

Gus,
I’ve taken up your suggestions,
now my C skills are rather limited coming from C# so I came up with this:

int Convert32BPPBitmapToLedBitmap(unsigned char *generalArray, void **args, unsigned int argsCount, unsigned int *argSize)
{
	unsigned char *rawData = (unsigned char*)args[0];
	
	//Will get these as parameters after testing
	int width = 128;
	int height = 16;
	
	unsigned char ledBitmap[width * height / 8];

	int horizontalLines = height / 16;
	int columns = width / 8;
		
	int horizontalLine;
	int column;
	int row;
	int bit;
	
	int r, g, b;
	int sourceOffset;
	int luminance;
	int targetIndex;	
	
	for (horizontalLine = 0; horizontalLine < horizontalLines; horizontalLine++)
		for(column = 0; column < columns; column++)
			for(row = horizontalLine * 16; row < 16 * horizontalLine + 16; row++)
				for(bit = 0; bit < 8; bit++)
				{
					sourceOffset = (horizontalLine * width / columns * 1024) + (column * 512) + (row * 32) + (bit * 4);
					r = rawData[sourceOffset];
					g = rawData[sourceOffset + 1];
					b = rawData[sourceOffset + 2];
					
					luminance = (r * 0.3 + g * 0.59 + b * 0.11);
					if (luminance > 127)
						SetBit(ledBitmap, targetIndex);
	
					targetIndex++;
				}
	
	return 0;
}

My question now is:

I know that when you pass in a byte[] from the managed side to the native side and you change that array in the native code it will also change on the managed side.

The problem here is that the byte[] I want to return is actually much smaller.

So I want to return the smaller array instead.
Is there a good way of doing this?

Thank you


#7

Your methods takes 2 arguments, 2 arrays for large one and for small one?

it is really up to you

…so you are loving RLP yet?


#8

Ah of course
And I’m absolutely loving RLP.

You see, I’m proficient with languages such as Python, C#, F#, VB.NET, PHP, software architecture, systems design, etc… you name it, all the high level stuff.

I never used any C before.

Now, we have these guys building LED controllers for us in China,
but they are hardware devs. They are very good at what they do,
but don’t ask them to expand on that and they do not understand our market.

We are hoping to build our own controller which suits our market.
The Chinese only want to display media, we need interactive systems
that integrate with external software systems etc…

Having those hardware guys implement something like that is a disaster.
Implementing our own controllers on “normal” microchips is out of the question, my people are software developers.

Enter the .NET Micro Framework, opening up the world of microprocessors
to people like me. But the hardware we have to control requires “realtime” (if I’m expressing it correctly) which is something managed code does not offer… so RLP is like the best thing since the invention of hot water.

We can use that for the really really high performance stuff,
which is easy enough for a C# guy to write (with some swearing along the way) and do all the complicated stuff in .NET

So yeah, we’re loving it :slight_smile:
Without GHI we wouldn’t be doing this, and I’d probably have to look for another job :smiley:

In fact, everything depends on us getting this thing to work,
believe it or not we have an entire company depending on it.

Our biggest issue is speed, RLP might just solve that.


#9

Here,
http://dl.dropbox.com/u/18986/videos/rlpspeed.wmv

The speed improvements thnx to RLP :slight_smile:


#10

Great work :clap: Welcome the world of GHI’s-RLP

Can you please post this video on youtube or vimo?


#11

Hi,
I will do that, and I’ll probably get to post a video doing this on a bigger LED wall as well


#12

Hi,

The video is now on Youtube:


#13

Thanks, it i snow easier to view


#14

That is a huge difference. Do you have a link for these led panels or is it something that you made yourself?


#15

We develop these internally,
will have to check what we can give away, sorry :slight_smile:


#16

Thank you but don’t worry I am not looking for one. I was just curious - never seen it before.


#17

They are intended for the european market.
Anyway what might be of interest is that nearly all LED panels in China work the same way and most of them are controlled using MBI chips.

http://www.mblock.com.tw/customer_FAQ.html