最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - cropper js resize and crop with image magic - Stack Overflow

programmeradmin3浏览0评论

How to perform resize and crop with ImageMagick using the data from cropperjs?

The user can upload a large image and zoom/pan to crop. Tried using blob but it looses too much quality and times out too often.

Example from fiddle with the following data:

Original Width: 1280
Original Height: 720
Width: 424.8717011756327
Height: 238.9903319112934
X: -155.17118867901692
Y: -1.4989251522088705
Scale: 23.82

Tried with this but it crops the wrong area. Also tried scaling the original image but that's too big for the server to handle.

convert orignial.jpg -resize "1280x720^" -gravity center -crop 424x238+-155+-1 +repage result.jpg 

Example: /

JS code:

$(function() {
    var image = $('#crop-image');
    var zoomSlider = document.getElementById('zoom-slider');
    var canvasSize = null;
    var pictureContainer = $('.picture-frame');
    var maxPictureContainerWidth = parseFloat(pictureContainer.css('max-width')) || 450;
    var maxPictureContainerHeight = parseFloat(pictureContainer.css('max-height')) || 350;
    var isSliderInUse = false;

    // Wall is in Cm, convert to Inches to work out pixel sizes at 300dpi
    var wallWpx = (0.393700787 * pictureContainer.attr('data-width')) * 300; // data-width is the wall width in pixels
    var wallHpx = (0.393700787 * pictureContainer.attr('data-height')) * 300; // data-height is the wall height in pixels

    var sampleImageScaleFactor = (image.attr('width') / image.attr('original-width'));

    var wallSize = {
        width: wallWpx * sampleImageScaleFactor, // scaling the wall size corresponding the sample size
        height: wallHpx * sampleImageScaleFactor,
        originalWidth: pictureContainer.attr('data-width'),
        originalHeight: pictureContainer.attr('data-height')
    };
    var wallAspectRatio = wallSize.originalWidth/wallSize.originalHeight;
    var pictureContainerSizes = {
        'width': maxPictureContainerWidth * (wallAspectRatio > 1 ? 1 : wallAspectRatio) ,
        'height': maxPictureContainerHeight / (wallAspectRatio > 1 ? wallAspectRatio : 1)
    };
    pictureContainer.css(pictureContainerSizes).removeClass('hidden');
    var zoomStep = 0.2;
    var biggerSide = null;

    var zoomModal = $('#modal-warning');
    var handleZoomHold, handleZoomFired;

    image.cropper({
        zoom: 0.2,
        guides: false,
        cropBoxResizable: false,
        cropBoxMovable: false,
        //viewMode: 3,
        dragMode: 'move',
        left: 0,
        top: 0,
        //width: canvasSize.width,
        //height: canvasSize.height,
        //aspectRatio: 1,
        toggleDragModeOnDblclick: false,
        zoomOnTouch: true,
        zoomOnWheel: true
    });  

    // Event
    image.on('built.cropper', function() {
        image.cropper('setCropBoxData', {
            left: 0,
            top: 0,
            width: pictureContainerSizes.width,
            height: pictureContainerSizes.height
        });
        canvasSize = {
            width: image.cropper('getCropBoxData').width,
            height: image.cropper('getCropBoxData').height
        };
        biggerSide = canvasSize.width === image.cropper('getImageData').width ? 'width' : 'height';

        var savedCropperSettings = {
            sliceW: parseFloat($('input[name=sliceW]').val()),
            sliceH: parseFloat($('input[name=sliceH]').val()),
            sliceX: parseFloat($('input[name=sliceX]').val()),
            sliceY: parseFloat($('input[name=sliceY]').val()),
            scale: parseFloat($('input[name=scale]').val()) // saved adoptedZoomFactor
        };

        if (!savedCropperSettings.scale) {
            return;
        }

        /* restoring saved settings */
        image.cropper('zoomTo', canvasSize[biggerSide]/(wallSize[biggerSide]/savedCropperSettings.scale.toFixed(1)));

        var cropboxData = image.cropper('getCropBoxData');
        var scaleFactor = wallSize.originalHeight / cropboxData.height;
        image.cropper('setCanvasData', {
            left: savedCropperSettings.sliceX / scaleFactor + cropboxData.left,
            top: savedCropperSettings.sliceY / scaleFactor + cropboxData.top
        });
    });

    var adoptedZoomFactor = NaN;
    var adoptedZoomElement = $('#adoptedZoom');
    image.on('crop.cropper', function() {
        var data = image.cropper('getData');
        var canvasData = image.cropper('getCanvasData');
        var cropboxData = image.cropper('getCropBoxData');
        var scaleFactor = wallSize.originalHeight / cropboxData.height;
        adoptedZoomFactor = parseFloat((wallSize[biggerSide] / data[biggerSide]).toFixed(2));
        adoptedZoomElement.text(adoptedZoomFactor);

        $('input[name=sliceW]').val(canvasData.width * scaleFactor);
        $('input[name=sliceH]').val(canvasData.height * scaleFactor);
        $('input[name=sliceX]').val((canvasData.left - cropboxData.left) * scaleFactor);
        $('input[name=sliceY]').val(canvasData.top * scaleFactor);
        $('input[name=scale]').val(adoptedZoomFactor);

    });

});

