Nearest Neighbor rendering in Canvas - javascript

I have a sprite that animates using a sprite sheet. He is only 16x16, but I want to scale him up to around 64x64 in all its pixel-y goodness!
The results are terrible, of course the browser is anti aliasing it. :/
Thanks!
EDIT:
No css needed, here is my draw function.
function drawSprite(offsetx:number,offsety:number,posx:number,posy:number){
ctx.drawImage(img, offsetx*32, offsety*32, 32, 16, posx*32, posy*8, 128, 32);
}
See it kinda working here (codepen)

In case someone ever stumbles upon this again (like me), Webkit supports a -webkit-optimize-contrast value for image-rendering, which (currently) is an implementation of the nearest neighbor upscaling. It can be applied to both images and canvases.
Here's an example of how it goes.
.nn128 {
width: 128px;
height: 128px;
image-rendering: -moz-crisp-edges;
image-rendering: -webkit-optimize-contrast;
}
<canvas class="nn128" width="16" height="16"></canvas>
<img src="path/to/small/image.png" alt="Small image" class="nn128">
With this setup, both WebkitSafari and Gecko/Firefox will enlarge the 16x16 canvas space and the small image to 128x128 with the nearest neighbor algorithm.
UPDATE The answer initially stated that Webkit browsers supported this; in fact, as of 2011-12-24, it works with Safari on Mac OS and Chrome on Mac OS, but not with Chrome one Windows (Safari on Windows was not verified), as stated on Issue 106662 of the Chromium bug tracker. Lexically, Chrome on Windows will accept the -webkit-optimize-contrast value in a CSS style sheet, but it won't have any effect. It is my expectation that it will work someday, and this method will be the right way to get nearest neighbor upscaling, but for now, using this method means Windows Chrome users will have to live with the blurriness.

In Firefox you can use this:
canvas {
image-rendering: -moz-crisp-edges;
}
But as far as I know for every other browser you are pretty much out of luck. One way around this perhaps is to scale up your sprite to 64x64 in Photoshop (or whatever), then use it scaled down in canvas. This way at least the image will not get blurry when "scaled up". It still won't exactly give you the pure mode7 like goodness of nearest neighbor though.
You could write your own scaling code using the imageData object. You will be incurring a significant performance penalty in doing so, but for a 16x16 image, it might not be that significant.

Related

How to prevent blur on image resize in Chrome?

The images are really blurry if you use resize an image, for example showing a small image with resized dimensions, like;
<img src="largeimage.jpg" width=30 height=30 \>
Its not blurry in other browsers, but in Chrome, its so blurry.
I have looked at in www.twitter.com , their new design has lots of resized images and somehow, they have managed to clear blur in resized images. I have tried these;
image-rendering: crisp-edges;
image-rendering: pixelated;
But unfortunately, it doesn't solve the problem.
Below is a comparison. On the left, you can see that it is quite blurry, compared to that on the right:
What is the correct way to do that ?
Have you tried this? :)
filter: blur(0);
-webkit-filter: blur(0);
transform: translateZ(0);
-webkit-transform: translateZ(0);
I've noticed that Chrome does a better job when you resize an image at a certain percentage. For example, if you resize a 375px image to 100, it gets blurry, but if you resize 200 to 100, it does a better job because it's a nice even 50% scale.
Without an editable test environment, I'm not sure if that would fix it for you, but it's worth a shot.
I understand that this is an old post and things might have changed since then; thus, I am posting this for future readers who might come accross this question.
You could set image-rendering to pixelated, in order to preserve the original pixelated form. The below should work as expected on Chrome (and Opera) browser as well.
img {
image-rendering: pixelated;
}
As per the documentation:
pixelated
Using the nearest-neighbor algorithm, the image is scaled up to the next integer multiple that is greater than or equal to its original size, then scaled down to the target size, as for smooth. When scaling up to integer multiples of the original size, this will have the same effect as crisp-edges.
I've just had this issue in a WordPress gallery with six images using WEBP files. One image was sharp the others slightly blurry in Chrome etc. but ok in Firefox. I cropped the five to the exact size of the sharp image which was 1200 x 650px and replaced the 'blurry' ones in the gallery with the newly cropped versions. They are all displaying ok now.
Some crops just shaved as little as 4 pixels from the depth.

Jquery responsive image resizing method that maintains the quality

I have a background image which is responsive. It adapts to the container with the background-size: 100% method which keeps the aspect ratio. However, for older browsers like Firefox 18 and below and all versions of internet explorer I get a bad image when scaled (jagged or blurry). I tried the css bicubic interpolation (internet explorer) and "image-rendering" (firefox) fix yet no effect what can be observed.
My question is: is there a jquery or javascript way that does the same job while preserving the quality? Like a browser independent scaling method. Googled but found nothing.
I know this is not ideal in terms of speed and I should instead do the resizing in my image editing software but this is not an option in my scenario.
Would be happy to hear about your answers,
Sincerely,
Michael
The only good solution I found to provide the best possible quality is by using a css responsive method.
For latest chrome & safari you have the new HTML attribute SRCSET.
For olders browsers, you can use your images as a div background and change it dynamically with CSS only.
For very old browsers, the only way is to grab images with different sizes using JS...

