Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Question] what is this error? #280

Open
jonatasfernandespimenta opened this issue Dec 14, 2020 · 2 comments
Open

[Question] what is this error? #280

jonatasfernandespimenta opened this issue Dec 14, 2020 · 2 comments

Comments

@jonatasfernandespimenta
Copy link

jonatasfernandespimenta commented Dec 14, 2020

Hey, I'm using Expo and I'm having the following error when running my Expo app on IOS (it works on android):

Possible Unhandled Promise Rejection (id: 2):
String {
  "0": "E",
  "1": "X",
  "10": "l",
  "11": "i",
  "12": "d",
  "13": " ",
  "14": "p",
  "15": "i",
  "16": "x",
  "17": "e",
  "18": "l",
  "19": " ",
  "2": "G",
  "20": "d",
  "21": "a",
  "22": "t",
  "23": "a",
  "24": " ",
  "25": "a",
  "26": "r",
  "27": "g",
  "28": "u",
  "29": "m",
  "3": "L",
  "30": "e",
  "31": "n",
  "32": "t",
  "33": " ",
  "34": "f",
  "35": "o",
  "36": "r",
  "37": " ",
  "38": "g",
  "39": "l",
  "4": ":",
  "40": ".",
  "41": "t",
  "42": "e",
  "43": "x",
  "44": "I",
  "45": "m",
  "46": "a",
  "47": "g",
  "48": "e",
  "49": "2",
  "5": " ",
  "50": "D",
  "51": "(",
  "52": ")",
  "53": "!",
  "6": "I",
  "7": "n",
  "8": "v",
  "9": "a",
}

My code:
Image.js

import React from 'react';
import rectCrop from 'rect-crop';
import rectClamp from 'rect-clamp';
import { Surface } from "gl-react-expo";
import { GLSL, Node, Shaders } from "gl-react";

const shaders = Shaders.create({
  image: {
    frag: GLSL`
      precision highp float;
      varying vec2 uv;
      uniform sampler2D t;
      uniform vec4 crop;
      vec2 invert (vec2 p) {${'' /* y is reversed in gl context */}
        return vec2(p.x, 1.0-p.y);
      }
      void main () {
        vec2 p = invert(invert(uv) * crop.zw + crop.xy);
        gl_FragColor =
          step(0.0, p.x) *
          step(0.0, p.y) *
          step(p.x, 1.0) *
          step(p.y, 1.0) *
          texture2D(t, p);
      }
    `,
  },
});

export default class Image extends React.PureComponent {
  render() {

    const { width, height, source, imageSize, resizeMode = 'cover', center, zoom } = this.props;

    if (!imageSize) {
      if (source.width && source.height) {
        imageSize = { width: source.width, height: source.height };
      } else {
        throw new Error(
          "gl-rect-image: imageSize is required if you don't provide {width,height} in source",
        );
      }
    }
    let crop;
    switch (resizeMode) {
      case 'cover': {
        if (!center) center = [0.5, 0.5];
        if (!zoom) zoom = 1;
        let rect = rectCrop(zoom, center)({ width, height }, imageSize);
        rect = rectClamp(rect, [0, 0, imageSize.width, imageSize.height]);
        crop = [
          rect[0] / imageSize.width,
          rect[1] / imageSize.height,
          rect[2] / imageSize.width,
          rect[3] / imageSize.height,
        ];

        break;
      }
      case 'contain': {
        if (center || zoom) {
          console.log(
            "gl-react-image: center and zoom props are only supported with resizeMode='cover'",
          );
        }
        const ratio = width / height;
        const imageRatio = imageSize.width / imageSize.height;
        crop =
          ratio > imageRatio
            ? [(1 - ratio / imageRatio) / 2, 0, ratio / imageRatio, 1]
            : [0, (1 - imageRatio / ratio) / 2, 1, imageRatio / ratio];
        break;
      }
      case 'stretch':
        if (center || zoom) {
          console.log(
            "gl-react-image: center and zoom props are only supported with resizeMode='cover'",
          );
        }
        crop = [0, 0, 1, 1];
        break;

      default:
        throw new Error('gl-react-image: unknown resizeMode=' + resizeMode);
    }

    return (
      <Node
      shader={shaders.image}
      uniforms={{
        t: { uri: source.uri },
        crop,
      }}
      />
    );
  }
}

ImageCrop

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { View, Image, PixelRatio, PanResponder } from 'react-native';
import { Surface } from 'gl-react-expo';
import GLImage from './Image';

