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

Error with Image on Xiaomi devices #239

Open
blackcand opened this issue May 6, 2020 · 0 comments
Open

Error with Image on Xiaomi devices #239

blackcand opened this issue May 6, 2020 · 0 comments

Comments

@blackcand
Copy link

_bug report

Every time I minimizing the application, I get the error of image always loss. It's just failing with xiaomi devices

with the following code:

// @flow
import * as React from "react";
import { Shaders, Node, GLSL, LinearCopy, Uniform } from "gl-react";

const shaders = Shaders.create({
    contain: {
        vert: GLSL`
        attribute vec2 _p;
        varying vec2 uv;
        uniform float tR;
        uniform vec2 res;
        float r;

        void main() {
          r = res.x / res.y;
          gl_Position = vec4(_p, 0.0, 1.0);
          uv = .5 + .5 * _p * vec2(max(r / tR, 1.), max(tR / r, 1.));
        }
    `,
        frag: GLSL`
        precision highp float;
        varying vec2 uv;
        uniform sampler2D t;
        uniform float alpha;

        void main() {
          vec4 c = texture2D(t, uv);
          gl_FragColor =
            step(0.0, uv.x) *
            step(0.0, uv.y) *
            step(uv.x, 1.0) *
            step(uv.y, 1.0) *
            c * sqrt(alpha);
        }
    `,
    },
    free: {
        vert: GLSL`
        attribute vec2 _p;
        varying vec2 uv;
        uniform float zoom;
        uniform vec2 center;
        uniform float tR;
        uniform vec2 res;
        float r;
        
        vec2 invert(vec2 p) {
          return vec2(p.x, 1.0 - p.y);
        }

        void main() {
          r = res.x / res.y;
          gl_Position = vec4(_p, 0.0, 1.0);
          // crop with zoom & center in a cover mode. preserving image ratio
          float maxR = max(r, tR);
          vec2 zoomedCanvasSize = vec2(
            (r / maxR) * zoom,
            (tR / maxR) * zoom
          );
          vec4 crop = vec4(
            center.x - zoomedCanvasSize.x / 2.,
            center.y - zoomedCanvasSize.y / 2.,
            zoomedCanvasSize.x,
            zoomedCanvasSize.y
          );
          // apply the crop rectangle
          uv = invert(invert(.5 + .5 * _p) * crop.zw + crop.xy);
        }
    `,
        frag: GLSL`
        precision highp float;
        varying vec2 uv;
        uniform sampler2D t;
        uniform float alpha;

        void main() {
          vec4 c = texture2D(t, uv);
          gl_FragColor =
            step(0.0, uv.x) *
            step(0.0, uv.y) *
            step(uv.x, 1.0) *
            step(uv.y, 1.0) *
            c * sqrt(alpha);
        }
    `,
    },
    cover: {
        // NB the cover vertex code can probably be simplified. good enough for now.
        vert: GLSL`
        attribute vec2 _p;
        varying vec2 uv;
        uniform float zoom;
        uniform vec2 center;
        uniform float tR;
        uniform vec2 res;
        float r;

        vec2 invert(vec2 p) {
          return vec2(p.x, 1.0 - p.y);
        }

        void main() {
          r = res.x / res.y;
          gl_Position = vec4(_p, 0.0, 1.0);
          // crop with zoom & center in a cover mode. preserving image ratio
          float maxR = max(r, tR);
          vec2 zoomedCanvasSize = vec2(
            (r / maxR) * zoom,
            (tR / maxR) * zoom
          );
          vec4 crop = vec4(
            center.x - zoomedCanvasSize.x / 2.,
            center.y - zoomedCanvasSize.y / 2.,
            zoomedCanvasSize.x,
            zoomedCanvasSize.y
          );
          // clamp to not escape the edges
          float w = crop[2], h = crop[3];
          float ratio = w / h;
          if (w > 1.) {
            w = 1.;
            h = w / ratio;
          }
          if (h > 1.) {
            h = 1.;
            w = h * ratio;
          }
          crop = vec4(
            max(0., min(crop.x, 1. - w)),
            max(0., min(crop.y, 1. - h)),
            w,
            h
          );
          // apply the crop rectangle
          uv = invert(invert(.5 + .5 * _p) * crop.zw + crop.xy);
        }
    `,
        frag: GLSL`
        precision highp float;
        varying vec2 uv;
        uniform sampler2D t;
        uniform float alpha;

        void main() {
          vec4 c = texture2D(t, uv);
          gl_FragColor = c * sqrt(alpha);
        }
    `,
    },
});

type ImageProps =
    | {
          source: { uri: string },
          center?: [number, number],
          zoom?: number,
          alpha?: number,
          onDraw?: () => mixed,
          resizeMode: "cover" | "free",
      }
    | {
          source: { uri: string },
          center?: [number, number],
          zoom?: number,
          alpha?: number,
          onDraw?: () => mixed,
          resizeMode: "contain",
      }
    | {
          source: { uri: string },
          center?: [number, number],
          zoom?: number,
          alpha?: number,
          onDraw?: () => mixed,
          resizeMode: "stretch",
      };

export default class Image extends React.PureComponent<ImageProps> {
    _isMounted = false;
    static defaultProps = { resizeMode: "cover", center: [0.5, 0.5], zoom: 1, alpha: 1 };

    state = { isAlready: false };

    componentDidMount() {
        this._isMounted = true;
        setTimeout(() => {
            // fix first draw is black screen ~1s
            if (this._isMounted) {
                this.setState({ isAlready: true });
            }
        }, 100);
    }

    componentWillUnmount() {
        this._isMounted = false;
    }

    render(): React.Node {
        let { source, resizeMode, center, zoom, alpha, onDraw, ...rest } = this.props;
        if (!this.state.isAlready) {
            onDraw = undefined;
        }

        if (resizeMode === "cover" || resizeMode === "free") {
            return (
                <Node
                    shader={resizeMode === "cover" ? shaders.cover : shaders.free}
                    uniforms={{
                        t: source,
                        tR: Uniform.textureSizeRatio(source),
                        res: Uniform.Resolution,
                        center,
                        zoom,
                        alpha,
                    }}
                    {...{ onDraw }}
                    {...rest}
                />
            );
        }

        if (resizeMode === "contain") {
            return (
                <Node
                    shader={shaders.contain}
                    uniforms={{
                        t: source,
                        tR: Uniform.textureSizeRatio(source),
                        res: Uniform.Resolution,
                        alpha,
                    }}
                    {...{ onDraw }}
                    {...rest}
                />
            );
        }

        // fallback on stretch, most basic thing
        return <LinearCopy {...rest}>{source}</LinearCopy>;
    }
}

library version

"gl-react": "^3.17.2",
"gl-react-expo": "^3.17.2",
"react-native-view-shot": "^3.1.2",
"react-native": "~0.61.5",

I don't find any solution for this. Any ideas?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant