In this picture, the diffuse part looks good and the specular too.
But the sum looks wrong because it's green where is should be white.
In your code, I see this: // Here I extrapolate the colors from the 0-1 range to 0-255 range. c.m_r = static_cast<int>(255.999 * c.m_r); c.m_g = static_cast<int>(255.999 * c.m_g); c.m_b = static_cast<int>(255.999 * c.m_b);
I don't think it's good to multiply red/green/blue by 255.999 because colors could be higher than 1 as we sum them in the lighting function.
Near the specular spot, the diffuse color is violet so r/g/b ~ 150/30/150 but we use values between 0 and 1 so it's 0.6/0.1/0.6
The center of the specular spot is almost white, let's say: 0.8/0.8/0.8
So the sum will be 1.4/0.9/1.4
When you multiply by 255.999 and cast to int you get: 358 / 230 / 358
I don't know what will happen with the red and blue component as they are higher than 255.
The green part is lower than 255 so it could explain why the spot looks green ?
Look at the book page 21 and the test: "Constructing the PPM pixel data", there is a case where color(1.5, 0,0) is transformed in to "255 0 0"
The tests may look like a waste of time slowing you down when you start but in the long term you'll realize it saves a lot of time !