Skip to content
canvas.js 8.93 KiB
Newer Older
Aitor Henry's avatar
Aitor Henry committed
import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import {setBeamMark,setROIMark,setPrevROIMark,setROI,updateDimensions} from '../actions/canvas.js'
Stuart Fisher's avatar
Stuart Fisher committed
import {updateBackground,setCrosshair,refreshImage} from '../actions/video.js'
import {setImgDisplay,setLiveChecked} from '../actions/options.js'
Aitor Henry's avatar
Aitor Henry committed


class Canvas extends React.Component {
  constructor(props) {
    super(props);
    this.updateImage=this.updateImage.bind(this);
    this.image = new Image();
    this.draw_Beam_Marker = this.draw_Beam_Marker.bind(this);
    this.handleMouseDown = this.handleMouseDown.bind(this);
    this.handleMouseMove = this.handleMouseMove.bind(this);
    this.draw_ROI_Marker = this.draw_ROI_Marker.bind(this);
    this.drawing = false;
    this.updateDimensions = this.updateDimensions.bind(this);
    this.canvasRef = React.createRef()
Aitor Henry's avatar
Aitor Henry committed
  }

  componentDidUpdate(prevProps){
    if (prevProps.client_id != this.props.client_id) {
      const ctx = this.canvasRef.current.getContext('2d');
      ctx.clearRect(0, 0, this.canvasRef.current.width, this.canvasRef.current.height)
    }
    if(prevProps!=this.props){
      this.updateImage(prevProps);
Aitor Henry's avatar
Aitor Henry committed
    }
  }
Aitor Henry's avatar
Aitor Henry committed

    const ctx = this.canvasRef.current.getContext('2d');
    this.image.src = "data:image/jpg;base64,"+this.props.imageSrc;
    
Aitor Henry's avatar
Aitor Henry committed
    this.image.onload = () => {
Stu Fisher's avatar
Stu Fisher committed
      ctx.drawImage(this.image, 0, 0,this.props.windowWidth,this.props.windowHeight);
Aitor Henry's avatar
Aitor Henry committed

      if(this.props.beam_markX > 0 && this.props.beam_markY > 0 && !this.props.activeROI){
        if(this.props.temperatureCheckedBool===1){
          ctx.strokeStyle = "#ffffff" // white cross
        }else{
          ctx.strokeStyle = "#ef0000" //red cross for beamlock, no color map
        }
        ctx.font = '15px Arial'
        ctx.fillStyle = "#ef0000" 
        ctx.beginPath();
        ctx.moveTo(0, this.props.beam_markY*this.props.windowHeight/this.props.imageMaxHeight);
        ctx.lineTo(this.props.windowWidth, this.props.beam_markY*this.props.windowHeight/this.props.imageMaxHeight);
        ctx.stroke();
        ctx.moveTo(this.props.beam_markX*this.props.windowWidth/this.props.imageMaxWidth, 0);
        ctx.lineTo(this.props.beam_markX*this.props.windowWidth/this.props.imageMaxWidth, this.props.windowHeight);
        ctx.stroke();
        ctx.font = '10px Arial'
        ctx.strokeText("x="+Math.round(this.props.beam_markX*this.props.calib_x)+", y="+Math.round(this.props.beam_markY*this.props.calib_y),(this.props.beam_markX*this.props.windowWidth/this.props.imageMaxWidth)+5, (this.props.beam_markY*this.props.windowHeight/this.props.imageMaxHeight)-5);
        ctx.strokeText("I="+this.props.intensityXY,(this.props.beam_markX*this.props.windowWidth/this.props.imageMaxWidth)+5, (this.props.beam_markY*this.props.windowHeight/this.props.imageMaxHeight)+10)
        ctx.closePath();
      } else {
        if(this.props.beam_markX != undefined && this.props.beam_markY != undefined){ // in order to execute it only once, 
          // this.props.setCrosshair(0,0);                                                //not everytime image is updated which will trigger webserver and tango device.
Aitor Henry's avatar
Aitor Henry committed
      }
Stu Fisher's avatar
Stu Fisher committed
      if(this.props.start_X != undefined && this.props.start_Y != undefined){
Aitor Henry's avatar
Aitor Henry committed
        this.draw_ROI_Marker()
      }
Stu Fisher's avatar
Stu Fisher committed
      if(this.props.bx>0 && this.props.by>0 && this.props.calib_x===prevProps.calib_x && this.props.calib_y===prevProps.calib_y){ // draw cross on point (x,y) found by bpm
        if(this.props.temperatureCheckedBool===1){
          // in case of colors the green cross won't be visible on green areas.
          ctx.strokeStyle = "#000000"
        }else{
          ctx.strokeStyle = "#00ff00" //green
        }
        ctx.font = '15px Arial'
        ctx.fillStyle = "#00ff00"
        ctx.beginPath();
        ctx.moveTo(0, (this.props.by/this.props.calib_y)*this.props.windowHeight/this.props.imageMaxHeight);
        ctx.lineTo(this.props.windowWidth, (this.props.by/this.props.calib_y)*this.props.windowHeight/this.props.imageMaxHeight);
        ctx.stroke();
        ctx.moveTo((this.props.bx/this.props.calib_x)*this.props.windowWidth/this.props.imageMaxWidth, 0);
        ctx.lineTo((this.props.bx/this.props.calib_x)*this.props.windowWidth/this.props.imageMaxWidth, this.props.windowHeight);
        ctx.stroke();
        ctx.closePath();
      }
      this.image.src=""; // Might avoid caching image.
Aitor Henry's avatar
Aitor Henry committed
    }
Aitor Henry's avatar
Aitor Henry committed
  }