const imageDimensionsAfterZoom = (viewport, dimensions, zoom) => {
  const ImageRatio = dimensions.width / dimensions.height;
  const ViewportRatio = viewport.width / viewport.height;
  if (ImageRatio > ViewportRatio) {
    return {
      height: Math.floor(viewport.height / zoom),
      width: Math.floor((viewport.height * ImageRatio) / zoom),
    };
  } else
    return {
      height: Math.floor(viewport.width / ImageRatio / zoom),
      width: Math.floor(viewport.width / zoom),
    };
};

const movementFromZoom = (gestureState, viewport, dimensions, offsets, zoom) => {
  let newPosX, newPosY;
  // X-axis
  let widthOffset = dimensions.width - viewport.width;
  let pxVsMovX = 1 / dimensions.width;
  let moveX = gestureState.dx * pxVsMovX * zoom;
  newPosX = parseFloat(offsets.x) - parseFloat(moveX);

  // Y-axis
  let heightOffset = dimensions.height - viewport.height;
  let pxVsMovY = 1 / dimensions.height;
  let moveY = gestureState.dy * pxVsMovY * zoom;
  newPosY = parseFloat(offsets.y) - parseFloat(moveY);
  return {
    x: newPosX,
    y: newPosY,
  };
};


class ImageCrop extends Component {
  constructor(props) {
    super(props);
    this.state = {
      zoom: 1,

      //pan settings
      centerX: 0.5,
      centerY: 0.5,

      //Image sizes
      imageHeight: 300,
      imageWidth: 300,
      imageDimHeight: 0,
      imageDimWidth: 0,
      currentCapture: '',
    };

    this.surfaceCont = React.createRef();
  }

  async captureSurface() {
    const pictureSave = await this.surfaceCont.current.glView.capture();
    return pictureSave;
  }

  UNSAFE_componentWillMount() {
    Image.getSize(this.props.image, (width, height) => {
      //update state
      this.setState({
        imageHeight: height,
        imageWidth: width,
      });
    });

    //
    //get dimensions after crop
    //
    this._dimensionAfterZoom = imageDimensionsAfterZoom(
      { height: this.props.cropHeight, width: this.props.cropWidth },
      { height: this.state.imageHeight, width: this.state.imageWidth },
      this.state.zoom,
    );

    this.setState({
      imageDimHeight: this._dimensionAfterZoom.height,
      imageDimWidth: this._dimensionAfterZoom.width,
    });

    this._panResponder = PanResponder.create({
      onStartShouldSetPanResponder: (evt, gestureState) => true,
      onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
      onMoveShouldSetPanResponder: (evt, gestureState) => true,
      onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,
      onPanResponderTerminationRequest: (evt, gestureState) => false,
      onShouldBlockNativeResponder: (evt, gestureState) => true,

      onPanResponderGrant: (evt, gestureState) => {
        //move variables
        this.offsetX = this.state.centerX;
        this.offsetY = this.state.centerY;

        //zoom variables
        this.zoomLastDistance = 0;
        this.zoomCurrentDistance = 0;
      },

      onPanResponderMove: (evt, gestureState) => {
        //We are moving the image
        if (evt.nativeEvent.changedTouches.length <= 1) {
          var trackX = (gestureState.dx / this.props.cropWidth) * this.state.zoom;
          var trackY = (gestureState.dy / this.props.cropHeight) * this.state.zoom;
          var newPosX = Number(this.offsetX) - Number(trackX);
          var newPosY = Number(this.offsetY) - Number(trackY);
          if (newPosX > 1) newPosX = Number(1);
          if (newPosY > 1) newPosY = Number(1);
          if (newPosX < 0) newPosX = Number(0);
          if (newPosY < 0) newPosY = Number(0);

          var movement = movementFromZoom(
            gestureState,
            { width: this.props.cropWidth, height: this.props.cropHeight },
            {
              width: this.state.imageDimWidth,
              height: this.state.imageDimHeight,
            },
            { x: this.offsetX, y: this.offsetY },
            this.state.zoom,
          );
          this.setState({ centerX: movement.x });
          this.setState({ centerY: movement.y });
        } else {
          //We are zooming the image
          if (this.zoomLastDistance == 0) {
            let a =
              evt.nativeEvent.changedTouches[0].locationX -
              evt.nativeEvent.changedTouches[1].locationX;
            let b =
              evt.nativeEvent.changedTouches[0].locationY -
              evt.nativeEvent.changedTouches[1].locationY;
            let c = Math.sqrt(a * a + b * b);
            this.zoomLastDistance = c.toFixed(1);
          } else {
            let a =
              evt.nativeEvent.changedTouches[0].locationX -
              evt.nativeEvent.changedTouches[1].locationX;
            let b =
              evt.nativeEvent.changedTouches[0].locationY -
              evt.nativeEvent.changedTouches[1].locationY;
            let c = Math.sqrt(a * a + b * b);
            this.zoomCurrentDistance = c.toFixed(1);

            //what is the zoom level
            var screenDiagonal = Math.sqrt(
              this.state.imageHeight * this.state.imageHeight +
                this.state.imageWidth * this.state.imageWidth,
            );
            var distance = (this.zoomCurrentDistance - this.zoomLastDistance) / 400;
            var zoom = this.state.zoom - distance;

            if (zoom < 0) zoom = 0.0000001;
            if (zoom > 1) zoom = 1;
            this.setState({
              zoom: zoom,
            });
            //Set last distance..
            this.zoomLastDistance = this.zoomCurrentDistance;
          }
        }
      },
    });
  }
  UNSAFE_componentWillReceiveProps(nextProps) {
    if (this.props.zoom != nextProps.zoom) {
      var zoom = (100 - nextProps.zoom) / 100;
      this.setState({ zoom: zoom });
    }

    //
    //get dimensions after crop
    //
    this._dimensionAfterZoom = imageDimensionsAfterZoom(
      { height: this.props.cropHeight, width: this.props.cropWidth },
      { height: this.state.imageHeight, width: this.state.imageWidth },
      this.state.zoom,
    );

    this.setState({
      imageDimHeight: this._dimensionAfterZoom.height,
      imageDimWidth: this._dimensionAfterZoom.width,
    });
  }
  render() {
    return (
      <View {...this._panResponder.panHandlers}>
        <Surface
          style={{ width: this.props.cropWidth, height: this.props.cropHeight }}
          pixelRatio={this.props.pixelRatio}
          backgroundColor="transparent"
          ref={this.surfaceCont}
        >
          <GLImage
            height={this.props.cropHeight}
            width={this.props.cropWidth}
            source={{ uri: this.props.image }}
            imageSize={{
              height: this.state.imageHeight,
              width: this.state.imageWidth,
            }}
            resizeMode="cover"
            zoom={this.state.zoom}
            center={[this.state.centerX, this.state.centerY]}
          />
        </Surface>
      </View>
    );
  }
  crop() {
    return this.surfaceCont.current.glView.capture({
      quality: this.props.quality,
      type: this.props.type,
      format: this.props.format,
      filePath: this.props.filePath,
    });
  }
}
ImageCrop.defaultProps = {
  image: '',
  cropWidth: 300,
  cropHeight: 300,
  zoomFactor: 0,
  minZoom: 0,
  maxZoom: 100,
  quality: 1,
  pixelRatio: PixelRatio.get(),
  type: 'jpg',
  format: 'base64',
  filePath: '',
};
ImageCrop.propTypes = {
  image: PropTypes.string.isRequired,
  cropWidth: PropTypes.number.isRequired,
  cropHeight: PropTypes.number.isRequired,
  zoomFactor: PropTypes.number,
  maxZoom: PropTypes.number,
  minZoom: PropTypes.number,
  quality: PropTypes.number,
  pixelRatio: PropTypes.number,
  type: PropTypes.string,
  format: PropTypes.string,
  filePath: PropTypes.string,
};

