防止渐进式jpeg完全加载

时间:2015-11-05 07:56:07

标签: jpeg progressive

所以,假设我有一个大版本的图像只能作为缩略图显示。是否可以通过使用渐进式jpeg避免为缩略图设置单独的文件,在达到一定数量的扫描时停止加载,并且仅在用户选择完全打开时继续加载?

如果是这样,如何控制图像的加载?

提前致谢。

2 个答案:

答案 0 :(得分:7)

有两种方法:

1。客户端重

<强>前提条件

  • 图像服务器必须支持range HTTP header
    • 例如。 Range: bytes=0-1024表示您只请求前1024个字节
  • 必须事先知道您想要请求的字节数
    • 如果从服务器端推送该值,则可以说是完整大小的1/8
    • 所以在客户端
    • 应该知道确切的字节数
  • 如果Range无效或不受支持,那么服务器将返回整个图片,这是一个很好的自然“后备”

跨域请求:如果html和图片位于不同的域

    必须设置
  • Access-Control-Allow-Headers: "range"

图像服务器上的Apache .htaccess示例

<IfModule mod_headers.c>
    Header set Access-Control-Allow-Origin "*"
    Header set Access-Control-Allow-Headers: "range"
</IfModule>
  • 如果浏览器由于CROS设置不当而无法提出请求,则代码会回退以将data-src属性设置为src属性

<强>概述

  1. 请求带有AJAX请求的图片
    • Range请求的AJAX标头设置为您想要返回的字节数
    • mimeType设置为明文(以便我们以后可以对其进行base64编码)
  2. Base64编码数据并将其设置为图像的src属性(<img src="data:image/jpeg;base64,...">
    • 要注意较大的图像,这在客户端可能会非常沉重
  3. 如果因任何原因设置src属性失败(例如,CROS设置不当),则回退以将data-src属性设置为src属性
  4. 代码

    这是建立在gaetanoM这里很棒的答案:Get Image using jQuery.ajax() and decode it to base64

    // for each img, which has data-src and data-bytes attributes
    $('img[data-src][data-bytes]').each(function(i,e){
    	$.ajax({
    	    url: $(e).data('src'), // url of image
    	    type: 'GET',
    	    headers: {
    	    	'Range':'bytes=0-'+$(e).data('bytes') // Range header, eg. Range: bytes=0-1024
    	    },
    	    mimeType: "text/plain; charset=x-user-defined"
    	}).done(function( data, textStatus, jqXHR ) {
    	    $(e).attr('src', 'data:image/jpeg;base64,' + base64encode(data)); // on success we set the base64 encoded data to the image's src attribute
    	}).always(function(){
    	    // if setting the src failed for whatever reason, we fall back to set the data-src attribute to src attribute
    	    if(!$(e).attr('src'))
    	        $(e).attr('src', $(e).data('src'));
    	});
    });
    
    function base64encode(str) {
        var CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
        var out = "", i = 0, len = str.length, c1, c2, c3;
        while (i < len) {
            c1 = str.charCodeAt(i++) & 0xff;
            if (i == len) {
                out += CHARS.charAt(c1 >> 2);
                out += CHARS.charAt((c1 & 0x3) << 4);
                out += "==";
                break;
            }
            c2 = str.charCodeAt(i++);
            if (i == len) {
                out += CHARS.charAt(c1 >> 2);
                out += CHARS.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
                out += CHARS.charAt((c2 & 0xF) << 2);
                out += "=";
                break;
            }
            c3 = str.charCodeAt(i++);
            out += CHARS.charAt(c1 >> 2);
            out += CHARS.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
            out += CHARS.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6));
            out += CHARS.charAt(c3 & 0x3F);
        }
        return out;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <!-- total filesize is 35 933 bytes -->
    <img data-src="http://shoepimper.com/doklist.com-logo.jpg" data-bytes="1900">
    <img data-src="http://shoepimper.com/doklist.com-logo.jpg" data-bytes="2500">
    <img data-src="http://shoepimper.com/doklist.com-logo.jpg" data-bytes="5600">
    
    <!-- if data-bytes are erroneous the server will return the whole image -->
    <img data-src="http://shoepimper.com/doklist.com-logo.jpg" data-bytes="error">
    <!-- if CROS fails, then it falls back to set the data-src attribute to the src attribute -->
    <img data-src="https://i.stack.imgur.com/QOPRf.jpg" data-bytes="error">

    2。服务器端重

    根据ProgressiveMonkey的评论,您可以使用php或任何其他服务器端编程语言轻松修剪图像数据。

    <强>概述

    服务器端代码

    <?php
        $div = isset($_GET['div']) && intval($_GET['div'])>1 ? intval($_GET['div']) : 1; // what fraction of the image shall we return
        $img = 'doklist.com-logo.jpg';
        $size = round(filesize($img) / $div); // calculating the size in bytes what we return
    
        // setting the headers
        header("Content-Type: image/jpeg");
        header("Content-Length: $size");
    
        $fp = fopen($img, 'r');
            echo fread($fp, $size); // returning the necessary amount of bytes
        fclose($fp);
    ?>
    

    <强>实施例

    请在此处查看我们网站徽标(Doklist.com

    之一的示例

    请随意使用此网址的div参数(另请注意,我的测试服务器可能无法很好地处理增加的流量): http://shoepimper.com/progressive-thumb.php?div=14

    只读取 1/24 的文件大小并将其作为整个图像返回: <img src="http://shoepimper.com/progressive-thumb.php?div=24"> enter image description here

    阅读 1/14 图片: <img src="http://shoepimper.com/progressive-thumb.php?div=14"> enter image description here

    阅读 1/6 图片: <img src="http://shoepimper.com/progressive-thumb.php?div=6"> enter image description here

    阅读整个图片(1/1) <img src="http://shoepimper.com/progressive-thumb.php?div=1"> enter image description here

    如果您需要帮助来确定图像是否是逐步编码的,请使用:http://codepen.io/sergejmueller/full/GJKwv

    如果您无法直接访问图像,那么您应该使用代理,这意味着代码本身的结构并没有真正改变,您只需“打开”远程文件。

答案 1 :(得分:1)

有可能。您只需要修改解码器就可以了。

只要您有权访问数据流,就可以控制加载。