简体   繁体   中英

Trying to compress image using Canvas but JPG or PNG is returning a black image or transparent/empty image

I am trying to compress an image before upload.

Clicking on Browse button, selecting an image and in onChange calling onFileSelect function.

Here i am facing 2 issues

  1. Not able to get img width and height, not sure why it always returns zero
  2. final output dataurl is a string of characters but when loaded JPG images will be black image and for PNG it will be empty transparent box/image

Tried multiple ways but without any success.

Below is the code

//HTML

<input type="file" accept=".png,.jpg,.jpeg"  onChange=this.onFileSelect.bind(this)/>

//JS

onFileSelect(evt){
        var filesArr = evt.target.files;
        var reader = new FileReader();
        if(filesArr === undefined || filesArr.length === 0)return;
        var img = document.createElement("img");
        reader.onload = function (e) {
            img.src = e.target.result;

            var canvas = document.createElement("canvas");
            //var ctx = canvas.getContext("2d");
            //ctx.drawImage(img, 0, 0);

            var MAX_WIDTH = 400;
            var MAX_HEIGHT = 400;
            var width = img.width?img.width:MAX_WIDTH;//not getting img width so ternary operator
            var height = img.height?img.height:MAX_HEIGHT;//not getting img height so ternary operator

            if (width > height) {
                if (width > MAX_WIDTH) {
                    height *= MAX_WIDTH / width;
                    width = MAX_WIDTH;
                }
            } else {
                if (height > MAX_HEIGHT) {
                    width *= MAX_HEIGHT / height;
                    height = MAX_HEIGHT;
                }
            }
            canvas.width = width;
            canvas.height = height;
            var ctx = canvas.getContext("2d");
            ctx.drawImage(img, 0, 0, width, height);

            var dataurl = canvas.toDataURL(filesArr[0].type);
            this.setState({
                imagePath: dataurl,
                showImageEditor:true,
            })
        }
        reader.readAsDataURL(filesArr[0]);
    }

you have to render the img before you get the width

import React, { Component } from 'react'

export default class App extends Component {
  constructor() {
    super()
    this.state = {
      imagePath: '',
      showImageEditor: false,
    }
    this.onFileSelect = this.onFileSelect.bind(this)
  }
  onFileSelect(evt) {
    var filesArr = evt.target.files
    console.log('filesArr', filesArr)
    let self = this
    var reader = new FileReader()
    if (filesArr === undefined || filesArr.length === 0) return
    var img = document.createElement('img')
    reader.onload = function (e) {
      img.src = e.target.result
      var canvas = document.createElement('canvas')
      //var ctx = canvas.getContext("2d");
      //ctx.drawImage(img, 0, 0);
      img.onload = function (i) {
        
        console.log('img', img.width)
        var MAX_WIDTH = 400
        var MAX_HEIGHT = 400
        var width = img.width ? img.width : MAX_WIDTH //not getting img width so ternary operator
        var height = img.height ? img.height : MAX_HEIGHT //not getting img height so ternary operator

        if (width > height) {
          if (width > MAX_WIDTH) {
            height *= MAX_WIDTH / width
            width = MAX_WIDTH
          }
        } else {
          if (height > MAX_HEIGHT) {
            width *= MAX_HEIGHT / height
            height = MAX_HEIGHT
          }
        }
        canvas.width = width
        canvas.height = height
        var ctx = canvas.getContext('2d')
        ctx.drawImage(img, 0, 0, width, height)

        var dataurl = canvas.toDataURL(filesArr[0].type)
        self.setState({
          imagePath: dataurl,
          showImageEditor: true,
        })
      }
    }
    reader.readAsDataURL(filesArr[0])
  }
  render() {
    const {imagePath}=this.state
    return (
      <div>
        <input
          type='file'
          accept='.png,.jpg,.jpeg'
          onChange={this.onFileSelect}
        />
        {this.state.imagePath ? (
          <img src={this.state.imagePath} alt='' />
        ) : null}
      </div>
    )
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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