RGB subpixel rendering for graphics? - vector-graphics

I wonder if there is any graphics library that supports RGB subpixel rendering (like ClearType) for general graphics, not just for text. This would allow one to practically triple the horizontal resolution, and put graphics on third-pixel x positions.
While I think this would be very useful, I couldn't find much on the internet about it, except the following:
How Sub-Pixel Font Rendering Works (there are some line images around the middle)
Subpixel rendering and image resizing (some interesting thoughts on applying subpixel rendering to resizing bitmaps)
Is there any library that implements this, or are there efforts to bring something like this to the Cairo library, for example?
Update:
I'm referring specifically to rendering techniques that take into account that current LCD screens use sub-pixels of different colors. To make a white point, you set all sub-pixels to 'on' or 255. A white line would be several subpixels on top of each other:
...RGB...
...RGB...
...RGB...
...RGB...
...RGB...
...111...
(where . is a fully black sub-pixel, and R, G or B are fully-lit red, green, or blue sub-pixels). Because our eyes can't resolve the sub-pixels, they blend together to make a white line. I could however also make a white line from the following:
....GBR..
....GBR..
....GBR..
....GBR..
....GBR..
....111..
Note that it is perfectly sharp, but positioned at x = 1 1/3 pixels. This is not possible with traditional rendering techniques that draw a slightly blurry white line instead. Here for example R=70% lit, r=30% lit. I didn't work out the math, this is just so you get the idea:
...RGBrgb...
...RGBrgb...
...RGBrgb...
...RGBrgb...
...RGBrgb...
...777333...
Another example is a slope, which you can do a) with full pixels, b) antialiased, or c) with subpixel rendering:
a) RGB...... b) RGB...... c) RGB......
RGB...... RGBrgb... .GBR.....
...RGB... rgbRGB... ..BRG....
...RGB... ...RGB... ...RGB...
...RGB... ...RGBrgb ....GBR..
......RGB ...rgbRGB .....BRG.
......RGB ......RGB ......RGB
Again, note that this is just a crude example to give you the general idea, but you see that a) is jaggy or aliased, b) is blurry, and c) is as sharp as you can get it on a LCD.
Real implementations of this, for font display (ClearType on Windows and the subpixel rendering in FreeType) have a more sophisticated algorithm. They take into account that individual sub-pixels bleed or shine into each other, they preserve the total color intensity or energy. They also take into account that the subpixel spacing is not even (the spacing between R and G, or G and B (in the pixel) may be smaller than between B and R), and finally that some displays have entirely different pixel layouts.

As far as I know no graphic library with subpixel RGB rendering exists.
Here are a few possible reasons why :
Microsoft has a few patents on RGB subpixel rendering technology. I don't know if those patents applies only to font rasterization but if not, it is probably a very good reason why other graphic libraries do not use it.
Like pointed in the question, subpixel rendering is relying on a hardware implementation. It works well with displays that compose color by placing side by side 3 color cells (for instance an LCD monitor). For all other display types (plasma, projectors, old CRT), it doesn't work.
Subpixel rendering adds horizontal resolution only. This limitation is not problem for font rasterization since it is often horizontally that font needs more resolution (see bold and italic characters and kerning). With "custom" graphic it would be weird to have different resolution on each axis.
Subpixel rendering doesn't work with rotational display. For instance, mobile device have to use both RGB subpixel rendering and antialiasing.
Subpixel rendering works only with the native resolution of a display.
It looks like color blind people have problem with subpixel rendering. See this paper for more information.
Subpixel rendering works very well with black on white or white on black backgrounds. With other backgounds the "renderer" has to know the background color to adjust the subpixel effect. For this very reason Office 2013 stopped using ClearType.
This is more subjective but the difference between subpixel rendering and antialiasing is very subtle. The cons and added complexity of subpixel rendering might not be worth it.
IMHO, the future of better graphics is with higher pixel density like the Apple retina display.

Someone managed to get some interesting results using ImageMagick. The method and results, as well as an interesting discussion, are exposed here: https://www.imagemagick.org/discourse-server/viewtopic.php?t=19120
Interesting subject, indeed. But the point remains: how useful can the technique be, since such process would only benefit unscaled images on a specific type of display?

It appears to be possible with AGG at antigrain.com by defining your own conversion pipeline to map the output to device pixels.
See https://sourceforge.net/p/vector-agg/mailman/search/?q=LCD

Related

Render 2D text in Autodesk Forge without aliasing or blurring