How to perform resize and crop with ImageMagick using the data from cropperjs?

The user can upload a large image and zoom/pan to crop. Tried using blob but it looses too much quality and times out too often.

Example from fiddle with the following data:

Original Width: 1280
Original Height: 720
Width: 424.8717011756327
Height: 238.9903319112934
X: -155.17118867901692
Y: -1.4989251522088705
Scale: 23.82

Tried with this but it crops the wrong area. Also tried scaling the original image but that's too big for the server to handle.

convert orignial.jpg -resize "1280x720^" -gravity center -crop 424x238+-155+-1 +repage result.jpg 

Example: https://jsfiddle/1knw3a5e/

JS code:

$(function() {
    var image = $('#crop-image');
    var zoomSlider = document.getElementById('zoom-slider');
    var canvasSize = null;
    var pictureContainer = $('.picture-frame');
    var maxPictureContainerWidth = parseFloat(pictureContainer.css('max-width')) || 450;
    var maxPictureContainerHeight = parseFloat(pictureContainer.css('max-height')) || 350;
    var isSliderInUse = false;

    // Wall is in Cm, convert to Inches to work out pixel sizes at 300dpi
    var wallWpx = (0.393700787 * pictureContainer.attr('data-width')) * 300; // data-width is the wall width in pixels
    var wallHpx = (0.393700787 * pictureContainer.attr('data-height')) * 300; // data-height is the wall height in pixels

    var sampleImageScaleFactor = (image.attr('width') / image.attr('original-width'));

    var wallSize = {
        width: wallWpx * sampleImageScaleFactor, // scaling the wall size corresponding the sample size
        height: wallHpx * sampleImageScaleFactor,
        originalWidth: pictureContainer.attr('data-width'),
        originalHeight: pictureContainer.attr('data-height')
    };
    var wallAspectRatio = wallSize.originalWidth/wallSize.originalHeight;
    var pictureContainerSizes = {
        'width': maxPictureContainerWidth * (wallAspectRatio > 1 ? 1 : wallAspectRatio) ,
        'height': maxPictureContainerHeight / (wallAspectRatio > 1 ? wallAspectRatio : 1)
    };
    pictureContainer.css(pictureContainerSizes).removeClass('hidden');
    var zoomStep = 0.2;
    var biggerSide = null;

    var zoomModal = $('#modal-warning');
    var handleZoomHold, handleZoomFired;

    image.cropper({
        zoom: 0.2,
        guides: false,
        cropBoxResizable: false,
        cropBoxMovable: false,
        //viewMode: 3,
        dragMode: 'move',
        left: 0,
        top: 0,
        //width: canvasSize.width,
        //height: canvasSize.height,
        //aspectRatio: 1,
        toggleDragModeOnDblclick: false,
        zoomOnTouch: true,
        zoomOnWheel: true
    });  

    // Event
    image.on('built.cropper', function() {
        image.cropper('setCropBoxData', {
            left: 0,
            top: 0,
            width: pictureContainerSizes.width,
            height: pictureContainerSizes.height
        });
        canvasSize = {
            width: image.cropper('getCropBoxData').width,
            height: image.cropper('getCropBoxData').height
        };
        biggerSide = canvasSize.width === image.cropper('getImageData').width ? 'width' : 'height';

        var savedCropperSettings = {
            sliceW: parseFloat($('input[name=sliceW]').val()),
            sliceH: parseFloat($('input[name=sliceH]').val()),
            sliceX: parseFloat($('input[name=sliceX]').val()),
            sliceY: parseFloat($('input[name=sliceY]').val()),
            scale: parseFloat($('input[name=scale]').val()) // saved adoptedZoomFactor
        };

        if (!savedCropperSettings.scale) {
            return;
        }

        /* restoring saved settings */
        image.cropper('zoomTo', canvasSize[biggerSide]/(wallSize[biggerSide]/savedCropperSettings.scale.toFixed(1)));

        var cropboxData = image.cropper('getCropBoxData');
        var scaleFactor = wallSize.originalHeight / cropboxData.height;
        image.cropper('setCanvasData', {
            left: savedCropperSettings.sliceX / scaleFactor + cropboxData.left,
            top: savedCropperSettings.sliceY / scaleFactor + cropboxData.top
        });
    });

    var adoptedZoomFactor = NaN;
    var adoptedZoomElement = $('#adoptedZoom');
    image.on('crop.cropper', function() {
        var data = image.cropper('getData');
        var canvasData = image.cropper('getCanvasData');
        var cropboxData = image.cropper('getCropBoxData');
        var scaleFactor = wallSize.originalHeight / cropboxData.height;
        adoptedZoomFactor = parseFloat((wallSize[biggerSide] / data[biggerSide]).toFixed(2));
        adoptedZoomElement.text(adoptedZoomFactor);

        $('input[name=sliceW]').val(canvasData.width * scaleFactor);
        $('input[name=sliceH]').val(canvasData.height * scaleFactor);
        $('input[name=sliceX]').val((canvasData.left - cropboxData.left) * scaleFactor);
        $('input[name=sliceY]').val(canvasData.top * scaleFactor);
        $('input[name=scale]').val(adoptedZoomFactor);

    });

});
Share Improve this question edited Aug 29, 2018 at 18:57 user1918032 asked Aug 29, 2018 at 18:51 user1918032user1918032 331 gold badge1 silver badge5 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 2