  handleMouseDown(e){
    if(this.props.activeROI){
      this.canvasRef.current.style.cursor = "crosshair"
Aitor Henry's avatar
Aitor Henry committed
      this.drawing = true;
      this.props.setROIMark(e.nativeEvent.offsetX,e.nativeEvent.offsetY)
    }
  }

  handleMouseMove(e){
   if(this.props.activeROI && this.drawing === true){
       if(this.props.start_X != undefined && this.props.start_Y != undefined && this.props.prevY != undefined && this.props.prevY != undefined ){
         this.props.setPrevROIMark(e.nativeEvent.offsetX,e.nativeEvent.offsetY,(e.nativeEvent.offsetX - this.props.start_X),(e.nativeEvent.offsetY - this.props.start_Y));
Aitor Henry's avatar
Aitor Henry committed
      }
    }
  }

  draw_ROI_Marker(){
   if(this.props.activeROI){
     const ctx = this.canvasRef.current.getContext('2d');
Aitor Henry's avatar
Aitor Henry committed
     ctx.strokeStyle = "blue";
     ctx.beginPath();
     ctx.rect(this.props.start_X + 0.5, this.props.start_Y + 0.5,  this.props.prevX - this.props.start_X, this.props.prevY - this.start_Y);
     ctx.rect(this.props.start_X + 0.5, this.props.start_Y + 0.5,  this.props.prevX - this.props.start_X, this.props.prevY - this.props.start_Y);
     ctx.stroke();
     ctx.closePath();
   }
  }

