Rotating a bitmap

Before murdering me my knowledge and terminology is limited but I’m doing my best to learn.

I’m trying to rotate a bitmap on a 128x64 oled screen(http://www.banggood.com/0_96-Inch-4Pin-White-IIC-I2C-OLED-Display-Module-12864-LED-For-Arduino-p-958196.html?utm_source=review_email_1.1&utm_medium=rem_1.1_us_product&utm_term=rem_1.1_us_product&utm_content=rem_1.1_us_product&utm_campaign=rem_1.1_us_product) and i’m using the adafruit library for their ssd1306(GitHub - adafruit/Adafruit_SSD1306: Arduino library for SSD1306 monochrome 128x64 and 128x32 OLEDs) all powered by an Uno.

I can’t seem to figure out how to rotate a bitmap but can only have it move horizontal or vertical on the x and y axis. I just want to rotate it let’s say 15*. Can someone point me in the right direction here?

Found this with Google that may help :slight_smile:

I saw that earlier. Unfortunately that uses an old library that isn't supported on newer arduinos :\

1 Like

Ignore the old library, it is the principles of bitmap manipulation and rotation function which can be adapted to your display.

Figure out how the “Rotate_and_Draw_Bitmap” function does the rotation with trigonometry (sine and cosine) and adapt the plotting to your library and you will have cracked the problem.

If you just want it rotated once to use it as that, do it in Photoshop and play with the bitmap programs for OLEDs.

I wrote this for Arduino to read a bitmap from SD card and reproduce it on a PAL TV display, 200*200 pixels I think, also added full 360 rotation and zoom in/out, but it was written in assembler and a real bugger to get right

You want full rotation or just 90 degrees ?

Ah-ha. At least he does not want to use a Tiny25.

The 128x64 monochrome display is generally handled with a mirror-image in SRAM. i.e. 1024 bytes.
The UNO has only got 2048 bytes of SRAM. So you can not afford to have a second mirror.

Which means that you have to decide the amount of image to rotate. Calculate a new pixel. Save the old contents. Write the new pixel. Rinse and repeat for your "saved" pixel. Then update the OLED from the mirror.

This ends up as a lot of work. (if you want to keep the mirror containing the new image)

Alternatively, you take a pixel from the mirror, calculate the new position and write directly to the OLED. The mirror still contains the unrotated image.

i.e. one approach gives you a permanent 15 degree change. The other is better for animations where you do a continuous rotation.

Horizontal or Vertical scrolling is relatively easy to do with an OLED. Rotations look seriously difficult. It would be interesting to see how mcnobby has done it.

David.

bodmer:
Ignore the old library, it is the principles of bitmap manipulation and rotation function which can be adapted to your display.

Figure out how the “Rotate_and_Draw_Bitmap” function does the rotation with trigonometry (sine and cosine) and adapt the plotting to your library and you will have cracked the problem.

ah, as soon as i saw the old libraries i figured that’s where everything was and moved on.
i’ll dig back into it today!

INTP:
If you just want it rotated once to use it as that, do it in Photoshop and play with the bitmap programs for OLEDs.

too much memory for that, i would need a bunch of bitmaps, like 50+ and i’m already at 70% of memory used on my uno

mcnobby:
SmartShow ProjeX-SD with bitmap scale & rotation AVR DMX Arduino - YouTube

I wrote this for Arduino to read a bitmap from SD card and reproduce it on a PAL TV display, 200*200 pixels I think, also added full 360 rotation and zoom in/out, but it was written in assembler and a real bugger to get right

You want full rotation or just 90 degrees ?

i’ll look into what you’ve done as well. Basically i’m going to have my bitmap rotate to x degree based on input. Could be 5*, could be 12*, could even be 45*. Baby steps though, I figured once I can get it rotated at least once I can look and manipulate it as I need

david_prentice:
Ah-ha. At least he does not want to use a Tiny25.

The 128x64 monochrome display is generally handled with a mirror-image in SRAM. i.e. 1024 bytes.
The UNO has only got 2048 bytes of SRAM. So you can not afford to have a second mirror.

Which means that you have to decide the amount of image to rotate. Calculate a new pixel. Save the old contents. Write the new pixel. Rinse and repeat for your "saved" pixel. Then update the OLED from the mirror.

This ends up as a lot of work. (if you want to keep the mirror containing the new image)

Alternatively, you take a pixel from the mirror, calculate the new position and write directly to the OLED. The mirror still contains the unrotated image.

i.e. one approach gives you a permanent 15 degree change. The other is better for animations where you do a continuous rotation.

Horizontal or Vertical scrolling is relatively easy to do with an OLED. Rotations look seriously difficult. It would be interesting to see how mcnobby has done it.

David.

I'm going to purchase an arduino mega eventually, i was just trying to get the basics done on this first. I can't believe how complicated image rotation is(coming from a web developer too though).

Have you thought about just attaching your OLED to a servo? :roll_eyes:

haha, that wouldn't work for this although it seems that would be easier than trying to figure this out!

Well, i'm making progress! Looking at the code from the linked forum post by @bodmer. I don't understand the calculations but i'm at least making progress. i've manually set the height and width of my bmp i'm using but it seems no matter what i set that or even the drawing bmp height and width it still turns out like the video below. actually if it goes over anything about 10x30 it seems to double the bmp instead of stretch it. my guess is it things it is in portrait instead of landscape?

sk8jess:
Before murdering me my knowledge and terminology is limited but I'm doing my best to learn.

I'm trying to rotate a bitmap on a 128x64 oled screen(http://www.banggood.com/0_96-Inch-4Pin-White-IIC-I2C-OLED-Display-Module-12864-LED-For-Arduino-p-958196.html?utm_source=review_email_1.1&utm_medium=rem_1.1_us_product&utm_term=rem_1.1_us_product&utm_content=rem_1.1_us_product&utm_campaign=rem_1.1_us_product) and i'm using the adafruit library for their ssd1306(GitHub - adafruit/Adafruit_SSD1306: Arduino library for SSD1306 monochrome 128x64 and 128x32 OLEDs) all powered by an Uno.
I can't seem to figure out how to rotate a bitmap but can only have it move horizontal or vertical on the x and y axis. I just want to rotate it let's say 15*. Can someone point me in the right direction here?

The key to your problem is rectangular to polar and polar to rectangular conversion.

Think of your bitmap image (a rectangle) sitting inside a circle. From the center of the circle to a pixel is the radius, and you use sine and cosine to determine the angle of the imaginary line from the center of the circle to the pixel.

Then, change that angle by the amount you want to rotate the image, convert the polar coordinates back to rectangular and draw the pixel at it's new location.

Repeat for each pixel and your image is rotated.

Of course, be warned... a 128 x 64 display has 8192 pixels... times all that floating point calculation... on an AVR... it's gonna be S-L-O-W.

And, you need at least 1K of free memory... you read the pixels from the display, determine their new locations, store them in ram, then re-draw the whole screen from ram.

Why 1K? Because there are 8 bits per byte... 8192 / 8 = 1024.

I've already tried this with a Noritake GU128X64-U100 vacuum florescent display (a 128 x 64 pixel display) and it literally takes almost 1/2 second to do an arbitrary rotation of the whole screen. Plus, the edges and/or corners get cut off (a portrait oriented bitmap cannot fit in a landscape oriented display!).

Have fun... take lots of aspirin. You'll need it.

INTP:
Have you thought about just attaching your OLED to a servo? :roll_eyes:

BWAHAAA!!! Too funny!

I'm already getting a headache from your post haha, not a good sign.

That being said, i'm taking a break for the night. I'm not making any more progress on my end.

If anyone is curious about my code it can be found here http://pastebin.com/rCBFdCEm
The image I'm using is a square and it's 32x32

feel free to find the problem, ha.

Also consider any savings you might need to make to save memory and time

In my example I was only rotating circular objects, so the image would not actually have to be the full X*Y pixel size because as you rotate, chunks are sliced off of the corners

So I made savings as I only scanned the original image in the circular areas, and translated them to new points also within a circle

There are also other tricks I used with my example (its a con !).. What you see is actually half an image from the SD, but mirrored in XY (thus making two matching halves) the original BMPs were developped so that they matched when cropped then put back together in this way.. This saved half the ram for the original image, half the space on the SD and half the loading time for the image, half the maths calulations for new points because one original image pixel would then create TWO target pixels (mirror-mirror)

Also, naughty me, I was running at some ridiculous speed, like 32Mhz, but it was an ATMega328

I was also having to recreate PAL frames at 30fps, which nobbles about a great deal of the processor time

I can post some code, but to be honest it would look like ASM gobbledy-gook !! but it does work :slight_smile:

One other thing... its important to decide which way you work the transformation

(a) Scan the original image array and create new target XY points from original XY points
(b) Go through the XY of target image array and pull the on/off pixel value from the original image using trig

I can tell you that using (a), the rotated image will have holes in it due to rounding errors etc, where as (b) will be pretty much perfect

Do not use sin/cos etc, use a progmem look up table (per degree). I used half sized tables (I think) as parts of each sin/cos table are repeated/refected. From memory I used an int_8 for one and a uint_8 for the other (cant remember which right now), since you are only using a low res image, you wont need the resolution of maths. Since I was doing this in assembler I just had to do a simple MUL/MULS/MULSU which only took one processor cycle

Anyway these are some of the thing I found to speed up calculations

I hate to say it but advanced math is totally over my head right now. And here I am thinking this was going to be a simple project.
I'm honestly starting to thinking jumping onto an arduino mega or zero for more memory here. If i had more memory I would just do a bunch of slightly rotated rotated images and call on them when needed. I'm starting to think that is going to be the best bet here.

Wow, i was completely overdoing this project. I just loaded 3 more of my bitmaps into my project and my memory has barely changed. I'm going to try and make individual bitmaps for everything I need here and just call them when needed.

sk8jess:
I saw that earlier. Unfortunately that uses an old library that isn't supported on newer arduinos :\

but it should work with openGLCD.

--- bill