简体   繁体   English

通过画布旋转人像图像无法正确居中(Javascript)

[英]rotating portrait image via canvas not properly center (Javascript)

I'm creating a hybrid mobile app where the user can take photo from their phone and then upload it to a server. 我正在创建一个混合移动应用程序,用户可以在其中使用手机拍照,然后将其上传到服务器。 The problem that I am facing is that when user takes a portrait image, the image is not properly centered and it leaves a black border beside it. 我面临的问题是,当用户拍摄人像图像时,图像没有正确居中,并在其旁边留下黑色边框。

Here is an example of a portrait photo taken from my app: Uploaded Photo 这是从我的应用中拍摄的人像照片的示例: 上传的照片

Below is the code that I am using to rotate the image based on orientation and compress it 以下是我用于根据方向旋转图像并对其进行压缩的代码

function processFile(dataURL, fileType, orientation) {

var maxWidth = 800;
var maxHeight = 600;

var image = new Image();
image.src = dataURL;

image.onload = function () {
    var width = image.width;
    var height = image.height;
    var shouldResize = (width > maxWidth) || (height > maxHeight);

    if (!shouldResize) {
        dataURL = dataURL.substring(dataURL.indexOf(',')+1);

        return;
    }


    var newWidth;
    var newHeight;

    if (width > height) {
        newHeight = height * (maxWidth / width);
        newWidth = maxWidth;
    } else {
        newWidth = width * (maxHeight / height);
        newHeight = maxHeight;
    }

    var canvas = document.createElement('canvas');

    canvas.width = newWidth;
    canvas.height = newHeight;

    var context = canvas.getContext('2d');

    console.log("orientation here: "+orientation);
   switch(orientation){
case 2:
    // horizontal flip
    context.translate(canvas.width, 0);
    context.scale(-1, 1);
    break;
case 3:
    // 180° rotate left
    context.translate(canvas.width, canvas.height);
    context.rotate(Math.PI);
    break;
case 4:
    // vertical flip
    context.translate(0, canvas.height);
    context.scale(1, -1);
    break;
case 5:
    // vertical flip + 90 rotate right
    context.rotate(0.5 * Math.PI);
    context.scale(1, -1);
    break;
case 6:
    // 90° rotate right
    context.rotate(0.5 * Math.PI);
    context.translate(0, -canvas.height);
    break;
case 7:
    // horizontal flip + 90 rotate right
    context.rotate(0.5 * Math.PI);
    context.translate(canvas.width, -canvas.height);
    context.scale(-1, 1);
    break;
case 8:
    // 90° rotate left
    context.rotate(-0.5 * Math.PI);
    context.translate(-canvas.width, 0);
    break;
}

      context.drawImage(this, 0, 0, newWidth, newHeight);



        dataURL = canvas.toDataURL(fileType,0.7);
        dataURL = dataURL.substring(dataURL.indexOf(',')+1);
        console.log("dataURL here: "+dataURL);

    };

    image.onerror = function () {
        alert('image error');
    };
}

I would really appreciate if somebody can tell me what i'm doing wrong with my code and how to fix it. 如果有人可以告诉我我的代码在做什么以及如何解决它,我将不胜感激。

Thanks in advanced 提前致谢

You just forgot to use context.save() and context.restore() . 您只是忘记使用context.save()context.restore() Apart from that there are a few things 除此之外,还有几件事

  1. There is no need to load image on every call to processFile. 无需在每次调用processFile时加载映像。
  2. drawImage takes 9 arguments . drawImage需要9个参数 Many of these are optional. 其中许多是可选的。 First is image. 首先是图像。 From second to fifth is the clipping region of image. 从第二到第五是图像的裁剪区域。 From sixth to ninth is drawing region of canvas. 从第六到第九是画布的绘制区域。 So you can't use context.drawImage(this, 0, 0, newWidth, newHeight); 所以你不能使用context.drawImage(this, 0, 0, newWidth, newHeight);
    You have to use context.drawImage(image, 0, 0, width, height, x, y, newWidth, newHeight); 您必须使用context.drawImage(image, 0, 0, width, height, x, y, newWidth, newHeight);
  3. Also there's no need to create canvas element every time processFile() is called, one hidden canvas can be used for all the processing. 同样,也不需要每次调用processFile()时都创建canvas元素,一个隐藏的canvas可以用于所有处理。
  4. Image's src attribute should be assigned after onload/onerror events are bound otherwise there's a possibility that they will not get a chance to run. 应在绑定onload / onerror事件之后分配图像的src属性,否则可能无法获得运行的机会。

Here is the working JsFiddle link 这是有效的JsFiddle链接

http://jsfiddle.net/48qfy71a/ http://jsfiddle.net/48qfy71a/

