调整HTML5画布中的图像大小

Telanor提出了一个问题:Resizing an image in an HTML5 canvas,或许与您遇到的问题类似。

回答者Mikksyockit给出了该问题的处理方式:

So what do you do if all the browsers (actually, Chrome 5 gave me quite good one) won't give you good enough resampling quality? You implement them yourself then! Oh come on, we're entering the new age of Web 3.0, HTML5 compliant browsers, super optimized JIT javascript compilers, multi-core(†) machines, with tons of memory, what are you afraid of? Hey, there's the word java in javascript, so that should guarantee the performance, right? Behold, the thumbnail generating code:

// returns a function that calculates lanczos weight
function lanczosCreate(lobes) {
    return function(x) {
        if (x > lobes)
            return 0;
        x *= Math.PI;
        if (Math.abs(x) < 1e-16)
            return 1;
        var xx = x / lobes;
        return Math.sin(x) * Math.sin(xx) / x / xx;
    };
}

// elem: canvas element, img: image element, sx: scaled width, lobes: kernel radius
function thumbnailer(elem, img, sx, lobes) {
    this.canvas = elem;
    elem.width = img.width;
    elem.height = img.height;
    elem.style.display = "none";
    this.ctx = elem.getContext("2d");
    this.ctx.drawImage(img, 0, 0);
    this.img = img;
    this.src = this.ctx.getImageData(0, 0, img.width, img.height);
    this.dest = {
        width : sx,
        height : Math.round(img.height * sx / img.width),
    };
    this.dest.data = new Array(this.dest.width * this.dest.height * 3);
    this.lanczos = lanczosCreate(lobes);
    this.ratio = img.width / sx;
    this.rcp_ratio = 2 / this.ratio;
    this.range2 = Math.ceil(this.ratio * lobes / 2);
    this.cacheLanc = {};
    this.center = {};
    this.icenter = {};
    setTimeout(this.process1, 0, this, 0);
}

thumbnailer.prototype.process1 = function(self, u) {
    self.center.x = (u + 0.5) * self.ratio;
    self.icenter.x = Math.floor(self.center.x);
    for (var v = 0; v < self.dest.height; v++) {
        self.center.y = (v + 0.5) * self.ratio;
        self.icenter.y = Math.floor(self.center.y);
        var a, r, g, b;
        a = r = g = b = 0;
        for (var i = self.icenter.x - self.range2; i <= self.icenter.x + self.range2; i++) {
            if (i < 0 || i >= self.src.width)
                continue;
            var f_x = Math.floor(1000 * Math.abs(i - self.center.x));
            if (!self.cacheLanc[f_x])
                self.cacheLanc[f_x] = {};
            for (var j = self.icenter.y - self.range2; j <= self.icenter.y + self.range2; j++) {
                if (j < 0 || j >= self.src.height)
                    continue;
                var f_y = Math.floor(1000 * Math.abs(j - self.center.y));
                if (self.cacheLanc[f_x][f_y] == undefined)
                    self.cacheLanc[f_x][f_y] = self.lanczos(Math.sqrt(Math.pow(f_x * self.rcp_ratio, 2)
                            + Math.pow(f_y * self.rcp_ratio, 2)) / 1000);
                weight = self.cacheLanc[f_x][f_y];
                if (weight > 0) {
                    var idx = (j * self.src.width + i) * 4;
                    a += weight;
                    r += weight * self.src.data[idx];
                    g += weight * self.src.data[idx + 1];
                    b += weight * self.src.data[idx + 2];
                }
            }
        }
        var idx = (v * self.dest.width + u) * 3;
        self.dest.data[idx] = r / a;
        self.dest.data[idx + 1] = g / a;
        self.dest.data[idx + 2] = b / a;
    }

    if (++u < self.dest.width)
        setTimeout(self.process1, 0, self, u);
    else
        setTimeout(self.process2, 0, self);
};
thumbnailer.prototype.process2 = function(self) {
    self.canvas.width = self.dest.width;
    self.canvas.height = self.dest.height;
    self.ctx.drawImage(self.img, 0, 0, self.dest.width, self.dest.height);
    self.src = self.ctx.getImageData(0, 0, self.dest.width, self.dest.height);
    var idx, idx2;
    for (var i = 0; i < self.dest.width; i++) {
        for (var j = 0; j < self.dest.height; j++) {
            idx = (j * self.dest.width + i) * 3;
            idx2 = (j * self.dest.width + i) * 4;
            self.src.data[idx2] = self.dest.data[idx];
            self.src.data[idx2 + 1] = self.dest.data[idx + 1];
            self.src.data[idx2 + 2] = self.dest.data[idx + 2];
        }
    }
    self.ctx.putImageData(self.src, 0, 0);
    self.canvas.style.display = "block";
};

