preface

Some phones, including the iPhone and some Samsung phones, had the image rotated 90 degrees D when taking photos and uploading images using the Input TAB. The problem only occurs when the phones are taken vertically, so the picture will look fine when taken horizontally. Therefore, you can solve this problem by getting the camera Angle of the phone to rotate the photo.

Orientation

Not all pictures have this parameter, but the pictures taken by the phone have this parameter.

Rotation Angle The parameter value
0 ° 1
Clockwise 90 ° 6
90 ° anticlockwise 8
180 ° 3

When the parameter is 1, the display is normal, so in these mobile phones with normal horizontal display, namely Orientation = 1, the parameter of vertical shoot is 6.

To get Orientation parameters, use the exif.js library. Exif.js has a lot of features and a large volume, 30K before compression, which has a great impact on mobile page loading. I just need to get the Orientation information, so HERE I cut some of the exif.js library code down to a few kilobytes.

Exif.js get Orientation:

EXIF.getData(file, function() {  
    var Orientation = EXIF.getTag(this.'Orientation');
});Copy the code

File is the file uploaded to the input file form. FileReader. ReadAsDataURL (file) can be used to preview the image

rotating

The rotate() method of the canvas is used.

ctx.rotate(angle);Copy the code

The rotate method takes radians of rotation. Need to convert Angle to radians: degrees * math.pi / 180

By default, the center of rotation is at the starting point of the canvas, i.e. (0, 0). The principle of rotation is shown as follows:

Rotation schematic

After the rotation, if you drawImage() from (0, 0), the position you draw is 90 degrees from the image on the left, not visible. When I rotate it, I rotate the axis, and if I want it to be visible, I move (0, 0) y units in the opposite direction of the y axis, and I start at (0, -y).

Similarly, we can obtain the starting point of rotation -90 degrees is (-x, 0), and rotation 180 degrees is (-x, -y).

The compression

Cell phone photos are too large, and base64 encoded photos are larger than the original, so compression is necessary when uploading. Nowadays, mobile phones have such high pixels, and the photos taken are thousands of pixels in width and height. It is relatively slow to render the photos with canvas.

Therefore, the first step is to limit the width and height of the uploaded photo, judge whether the width or height exceeds any range, and then compress its width and height equally.

var ratio = width / height;
if(imgWidth > imgHeight && imgWidth > xx){
    imgWidth = xx;
    imgHeight = Math.ceil(xx / ratio);
}else if(imgWidth < imgHeight && imgHeight > yy){
    imgWidth = Math.ceil(yy * ratio);
    imgHeight = yy;
}Copy the code

The second step is to compress the photo quality with the canvas.todataURL () method.

canvas.toDataURL("image/jpeg".1);Copy the code

The toDataURL() method returns a data URI containing the image presentation. Use two parameters, the first parameter is the image format, the default is image/ PNG. The second parameter is compression quality, which can be selected from 0 to 1 if the image format is image/ JPEG or image/webp.

conclusion

Taken together, the sample code includes the simplified exif.js library address: file-demo

The main core code is as follows:

<input type="file" id="files" >
<img src="blank.gif" id="preview">
<script src="small-exif.js"></script>
<script>
var ipt = document.getElementById('files'),
    img = document.getElementById('preview'),
    Orientation = null;
ipt.onchange = function () {
    var file = ipt.files[0],
        reader = new FileReader(),
        image = new Image();

    if(file){
        EXIF.getData(file, function() {  
            Orientation = EXIF.getTag(this.'Orientation');
        });
        reader.onload = function (ev) {
            image.src = ev.target.result;
            image.onload = function () {
                var imgWidth = this.width,
                    imgHeight = this.height;
                // Control the width and height of the uploaded image
                if(imgWidth > imgHeight && imgWidth > 750){
                    imgWidth = 750;
                    imgHeight = Math.ceil(750 * this.height / this.width);
                }else if(imgWidth < imgHeight && imgHeight > 1334){
                    imgWidth = Math.ceil(1334 * this.width / this.height);
                    imgHeight = 1334;
                }

                var canvas = document.createElement("canvas"),
                ctx = canvas.getContext('2d');
                canvas.width = imgWidth;
                canvas.height = imgHeight;
                if(Orientation && Orientation ! =1) {switch(Orientation){
                        case 6:     // Rotate 90 degrees
                            canvas.width = imgHeight;    
                            canvas.height = imgWidth;    
                            ctx.rotate(Math.PI / 2);
                            // (0, -imgheight) The starting point obtained from the rotation schematic
                            ctx.drawImage(this.0, -imgHeight, imgWidth, imgHeight);
                            break;
                        case 3:     // Rotate 180 degrees
                            ctx.rotate(Math.PI);    
                            ctx.drawImage(this, -imgWidth, -imgHeight, imgWidth, imgHeight);
                            break;
                        case 8:     // Rotate -90 degrees
                            canvas.width = imgHeight;    
                            canvas.height = imgWidth;    
                            ctx.rotate(3 * Math.PI / 2);    
                            ctx.drawImage(this, -imgWidth, 0, imgWidth, imgHeight);
                            break; }}else{
                    ctx.drawImage(this.0.0, imgWidth, imgHeight);
                }
                img.src = canvas.toDataURL("image/jpeg".0.8); } } reader.readAsDataURL(file); }}</script>Copy the code

More articles:lin-xin/blog

WeChat appreciates

Thank you for your support