Ok, reading a 24-bit BMP file and pass to the leds array:

Ok, reading a 24-bit BMP file and pass to the leds array: done. Reading it in columns? Um, say what? A BMP file stores data row by row … I need to read the data in columns. So, I can’t simply do an bmpFile.read((char*)leds, NUM_LEDS * 3) with a standard, “upright” BMP file …

So I need suggestions. I need to read fast and efficient, which is why I love reading the full array in with one call. Having to write this as nested loops is going to be rather slow.

I can always rotate the BMP and get what I need that way, but that goes back into the realm of pre-processing the image, in which case I may as well stick with what I’m doing now.

Preprocess and rotate if you are going
to read a column at a time. When reading from something like disk or sdcard you want to think about locality - eg reading bytes that are adjacent to each other will always be faster than reading individual, separated bytes (especially if the intermediate storage mechanism is dong any kind of caching internally).

Unless you can read the whole image into memory, which I doubt you can here :slight_smile:

Yeah, if I’m going to do that, I may as well stick with the preprocessing I’m doing now. I just don’t bother saving back in a human readable or viewable format. I keep it compact and small. Saves a bit of space as I don’t have to save the file header.

A friend of mine gives a fantastic presentation on data access latencies across the entire spectrum, from on device memory (and the various caches/prefetch involved there) all the way up to large scale (I.e. Intercontinental) distributed systems. It can change the way you think about organizing/accessing data if you haven’t come across these issues before. I should see if he has a video up of it anywhere.

If I read this stuff any faster, you wouldn’t be able to see anything. :slight_smile: I’m pushing a full column of 48 RGB pixels out about every 660usecs. That includes reading the data from an SD card into the leds array and calling .show().

I was just wondering if there was a way to read a BMP file without having to rotate it to get the data in the right format that I need. Keeping a BMP file will give an end user a viewable image, as opposed to a binary file they can’t view in anything.

Perhaps a rotated bitmap that is still viewable is an ok compromise compared to pre-processing into a completely unreadable binary file?

I say that because you mention your goal is to maintain a “viewable image as opposed to a binary file”.

It’d be easy to rotate back (most desktop and smartphone platforms I’ve noticed have a rotate feature included in their UI) if the user wants to use that file for something else.

An uncle of mine once shared the wisdom to not be afraid to implement a simple compromise.

I do this by preprocessing all the way to a binary file and using that on the sd card. i considered using .bmp files but 1) the code gets far too fiddly and low level 2) it’s a bit slower than reading plain data 3) it’s not going to work if the .bmp files are not the right type so ideally still need a batch process step to convert them.
My solution was to write a minimal format with a header consisting only of the dimensions and then all the rgb data. i then wrote a viewer in processing as well as the converter so i can view a directory of them, i called them .LED files for now.
I have a couple more steps i’d like to add and a lot more useability but it’s working for now, if i get the converter capable of doing a directory full of assorted image types without freaking out over transparencies or doing horrible things to scalings then i shall unleash the code for it on my site and post in here :slight_smile:

Yeah, right now I preprocess all the images in a similar way, a simple header containing the dimensions followed by the RGB data.

The advantage of that is that I can do more to the original image, such as scaling it if it’s too large. The disadvantage is that the resulting file isn’t viewable anymore. However, there’s nothing that says I can’t keep a viewable thumbnail of the image so the user can easily see it.

Oh, as for speed, I’m reading data and pushing it out in, on average 660usecs. That’s how long the loop that does an SD.read() followed by LEDS.show() takes. 75% of the time it’s reading the SD buffer, on the fourth read, the buffer’s empty and it goes back to the card to read more data and that takes about 1100usecs. That’s still pretty dang fast.

Ashley, did you tried teensy with Octows2811 or something like this? I think that best way to get plain image showing on LEDs - get more powerfull microcotroller, with DMA and higher speed. So on teensy 3 or any other arm MCU you can read data with processor main program and send it to array, and later send it thru DMA to LEDs. I think it’s best way - that’s why i’m waiting for arriving of Spark Core and Teensy 3.1 :wink:

