The specs say:
When scaling up, if the imageSmoothingEnabled attribute is set to false, then the image must be rendered using nearest-neighbor interpolation.
So when imageSmoothingEnabled
is false and the process is scaling up, it uses nearest-neighbor which is what I want. But I also want to use nearest-neighbor for scaling down (and if it’s considered another thing, when the scaling is same), basically all the time.
The specs also say these:
When scaling up, if the imageSmoothingEnabled attribute is set to true, the user agent should attempt to apply a smoothing algorithm to the image data when it is scaled. User agents which support multiple filtering algorithms may use the value of the imageSmoothingQuality attribute to guide the choice of filtering algorithm when the imageSmoothingEnabled attribute is set to true. Otherwise, the image must be rendered using nearest-neighbor interpolation.
This specification does not define the precise algorithm to use when scaling an image down, or when scaling an image up when the imageSmoothingEnabled attribute is set to true.
As far as I understand when imageSmoothingEnabled
is false and if it’s not scaling up, it is not guaranteed to use nearest-neighbor.
I don’t know any way to test it properly and definitively. Chrome (Chromium) and Firefox are open source. I checked their repos but couldn’t find anything useful. All I could find was test code.
Is there a way to be sure that the drawImage
uses nearest-neighbor? If so, how?
I don’t think so but if it matters I use 9 parameter version and do all scaling up/down/same from time to time. Also it’s a browser extension project. So no frameworks and OffscreenCanvas.
I’ve seen this question but it’s pretty old and the answer didn’t satisfy me. An example code to run or a link to source code is preferred.
Thanks in advance.
I tried searching the repo’s but couldn’t find the related functions. I couldn’t think any other way.
2
Answers
I found a few files in the Firefox source code that you might want to look at. I also attached the link to the search area I used, so you can search more in depth if you want. I couldn’t find anything on the Google’s implementation of drawImage() so you might need to search that yourself. Also, if you didn’t know
context
is an instance ofCanvasRenderingContext2D
The actual function definition
The definition file (.h)
My search in the Firefox code
Here is the only use of imageSmoothingEnabled in the
drawImage
function by the way on Line 5753 on the first link I attached. I’m sure you can look deeper into that if you would likeMDN says;
So setting
imageSmoothingEnabled
false andimageSmoothingQuality
"low" wouldn’t matter. Also it wouldn’t be feasible for you because Firefox doesn’t supportimageSmoothingQuality
.There’s a test in here. The image is still alive at the moment. With the help of MS Paint, I changed it a bit and got a mess. The code doesn’t explain itself because it’s a mess. I’m not gonna spend more time to make it better. I’m just gonna try to explain it.
In the left canvas top left one is the original one. it’s a 64×64 pixel image. The star is 60×60. The stroke/edge is 1 pixel. The other ones are its upscaled versions with 9 parameter
drawImage
withimageSmoothingEnabled
set to false.In the right one the big one is the original one. It’s 576×576 pixel image (64 * 9). The star is 574×574. The stroke/edge is 1 pixel. The other ones are its downscaled versions with 9 parameter
drawImage
withimageSmoothingEnabled
set to false and true. True ones are on the left. It’s not symmetrical you should be able to figure that out from the size difference.My Chrome doesn’t render it the way I expected. You can save the images with right click & save image and see it in MS Paint. Firefox has the same rendering behavior. Somehow when I do right click & save image, nothing happens. I opened it in a new tab and saved it.
In the end, I believe the messy code answers some questions.
As the code says, Firefox doesn’t use nearest-neighbor when its downscaling. But Chrome does. We’ve seen it. And the code is in here. It’s technically
imageSmoothingQuality
function, when you changeimageSmoothingEnabled
it calls it.