|
ForumsSega Master System / Mark III / Game GearSG-1000 / SC-3000 / SF-7000 / OMV |
Home - Forums - Games - Scans - Maps - Cheats - Credits Music - Videos - Development - Hacks - Translations - Homebrew |
Author | Message |
---|---|
|
[Front page] Random sprite ugly in Firefox 3
Posted: Wed Mar 26, 2008 8:15 pm
|
Firefox 3 includes smoothing for images that are being stretched. That helps a lot when you would rather see a smooth image than a pixellated one, but for our front page random sprite feature, it's very ugly:
I'm hoping there'll a way to turn it off in time for the official release. |
|
|
Posted: Wed Mar 26, 2008 8:26 pm |
If nothing else, fallback plan could be to pre-stretch some image hoping it would not make them much bigger. | |
|
Posted: Wed Mar 26, 2008 9:01 pm |
Actually Safari and Camino for Mac always had that problem.
Didn't bother me that much. |
|
|
Posted: Tue Jul 01, 2008 1:53 am |
I am running the firefox 3 release here, I cannot find an option to turn it off. | |
|
Posted: Tue Jul 01, 2008 9:33 am |
They didn't add an option for it. How a browser scales images is not fixed in the various HTML/CSS/etc specs, and for everything but pixel art, smoothing is better.
There's a Firefox request to make this optional here: https://bugzilla.mozilla.org/show_bug.cgi?id=423756 which you can vote on if you like; but so far nobody's on it. It's tricky because it would require a non-standard CSS style or HTML tag to select the option, and interaction with full-page zoom is hard. |
|
|
Idea
Posted: Wed Jul 02, 2008 12:44 am
|
Had a subtle idea guys:
What if we code a flash movie that is fed with an URL of the original figure and let it stretch it without modifications ? It´s risky, I don't know if this works, will try at home later, but if it does it's a nice shot! |
|
|
Posted: Wed Jul 02, 2008 5:47 am |
That'd work, but it would require flash. Could it do the pixel counting too? | |
|
Posted: Wed Jul 02, 2008 7:20 am |
Well it's pretty trivial to code that in flash, yes. The problem is really that it increase compatibility requirements. Maybe can fallback to a plugin? | |
|
Posted: Wed Jul 02, 2008 8:06 am |
What about adding a check, if it is found the user has the flash plugin then use it, else if the user does not have the flash plugin then default to the old code, is this possible?
It would be pretty rare to not have the flash plugin nowadays as you need it for Youtube, although there is a regular on the IRC channel who refuses to use it.. I don't know if he visits the forums though. |
|
|
Posted: Wed Jul 02, 2008 8:28 am |
A lot of people block Flash and also Javascript, which makes detection difficult. One option is to serve the image as it is now and then replace it with Flash dynamically if detected, somewhat like SIFR for text. It might also be worth trying for non-integer scaling in Flash, perhaps for magnifications above 4x to avoid blurriness on the larger images.
Since Bock is now a Flash expert (!) I'm sure we can come up with something. |
|
|
Posted: Wed Jul 02, 2008 3:32 pm |
Well, I did some research. Normal scaling in Flash is just like FF3 is handling this issue. So we have to fall back upon other strategy. ... Fortunately, there is a class called BitmapData in Flash 8 (I did all my work using Flash MX 2004, which DOES NOT have this class), which allows pixel zooming in a movieclip, which in turn can be defined as a picture, so we have what we want here.
I don't think we need the movie to do so, we can just let the current program calculate the dots and then feed this information, altogether with the image, to the flash movie.
o.O I was thinking of doing the flash part. Hey, Bock, stealing my position huh. =D |
|
|
Posted: Wed Jul 02, 2008 3:37 pm |
Hell no, I'm too busy to do anything, you're welcome to do the flash part :) I only did a few weeks of flash and barely understood it. |
|
|
Humble administrator
Posted: Wed Jul 02, 2008 4:09 pm
|
Well, I´m pretty sure the physics involved in Soul Bubbles are not easily found on the Internet or even in books examples, so I appreciate your humility! (Now you have to prove yourself on the other 7 virtues hehe...) Seriously, I will definitely work on this only by the weekend cause I have 2 more tests in college, one is tomorrow. |
|
|
Re: Humble administrator
Posted: Wed Jul 02, 2008 6:10 pm
|
Of course they are! The basics of verlet integration and constraints are trivial to implement, see http://www.gamasutra.com/resource_guide/20030121/jacobson_01.shtml Seriously, converting C++ to ActionScript code doing math processing is trivial, understanding underlying Flash structure and features is another thing. |
|
|
Posted: Wed Jul 02, 2008 8:44 pm |
A lighter alternative to Flash is to use the canvas element. Here's a bit of JavaScript code that searches for an element with an id of randomSprite; if it finds it it replaces it with a canvas element, loads the image and paints it as a series of filled rectangles. It should degrade gracefully if the canvas is not supported. (Tested in IE7 [ignored], Firefox 3, Opera 9.5).
if (window.addEventListener) {
window.addEventListener('DOMContentLoaded', function() { // Grab the old image. var spriteImg = document.getElementById('randomSprite'); if (!spriteImg) return; // Create a canvas to replace it. var spriteCanvas = document.createElement('canvas'); if (!spriteCanvas) return; spriteCanvas.width = spriteImg.width; spriteCanvas.height = spriteImg.height; // Get 2D drawing context. var context = spriteCanvas.getContext("2d"); if (context) { // We have a 2D drawing context, so replace the old image with the new canvas. spriteImg.parentNode.replaceChild(spriteCanvas, spriteImg); var sourceImg = new Image(); sourceImg.onload = function() { // Get the source pixel data. context.drawImage(sourceImg, 0, 0); var spritePixels = context.getImageData(0, 0, sourceImg.width, sourceImg.height); context.clearRect(0, 0, sourceImg.width, sourceImg.height); // Paint the destination image pixel by pixel: var xScale = spriteCanvas.width / spritePixels.width; var yScale = spriteCanvas.height / spritePixels.height; for (var p = 0, y = 0; y < sourceImg.height; ++y) { for (var x = 0; x < sourceImg.width; ++x, p += 4) { if (spritePixels.data[p + 3] >= 0.5) { context.fillStyle = 'rgb(' + spritePixels.data[p + 0] + ',' + spritePixels.data[p + 1] + ',' + spritePixels.data[p + 2] + ')'; context.fillRect(x * xScale, y * yScale, xScale, yScale); } } } } sourceImg.src = spriteImg.src; } }, false); } All you should need to do is add id="randomSprite" to the sprite on the homepage and a reference to the script above. Hope this helps! (Sorry if the code's a bit messy, especially that string concatenation bit for setting the fill colour, but I couldn't find much documentation for the canvas). |
|
|
Posted: Thu Jul 03, 2008 9:25 am |
I added it; it seems to work well. Rather annoyingly, it fails with a DOM security error when you try to use it from a local file, though. I'm sure there will still be gaps in the browser support but Firefox 3 is a nice one to have covered.
Edit: It seems to not handle 1:1 scaled images very well: ...but I don't have time to debug it right now. Edit the second: that image had bad size metadata giving it anamorphic non-integer scaling. I fixed it. |
|
|
Posted: Thu Jul 03, 2008 10:36 am |
The DOM security error doesn't affect Opera 9.5, if you'd like to test locally (however, Opera doesn't apply smooth filtering to the first frame of palettised images so a "fix" isn't required). Whoops, I didn't bother checking that. Here you go: if (window.addEventListener) {
window.addEventListener('DOMContentLoaded', function() { // Grab the old image. var spriteImg = document.getElementById('randomSprite'); if (!spriteImg) return; // Create a canvas to replace it. var spriteCanvas = document.createElement('canvas'); if (!spriteCanvas) return; spriteCanvas.width = spriteImg.width; spriteCanvas.height = spriteImg.height; // Get 2D drawing context. var context = spriteCanvas.getContext("2d"); if (context) { // We have a 2D drawing context, so replace the old image with the new canvas. spriteImg.parentNode.replaceChild(spriteCanvas, spriteImg); var sourceImg = new Image(); sourceImg.onload = function() { // Get the source pixel data. context.drawImage(sourceImg, 0, 0); var spritePixels = context.getImageData(0, 0, sourceImg.width, sourceImg.height); context.clearRect(0, 0, sourceImg.width, sourceImg.height); // Paint the destination image pixel by pixel: var xScale = spriteCanvas.width / spritePixels.width; var yScale = spriteCanvas.height / spritePixels.height; for (var p = 0, y = 0; y < sourceImg.height; ++y) { for (var x = 0; x < sourceImg.width; ++x, p += 4) { if (spritePixels.data[p + 3] >= 0.5) { context.fillStyle = 'rgb(' + spritePixels.data[p + 0] + ',' + spritePixels.data[p + 1] + ',' + spritePixels.data[p + 2] + ')'; var xDest = [Math.round((x + 0) * xScale), Math.round((x + 1) * xScale)]; var yDest = [Math.round((y + 0) * yScale), Math.round((y + 1) * yScale)]; context.fillRect(xDest[0], yDest[0], xDest[1] - xDest[0], yDest[1] - yDest[0]); } } } } sourceImg.src = spriteImg.src; } }, false); } |
|
|
Posted: Thu Jul 03, 2008 4:01 pm |
It could just be me, but in IE7 the sprite seems slightly more blocky than usual :| | |
|
Posted: Thu Jul 03, 2008 4:31 pm |
Can you post a screenshot? (I have no IE7 *cough*) | |
|
Posted: Thu Jul 03, 2008 6:44 pm |
I noticed that some sprites are more blocky than others.... Kung fu kid is fine for me but, the "eyed hollow shell" from Psycho Fox is extremely large. Also, in FF3, it always loads and displays the blurred image before applying the block transformation. Other than that, it was a fast solution! |
|
|
Posted: Thu Jul 03, 2008 7:20 pm |
Smaller sprites are scaled up by more to fit in the box. It's always been like that.
The flicker as it goes from blurry to pixelly is annoying but better then no pixels at all. It has to wait for the image to load so it can read back the pixels; also, the image is the fallback so it has to be there. |
|
|
Posted: Thu Jul 03, 2008 8:28 pm |
In theory it shouldn't, really; DOMContentLoaded should fire after the DOM has been loaded and is accessible, but before images have been downloaded (the body "onload" event is fired after all images have been downloaded). The old image is swapped out and replaced by the empty canvas before the image is downloaded for reading its pixels, but I suspect that as the homepage is quite large and the sprite image is so small Firefox will have downloaded the original image before the rest of the page is ready in some circumstances, causing the noticable flicker. |
|
|
Posted: Fri Jul 04, 2008 2:50 am |
It was hard to tell without having javascript off, but since experimenting it seems there is no difference at all. |
|
|
Posted: Fri Jul 04, 2008 10:08 am |
IE7 doesn't support <canvas>, so you'll be seeing the same image that you always have. |
|
|
Posted: Fri Aug 01, 2008 8:39 am |
I dunno if this problem was fixed but in Firefox 3.0.1 it looks ugly again. | |
|
Posted: Fri Aug 01, 2008 9:10 am |
It was my fault, I didn't commit my changes to our secret repository and as a result, Bock's recent update of the links section overwrote the fix.
Note to self: remember to check it in. |
|
|
Posted: Wed Sep 03, 2008 2:55 am |
I'm trying out Chrome (new browser from Google) and it behaves differently again. The sprite stays its natural size (small) and anchors to the top left of the canvas. | |
|
Posted: Wed Sep 03, 2008 6:48 am |
Chrome is based on WebKit and thus ought to render the same as Safari. I'll look into it later.
Edit: WebKit doesn't* support getImageData on a canvas, which is pretty much the basis for the fix so we'll just have to leave it as it is there. I've made some changes to the script so it ought to fail more gracefully. Unfortunately Chrome is sufficiently buggy that I can't test it on this computer. |
|
|
Posted: Fri Oct 03, 2008 12:11 am |
Latest Firefox 3.0.3 - looks good! | |
|
Posted: Mon Dec 15, 2008 8:59 am |
Broken again in IE8 Beta lol... which now suffers the same blurry picture syndrom. | |
|
Posted: Mon Dec 15, 2008 3:38 pm |
IE 8 doesn't support the canvas, so we're stuck there sadly. I wish there was a way to opt-out of this filtering, as IE 8's GIF renderer makes an absolute mess of scaled-up animations. | |