开发者

Creating thumbnail squares of images in javascript (without losing aspect ratio)

I am making a client side Drag and Drop file upload script as a bookm开发者_开发技巧arklet. Before uploading I am using the File API to read the images into base64 format and display them as thumbnails.

This is how my thumbnails look like. I want them to look more square but without loosing their aspect ratio. (please ignore progress bar)

Creating thumbnail squares of images in javascript (without losing aspect ratio)

This is how I want the thumbnails to be like, they are centered and being cropped based on min(height,width).

Creating thumbnail squares of images in javascript (without losing aspect ratio)

Can I do this using javascript only (changing styles via script will do)? Please try to make sure that your solution will fit with base64 images (after the images are read via file API as DATA URL).

I have uploaded these exact set of images here.

Thanks for the help.


Just wanted to share how I resolved my issue. Since I wanted a purely javascript only solution, I used throwaway canvas elements to do the dirty work.

Here is my code for the same:

function resizeImage(url, width, height, callback, file) {
  console.log("In_resizeImage");
  var sourceImage = new Image();

  sourceImage.onload = (function (f) {
      return function (evt) {
        console.log("In_sourceImage_onload");
        console.log("sourceImage.width:" + sourceImage.width);
        console.log("sourceImage.height:" + sourceImage.height);
        var canvas = document.createElement("canvas");
        canvas.width = width;
        canvas.height = height;

        if (sourceImage.width == sourceImage.height) {
          canvas.getContext("2d").drawImage(sourceImage, 0, 0, width, height);
        } else {
          minVal = Math.min(sourceImage.width, sourceImage.height);
          if (sourceImage.width > sourceImage.height) {
            canvas.getContext("2d").drawImage(sourceImage, (sourceImage.width - minVal) / 2, 0, minVal, minVal, 0, 0, width, height);
          } else {
            canvas.getContext("2d").drawImage(sourceImage, 0, (sourceImage.height - minVal) / 2, minVal, minVal, 0, 0, width, height);
          }
        }
        callback(canvas.toDataURL(), f);
      }
    })(file);

  sourceImage.src = url;
}

I was directly dealing with image files so I was able to use Image object. For others to use, little bit tweaking might be required.


Instanciate another html-element (I would chose a table, but I'm old and outdated) and align the picture as a background picture with CSS, something like

thetable { background: url('planets.jpg') 0px -150px no-repeat; width: 60 px; height 60 px}

I stole it all from here: How to create CSS-sprites


This should support both image and video. It will create a thumbnail for the media but will also keep the media aspect ratio.

This should also clean up after itself so no event leaks should persist. It will also smooth the thumbnail image.

/* example to resize an image to 300px width 
and keep the aspect */ 
resizeMedia('/images/logo.jpg', 300, function(data)
{
    console.log(data); // the new thumbnail data uri 
});  


/* this will create a thumbnail of an image or video 
and keep the aspect. 
@param (string | object) media = the image string or video object 
@param (int) width = the new width to contain the media 
@param (function) callBack = the callBack to handle the 
image data uri */ 
function resizeMedia(media, width, callBack) 
{
    var self = this; 

    /* this will get the type by checking ifthe media 
    is a string (e.g. img src or dataUri) */ 
    var type = typeof media === 'string'? 'image' : 'video'; 

    /* this will get the height and width of the resized 
    media and keep the aspect. 
    @param (int) udateSize = the width the modify 
    @param (int) width = the old width 
    @param (int) height = the old height 
    @return (object) the width and height to modify the 
    media */ 
    var getModifySize = function(updateSize, width, height) 
    { 
        var getModifyAspect = function(max, min, value)
        {
            var ratio = max / min;
            return value * ratio;
        };   

        return { 
            width: updateSize,
            height: getModifyAspect(updateSize, width, height) 
        }; 
    }; 

    /* this will create a canvas and draw the media 
    on the canvas. 
    @param (object) media = the image or video 
    object 
    @param (int) width = the canvas width
    @param (int) height = the canvas height 
    @return (object) the new canvas */ 
    var createCanvas = function(media, width, height)
    { 
        var canvas = document.createElement("canvas");
        var ctx = canvas.getContext("2d"); 

        canvas.width = width;
        canvas.height = height;

        ctx.mozImageSmoothingEnabled = true;
        ctx.webkitImageSmoothingEnabled = true;
        ctx.msImageSmoothingEnabled = true;
        ctx.imageSmoothingEnabled = true;

        /* we need to draw on load to make sure
        the image is ready to be used */
        ctx.drawImage(media, 0, 0, width, height);

        /* this will convert the canvas to a data uri
        using jpeg to speed up the process. if you need 
        to keep transparency remove the mime type 
        and it will default to png */ 
        callBack(canvas.toDataURL('image/jpeg'));

        return canvas; 
    }; 

    if(type === 'image') 
    { 
        var img = new window.Image();
        img.crossOrigin = "anonymous";
        img.addEventListener('load', function loadImage() 
        {
            var modify = getModifySize(width, img.width, img.height);

            createCanvas(img, modify.width, modify.height); 
            img.removeEventListener('load', loadImage);
        });

        img.src = media;
    } 
    else if(type === 'video') 
    { 
        var modify = getModifySize(width, media.videoWidth, media.videoHeight);
        createCanvas(media, modify.width, modify.height);
    }
}; 


You can also "clip" directly a centered square in the image onto the canvas with drawImage(), you simply have to put theses parameters :

canvas.getContext("2d").drawImage(img,sx,sy,swidth,sheight,x,y,width,height);

sx Optional. The x coordinate where to start clipping

sy Optional. The y coordinate where to start clipping

swidth Optional. The width of the clipped image

sheight Optional. The height of the clipped image

x The x coordinate where to place the image on the canvas

y The y coordinate where to place the image on the canvas

width Optional. The width of the image to use (stretch or reduce the image)

height Optional. The height of the image to use (stretch or reduce the image)

Regards,

Pierrick

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