使用jQuery自动裁剪图像空白区域 [英] Crop image white space automatically using jQuery

查看:168
本文介绍了使用jQuery自动裁剪图像空白区域的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有100,000张不受我控制的图像。其中一些图像非常出色,因为图像会延伸到边界,而有些图像会占用过多的空白区域。



当空白区域过多时,页面看起来很糟糕并且意味着屏幕上的图像看起来都不同。



你可以在这里看到我的意思:





它仅适用于您域中的图像,如前所述。您可以选择自己的白色背景图片并更改最后一行:

  //在此处定义您域中的图片
img.src ='http://localhost/strawberry2.jpg';

显然,您需要运行域中的代码,而不是jsFiddle。






编辑2:如果要裁剪和缩放以保持相同的宽高比,请更改此

  var $ croppedCanvas = $(< canvas>)。attr({width:cropWidth,height:cropHeight}); 

//终于裁掉那个人
$ croppedCanvas [0] .getContext(2d)。drawImage(canvas,
cropLeft,cropTop,cropWidth,cropHeight,
0,0,cropWidth,cropHeight);

  var $ croppedCanvas = $(< canvas>)。attr({width:imgWidth,height:imgHeight}); 

//终于裁掉那个人
$ croppedCanvas [0] .getContext(2d)。drawImage(canvas,
cropLeft,cropTop,cropWidth,cropHeight,
0,0,imgWidth,imgHeight);






编辑3:一在浏览器上裁剪图像的快捷方法是通过使用 Web Workers 来并行化工作负载,因为这是优秀文章解释。


I have 100,000 images which are not under my control. Some of these images are excellent in that the image stretches to the boundaries whilst some have excessive amounts of white space.

When there is excessive white space it makes the page look terrible and means images on the screen all look like they are different sizes.

You can see what I mean here:

http://www.fitness-saver.com/uk/shop/mountain-bikes/

What I have been hunting for is a jQuery method of cropping the images and removing the whitespace automatically.

1) The amount of whitespace is different in every image 2) The ratios of the images are different 3) I want to use javascript rather than pre-processing the images.

I hope you can help!

Edit: Here's an example image - http://images.productserve.com/preview/3395/128554505.jpg. Note the images come from various affiliate sites and are definitely from a different domain.

解决方案

To analyse the blank spaces in an image, the only way I know is to load that image into a canvas:

var img = new Image(),
    $canvas = $("<canvas>"), // create an offscreen canvas
    canvas = $canvas[0],
    context = canvas.getContext("2d");

img.onload = function () {
   context.drawImage(this, 0, 0); // put the image in the canvas
   $("body").append($canvas);
   removeBlanks(this.width, this.height);
};

// test image
img.src = 'http://images.productserve.com/preview/1302/218680281.jpg';

Next, use the getImageData() method. This method returns an ImageData object that you can use to inspect each pixel data (color).

var removeBlanks = function (imgWidth, imgHeight) {
    var imageData = context.getImageData(0, 0, canvas.width, canvas.height),
             data = imageData.data,
           getRBG = function(x, y) {
                      return {
                        red:   data[(imgWidth*y + x) * 4],
                        green: data[(imgWidth*y + x) * 4 + 1],
                        blue:  data[(imgWidth*y + x) * 4 + 2]
                      };
                    },
          isWhite = function (rgb) {
                      return rgb.red == 255 && rgb.green == 255 && rgb.blue == 255;
                    },
            scanY = function (fromTop) {
                      var offset = fromTop ? 1 : -1;

                      // loop through each row
                      for(var y = fromTop ? 0 : imgHeight - 1; fromTop ? (y < imgHeight) : (y > -1); y += offset) {

                        // loop through each column
                        for(var x = 0; x < imgWidth; x++) {
                            if (!isWhite(getRBG(x, y))) {
                                return y;                        
                            }      
                        }
                    }
                    return null; // all image is white
                },
            scanX = function (fromLeft) {
                      var offset = fromLeft? 1 : -1;

                      // loop through each column
                      for(var x = fromLeft ? 0 : imgWidth - 1; fromLeft ? (x < imgWidth) : (x > -1); x += offset) {

                        // loop through each row
                        for(var y = 0; y < imgHeight; y++) {
                            if (!isWhite(getRBG(x, y))) {
                                return x;                        
                            }      
                        }
                    }
                    return null; // all image is white
                };


        var cropTop = scanY(true),
            cropBottom = scanY(false),
            cropLeft = scanX(true),
            cropRight = scanX(false);
    // cropTop is the last topmost white row. Above this row all is white
    // cropBottom is the last bottommost white row. Below this row all is white
    // cropLeft is the last leftmost white column.
    // cropRight is the last rightmost white column.
};

Frankly I was unable to test this code for a good reason: I came across the infamous "Unable to get image data from canvas because the canvas has been tainted by cross-origin data." security exception.

This is not a bug, it is an intended feature. From the specs:

The toDataURL(), toDataURLHD(), toBlob(), getImageData(), and getImageDataHD() methods check the flag and will throw a SecurityError exception rather than leak cross-origin data.

This happens when drawImage() loads files from external domains, which causes the canvas's origin-clean flag to be set to false, preventing further data manipulations.

I am afraid you will run into the same problem, but anyway, here is the code.

Even if this works on client side, I can imagine how miserable will be performance-wise. So, as Jan said, if you can download the images and pre-process them on the server side, that would be better.


Edit: I was curious to see if my code would really crop an image, and indeed it does.

You can check it out here

It only works for images from your domain, as stated before. You can choose your own image with white background and change the last line:

// define here an image from your domain
img.src = 'http://localhost/strawberry2.jpg'; 

Obviously, you will need to run the code from your domain, not from jsFiddle.


Edit2: If you want to crop and scale up to keep the same aspect ratio, then change this

var $croppedCanvas = $("<canvas>").attr({ width: cropWidth, height: cropHeight });

// finally crop the guy
$croppedCanvas[0].getContext("2d").drawImage(canvas,
    cropLeft, cropTop, cropWidth, cropHeight,
    0, 0, cropWidth, cropHeight);

to

var $croppedCanvas = $("<canvas>").attr({ width: imgWidth, height: imgHeight });

// finally crop the guy
$croppedCanvas[0].getContext("2d").drawImage(canvas,
    cropLeft, cropTop, cropWidth, cropHeight,
    0, 0, imgWidth, imgHeight);


Edit3: One fast way to crop images on the browser, is to parallelize the workload through the use of Web Workers, as this excellent article explains.

这篇关于使用jQuery自动裁剪图像空白区域的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