How to write curved text

How to write curved text on a tft display. I have a circle and like to write my text curved on the circle .
Is it possible ?


Yes, it is possible but extremely difficult.

I suggest that you prepare your picture on the PC with a PC program. Rotate each letter.
Save the result to BMP or JPG file on your SD card.

Inspect the result. It will not be perfect. IrfanView will attempt to render the curves on rotated letters by anti-aliasing.

This is why companies employ graphics designers for their Logos and Trademarks.
Everything should look nice even on a match head or the side of a lorry.

You can draw your artwork in a large size. Then ask IrfanView to scale it to your desired size.


OK , David ,

I did that but found it hard to do , was looking for an other way to do it .

Thanks , and have a nice sunday


Do you want a fixed curved text? e.g. a Logo
Or do you want to print different curved text at run time?

Rotating a letter is relatively easy. UTFT can print a letter at different angles. It will look a little messy.

Anti-aliased letters will look much nicer but you really need a PC program to do this for you.

My advice is: think of a cunning plan.


OK David , please find herewith my 'start ’ sketch.
The 'degrees ’ (30 , 60 … ) between the two white circles are horizontal now .
The idea was to write them 'curved ’ . ( as the circle )


New_Rotator_sketch.ino (4.34 KB)

Perhaps a silly question David , I know perfectly well how to build a B/W picture on a SD , but what kind of programm I have to use to make a RGB color picture on my SD once ready with IRFAN ?