  draw_Beam_Marker(e){
    const ctx = this.canvasRef.current.getContext('2d');
    if(!this.props.activeROI){
      if(e != undefined){
        if((this.props.beam_markX != e.nativeEvent.offsetX*this.props.imageMaxWidth/this.props.windowWidth || this.props.beam_markY != e.nativeEvent.offsetY*this.props.imageMaxHeight/this.props.windowHeight) && !this.props.lockCrosshair){ 
          this.props.setBeamMark(Math.round(e.nativeEvent.offsetX*this.props.imageMaxWidth/this.props.windowWidth),Math.round(e.nativeEvent.offsetY*this.props.imageMaxHeight/this.props.windowHeight)).then(() => {
Stuart Fisher's avatar
Stuart Fisher committed
              this.props.setCrosshair().then(() => {
                if (!this.props.liveCheckedBool) this.props.refreshImage()
              })
Aitor Henry's avatar
Aitor Henry committed
        }
      } 
    }
      else if(this.props.activeROI){
        this.drawing = false;
        this.canvasRef.current.style.cursor = "default";
        this.props.setROI().then(() => {
          if(this.props.activeBkgnd===true){ //if there is a bkg before ROI, then we need to reset it because of changes in dimensions.
            this.props.updateBackground();
          }
          this.props.setLiveChecked(0);
          this.props.setImgDisplay();
        })
Aitor Henry's avatar
Aitor Henry committed
      }
Aitor Henry's avatar
Aitor Henry committed


  updateDimensions(){
    if (window.innerWidth && window.innerHeight) this.props.updateDimensions(window.innerWidth,window.innerHeight);
Aitor Henry's avatar
Aitor Henry committed
  }

  render(){
    return <canvas 
      ref={this.canvasRef} 
      width={this.props.windowWidth} height={this.props.windowHeight} 
      onMouseDown={this.handleMouseDown} 
      onMouseMove={this.handleMouseMove} 
      onMouseUp={this.draw_Beam_Marker} 
      style={{ background:"#EFEFEF" }} />
Aitor Henry's avatar
Aitor Henry committed
  }
}


function mapStateToProps(state) {
  return {
    beam_markX:state.canvas.beam_markX,
    beam_markY:state.canvas.beam_markY,
    activeCrosshair:state.video.activeCrosshair,
    lockCrosshair: state.video.lockCrosshair,
Aitor Henry's avatar
Aitor Henry committed
    intensity:state.canvas.intensity,
    activeROI:state.video.activeROI,
    start_X:state.canvas.start_X,
    start_Y:state.canvas.start_Y,
    start_X_display: state.canvas.start_X_display,
    start_Y_display: state.canvas.start_Y_display,
Aitor Henry's avatar
Aitor Henry committed
    prevX:state.canvas.prevX,
    prevY:state.canvas.prevY,
    imageMaxWidth:state.canvas.imageMaxWidth,
    imageMaxHeight:state.canvas.imageMaxHeight,
    windowWidth:state.canvas.windowWidth,
    windowHeight:state.canvas.windowHeight,

    intensityXY:state.canvas.intensityXY,
    bx:state.canvas.bx,
    by:state.canvas.by,
    calib_x:state.options.calib_x,
    calib_y:state.options.calib_y,
    imageSrc:state.canvas.imageSrc,
    temperatureCheckedBool:state.video.temperatureCheckedBool,
    client_id: state.bpmState.client_id,
Stuart Fisher's avatar
Stuart Fisher committed
    liveCheckedBool: state.options.liveCheckedBool,
Aitor Henry's avatar
Aitor Henry committed
  };
}

function mapDispatchToProps(dispatch) {
Aitor Henry's avatar
Aitor Henry committed
  return {
    setBeamMark : bindActionCreators(setBeamMark, dispatch),
    setROIMark : bindActionCreators(setROIMark, dispatch),
    setPrevROIMark : bindActionCreators(setPrevROIMark, dispatch),
    setROI: bindActionCreators(setROI, dispatch),
    updateDimensions:bindActionCreators(updateDimensions, dispatch),
    setCrosshair: bindActionCreators(setCrosshair, dispatch),
    updateBackground: bindActionCreators(updateBackground,dispatch),
    setImgDisplay:bindActionCreators(setImgDisplay,dispatch),
    setLiveChecked:bindActionCreators(setLiveChecked,dispatch),
Stuart Fisher's avatar
Stuart Fisher committed
    refreshImage: bindActionCreators(refreshImage, dispatch),
Aitor Henry's avatar
Aitor Henry committed
  };
}

export default connect(mapStateToProps,mapDispatchToProps)(Canvas);