# Subpixel rendering in Processing

**URL:** <https://discourse.processing.org/t/subpixel-rendering-in-processing/3958>\
**Category:** Gallery\
**Created:** [September 29, 2018, 6:11pm UTC](https://discourse.processing.org/t/subpixel-rendering-in-processing/3958 "2018-09-29T18:11:31Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![lqdev](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/lqdev/32/29_2.png) [@lqdev](https://discourse.processing.org/u/lqdev)\
**Post date:** [September 29, 2018, 6:11pm UTC](https://discourse.processing.org/t/subpixel-rendering-in-processing/3958/1 "2018-09-29T18:11:31Z")

</div>

Hello,

Lately I had been working on a rewrite of my Processing application in JavaFX, and I had been wondering how to create subpixel rendered shapes. I know it’s possible to use Java’s font smoothing for text (which - in JavaFX - is CoolType), which works great, and it’s possible to do this in Processing too:

```auto
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.text.FontSmoothingType;

void setup() {
  GraphicsContext ctx = (GraphicsContext) surface.getNative().getGraphicsContext2D();
  ctx.setFontSmoothingType(FontSmoothingType.LCD);
  // draw some of that smoooooth CoolType text
}

```

However, I wanted something that’s usable cross-renderer, so I came up with my own solution. Introducing: TerribleType, the worst subpixel rendering. (also present in OpenJDK’s subpixel text rendering implementation for Swing)  
 ![TerribleType demo](https://yyz2.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/d/dc0191357b2c96a6c81bebc2018c2dc4f1e87eb1.png)  
_Just look at that juicy color fringing!_  
However, unlike JavaFX and others, this rendering works on _ **anything** _, shapes and SVGs included!

_ **But how is it so good!?!?!?** _

Well, I put a lot of work into thinking through the possible solutions, like creating my own shape renderer (which was the worst of them all), but I finally got one that worked half-decent. That solution was to render all the shapes at triple the horizontal scale, and then “beat them down” to the correct scale using RGB channels. As you can see above, the solution isn’t as good as I imagined. Here’s the source code:

```auto
PImage subpixelRender(CanvasSpec spec) {
  PGraphics pg = createGraphics(spec.width * 3, spec.height);
  
  pg.beginDraw();
  pg.scale(3, 1);
  spec.draw(pg);
  pg.endDraw();
  
  PImage src = pg.get();
  PImage render = createImage(spec.width, spec.height, ARGB);
  
  src.loadPixels();
  render.loadPixels();
  
  for (int i = 0; i < src.pixels.length; i += 3) {
    float alpha = max(alpha(src.pixels[i]), alpha(src.pixels[i + 1]), alpha(src.pixels[i + 2]));
    float red = red(src.pixels[i]);
    float green = green(src.pixels[i + 1]);
    float blue = blue(src.pixels[i + 2]);
    color col = color(red, green, blue, alpha);
    render.pixels[i / 3] = col;
  }
  
  render.updatePixels();
  
  return render;
}

abstract class CanvasSpec {
  int width;
  int height;
  
  CanvasSpec(int w, int h) {
    this.width = w;
    this.height = h;
  }
  
  public abstract void draw(PGraphics pg);
}

```

How to use it:

```auto
PImage subp = subpixelRender(new CanvasSpec(width, height) { // try not to use the full width and height of the window, for performance reasons
  public void draw(PGraphics pg) {
    // important! if this isn't executed the rendering won't work properly
    // this isn't called by default because different colors may work better if there's too much color fringing
    pg.background(255, 0);
    pg.fill(255); pg.stroke(0);
    pg.ellipse(32, 32, 64, 64);
  }
});
image(subp, 0, 0);

```

![screenshot of the example code](https://yyz2.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/f/f7072eb3a714e716f76ae41725f693c7d1b5ced8.png)  
As you can see, it doesn’t look that bad with shapes (it actually does), just don’t use it for text:  
 ![screenshot of text](https://yyz2.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/c/c1249bbdb5311da6cc4ce893903320a7074fd76c.png)  
Changing out the background color to `127, 0` looks _a bit_ better, but still pretty terrible.  
 ![screenshot of text with changed background](https://yyz2.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/b/b6527f862e8fc7e33e51e1293790c90bba27c7f5.png)  
It doesn’t look as bad with this SVG, though.  
 ![screenshot of rendered SVG](https://yyz2.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/3/3df3cf6bdd5cd726b768ac5cef0dd38fa3dfbc7b.png)  
Close up:

 ![the previous screenshot, but zoomed in](https://yyz2.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/2/2e0bf0484b79c8f9a774d2c3bd40e67df29b8831.png)  
You can see some of the color on the bottom.  
_source: [material design icons](http://materialdesignicons.com/)/test-tube_  
This SVG doesn’t look as good though.  
 ![v](https://yyz2.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/8/8726f20e0d661bc52ecb26347e6257665ddafe5c.png)

So, there’s definitely room for improvement, and I will actually keep on improving this renderer so it produces (at least) acceptable images.

Now, let me clear up one thing:  
_Why the heck did you use abstract classes instead of Java 8 lambdas!?_  
There’s only one reason, and that reason is Processing’s parser. Behind the scenes Processing does pretty much all of its error checking and Processing to Java transformations using an ANTLR grammar, which doesn’t support Java 8 features yet. _Yet._

Anyways, I hope you liked this post. I know, my renderer isn’t the best, and probably will never be, but hey, it works!  
Feel free to use it in your own sketches, you don’t even have to give credit, but I’d appreciate if you would.

---

<div class="post-metadata">

**Author:** ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)\
**Post date:** [September 30, 2018, 4:20pm UTC](https://discourse.processing.org/t/subpixel-rendering-in-processing/3958/2 "2018-09-30T16:20:02Z")

</div>

> [@lqdev](#):
>
> TerribleType

If it comes with “Juicy Color Fringing” then it sounds like you could sell that as an AfterEffects filter for a lot of money.

You should name your subpixelRender function to indicate its non-type purpose.

> [@lqdev](#):
>
> That solution was to render all the shapes at triple the horizontal scale, and then “beat them down” to the correct scale using RGB channels.

Pixel Beat-Down?

---

<div class="post-metadata">

**Author:** ![lqdev](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/lqdev/32/29_2.png) [@lqdev](https://discourse.processing.org/u/lqdev)\
**Post date:** [September 30, 2018, 5:41pm UTC](https://discourse.processing.org/t/subpixel-rendering-in-processing/3958/3 "2018-09-30T17:41:34Z")

</div>

> [@jeremydouglass](#):
>
> Pixel Beat-Down?

Well, I didn’t know the correct wording in English, what I actually meant is to squash them horizontally.

---

<div class="post-metadata">

**Author:** ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)\
**Post date:** [September 30, 2018, 6:10pm UTC](https://discourse.processing.org/t/subpixel-rendering-in-processing/3958/4 "2018-09-30T18:10:24Z")

</div>

No, I think it is great! I also love “TerribleType.”

Common English might be compress (or crunch, or squash). But PixelSquasher doesn’t have the same ring to it as PixelBeatDowner, in my opinion. Although… “beat-down” also means “a one sided fight, an assault”, so maybe that is too violent. “Tamp down” is a bit more neutral…?

Well, the point is, thanks for sharing your subpixel renderer – you should name your hard work!

---

<div class="post-metadata">

**Author:** ![lqdev](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/lqdev/32/29_2.png) [@lqdev](https://discourse.processing.org/u/lqdev)\
**Post date:** [September 30, 2018, 6:24pm UTC](https://discourse.processing.org/t/subpixel-rendering-in-processing/3958/5 "2018-09-30T18:24:34Z")

</div>

Yeah, I used Google Translate to get the correct word translated from my own language, but as we all know it doesn’t always do a great job. Anyways, thanks for your opinion!
