TColor from HTML code not quite right

I use TColor::GetColor to get custom colours from the HTML RGB code. However, when I then look at the generated PNG and check the colours, they’re not quite right, giving, for example, “#f0f0f0” instead of “#eeeeee”.

1 Like

Can you provide a small script showing this problem ?

Try this:

TCanvas canv;
TBox box(0.2,0.2,0.8,0.8);
auto color = TColor::GetColor("#eeeeee");
box.SetFillColor(color);
box.Draw();
canv.SaveAs("test.png");

Using a colour picker on the canvas itself, colours are correct. In the PNG, the box colour is “#ececec” (for me, at least).

I see a difference when I look at the png generated in batch mode.

In interactive mode the canvas on screen and the png are the same and R=G=B = 238.

In batch mode I get R=G-B=242 for the png.

In batch mode we use the libafterimage library…right now I have no idea how to fix that.

Sorry, that seems to be a Gwenview bug. Try this instead:

auto color = TColor::GetColor("#eeeeee");
gStyle->SetCanvasColor(color);
TCanvas canv;

Picking the colour off the canvas now gives me #F3F3F3.

if I do that the png file is fine in both cases (242).

But #eeeeee should have a value of 238 for R, G, and B.

Agreed: #eeeeee Color Hex

On mac when I do this:

auto color = TColor::GetColor("#eeeeee");
gStyle->SetCanvasColor(color);
TCanvas canv;

I get R = G = B = 242 with the Cocoa back end
And R = G = B = 243 with the X11 backend.

(For the TCanvas on screen). I will check.

ROOT does not store the R G B values as integers between 0 and 255 but as float between 0 and 1. What we get here might be a rounding effect. The following macro also give 242;

{
   int i = TColor::GetColor("#eeeeee");
   TColor *c = gROOT->GetColor(i);
   float r = c->GetRed();
   printf ("Red value = %g %d\n",r,(int)(r*255));
}

it gives:

root [0] .x color.C
Red value = 0.95 242

It looks like dividing by 255 is a bad way of doing the conversion, because it gives answers that are inexact in binary. Dividing by 256 instead gives 238/256 = 0.9297, then 0.9297 * 255 = 237 which is much closer than 242.

In other words, GetColor should divide by 256 instead of 255 (special casing 255 -> 1.0).

(int)(r * 255.0 + 0.5)

It needs to convert an int to a float, not the other way around. To divide by 256, it sets the mantissa to the int value, and the exponent to -8.

This issue is not connected to rounding. In GetColor there is a logic to find the closest color. If one is found (within a given threshold) it is used. That’s why we get 242. If I comment this logic I get exactly 238.

It’s probably a good idea to make the threshold configurable then.

1 Like

This is now implemented in the ROOT master:

$ root
   ----------------------------------------------------------------
  | Welcome to ROOT 6.11/01                    http://root.cern.ch |
  |                                   (c) 1995-2017, The ROOT Team |
  | Built for macosx64                                             |
  | From heads/master@v6-09-02-983-g9f8fdce, May 24 2017, 16:37:13 |
  | Try '.help', '.demo', '.license', '.credits', '.quit'/'.q'     |
   ----------------------------------------------------------------

root [0] int i = TColor::GetColor("#eeeeee");
root [1] TColor *c = gROOT->GetColor(i);
root [2] printf ("%d\n",(int)(c->GetRed()*255));
242
root [3] TColor::SetColorThreshold(0.);
root [4] i = TColor::GetColor("#eeeeee");
root [5] c = gROOT->GetColor(i);
root [6] printf ("%d\n",(int)(c->GetRed()*255));
238
root [7] 
2 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.