export default ImageCrop;

I really don't know what to do and I didn't find anything on internet :/

@jonatasfernandespimenta jonatasfernandespimenta changed the title what is this error? [Question] what is this error? Dec 14, 2020
@gre gre self-assigned this Dec 23, 2020
@Shamash2014
Copy link

@gre @jonatasfernandespimenta I got this error when actually the url of the image is null or some empty string

@gre
Copy link
Owner

gre commented Dec 26, 2020

I can't reproduce this (at least not in latest versions)

I tried to do

//@flow
import React, { Component } from "react";
import { Shaders, Node, GLSL } from "gl-react";
import { Surface } from "../../gl-react-implementation";

const shaders = Shaders.create({
  DiamondCrop: {
    frag: GLSL`
precision highp float;
varying vec2 uv;
uniform sampler2D t;
void main() {
gl_FragColor = mix(
  texture2D(t, uv),
  vec4(0.0),
  step(0.5, abs(uv.x - 0.5) + abs(uv.y - 0.5))
);
}`,
  },
});

export const DiamondCrop = ({ children: t }) => (
  <Node shader={shaders.DiamondCrop} uniforms={{ t }} />
);

export default class Example extends Component {
  render() {
    const { width } = this.props;
    return (
      <Surface style={{ width, height: width }}>
        <DiamondCrop>{{ uri: "" }}</DiamondCrop>
      </Surface>
    );
  }
}

and it doesn't crash with this error. it renders white (as the uri is invalid) and it just have a warning about the wrong url.

Capture d’écran 2020-12-26 à 17 32 19

Capture d’écran 2020-12-26 à 17 32 22

any help on this is welcomed because I can't reproduce. (or need a very minimal example i can play with)

@gre gre removed their assignment Dec 26, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants