Okay, here is a (dirty) hack that gets the job done:
In xhtml.php, find this:
$ret .= '<img src="' . ml($src,array('w' => $width, 'h' => $height,'cache' => $cache,'rev' => $this->_getLastMediaRevisionAt($src))) . '"';
Replace with:
$ret .= '<img src="' . ml($src,array(null, null,'cache' => $cache,'rev' => $this->_getLastMediaRevisionAt($src))) . '"' . 'style=" display: block; width:auto; height:auto; max-width:'.$width.'px; max-height:'.$width.'px;"';
In template.php, find this:
$src = ml($IMG, array('cache'=> $INPUT->str('cache'),'rev'=>$REV, 'w'=> $w, 'h'=> $h), true, '&');
Replace with:
$src = ml($IMG, array('cache'=> $INPUT->str('cache'),'rev'=>$REV, null, null), true, '&');
For media manager:
In media.php, find this:
$more['w'] = $size[0];
$more['h'] = $size[1];
Replace with:
$more['w'] = null;
$more['h'] = null;
Find this:
$src = ml($item['id'],array('w'=>$w,'h'=>$h,'t'=>$item['mtime']));
Replace with:
$src = ml($item['id'],array(null,null,'t'=>$item['mtime']));
BTW, in original media manager when you hover on image it says "view original file", but clicking on it will take you to a modified small preview, not to "original file". This is an apparent error. The fix described above solves this and will show the original file, as intended.
I tested it on my local installation, and it seems to work fine (didn't test for compatibility issues with all possible extensions and setups, though). Now images remain perfectly clear and you can use the same syntax {{image.jpg?250}}
I would be thankful if somebody instructed me on how to turn this hack into a new extension so that other people can use it, too. This could be incorporated as an optional toggle, allowing to switch entire wiki from libGD resize to CSS resize, or provide alternative syntax (like using {{image.jpg!250}} for CSS resize and keep {{image.jpg?250}} for libGD resize, I think?