That cropper tool does not work correctly on my Mac in Safari or Firefox or Chrome. It does not respect the scale values that are entered. It always es out with results of scale=1. Perhaps I am doing it wrong.

But if you want to do it in ImageMagick, the correct way would be:

Original:

Cropper Screen Snap:

Cropper Result (dimensions 320x180; still scale=1):

Using ImageMagick (dimensions 640x360):

ww=320
hh=180
xx=40
yy=60
rotate=0
scale=2
scale=`convert xc: -format "%[fx:$scale*100]" info:`
convert barn.jpg -virtual-pixel white -define distort:viewport=${ww}x${hh}+${xx}+${yy} -filter point -distort SRT "$rotate" +repage -resize $scale% test.jpg


Note that ImageMagick -distort SRT permits scaling, but the scale is done before the cropping from the viewport. So I had to use the viewport crop first and then add -resize in percent (as scale=2 --> scale=200%)

The reason I used -distort SRT with the viewport crop is that it would allow offset cropping when the xx and yy values are negative. You cannot do that with a simple -crop.

So for example:

ww=320
hh=180
xx=-40
yy=-60
rotate=0
scale=1
scale=`convert xc: -format "%[fx:$scale*100]" info:`
convert barn.jpg -virtual-pixel white -define distort:viewport=${ww}x${hh}+${xx}+${yy} -filter point -distort SRT "$rotate" +repage -resize $scale% test2.jpg


If you download the image, you will see it is padded at the top and right with white, but still has a size of 320x180.

If you are cropping only within the bounds of the image, then you can use -crop and the Imagemagick mand would be:

ww=320
hh=180
xx=40
yy=60
rotate=0
scale=2
scale=`convert xc: -format "%[fx:$scale*100]" info:`
convert barn.jpg -crop ${ww}x${hh}+${xx}+${yy} +repage -resize $scale% test4.jpg


Which produces the same results as my original viewport crop.

I've had success just using the data from getData without doing any math on the results.

var croppable = $('.croppable');
croppable.cropper({
  autoCrop: true, 
  viewMode: 0,
  background: false,
  modal: true,
  zoomable: true,
  responsive: false, 
  crop: function(e) {
    data = croppable.cropper('getData');
    $('#extract_image_crop_x').val(data.x);
    $('#extract_image_crop_y').val(data.y);
    $('#extract_image_crop_width').val(data.width);
    $('#extract_image_crop_height').val(data.height);
    $('#extract_image_crop_rotate').val(data.rotate);
  }
});
发布评论

评论列表(0)

  1. 暂无评论