【问题标题】:Image rotation in Angular4Angular4中的图像旋转
【发布时间】:2018-01-18 03:06:22
【问题描述】:

我正在尝试在上传到我的服务器之前旋转图像。到目前为止我采取的步骤是:

  1. 将图像转换为 Base64。
  2. 使用画布旋转 base64 字符串。
  3. 将旋转后的 Base64 转换为图像。

但我无法将其转换回图像格式。最终图像文件(旋转后)无法上传,因为它是一个 blob。

您能否告诉我如何将旋转后的 Base64 字符串转换为图像文件,以便我可以创建一个 blob 并上传它。

我想我的旋转函数也不正确,因为我试图转换它并将转换后的 base64 字符串在https://codebeautify.org/base64-to-image-converter 上查看,它给了我一个空白文件(黑色图像文件)。

此问题的根源是当用户在 iOS 或 Android 上单击图像并将其上传时,图像会出现横向显示。为了解决这个问题,我尝试根据其 EXIF 方向旋转图像。

function detectFiles(event) {
    this.getOrientation(event.target.files[0], function (orientation) {
        this.imageOrientation = orientation;
    }.bind(this));
    console.log('the original image data', event.target.files);
    this.selectedFiles = event.target.files;

    // SAS : Converting the selected image to Base64 for rotation.
    const reader = new FileReader();
    reader.onloadend = (e) => {
        this.base64Data = reader.result;
        const rotatedData = this.rotateBase64Image(this.base64Data);

        // SAS: Calling the data uri to blob
        const selFile = this.dataURItoBlob(rotatedData);
        this.uploadFiles(selFile);
    }

    reader.readAsDataURL(event.target.files[0]);

}

// SAS: Rotate the image.
function rotateBase64Image(base64ImageSrc) {
    const canvas = document.createElement('canvas');
    const img = new Image();
    img.onload = function () {
        canvas.width = img.width;
        canvas.height = img.height;
        console.log('image height and width', canvas.width , canvas.height);
    }
    img.src = base64ImageSrc;
    const context = canvas.getContext('2d');
    context.translate((img.width), (img.height));
    // context.rotate(180 * (Math.PI / 180));
    context.rotate(90);
    context.drawImage(img, 0, 0);
    console.log(canvas);
    console.log('the rotated image', canvas.toDataURL());
    return canvas.toDataURL();
}

// SAS: Data URI to Blob
function dataURItoBlob(dataURI) {
    // convert base64 to raw binary data held in a string
    // doesn't handle URLEncoded DataURIs
    const byteString = atob(dataURI.split(',')[1]);

    // separate out the mime component
    const mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]

    // write the bytes of the string to an ArrayBuffer
    const ab = new ArrayBuffer(byteString.length);

    // create a view into the buffer
    const ia = new Uint8Array(ab);

    // set the bytes of the buffer to the correct values
    for (let i = 0; i < byteString.length; i++) {
        ia[i] = byteString.charCodeAt(i);
    }

    // write the ArrayBuffer to a blob, and you're done
    const blob = new Blob([ab], {type: mimeString});
    console.log('the value of the blob', blob);
    return blob;
}

在此之后,我尝试使用以下接受图像文件的函数上传数据。

uploadFiles(selFile) {
    // SAS: Setting the 'image uploaded flag' to be retrieved in quick post to prevent duplicate placeholders.

    // const file = this.selectedFiles.item(0);
    const file = selFile;
    this.currentUpload = new Upload(file);

// This is the API call to upload the file.
    this.storageApiService.createBlob(file).subscribe((response) => {

      console.log(response);
    }, (error) => {
      console.log(error);
    });
  }
}

【问题讨论】:

    标签: javascript angular image


    【解决方案1】:

    您可以为他们处理 exif 旋转,这样他们就不必旋转图像

    我创建了一个库,无需使用名为 screw-filereader 的文件阅读器,而且只需调用 blob.image().then(success, fail) 即可非常轻松地从 blob 创建图像,它会为您处理图像 exif 旋转。

    // unrelevant code (just to get a rotated image with exif metadata)
    var exifImage = 'https://cors-anywhere.herokuapp.com/http://duckz.serveblog.net/risorse/foto/francia/P1831_21-02-10.jpg'
    
    fetch(exifImage)
      .then(res => res.blob())
      .then(blob => {
    
        // just to show the problem you have with your image
        const objectURL = URL.createObjectURL(blob)
        const img = new Image()
        img.src = objectURL
        document.body.appendChild(img)
        
        // what screw-filereader can do (auto rotate based on exif data)
        // will resolve at img.onload event with a new img element
        // will also cast a error if blob isn't a image (img.onerror)
        // this is what you need...
        blob.image().then(img => {
         
          // convert image back to blob
          var canvas = document.createElement('canvas')
          canvas.width = img.width
          canvas.height = img.height
          const ctx = canvas.getContext('2d')
          ctx.drawImage(img, 0, 0)
          canvas.toBlob(uploadFiles)
          
          // just to show the rotated image 
          document.body.appendChild(img)
        })
      })
      
    function uploadFiles(blob) {
      // upload blob
    }
    img {
      width: 100px
    }
    &lt;script src="https://cdn.jsdelivr.net/npm/screw-filereader@1.4.3/index.min.js"&gt;&lt;/script&gt;

    额外提示,使用 canvas.toBlob 而不是使用 dataURItoBlob

    【讨论】:

    • 感谢您的宝贵回答,这肯定会帮助很多面临同样问题的人。虽然由于某种原因,当我尝试使用它时,但它给了我错误“类型 blob 上不存在属性图像”..
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多