...with which you can produce results like these!

so anyway, here is a 'fixed' version of your example:

img.onload = function() {
    var canvas = document.createElement("canvas");
    new thumbnailer(canvas, img, 188, 3); //this produces lanczos3
    // but feel free to raise it up to 8\. Your client will appreciate
    // that the program makes full use of his machine.
    document.body.appendChild(canvas);
};

Now it's time to pit your best browsers out there and see which one will least likely increase your client's blood pressure!

Umm, where's my sarcasm tag?

(since many parts of the code is based on Anrieff Gallery Generator is it also covered under GPL2? I dunno)

actually due to limitation of javascript, multi-core is not supported.

希望本文对你有帮助,欢迎支持JavaScript中文网

原文链接:stackoverflow.com

上一篇:jQuery能获得与元素相关联的所有CSS样式吗?
下一篇:在数组中获取所有非唯一值(即:重复/多个事件)

相关推荐

  • 鼠标在画布上的位置

    Dagg NabbitSam Lee提出了一个问题:Getting mouse location in canvas,或许与您遇到的问题类似。 回答者Jani Hartikainen给出了该问题的处理...

    2 年前
  • 防止对HTML5的浏览器历史popstate滚动

    Alex Malet de Carteret提出了一个问题:Prevent browser scroll on HTML5 History popstate,或许与您遇到的问题类似。

    3 年前
  • 防止HTML5视频被下载(右键保存)?

    Mureinikpython提出了一个问题:Prevent HTML5 video from being downloaded (right-click saved)?,或许与您遇到的问题类似。

    3 年前
  • 选择移动Web HTML5框架[关闭]

    Andrew BarberSarfraz提出了一个问题:Choosing Mobile Web HTML5 Framework [closed],或许与您遇到的问题类似。

    3 年前
  • 调整HTML5画布大小以适应窗口

    shekhardevyn提出了一个问题:Resize HTML5 canvas to fit window,或许与您遇到的问题类似。 回答者devyn给出了该问题的处理方式: I believe I ...

    3 年前
  • 读 《HTML5 揭秘》有感

    最近在补一些 HTML 的书籍,偶尔读到这本书,虽然这本书已经是10年以前的书籍了,不过其中有些有趣的知识点与观点被我提取了出来。 标准创建与技术实现冲突 作者在开始就提出了 Mozilla 开发人员...

    6 个月前
  • 详解HTML5游戏玩家流失原因

    对任何类型的电子游戏来说,玩家流失都是一个无法回避的问题。玩家为什么离开游戏?近日,HTML5游戏设定师纳森·洛维托(Nathan Lovato)在游戏开发者网站Gamasutra撰写文章,解读了玩家...

    5 年前
  • 设置自定义HTML5所需的字段验证消息

    G5WSumit Bijvani提出了一个问题:Set custom HTML5 required field validation message,或许与您遇到的问题类似。

    3 年前
  • 设置HTML5音频位置

    katspaugh提出了一个问题:Setting HTML5 audio position,或许与您遇到的问题类似。 回答者soemarko给出了该问题的处理方式: Works on my chrom...

    2 年前
  • 让HTML5 localStorage键

    Brian Tompsett - 汤莱恩Simone提出了一个问题:Get HTML5 localStorage keys,或许与您遇到的问题类似。 回答者Kevin Ennis给出了该问题的处理方式...

    3 年前

官方社区

扫码加入 JavaScript 社区