MATLAB Answers

0

Pixelated text in figures using text() function

Asked by Hrefna on 3 Feb 2015
Latest activity Commented on by Mike Garrity
on 6 Feb 2015
Hi,
The text() function when adding text to figures seems to me misbehaving. The text is noticeably pixelated when compared to all the other figure text, both on my monitor, and also when I print out to jpg, see
Any hints about settings that could fix this? How do I make the text look more like the default figure text? The pixelation becomes glaringly ugly when projected onto a big screen.

  2 Comments

I've noticed this too. The "improved" graphics of R2014b also make circle 'ro' markers look awful.
Yay! That makes me feel slightly less insane. :)

Sign in to comment.

2 Answers

Answer by Hrefna on 4 Feb 2015
 Accepted Answer

Ooooh! I fixed it!!
I took the text commands out of the for loop, so they're only run once, and BINGO! Smooth text! :)
Here's the let's-give-the-for-loop-less-to-do code:
figure(10); clf;
lineCol = get(gca, 'colororder');
legText{1} = 'Red legend';
legText{2} = 'Blue legend';
for nS = 1:10
pp = [];
pp{1} = plot(nS, randi(95, 1, randi(3,1)),'o', 'linewidth', 2,'color', lineCol(2,:)); grid on; hold on;
pp{2} = plot(nS, randi(95, 1, randi(3,1)),'x', 'linewidth', 1.5,'color', lineCol(1,:));
end
plot([1 10], [80 80],'k', 'linewidth', 1.5 )
t1 = text(1.5, 83, 'text(1.5, 83, ThisTest and ABCDEFGHIJKLMNOPQRSTUVXYZ)', 'fontname', 'Verdana')
text(1.5, 62, 'text(1.5, 62, ThisText and abcdefhijklmnopqrstuvxyz 123456789)', 'fontsize', 14)
xlabel('xlabel')
ylabel('ylabel');
legend([pp{1}(1) pp{2}(1)], legText, 'location','southeast')
title('Title')
print -djpeg100 texttestfig_fixed.jpg
And here's the pretty image:
Now that I think about it, I've had weird pixelations happen on LINES too, maybe that was a for-loop thing too?
Anyway, problem fixed! Sort of. :)

  3 Comments

Ah, that makes sense.
If you draw multiple copies of the same text string, and you have FontSmoothing enabled, then the smoothed pixels around the edges will be showing the results of blending the background color with multiple copies of the text color. This makes that pixels darker than they should be and spoils the antialiasing effect.
Note that this doesn't happen when FontSmoothing is off because each pixel is either background color or text color. Setting the pixel multiple times doesn't change the result.
That's why this code
for i=1:10
for j=1:i
text(.25,i/11,'Monkey', ...
'HorizontalAlignment','center', ...
'FontSmoothing','on');
text(.75,i/11,'Monkey', ...
'HorizontalAlignment','center', ...
'FontSmoothing','off');
end
end
results in this picture
Yeah, it makes sense, but it's unfortunate :)
Maybe matlab-in-the-future will learn to only print identical text commands once. :)
That'd actually be very tricky to implement.
In some ways the real issue is in how FontSmoothing is implemented. It's different from how GraphicsSmoothing is implemented. GraphicsSmoothing uses a technique called MSAA. This actually figures out what portion of the pixel is covered by the different primitives that touch it. This correctly handles some of the hard cases, but it gets very expensive as the number of samples gets large. We use it for most graphics primitives because it prevents artifacts like the white lines you see between abutting polygons in apps like Adobe Reader which use simpler anti-aliasing techniques.
FontSmoothing uses a simpler technique which just uses the coverage percentage for each primitive that touches the pixel. It's usually good enough for text because you usually don't have multiple text strings touching the same pixel. But, as you see it, it can fail in some situations.
It's unfortunate that text doesn't look good with GraphicsSmoothing='on' and FontSmoothing='off'. The reason for this is that GraphicsSmoothing needs "sub-pixel information", and the way fonts get rasterized eliminates that.

Sign in to comment.


Answer by Mike Garrity
on 4 Feb 2015

There are an awful lot of variables in play during font rasterization. I'd have to know a lot more about what you're doing. Here's the closest I was able to get by guessing:
figure
h(1) = plot(randi(10,[1 40]),55+40*rand(1,40),'ro')
hold on
h(2) = plot(randi(10,[1 40]),55+40*rand(1,40),'bx')
t(1) = text(1.5,83,'text(1.5, 83, ThisTest and ABCDEFGHIJKLMNOPQRSTUVXYZ)')
t(2) = text(1.5,62,'text(1.5, 62, ThisText and abcdefhijklmnopqrstuvxyz 123456789)')
ylabel ylabel
xlabel xlabel
set(h,'LineWidth',2)
t(2).FontSize = 16
grid on
legend('Red Legend','Blue Legend','Location','SouthEast')
set(gcf,'Color','white')
l = line([1 10],[80 80],'LineWidth',2,'Color','black')
print -djpeg -r150
Which results in the following on my windows box:
If you zoom in on the two images you'll see that they're close, but there are some artifacts in your text which aren't in mine. If I guessed reasonably closely, I would wonder about things like:
  • What platform (windows, linux, mac) you're on
  • Whether you've got unusual fonts installed
  • What 'opengl info' says
  • What get(0,'ScreenPixelsPerInch') says