I need HQ bevause I like to preserve the colors I made on my tft . ( I'm a snob and it have to be perfect (lol) )

Hi David ,

I made this bmp. Is this bmp OK or to big for a 3.5" , a Mega and a SD ?
I made this one with Inkscape because I’m more familiar with that prog.

Marco (with the flue - snif )

My bmp is not accepted ( 1.9Mb) , therefore this JPEG file

Yes, that looks nice. IrfanView or Paint should be able to scale it to suit your 480x320 display. And the digits will be anti-aliased nicely.

Draw the background image from SD card or JPG in Flash memory.

You can redraw the old pointer background and plot your new pointer easily if you keep within the inner white circle. You calculate the green colour depth.
If you had a “background” photo on SD card it is still possible to redraw the background vacated by the old pointer. It just gets fiddly.


Hi David , me again .
I used irfan like before and image_converter_565 to transform the jpg because Image converter don't accept bmp.

Once converted I have following info :
the .c file = 1.4MB ( pretty big )

// Generated by : ImageConverter 565 Online
// Generated from : rotator better_1.jpg
// Time generated : Mon, 11 Feb 19 09:31:44 +0100 (Server timezone: CET)
// Image Size : 480x320 pixels
// Memory usage : 307200 bytes

I tried it out anyway
I opened the sketch I found here :

Arduino Forum

Using Arduino
Diplay a RGB Bitmap on TFT Shield without SD

and replaced the existing .c file by my rotator file .....
but just like I thought , the file is way too larg.

What should be done ? Is it perhaps impossible from the flash memory and imperative a SD should be used ?

Yes, your RAW image is 307kB which is far too big for the MEGA2560 Flash.
You can display it from the SD card. Size is no problem.
Or you could display the .BMP file from the SD card.

If you don't want to use an SD card, you could display the .JPG file from Flash.
IrfanView can compress the JPEG dramatically. Experiment on the PC. You will be amazed how far you can compress.

The alternative is to draw your picture with regular graphics commands. Easy to do the colour gradations. Not so easy to produce anti-aliased text.

The simple answer is:
.RAW and .BMP files must use the SD card. Very simple to display. Even a Uno will be ok.
.JPG can use SD card. A compressed .JPG will fit in Flash. A MEGA2560 has enough SRAM to render .JPG but it requires an extra library.


Thanks David ,

When I use " showBMP_not_Uno , I get a clear picture from the SD-card . Only thing , the picture is vertical and not horizontal .
I wrote : tft.setRotation(3) ; in the setup but no correct picture .

I think the best way is to use your showBMP_not_uno file and try to eliminate all the not needed lines which is not so easy .

But the bmp is clear and very visuable .


Problem solved ,
tft.setRotation (3); was not on the correct place . ( should be the fluw - snif )


Your NW, NE, ... are not at 315 degrees, 45 degrees, ...
Your green and magenta lines are not intuitive. e.g. 7.5 degrees.

Incidentally, I reduced your 999x666 JPEG to 480x320. Then saved the JPG at different compressions e.g.
30% 11.1kB
75% 19.6kB
90% 29.8kB
100% 76.0kB

The 30% looks blocky. The other compressed images look just as good as the original.

Your app only uses one 480x320. But imagine other apps that could render several JPEGs stored in Flash.


I saw that , and rectified it , David .( NE and ..... )

Oh , thanks a lot for your efforts , I will try that way also .
I prefere , if possible , not using a SD card , but the direct flash .

With a SC the whole thing looks very nice now .

I'm no specialist and still learning . Today , I downloaded and printed out the presenting ideas on displays from hacker.ino . For me , as beginner , wonderful stuff

Many thanks , Marco
Stormy Southern France

Correct me if I'm wrong but to use an image with the flash memory , I have to convert the image in a .c file . I use 'image_converter_565 on-line (Rinky-Dink )as some users (and ) proposed .
Strange but true , every image ( JPG 35kB , 21kB , 12kB ....) is converted into a 1.4 MB .c-file .

I thought that 12kB should be smaller than 21kB .(lol)
Is there an other way (program)to convert JPG in color.c files ?

This back-ground image is the most difficult thing I ever done with arduino .

A .JPG is simply a binary file that obeys a JPEG format.
You can simply read the bytes and write them to a C array in PROGMEM.

Then include the array in your sketch.


Hi David ,
please don’t think that I’m not searching for the solution( several houres this night and all morning ) but :

I understand that a jpg-file is build in a binary way.
I did a lot of reading on-line.
I found an online converter (jpg->binary ) and made a binary file .
I can not simply read the binary and write them to a C array. I need some tool for that , but what ?
I didn’t find this tool.

BTW , I made a jpg-file of 19.3Kb and one of 31.5Kb ( pictures ) . As a MEGA have a flash memory of 256Kb , I should be able to use a C array of MAX that size .

GitHub - Bodmer/JPEGDecoder: A JPEG decoder library in this sketch the baboon use 75kB on a MEGA and is just fine.
It’s a nice sketch and since it used your MCUFRIEND I could use my tft .

Could you please have an other look to my attachments and help me once more to convert those into usable files ?

I’m very sorry for all the troubles I make and understand completely if you will no longer waste your time with me.

Marco , France



Google “bin2c”. You can create the C file on your PC via a command line.

Or you could write a sketch on your Arduino to read a binary file on the SD and create the C file on the Serial Terminal. e.g. thanks to Bodmer

//   Open a Jpeg file on an SD card and dump it to the Serial port as a C array
void createArray(const char *filename) {

  File jpgFile;  // File handle reference For SD library
  if ( !( jpgFile = filename, FILE_READ))) {
    Serial.println(F("JPEG file not found"));

  uint8_t data;
  byte line_len = 0;
  Serial.println("// Generated by a JPEGDecoder library example sketch:");
  Serial.println("#if defined(__AVR__)");
  Serial.println("  #include <avr/pgmspace.h>");
  Serial.print("const uint8_t ");
  while (*filename != '.') Serial.print(*filename++);
  Serial.println("[] PROGMEM = {"); // PROGMEM added for AVR processors

  while ( jpgFile.available()) {

    data =;
    Serial.print("0x"); if (abs(data) < 16) Serial.print("0");
    Serial.print(data, HEX); Serial.print(",");// Add value and comma
    if ( line_len >= 32) {
      line_len = 0;




Thanks David , that explain a lot