5

I'm trying to draw 8-bit pixel text on an HTML5 canvas. I've tried:

_context['imageSmoothingEnabled'] = false;
_context['mozImageSmoothingEnabled'] = false;
_context['oImageSmoothingEnabled'] = false;
_context['webkitImageSmoothingEnabled'] = false;
_context['msImageSmoothingEnabled'] = false;

and some other things having to do with the HTML & CSS font face while googling for over an hour. This is the font-face:

@font-face {
    font-family: "undertalefont";
    src: url("bitops.ttf");
    font-style: normal;
    -webkit-font-smoothing: none;
}

When using it in HTML, it attempts to use an odd form of subpixel anti-aliasing. And it of renders the font as expected in image-editing programs.

So my question is, how do I stop this... (scaled to 200% to see the bad AA)

Ugly AA

and make it pixel-perfectly crisp?

EDIT: I'm rendering the text with:

_context.fillStyle = "white";
_context.font = "24px 'undertalefont'";
_context.fillText("Font rendering.", 32, 20);
Accumulator
  • 873
  • 1
  • 13
  • 34
  • How are you rendering the text? – Blindman67 Jan 19 '16 at 02:10
  • @Blindman67 added that – Accumulator Jan 19 '16 at 02:43
  • can you please change 24px to 18pt? – ymz Jan 19 '16 at 02:47
  • @ymz I did that and there is no difference. – Accumulator Jan 19 '16 at 02:50
  • if you render it with a very large size (like 100pt) - would the anti-aliasing effect still exists? – ymz Jan 19 '16 at 02:56
  • can you confirm that this is happening for several fonts? (and not just this particular one) – ymz Jan 19 '16 at 03:19
  • Yes, I tried the other variations on the font I am using, and I tried several other pixel fonts. They all do this. – Accumulator Jan 19 '16 at 03:29
  • 1
    Also is your canvas resolution the same as its display size. IE is `canvas.style.width` the same as `canvas.width` ? If they do not match and width is greater than style.width you will have blurring on all pixels not just the fonts. Try drawing a pixel with `var d = context.getImageData(10,10,1,1); d.data[0] = d.data[1] = d.data[2] =d.data[3] = 255; context,putImageData(d,10,10);` if that perfect pixel is blurred it is the canvas being displayed to large and not matching the pixel resolution of the display device. – Blindman67 Jan 19 '16 at 04:20
  • 1
    Yes, they are equal, I made sure of that. And doing that draws a single pixel, yes, I checked with an image editor. – Accumulator Jan 19 '16 at 04:45
  • Is the single pixel blurred or not? – Blindman67 Jan 19 '16 at 04:56
  • No, it is a single, full-alpha, full-color (I made it red) pixel. – Accumulator Jan 19 '16 at 05:18
  • 1
    @Omega Glad you got it sorted. :-) If your fix was basically fixing a typo (px vs pt font sizing) then you might delete this question (typos are not typically useful to future viewers). Otherwise you might add your own answer and accept it so this question comes off the "unanswered" queue. – markE Jan 19 '16 at 07:50
  • 1
    Actually it still is a little bit off... after fixing the pt and adding 0.5/-0.5 to x, if you look closely you still notice it a little bit. – Accumulator Jan 19 '16 at 19:10
  • @ymz, @ Blindman67, Watch https://jsfiddle.net/fh2k93qc/ I see a big difference. Using Chrome Max OS X (macbookpro 2017). – Pacerier Nov 04 '17 at 21:25
  • Fixed here: https://jsfiddle.net/crxyfmjz/1/ – themartin Feb 28 '23 at 13:22

1 Answers1

0

You can achieve the same text sharpness by doubling the size of the canvas element, and the items within it, then scaling back down with CSS.

This is caused by many screens rendering two pixels for every pixel, essentially having double the resolution.

Canvas does not have access by default to the pixel scaling that the document has when rendering text.

I have fixed @Pacerier jsfiddle by adding a few lines here.

So the canvas element changes from

<canvas id="myCanvas" width="200" height="100">no support</canvas>

To

<canvas id="myCanvas" width="400" height="200">no support</canvas>

And we add some CSS:

<style>
  #myCanvas{
    width: 200px;
    height: 100px;
  }
</style>

You must then double the size of everything rendered in canvas so

ctx.font = "30px asd"

becomes

ctx.font = "60px asd";

More information in this answer.

themartin
  • 87
  • 11