I can already read the image as fast as I need it to (any faster and it won’t work.) The issue here was that I needed to read in columns versus rows, and BMP data is stored in rows. So unless I rotate the image, I’ll have to do a lot of calculations. For the amount of work that it takes, it’s not worth it. I’ll stick to the pre-processing that I do now and generate a specific data file.

Yes, and for reading columns you need to do jump between every pixel to read next one in column, and this can’t be done with AVR, as i understand.

It can just fine. Regardless of what MCU is used, the calculations done are exactly the same.

So, if it can, why you don’t just do this?:slight_smile:

recently i’ve talked about this possibilities in AVR with one man. And we discussed that AVR have hardware timers, which can be used to get correct length of bitbanding impulses. So between settings of timer we can go read pixels in column. Didn’t tried this, but it’s possible to speed up getting pixels, if we do this between timer configurations and finish after this.

It won’t matter as the data doesn’t get pushed out till all necessary bits are read in, and in my case that’s 144 bytes of data. Once they’re all read, then it gets pushed out.

Like I said, for what I’m doing, it’s not worth doing calculations. I’ll simply rotate the image and read the full row in, the whole 144 bytes, and push it out. No loops needed to jump row by row. No calculations needed.

uh, i think there is somewhere my english have problems :slight_smile:

Shure i’ve understood that there must be all bits of data readed in before transfer to LED.

And i’ve understood that in this way: bmpFile.read((char*)leds, NUM_LEDS * 3) you will get file data from down to up but whole leds at once.
Did you tried to use loop thru reading BMP in right alignment?
It’s really slows all work?

I’m writing here, because i’m plan to do almost same things as you. But for now i’m working now on node.js driver for ws2811 for beaglebone black . It’s working now, and i’m already can load png image from filesystem and blink it on leds. It’s pretty easy with 1gb RAM…

Preprocessing is really solves this problem, but also preprocessing itself is a problem. And as i see - there is no way to solve this problem without switchin MCU to ARM…

No, you get data from one row, column 0 to column 48*3+padding because that’s how BMP stores information. I need one column, row 0 to row 48, which is the same as rotating a BMP file 90 degrees in either direction.

It’s easy to do this
for (row = 0; row < BMPHeight; row++) {
bmpFile.read(…, 144);
}

which will get you the data per row, which is not what I need.

It’s not as easy to do that per column because you have to read data three columns at a time for each row:
row 0 -> column 0-2
row 1 -> column 3-5
row 2 -> column 6-8
etc., etc.

You’re nesting two loops, one for the column and another for the row inside of it and reading the data one at a time. You can not perform a single .read(…) at that point. Regardless of MCU, an SD.read() is expensive and takes time, so the less time one has to do that, the better. One single .read() that fills all 144 bytes in the array is way better than 48 .read()s to fill the same array.

As I said, rotating the BMP file will get me what I need and the columns would have them become rows and you read in a full row.

There is no reason to switch MCU, an AVR CAN do the calculations to do what I need without having to rotate the image, however it’s simply not worth the time to do because a) rotating the image is much easier, or b) preprocessing it into a custom binary file will get the data in the correct format that I need. And since I’m already doing (b) well before I threw BMPs in the mix, I’m sticking with it. So there’s no need to add anything complicated to the mix. It’s already done.

This is a moot point as it’s already been resolved, and again, switching MCU isn’t magically going to solve the problem: the same calculations will still need to be done, and the same SD.read() will still need to be performed.

Hm, why two loops needed? As i understand you just can read 3 bytes per operation with bmpFile.read((char*)leds, 3) it’s just needed one liip to jump between rows. And one more to jump between columns to show animation…
And why i’m still thinking about more powerfull MCU - you can read sd in one array, while DMA sending data to leds from another one. And you can read this faster with SDIO instead of spi…

“it’s just needed one liip to jump between rows. And one more to jump between columns”

Don’t look now, but you just described why you need two loops.