Zooming SVG is blury or pixelated, not sharp

vI know to some extent this is a known issue that has been asked here but never answered, but I'm hoping for some additional insight.
I have a simple SVG image in a div on a web page. I want to be able to zoom the image using pinch gestures and have the SVG render sharply. It doesn't need to be sharp during the zoom, but should be sharp after the gesture is complete.
I'm doing my testing on a Windows 8.1 computer with a touch monitor, on an iPad, and on an old Android Galaxy Tab. On the main computer, I'm using IE11 and Chrome. For handling touch gestures, I'm using Hammer.js. I'm doing the zooming by modifying the transform CSS using the jQuery css() function (I'm setting scale3d and translate3d).
IE11 on my computer works exactly like I would like it to. It keeps the SVG image sharp throughout the pinch zoom and the image is always sharp regardless of when I set the CSS.
Chrome on my computer always renders the SVG blocky when I am zoomed in using pinch zoom. It is blocky during the zoom and does not get sharp afterwards. If I add a call to zoom the image after the page (x13) is loaded, the image is sharp. If I use a setTimeout() call to reset the zoom and then rezoom the image after the pinch zoom ends, the image is sharp.
On the iPad and Android tablet, the SVG never renders sharply, regardless of when I zoom it in code.
Does anyone have any ideas of how to reliably end up with a sharp rendering of SVG after a pinch-zoom is completed? Does anyone have a better solution? Using the SVG viewBox to zoom and pan during the gesture does not provide good enough performance for our more complex SVG images. I'm thinking of attempting to use the hardware accelerated scale3d/translate3d during the gesture and then attempt to convert this to new SVG viewBox settings afterwards, but this is a challenge and I'm not sure panning will work correctly after this is done. Any pointers or ideas are greatly appreciated.
Having just tried to answer your other SVG Question I will have a try at this one.
Michael Mullany is spot on that GPU translations will never give you a sharp image. This is because the GPU just maps one array of pixels to a new one. Because it has no concept of lines or rectangles the resolution is set by the time the GPU gets the image. The CPU will always struggle to re-render in time for a smooth drag.
What happens to allow some browsers to produce a sharp image is they do clever manipulations like rendering more pixels than they need so some zooming can happen without loss of resolution. These however are completely inconsistent and just not possible to rely on.
The as I see it 'correct' solution is to translate and zoom with hardware accelerated transformations during a pinch or zoom and then to refresh the viewbox with no css transformation when the translation has finished.
Challenges to overcome are
The css transformation will use screen coordinates but the viewBox manipulation will use the SVG coordinate system.
There are browser inconsistencies in both screenCTM and device pixel ratio
limits so that people don't drag or zoom too far need to be calculated in both systems
Pinch centerpoints also need to be calculated in both
To improve performance further the css transforms will be wrapped into updating on the requestAnimationFrame loop.
My working solution is hammerhead2. I am concentrating on desktops and android mobiles first and it seams to be working for them. To simplify the problem zoom is always centered to the screen center. I do however thing this is currently one of the only solutions. Here is an example of it working.

Browser Image Rendering

I am dynamically sizing a transparent .gif on my web page using JavaScript. The original image size is around 200x200 pixels and it’s typically resized to between 600x600 and 800x800. In IE8 and FF3, the resized image results in a nice looking gradient where the colors appear to be stretched. However, in older browsers such as IE7 and FF2, the resized image does not show a gradient, but just blocks of the same color. Obviously, there is something built into the browsers that causes this however I am curious if there is a way around this without having to change my original image.
There isn't. Older browsers just take the pixels in the image, and multiply them according to the new size you gave the image.
Newer browsers seem to have more advanced image rendering with anti-aliasing and such, but older browsers just aren't capable of that. If you want the image to look good in all sizes, take the biggest you can and then let it shrink if needed. Upsizing a small image will look ugly, expecially in the old browsers, and there's nothing you can do.
If you are just using it as a gradient, why not just whip up a new one in Photoshop/Gimp that's at the correct resolution for what you need. It will be far simpler in the long run then trying to get an up-scaled image to display properly in all browsers.
It looks like IE7 supports bicubic if you add "-ms-interpolation-mode:bicubic;" to your img css style. I haven't tried it myself, and wonder if it'd work on gifs or if it'd only work on true color images.

Web: solution for image rotate and zoom

I have a web page which displays a large image, for example a page from a magazine. I have no control over the image size or orientation. It's possible that the image may need to be rotated by the user to orient it correctly.
Are there any Javascript or Flash solutions that will allow someone to rotate and zoom a given image? Ideally I'd specify a single image and the dimensions to use when displaying it. If the image is larger than those dimensions, the user could zoom in and view a portion of the image in greater detail.
I've seen a couple of solutions for rotating images with straight Javascript and CSS. Raphael would do the trick. There is apparently even an example featuring rotating an image. (it uses SVG but is support on all major browsers)
This one is not cross browser, but is an interesting exercise nevertheless.
As for flash rotation etc...
For rotating images, I used jquery-rotate and it works very well.
It is not totally cross-browser, it doesn't work with IE6 (and probably other old browsers).
For zooming, I guess you could make your own implementation using javascript, you can just resize the image (easy with jQuery).

Categories

Resources