I have removed the shouldResize check condition, please add it as you need. 我已经删除了shouldResize检查条件,请根据需要添加它。 Also I have created an image on canvas to give as input to the program as I wasn't able to find third party images which will not taint canvas. 另外,我在画布上创建了一个图像作为程序的输入,因为我无法找到不会弄脏画布的第三方图像。

You can use any image you need as below 您可以使用所需的任何图像,如下所示

//instead of
var imageUrl = createImageUrl();
// use this
var imageUrl = "test.jpg";

Here's the code for backup 这是备份代码

HTML 的HTML

<html>
    <head>

    </head>
    <body>
        <strong>Orientation </strong><select id="selectOption">
            <option value="1">1</option>
            <option value="2">2</option>
            <option value="3">3</option>
            <option value="4">4</option>
            <option value="5">5</option>
            <option value="6">6</option>
            <option value="7">7</option>
            <option value="8">8</option>
        </select><br/>
        <canvas id="testCanvas" width="800", height="600" style="border:1px solid red;"></canvas>
        <script src="script.js"></script>
    </body>
</html>

Script 脚本

//var imageUrl = "test.jpg";
var imageUrl = createImageUrl();

function createImageUrl() {
    var canvas = document.createElement("canvas");
    var context = canvas.getContext("2d");
    canvas.width = 800;
    canvas.height = 600;
    context.font = 'italic 60pt Calibri';
    context.textAlign = 'center';
    context.fillText('Hello World!', canvas.width/2, canvas.height/2);

    return canvas.toDataURL("jpg", 0.7);
}

document.getElementById("selectOption").onchange = function () {
    processFile("jpg", parseInt(this.value));
}

var image = new Image();

image.onload = function () { processFile("jpg", 1);};
image.onerror = function() {
    alert('image error');
};
image.src = imageUrl;

function processFile(fileType, orientation) {

    var maxWidth = 800;
    var maxHeight = 600;

    var width = image.width;
    var height = image.height;
    var shouldResize = (width > maxWidth) || (height > maxHeight);

    var canvas = document.getElementById('testCanvas');

    /*if (!shouldResize) {
        dataURL = dataURL.substring(dataURL.indexOf(',') + 1);

        return;
    }*/

    var newWidth;
    var newHeight;

    if (width > height) {
        newHeight = height * (maxWidth / width);
        newWidth = maxWidth;
    } else {
        newWidth = width * (maxHeight / height);
        newHeight = maxHeight;
    }

    canvas.width = newWidth;
    canvas.height = newHeight;

    var context = canvas.getContext('2d');

    console.log("orientation here: " + orientation);
    context.save();
    switch (orientation) {
        case 2:
            // horizontal flip
            context.translate(newWidth, 0);
            context.scale(-1, 1);
            drawScalledImage(0, 0);
            break;
        case 3:
            // 180° rotate left
            context.translate(canvas.width, canvas.height);
            context.rotate(Math.PI);
            drawScalledImage(0, 0);
            context.translate(-canvas.width, -canvas.height);
            break;
        case 4:
            // vertical flip
            context.translate(0, newHeight);
            context.scale(1, -1);
            drawScalledImage(0, 0);
            break;
        case 5:
            // vertical flip + 90 rotate right
            context.translate(newWidth / 2, newHeight / 2);
            context.rotate(0.5 * Math.PI);
            context.scale(1,-1);
            drawScalledImage(-newWidth / 2, -newHeight / 2);
            break;
        case 6:
            // 90° rotate right
            context.translate(newWidth / 2, newHeight / 2);
            context.rotate(0.5 * Math.PI);
            drawScalledImage(-newWidth / 2, -newHeight / 2);
            break;
        case 7:
            // horizontal flip + 90 rotate right
            context.translate(newWidth / 2, newHeight / 2);
            context.rotate(0.5 * Math.PI);
            context.scale(-1,1);
            drawScalledImage(-newWidth / 2, -newHeight / 2);
            break;
        case 8:
            // 90° rotate left
            context.translate(newWidth / 2, newHeight / 2);
            context.rotate(-0.5 * Math.PI);
            drawScalledImage(-newWidth / 2, -newHeight / 2);
            context.rotate(0.5 * Math.PI);
            context.translate(-newWidth / 2, -newHeight / 2);
            break;
        default:
            drawScalledImage(0, 0);
            break;
    }

    function drawScalledImage(x,y) {
        context.drawImage(image, 0, 0, width, height, x, y, newWidth, newHeight);
    }
    context.restore();

    window.context = context;
    var base64Image = canvas.toDataURL(fileType, 0.7);
    base64Image = base64Image.substring(base64Image.indexOf(',') + 1);

    //console.log("dataURL here: " + dataURL);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM