What Andrew is trying to tell, amongst a number of things, is you are not taking into account the border and other possible bounding contentions which add to the size of the button...

The button on the left is sized to match the image size, the button on the right takes into consideration the components Insest
s , allowing the content to be fit within the button without effecting the borders.
Also, I don't think html is the best choice for what you want to achieve.
UPDATED
When this blows up in your face, I didn't tell you ;)

URL url = getClass().getResource("/DukeWaveShadow48x48.png");
String text = "<html><table border='0' width='48' height='48' cellpadding='0' cellspacing='1' background='" + url.toExternalForm() + "'><tr><td width='46' height='46' align='center'>Hello</td></tr></table></html>";