But there are lots of other variables to consider. It looks like you've got GraphicsSmoothing and FontSmoothing turned on, is that correct? This looks like Helvetica, is that correct? Are you seeing the same issue with other fonts? I assume that your figure's Renderer is opengl, although that shouldn't make that much of a difference in R2014b.
The reason I'm asking is that I'm planning to do some posts on the graphics blog about how text gets drawn, but it's a fairly complex area. I'd like to get an idea of what sort of issues you're really encountering in this area.

  1 Comment

Whoa, that's a lot of work you put in your answer! Color me impressed! :)
And, your text() looks like I'd expect mine to look like, but it doesn't. Mine looks distinctly different (bolder, more pixelated) from the rest of the figure text.
From my point of view I don't have anything 'fancy' going on. I'm just innocently using text() and scratching my head at the result. I have never consciously turned fontsmoothing on.
The only thing I can think of that´s 'out of the ordinary' is that 2014b has occasionally crashed on me due to something in the graphics engine (low level graphics?), and I vaguely recall it wanting to switch between some mode or other. I'm not the best with error messages if the whole thing basically works once they flash by.
Anyway.
To answer your specific questions
  • 64-bit Windows 7
  • No unusual fonts that I know of. I certainly haven't installed any myself
>> opengl info
Version: '4.3.0'
Vendor: 'NVIDIA Corporation'
Renderer: 'Quadro K2100M/PCIe/SSE2'
MaxTextureSize: 16384
Visual: 'Visual 0x07, (RGBA 32 bits (8 8 8 8), Z depth...'
Software: 'false'
SupportsGraphicsSmoothing: 1
SupportsDepthPeelTransparency: 1
SupportsAlignVertexCenters: 1
Extensions: {304x1 cell}
MaxFrameBufferSize: 16384
>> get(0,'ScreenPixelsPerInch')
ans =
120
>>
I ran 'opengl software' just for kicks to turn it 'true', but it didn't fix the issue.
Now, I apparently deleted the code I used to make the image I submitted originally (long day), but here's a reworking of it, just so that you have it.
figure(10); clf;
lineCol = get(gca, 'colororder');
legText{1} = 'Red legend';
legText{2} = 'Blue legend';
for nS = 1:10
pp = [];
pp{1} = plot(nS, randi(95, 1, randi(3,1)),'o', 'linewidth', 2,'color', lineCol(2,:)); grid on; hold on;
pp{2} = plot(nS, randi(95, 1, randi(3,1)),'x', 'linewidth', 1.5,'color', lineCol(1,:));
plot([1 10], [80 80],'k', 'linewidth', 1.5 )
t1 = text(1.5, 83, 'text(1.5, 83, ThisTest and ABCDEFGHIJKLMNOPQRSTUVXYZ)')
text(1.5, 62, 'text(1.5, 62, ThisText and abcdefhijklmnopqrstuvxyz 123456789)', 'fontsize', 14)
xlabel('xlabel')
ylabel('ylabel');
legend([pp{1}(1) pp{2}(1)], legText, 'location','southeast')
title('Title')
end
print -djpeg100 texttestfig.jpg
Just for kicks, here are all the attributes of t1:
Annotation: [1x1 matlab.graphics.eventdata.Annotation]
BackgroundColor: 'none'
BeingDeleted: 'off'
BusyAction: 'queue'
ButtonDownFcn: ''
Children: []
Clipping: 'off'
Color: [0 0 0]
CreateFcn: ''
DeleteFcn: ''
DisplayName: ''
EdgeColor: 'none'
Editing: 'off'
Extent: [1.5000 80.5203 8.4043 4.9593]
FontAngle: 'normal'
FontName: 'Helvetica'
FontSize: 10
FontSmoothing: 'on'
FontUnits: 'points'
FontWeight: 'normal'
HandleVisibility: 'on'
HitTest: 'on'
HorizontalAlignment: 'left'
Interpreter: 'tex'
Interruptible: 'on'
LineStyle: '-'
LineWidth: 0.5000
Margin: 3
Parent: [1x1 Axes]
PickableParts: 'visible'
Position: [1.5000 83 0]
Rotation: 0
Selected: 'off'
SelectionHighlight: 'on'
String: 'text(1.5, 83, ThisTest and ABCDEFGHIJKLMNOPQRSTUVXYZ)'
Tag: ''
Type: 'text'
UIContextMenu: []
Units: 'data'
UserData: []
VerticalAlignment: 'middle'
Visible: 'on'
I'm attaching the resulting .jpg as well as a screen shot:
Screen shot:
You ask about other fonts. I tried Verdana with
t1 = text(1.5, 83, 'text(1.5, 83, ThisTest and ABCDEFGHIJKLMNOPQRSTUVXYZ)', 'fontname', 'Verdana')
I saw the font change, but the quality is as bad as before. :/
Ideas? More questions? :)

Sign in to comment.