Turns out I’m working with the Autodesk Forge viewer and Three.js, trying to render 2D text that can be interacted with (specifically select, rotate, and move).
To do this I am working with meshes (using MeshBasicMaterial, Mesh and TextGeometry) but it turns out that the text does not look perfectly sharp, it presents aliasing and I found that according to the API reference, the antialiasing is not applicable to 2d.
Here are some examples of the problem, as you can see, the more I move away from the plane, the worse the text looks (and even up close it doesn't look perfect):
I have tried to make a test representing the text with a Sprite (despite the fact that it would mean having to change the entire implementation already made with meshes of other functionalities) but apart from the fact that I cannot see it, I have seen example images and they do not appear either well: aliasing is visible from a distance and it looks really blurry up close. Here some examples:
Is there a way to correct this problem or is this the most I can get in 2D? I've tried searching for information on this but can't find anything helpful. And what has puzzled me the most has been realizing that antialiasing was not applicable in the case of 2d, like making it clear that nothing can be done to fix it.
I would be very grateful if you could solve my doubts, thank you very much in advance for your help.
An easier alternative, is to just use a higher pixel ratio for the renderer...
window.devicePixelRatio=2;
viewer.resize();
For example, using the custom geometry text, from Joao's demo, you can see the same aliasing issue at DPR=0.5 and DPR=1.0 ...
https://joaomartins-forge.github.io/textgeometry-sample/
But when I set the DPR=2.0, the text looks clean. The trade off is rendering performance, but your 2D drawings may be simple enough that it won't matter. You can use a 'mouse up' camera settle trick, to switch between DPR of 1 and 2, if you want a better UX experience.
There are a few ways to solve this aliasing issue for 2D (and 3D text).
The way I would recommend for your use case, is to use DIV elements (THREE.CSS3DRenderer), instead of text converted into three.js tessellated triangle geometry, as shown in this blog post:
https://forge.autodesk.com/blog/how-do-you-add-labels-forge-viewer
You can find out more information about THREE.CSS3DRenderer here:
https://threejs.org/docs/#examples/en/renderers/CSS3DRenderer
and an Example here: https://threejs.org/examples/#css3d_periodictable
Using CSS3DRenderer instead of CSS2DRenderer, means you will get the correct scaling (and rotation) of the div element as you zoom into your 2D drawing and the mathematics inside the calculation for the matrix transform has less edge-cases.
Once you are using DIV elements for your text, you will notice that the text is sharper and has no aliasing issues. That's because it is not being rasterized by the webGL pipeline, but by the SKIA library used by chrome/firefox/opera/etc for rasterizing text.
There is one final option, that uses signed-distance fields, but it's probably overkill for what you need.
Let me know if you want some example code.

Image interpolation in Google Chrome vs GIMP

I have a large png image (950x500px) which I have been scaling down using CSS to 500px wide (and 263 high). Before putting this webpage online I decided to scale the image using GIMP as scaling images with CSS is bad practice. However there is a noticeable reduction in image quality when I scale the image using GIMP rather than CSS in Google Chrome even though both images are png and have identical dimensions. I have tried using all four compression methods offered by GIMP (None, Linear, Cubic and Sinc (Lanczos3)) and none of them match the image quality given by Google Chrome.
What compression method does Google Chrome use to give such high-quality image scaling and how can I achieve this offline?
You may get the answer to your question here: How web browsers resize images
Chrome seems to be using several algorithms depending on the scaling factor:
With a very slight downscale (557 to 555 pixels), Chrome uses the same
linear interpolation as when upscaling. (The fact that this graph is
disconnected is an artifact of the way ResampleScope works, and has
nothing to do with Chrome.)
But look what happens if we downscale just a bit more, to 543 pixels:
[…] We get a completely different result: clearly a 3-lobed Lanczos
filter. Chrome’s strategy may be to use Lanczos when reducing an image
by more than 2.5%.
If you have to do it yourself (to get more control on the result), Cubic is usually the best bet scaling up and Sinc (Lanczos3) for scaling down.
If you scale the image yourself, you know how it will look on all browsers.
Note: There are more and more computers equipped with high resolution displays (around 4 times the pixel density of a classic display). You may want to check how images look on those computers. There is a high chance they are scaled up by the browser.
This is a very old question, but I was struggling with an image resize in Gimp yesterday. When I compared the image resized in Gimp with the image automatically resized in Chrome (and Safari), there was a visible difference.
I was resizing a PNG logo from 89x127 to 69x101 and the text blurred after the resize in Gimp no matter which interpolation I chose.
Thanks to the comment above saying that ImageMagick gave a better result when resizing an image, I found this article: Efficient Image Resizing With ImageMagick
The command from the article, despite its claims to be indistinguishable from Photoshop, did not produce a result that matched Chrome, however one of the commenters added a command that did create an image that produced the closest result (barring the resize my friend did in Photoshop):
convert SOURCE_IMAGE -resize OUTPUT_WIDTH -quality 90 -unsharp 0x0.55+0.55+0.008 OUTPUT_IMAGE
I think the trick lies mainly in the sharpening. I've tried different settings and can't exactly match Chrome, but this came pretty darn close.
For completeness, here is the command from the article. Please read the article for a full explanation of how it works:
mogrify -path OUTPUT_PATH -filter Triangle -define filter:support=2 -thumbnail OUTPUT_WIDTH -unsharp 0.25x0.25+8+0.065 -dither None -posterize 136 -quality 82 -define jpeg:fancy-upsampling=off -define png:compression-filter=5 -define png:compression-level=9 -define png:compression-strategy=1 -define png:exclude-chunk=all -interlace none -colorspace sRGB -strip INPUT_PATH

Squiggle using CSS

I am building the basic Set card patterns. I can do colours, numbers and fillings, and I have the diamond and oval shapes. Please see my progress in this fiddle.
The last piece of the puzzle is to build a squiggle class for the "squiggle" shape. How can I do the squiggle shape using CSS?
I'm pretty sure you'll have to resort to SVG for shapes like that.
SVG might also make your life easier for those other shapes too. On my Safari 6.0.2 I see a few small CSS rendering artifacts:
In particular, the spacing of the striped diamond due to how transform works (texture mapping) produces something that doesn't quite look completely uniform. You'll need to scale up this screenshot to see the artifacts at the corners of the diamond.
Basically, CSS is not meant for drawing shapes. SVG is meant for drawing shapes. Therefore since you are trying to draw shapes, there's a much higher chance you'll succeed with SVG.
Good job with the diamonds, though. (Note also SVG ought to work on platforms not supporting CSS3 3D; it is a neat trick to skew/scale square to make a diamond but at the end of the day its more or less a hack)

QPainter::rotate disables antialiasing of drawn text

I use QPainter::setRenderHint(QPainter::Antialiasing, true) to tell Qt that I want it to antialias any drawing I do (in this case, text drawn with drawText()).
This works fine and the text looks good, until I want to rotate the pixmap I'm drawing to e.g.
Painter.translate(0, height());
Painter.rotate(-90);
(to rotate the QPainter 90 degrees counterclockwise and bring it back into view)
The call to rotate() seems to disable antialiasing for any text drawn - the text is drawn at the correct rotation but without antialiasing. Other things seem unaffected - e.g. drawLine() still draws a nicely antialiased line.
Any idea what I'm doing wrong?
EDIT: Unsurprisingly, adding the text to a path and then filling that path gives me antialiased, rotatated text. I'd rather avoid this route if possible though.
EDIT (again): I've tried using QFont::setStyleStrategy(QFont::PreferAntialias) on the font I'm using, with no effect. However, some more experimentation shows that a basic font like Arial will still produce antialiased text when rotated, whereas my custom font (Swiss721 BlkCn BT for anyone who's interested) will not. Moreover, while this problem exists on Windows 7, I don't have the same issue when running on Ubuntu. This FAQ article would seem to suggest that Qt looks to the host OS to handle font antialiasing, so what kind of issues might Windows have in handling the rendering of this particular font (which is a TrueType, just like Arial)?
EDIT (last time, I promise): Upping the font size to 16pt or above kills the problem. It would seem that the issue is with rendering my particular font below 16pt - perhaps something to do with what was mentioned in the above blog article?:
On Windows 2000 fonts are usually not antialiased within a certain range (say sizes 8-16) to make text more crisp and readable.
I've actually had occasion to be in this part of the Qt code recently, and I think the behavior you are seeing is related to the following two bugs in Qt:
https://bugreports.qt.io/browse/QTBUG-21377
https://bugreports.qt.io/browse/QTBUG-20900
If I remember correctly (not 100%) sure, what you are actually seeing is the loss of the ClearType rendering on Windows. When there is a transformation applied, Qt gets the glyph pixels in a way that throws out the ClearType information, so things look more jagged.
If you wanted to look at the code yourself, the most likely place is /src/gui/text/qfontengine_win.cpp. You could also try turning off ClearType and see if they look similar.
One "guess" concerns your RenderHint. You use QPainter::Antialiasing here. Docu: "Indicates that the engine should antialias edges of primitives if possible." Primitives like lines, rects, etc. Try QPainter::TextAntialiasing instead.
Note: The RenderHints are flags, so you can bit-OR them if need be (and sounds like it is).

How to replicate PS multiply layer mode

Does anybody know of a good way to replicate Photoshop's multiply layer mode using either an image or CSS?
I'm working on a project that has thumbnails that get a color overlay when you hover over them, but the designer used a layer set to multiply and I can't figure out how to produce it on the web.
The best thing I've come up with is either using rgba or a transparent png, but even then it doesn't look right.
There are new CSS properties being introduced to do just this thing, they are blend-mode and background-blend-mode.
Currently, you won't be able to use them in any sort of production environment, as they are very very new, and currently only supported by Chrome Canary (experimental web browser) & Webkit Nightly.
These properties are set up to work nearly exactly the same as photoshop's blending modes, and allow for various different modes to be set as values for these properties such as overlay, screen, lighten, color-dodge, and of course multiply.. among others.
blend-mode would allow images (and possibly content? I haven't heard anything to suggest that at this point though.) layered on top of each other to have this blending effect applied.
background-blend-mode would be quite similar, but would be intended for background images (set using background or background-image) rather than actual image elements.
EDIT:
The next section is becoming a bit irrelevant as browser support is growing.. Check this chart to see which browsers have support for this: http://caniuse.com/#feat=css-backgroundblendmode
If you've got the latest version of Chrome installed on your computer, you can actually see these styles in use by enabling some flags in your browser (just throw these into your address bar:)
chrome://flags/#enable-experimental-web-platform-features
chrome://flags/#enable-css-shaders
* note that the flags required for this might change at any time
Enable those bad boys and then check out this fiddle: http://jsfiddle.net/cqzJ5/
(If the styles are properly enabled in your browser, the two images should be blended to make the scene look like it is underwater)
While this may not be the most legitimate answer at the current moment due to the almost entirely nonexistent support for this feature, we can hope that modern browsers will adopt these properties in the near future, giving us a really nice and easy solution to this problem.
Some extra reading resources on blending modes and the css properties:
http://blogs.adobe.com/webplatform/2013/06/24/css-background-blend-modes-are-now-available-in-chrome-canary-and-webkit-nightly/
http://demosthenes.info/blog/707/PhotoShop-In-The-Browser-Understanding-CSS-Blend-Modes
http://html.adobe.com/webplatform/graphics/blendmodes/
Simple with a bit of SVG:
<svg width="200" height="200" viewBox="10 10 280 280">
<filter id="multiply">
<feBlend mode="multiply"/>
</filter>
<image id="kitten" x="0" y="0" width="300" height="300" xlink:href="http://placekitten.com/300" />
</svg>
and some CSS:
#kitten:hover {
filter:url(#multiply);
}
The fiddle: http://jsfiddle.net/7uCQQ/381/
Just for the record, this guy is developing a library to do so. I just came into it while doing a research, haven't tried yet.
https://github.com/Phrogz/context-blender
It is possible with a 24.png - if you know the trick.
In illustrator you can export the graphic as a 24.png, but this never seems to work like multiply.
I've found away.
get your multiplied graphic on its own
place a solid black 100% box behind it, and select both graphics
in the transparency window select 'Make Mask' and then 'Invert Mask'
export as a 24.png file
works just like a multiply when z-index(ed) on top of a picture.
No such ability is available. The only compositing options you get that are even close are:
lighter compositing mode on an HTML5 <canvas> (which is a+b not a*b, and has about the opposite effect to multiply)
min or subtract Compositor filters in IE only.
Neither are really practical.
In general you should not attempt to export Photoshop comps as layers, but render them down to a single opaque image. For rollovers you can make two images (one for normal state, one for hovered) and swap between them using the CSS :hover style to choose a different background image, or—better, as it requires no preloading and reduces HTTP requests—combine both images into one and use background-image/background-position to display the right part of that image in each state as a background image. (“CSS sprites”)
I recently had the need to do exactly what the OP asked so I searched around. I found a great way to replicate the multiply effect by making a transparent PNG in Photoshop.
Create a new document with the same dimensions of your multiply
layer.
Fill the document with black.
Add a vector mask (the icon to the left of layer "fx" at the bottom of the layers window).
Alt/Option + click on the mask itself.
Now copy and paste your multiply layer into the mask.
Cmd/Ctrl + i to invert the layer you just pasted.
Create a new layer below this layer and add the image behind the multiply overlay.
Everything should look pretty close to your desired result. If needed, you can adjust the opacity of the masked layer we created.
When it looks good just toggle the bottom layer's visibility and save the masked layer as a PNG et voila!
All credit goes to Sojeong from https://superuser.com/questions/381704/multiply-blending-mode-to-png
Check this out:
http://www.webdesign.org/photoshop/photoshop-basics/remove-white-using-channels.10545.html
Using those instructions, I had great success watermarking a black-and-white image (ink drawing in my case, with blacks and greys on a solid white background) onto a dark background (wood in my case). There is hardly any difference with the real Multiply filter of Adobe.
I used the Photoshop instructions to remove the whites from my image, leaving only blacks and greys on a transparent background. Saving this to PNG and putting it on the wood in CSS/HTML still lookedmuch worse thanmultiply, but strongly reducing the brightness of the PNG solved it (the light greys stood out before, making it ugly).
In general I recommend you play around in photoshop, replicating the web situation: a semi-transparent (no special stuff) layer on top of a solid background. Tutorials such as the above may allow you to reproduce multiply or other fancy effects.
Not sure if you will have any luck. As far as I know, it isn't possible even if you tried to integrate some advanced JavaScript with it.

Resources