HTML5 scale bitmap smoothing antialiasing

Hej all,
I’ve a problem. I’ve searched everywhere, tried all the tips and still can’t get my resized image look pretty.
The original image is about 300x300 and I scale it to fit 50x50. I know it’s a big scale but when I scale my picture using CSS (outside openfl, in normal HTMLDom), it gives me a pretty picture like you can see on the screenshot below so it can be possible :
openfl

I’ve tried to do without OpenFL just raw canvas like below, and it gives me a good result (not as good as using simple CSS but better than everything I’ve tested using OpenFL). How can I achieve it using OpenFL please ?

<!DOCTYPE HTML>
<html>
  <head>
    <style>
      body {
        margin: 0px;
        padding: 0px;
      }
    </style>
  </head>
  <body>
    <canvas id="myCanvas" width="578" height="200"></canvas>
    <script>
      var canvas = document.getElementById('myCanvas');
      var context = canvas.getContext('2d');
      var width = 50;
      var height = 50;
      var imageObj = new Image();

      imageObj.onload = function() {
        context.drawImage(imageObj, 0, 0, width, height);
      };
      imageObj.src = '../media/avatars/natacha.jpg';
    </script>
  </body>
</html>

Sans-titre-13

Can you paste here your OpenFL code?

To have antialiasing enabled for HTML5 target try using <window antialiasing="4" if="html5" />

Thanks for your answer.
In fact, I’ve tried many solutions I’ve found googling. antialiasing=“4”, resizable=“true/false”, -Dcanvas, -Dwebgl, -Dcairo (?) even -Ddom
The code is quite simple, I’ve tried bmp.width = 50, bmp.height = 50, bmp.smoothing=true. I’ve also tried using draw() method using a matrix even drawWithQuality()…

Did you set bitmapData after or before setting smoothing? Because I think setting bitmapData resets smoothing to false.

I’m on the same boat about unable to enable antialiasing when using the draw methods.

Yes I forgot to mention that I do bmp.smoothing = true at the end. I know it’s a weired bug happening even on flash plateform for years.

Could you share a little bit of test code, so we could test it to? Maybe link an image like the one you’re working with? How does it look in OpenFL -Ddom?

Hej Joshua,
Thanks for your answer.
The original picture is this one :
natacha
I know, it’s strange picture and the scale is huge but once again, in CSS it scales nice as you can see upper.
Using -Ddom it gives quite the same ugly result and my whole project doesn’t run as expected too (I think I’ll create another topic for this problem later…)
The code is quite simple : I’ve tried simply setting bmp.width and bmp.height and at the end bmp.smoothing=true; And I’ve also tried scaling using a matrix and bmp.drawWithQuality()

I am currently facing the same issue in our project (also user avatars). Subscribing here :slight_smile:

OpenFL -Ddom

image

OpenFL -Dcanvas

image

OpenFL WebGL

image

Flash

image
image

I’m seeing pretty similar results across the board, though I do have to use <window allow-high-dpi="true" /> on canvas (and bump up the image size) in order to get a similar result as using DOM in OpenFL.

I can see how pure DOM does look better

image

It must be a smarter resize mechanism, or perhaps mipmapping on the GPU. We use bicubic sampling when resizing in native code, but in HTML5 canvas and WebGL, we’re really at the mercy of what the browser is using, even in DOM mode. We use 3D transformations for performance, which the browser must resize differently than a standard CSS style resize.

I think that the pattern of her hair makes this image a particularly bad case for the standard resizing algorithm. Is there a way you can process images in advance on a server, and provide thumbnail size images that have already gone through a more advanced downsample filter, or do it in advance with Photoshop?

1 Like

Thanks Joshua for your answer.
The pictures are dynamic (everybody can upload his avatar) so yes, I proceed with a server resize using ImageMagick. But It would be very nice if we find a solution in the futur and could do it without server and get the same result as pure DOM.

Perhaps a better resize algorithm could be implemented in code, something to go from a large BitmapData to a small one, using a new algorithm?

Hi,
I just found this topic by searching for another :yum:
I already had this issue 3 years ago, on a software that renders some kind of slideshow, and the pictures were uploaded at a super size, 8000x6000, and rendered then on a 1024x768 monitor.
I’ve used an iterative scale on bitmap, up or down, till I reached the desired resolution; for me, this works well at the value 1.75 for the multiplier.
I’ve attached down the code for you. Hope it helps you.
You should try with any value greater than 1 for multiplier.

private static var matrix:Matrix = new Matrix();
public static function scaleBitmapDataBilinearIterative(source:BitmapData, width:Int, height:Int, iterationMultiplier:Float=1.75):BitmapData
{
	var w:Int = source.width;
	var h:Int = source.height;
	var result:BitmapData = null;
	
	while (result == null || w != width || h != height) {
		w = source.width  > width  ? Std.int(Math.max(w / iterationMultiplier, width))  : Std.int(Math.min(w * iterationMultiplier, width));
		h = source.height > height ? Std.int(Math.max(h / iterationMultiplier, height)) : Std.int(Math.min(h * iterationMultiplier, height));
		
		var newResult:BitmapData = scaleBitmapDataBilinear(result != null ? result : source, w, h);
		if (result != null) {
			result.dispose();
		}
		result = newResult;
	}
	
	return result;
}
private static function scaleBitmapDataBilinear(source:BitmapData, width:Int, height:Int):BitmapData
{
	var result:BitmapData = new BitmapData(width, height);
	
	matrix.identity();
	matrix.scale(width / source.width, height / source.height);
	
	result.draw(source, matrix, null, null, null, true);
	
	return result;
}
1 Like

This seems to be a client-side analogue of ImageMagick?

Lime Image also is a resize, if someone wanted to test that, or test a different resize algorithm than the nearest method we use

Tested it, no difference (Lime must be using the browser’s capacities too).