Change Bitmap-Layout

Hi,
I wrote a small, basic driver for an ePaper-display (so 1bit bitmaps are used). I draw the screen into a Bitmap, then convert it to a 1bit-Bitmap (since I couldn’t find a way to create 1bit-Bitmaps), so send it to my display via SPI. The problem is, I think the

 
returns another Bitmap-layout, than my display wants to have. My display wants a stream of bytes in one line (I don't know how to describe it properly :D)

I want it that way:

```cs

7 6 5 4 3 2 1 0   7 6 5 4 3 2 1 0 ......
......

But I think the returned pattern is:


7   7   7 7 7 7 7 7 ......
6   6   6 6 6 6 6 6 ......
5   5   5 5 5 5 5 5 ......
4   4   4 4 4 4 4 4 ......
3   3   3 3 3 3 3 3 ......
2   2   2 2 2 2 2 2 ......
1   1   1 1 1 1 1 1 ......
0   0   0 0 0 0 0 0 ......
......

So I wrote a helper-method, that reads the bitmap pixel-by-pixel and creates a fitting array, but thats horribly slow on my G120 (about 350ms for one 112x208px bitmap, using a LargeBuffer instead of a byte[] it even takes ~650ms), the GHI…Convert()-Methos takes only 14ms…


        private static byte[] ImageConverter(Bitmap BMP)
        {
            int HORCNT = 0;
            int VERCNT = 0;
            int IMAGEHEIGHT = BMP.Height;
            int IMAGEWIDTH = BMP.Width;
            int ARRAYSIZE = (IMAGEWIDTH * IMAGEHEIGHT) / 8;

            byte[] DisplayBuffer = new byte[ARRAYSIZE];

                for (int cnt = 0; cnt < ARRAYSIZE; cnt++)
                {
                    DisplayBuffer[cnt] = 0;
                    for (int i = 0; i <= 7; i++)
                    {
                        if (BMP.GetPixel(HORCNT, VERCNT) != Microsoft.SPOT.Presentation.Media.Colors.Black)
                        {
                            if (i == 7) DisplayBuffer[cnt] += 1;
                            if (i == 6) DisplayBuffer[cnt] += 2;
                            if (i == 5) DisplayBuffer[cnt] += 4;
                            if (i == 4) DisplayBuffer[cnt] += 8;
                            if (i == 3) DisplayBuffer[cnt] += 16;
                            if (i == 2) DisplayBuffer[cnt] += 32;
                            if (i == 1) DisplayBuffer[cnt] += 64;
                            if (i == 0) DisplayBuffer[cnt] += 128;
                        }
                        HORCNT += 1;
                    }
                    if (HORCNT == IMAGEWIDTH)
                    {
                        VERCNT += 1;
                        HORCNT = 0;
                        //Debug.Print("Byte# " + cnt); 
                    }
                }

                return DisplayBuffer;
        }

So is there an simple way to convert the bitmap-layouts?
I added two images, one is the bitmap the GHI…Convert()-Method creates, the other is the one, my very slow Method creates…

I’m almost sure, the professional-coders here can solve this with one line of code :smiley: :wall: :think: :-[

@ glx - You could try to move your algorithm to RLP to speed it up.

1 Like

@ glx I have a ‘smoothline’ example in codeshare. It uses RLP to do some speedy graphics processing on the G120. Fairly sure you could hack that to solve your problem pretty quickly. Be sure to look at Simons ‘RLP in-depth’ guide to get you up and running.

https://www.ghielectronics.com/community/codeshare/entry/891

1 Like

Link to RLP In Depth PDF

http://www.stablepoint.biz/gadgeteering/wp-content/uploads/2014/09/RLP-in-depth-1.1.pdf

2 Likes

Hm nice, I didn’t know RLP is that much faster, on first sight it looks a bit complicated for me, but maybe I’ll try that :).
Until now I tought about, how to simply reallign the bytes, so that they are in the right order to send them to the display.
But first I have to do a nightshift in my real job now ;).

I finally ended up writing my owm Bitmap-class (without RLP, so it’s not that fast) :D… It uses much less RAM than a normal Bitmap, because it only uses 1bit-colordepth. I can share it if anyone needs it, I think even a G30 can be attached to a small display that way (I’ll test it when I get the G30TH I ordered). The only thing I didn’t understand, is the TinyFont-Format, so I “invented” my own format. By now it can draw lines (between two points or starting at one point and heading into a direction), circles, rectangles, single pixels and text (in two sizes by now, it’s just scaled). It also can be different bitmap-layouts selected (new ones could also be implemented easily). I added two pictures below :).

1 Like

@ glx -

Glad to see you got it working!

I can share it if anyone needs it -

Yes, that would be a nice codeshare.

I just got my library working a bit more this week :)… Maybe I can share some code soon :)… It’s a bit slow (the more pixels it has to draw, the slower it becomes). I also wrote a (until now incomplete) driver for an ISSI31FL3731 matrix-driver on an Adafruit-module (this one Overview | IS31FL3731 16x9 Charlieplexed PWM LED Driver | Adafruit Learning System) :).
I made a short video for those who are interessted :).

Usage should be easy and simple, it can be multiple layouts selected, to make it working for most (b/w) displays. The code below e.g. draws the heart in the video :D.

TinyBitmap tinyBuffer2 = new TinyBitmap(16, 9, 0x04); //Instanciates a new bitmap with the given size and layout
tinyBuffer2.DrawPixel(2, 0); //x,y
tinyBuffer2.DrawPixel(6, 0);
tinyBuffer2.DrawLine(1, 1, 3, 1); //x1,y1,x2,y2
tinyBuffer2.DrawLine(5, 1, 7, 1); //...
tinyBuffer2.DrawLine(0, 2, 8, 2);
tinyBuffer2.DrawLine(0, 3, 8, 3);
tinyBuffer2.DrawLine(0, 4, 8, 4);
tinyBuffer2.DrawLine(1, 5, 7, 5);
tinyBuffer2.DrawLine(2, 6, 6, 6);
tinyBuffer2.DrawLine(3, 7, 5, 7);
tinyBuffer2.DrawPixel(4, 8);

Text is also easy (but has only a fixed font in two sizes):



This accesses the byte-array to pass it directly to a display:

```cs]byte[] Buffer = tinyBuffer2.Frame;[/code
7 Likes

@ glx - very nice. Time for a tech talk about your project? :wink:

2 Likes