[html] Image scaling causes poor quality in firefox/internet explorer but not chrome

See http://jsfiddle.net/aJ333/1/ in Chrome and then in either Firefox or Internet Explorer. The image is originally 120px, and I'm scaling down to 28px, but it looks bad pretty much no matter what you scale it down to.

The image is a PNG and it has an alpha channel (transparency).

Here's the relevant code:

HTML:

<a href="http://tinypic.com?ref=2z5jbtg" target="_blank">
    <img src="http://i44.tinypic.com/2z5jbtg.png" border="0" alt="Image and video hosting by TinyPic">
</a>?

CSS:

a {
    width: 28px;
    height: 28px;
    display: block;
}

img {
    max-width: 100%;
    max-height: 100%;
    image-rendering: -moz-crisp-edges;
    -ms-interpolation-mode: bicubic;
}

The image-rendering and -ms-interpolation-mode lines of CSS didn't seem to do anything, but I found them online while doing some research on the problem.

This question is related to html css image cross-browser scaling

The answer is


It seems that you are right. No option scales the image better:
http://www.maxrev.de/html/image-scaling.html

I've tested FF14, IE9, OP12 and GC21. Only GC has a better scaling that can be deactivated through image-rendering: -webkit-optimize-contrast. All other browsers have no/poor scaling.

Screenshot of the different output: http://www.maxrev.de/files/2012/08/screenshot_interpolation_jquery_animate.png

Update 2017

Meanwhile some more browsers support smooth scaling:

  • ME38 (Microsoft Edge) has good scaling. It can't be disabled and it works for JPEG and PNG, but not for GIF.

  • FF51 (Regarding @karthik 's comment since FF21) has good scaling that can be disabled through the following settings:

    image-rendering: optimizeQuality
    image-rendering: optimizeSpeed
    image-rendering: -moz-crisp-edges
    

    Note: Regarding MDN the optimizeQuality setting is a synonym for auto (but auto does not disable smooth scaling):

    The values optimizeQuality and optimizeSpeed present in early draft (and coming from its SVG counterpart) are defined as synonyms for the auto value.

  • OP43 behaves like GC (not suprising as it is based on Chromium since 2013) and its still this option that disables smooth scaling:

    image-rendering: -webkit-optimize-contrast
    

No support in IE9-IE11. The -ms-interpolation-mode setting worked only in IE6-IE8, but was removed in IE9.

P.S. Smooth scaling is done by default. This means no image-rendering option is needed!


Your problem is that you are relying on the browser to resize your images. Browsers have notoriously poor image scaling algorithms, which will cause the ugly pixelization.

You should resize your images in a graphics program first before you use them on the webpage.

Also, you have a spelling mistake: it should say moz-crisp-edges; however, that won't help you in your case (because that resizing algorithm won't give you a high quality resize: https://developer.mozilla.org/En/CSS/Image-rendering)


Late answer but this works:

/* applies to GIF and PNG images; avoids blurry edges */
img[src$=".gif"], img[src$=".png"] {
    image-rendering: -moz-crisp-edges;         /* Firefox */
    image-rendering:   -o-crisp-edges;         /* Opera */
    image-rendering: -webkit-optimize-contrast;/* Webkit (non-standard naming) */
    image-rendering: crisp-edges;
    -ms-interpolation-mode: nearest-neighbor;  /* IE (non-standard property) */
}

https://developer.mozilla.org/en/docs/Web/CSS/image-rendering

Here is another link as well which talks about browser support:

https://css-tricks.com/almanac/properties/i/image-rendering/


You should try to maintain a proper aspect ratio between the sizes you're scaling from and to. For example, if your target size is 28px, then your source size should be a power of that, such as 56 (28 x 2) or 112 (28 x 4). This ensures you can scale by 50% or 25% rather than the 0.233333% you're currently using.


IE Scaling Depends on Amount of Downsize

Some people said that an even fraction downsize avoids the problem. I disagree.

In IE11 I find that reducing an image by 50% (e.g. 300px to 150px) yields a jagged resize (like it's using nearest-neighbor). A resize to ~99% or 73% (e.g. 300px to 276px) yields a smoother image: bilinear or bicubic etc.

In response I've been using images that are just retina-ish: maybe 25% bigger than would be used on a traditional 1:1 pixel mapping screen, so that IE only resizes a bit and doesn't trigger the ugliness.


Seems Chrome downscaling is best but the real question is why use such a massive image on the web if you use show is so massively scaled down? Downloadtimes as seen on the test page above are terrible. Especially for responsive websites a certain amount of scaling makes sense, actually more a scale up than scale down though. But never in such a (sorry pun) scale.

Seems this is more a theoretical problem which Chrome seems to deal with nicely but actually should not happen and actually should not be used in practice IMHO.


This is possible! At least now that css transforms have good support:

You need to use a CSS transform to scale the image - the trick is not just to use a scale(), but also to apply a very small rotation. This triggers IE to use a smoother interpolation of the image:

img {
    /* double desired size */
    width: 56px; 
    height: 56px;

    /* margins to reduce layout size to match the transformed size */ 
    margin: -14px -14px -14px -14px; 

    /* transform to scale with smooth interpolation: */
    transform: scale(0.5) rotate(0.1deg);
}

Remember that sizes on the web are increasing dramatically. 3 years ago, I did an overhaul to bring our 500 px wide site layout to 1000. Now, where many sites are doing the jump to 1200, we jumped past that and went to a 2560 max optimized for 1600 wide (or 80% depending on the content level) main content area with responsiveness to allow the exact same ratios and look and feel on a laptop (1366x768) and on mobile (1280x720 or smaller).

Dynamic resizing is an integral part of this and will only become more-so as responsiveness becomes more and more important in 2013.

My smartphone has no trouble dealing with the content with 25 items on a page being resized - neither the computation for resizing nor the bandwidth. 3 seconds loads the page from fresh. Looks great on our 6 year old presentation laptop (1366x768) and on the projector (800x600).

Only on Mozilla Firefox does it look genuinely atrocious. It even looks just fine on IE8 (never used/updated since I installed it 2.5 years ago).


I've seen the same thing in firefox, css transform scaled transparent png's looking very rough.

I noticed that when they previously had a background color set the quality was much better, so I tried setting an RGBA background with as low an opacity value as possible.

background:rgba(255,255,255,0.001);

This worked for me, give it a try.


One way to "normalize" the appearance in the different browsers is using your "server-side" to resize the image. An example using a C# controller:

public ActionResult ResizeImage(string imageUrl, int width)
{
    WebImage wImage = new WebImage(imageUrl);
    wImage = WebImageExtension.Resize(wImage, width);
    return File(wImage.GetBytes(), "image/png");
}

where WebImage is a class in System.Web.Helpers.

WebImageExtension is defined below:

using System.IO;
using System.Web.Helpers;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.Collections.Generic;

public static class WebImageExtension
{
    private static readonly IDictionary<string, ImageFormat> TransparencyFormats =
        new Dictionary<string, ImageFormat>(StringComparer.OrdinalIgnoreCase) { { "png", ImageFormat.Png }, { "gif", ImageFormat.Gif } };

    public static WebImage Resize(this WebImage image, int width)
    {
        double aspectRatio = (double)image.Width / image.Height;
        var height = Convert.ToInt32(width / aspectRatio);

        ImageFormat format;

        if (!TransparencyFormats.TryGetValue(image.ImageFormat.ToLower(), out format))
        {
            return image.Resize(width, height);
        }

        using (Image resizedImage = new Bitmap(width, height))
        {
            using (var source = new Bitmap(new MemoryStream(image.GetBytes())))
            {
                using (Graphics g = Graphics.FromImage(resizedImage))
                {
                    g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
                    g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                    g.DrawImage(source, 0, 0, width, height);
                }
            }

            using (var ms = new MemoryStream())
            {
                resizedImage.Save(ms, format);
                return new WebImage(ms.ToArray());
            }
        }
    }
}

note the option InterpolationMode.HighQualityBicubic. This is the method used by Chrome.

Now you need publish in a web page. Lets going use razor:

<img src="@Url.Action("ResizeImage", "Controller", new { urlImage = "<url_image>", width = 35 })" />

And this worked very fine to me!

Ideally will be better to save the image beforehand in diferent widths, using this resize algorithm, to avoid the controller process in every image load.

(Sorry for my poor english, I'm brazilian...)


Examples related to html

Embed ruby within URL : Middleman Blog Please help me convert this script to a simple image slider Generating a list of pages (not posts) without the index file Why there is this "clear" class before footer? Is it possible to change the content HTML5 alert messages? Getting all files in directory with ajax DevTools failed to load SourceMap: Could not load content for chrome-extension How to set width of mat-table column in angular? How to open a link in new tab using angular? ERROR Error: Uncaught (in promise), Cannot match any routes. URL Segment

Examples related to css

need to add a class to an element Using Lato fonts in my css (@font-face) Please help me convert this script to a simple image slider Why there is this "clear" class before footer? How to set width of mat-table column in angular? Center content vertically on Vuetify bootstrap 4 file input doesn't show the file name Bootstrap 4: responsive sidebar menu to top navbar Stylesheet not loaded because of MIME-type Force flex item to span full row width

Examples related to image

Reading images in python Numpy Resize/Rescale Image Convert np.array of type float64 to type uint8 scaling values Extract a page from a pdf as a jpeg How do I stretch an image to fit the whole background (100% height x 100% width) in Flutter? Angular 4 img src is not found How to make a movie out of images in python Load local images in React.js How to install "ifconfig" command in my ubuntu docker image? How do I display local image in markdown?

Examples related to cross-browser

Show datalist labels but submit the actual value Stupid error: Failed to load resource: net::ERR_CACHE_MISS Click to call html How to Detect Browser Back Button event - Cross Browser How can I make window.showmodaldialog work in chrome 37? Cross-browser custom styling for file upload button Flexbox and Internet Explorer 11 (display:flex in <html>?) browser sessionStorage. share between tabs? How to know whether refresh button or browser back button is clicked in Firefox CSS Custom Dropdown Select that works across all browsers IE7+ FF Webkit

Examples related to scaling

Can anyone explain me StandardScaler? How to scale images to screen size in Pygame How can I make an svg scale with its parent container? CSS scale down image to fit in containing div, without specifing original size Image scaling causes poor quality in firefox/internet explorer but not chrome How to scale down a range of numbers with a known min and max value Android and setting width and height programmatically in dp units Android Webview - Webpage should fit the device screen