gre / gl-react

gl-react – React library to write and compose WebGL shaders
https://gl-react-cookbook.surge.sh
MIT License
2.94k stars 163 forks source link

How to capture effected image and save it to file? #93

Closed kesha-antonov closed 4 years ago

kesha-antonov commented 7 years ago

Hello!

In v2 we've had captureFrame function. https://github.com/ProjectSeptemberInc/gl-react-native/blob/cf77646239ee1c9d6002c28cb8864cb65d2de898/src/GLCanvas.js#L55

But there is no such function in "v3", right? Or I can save image with capture() somehow?

Please help.

I've asked something similar in "v2" repo: https://github.com/ProjectSeptemberInc/gl-react-native/issues/96

question

library version: gl-react/next + gl-react-native/next

gl-react@3.0.0-alpha.6
gl-react-native@3.0.0-alpha.6

Expected behavior

Expected to find some simple function to call and save effected image to file in cache directory

refs.surface.captureFrame({
       type: 'jpg'
       format: 'file'
       quality: 1
       filePath: "#{RNFS.DocumentDirectoryPath}/#{new Date().getTime()}.jpg"
}).then((newImageUri) =>
 ....

Actual behavior

this.refs.surface.capture()

returns array of pixels (right?)

kesha-antonov commented 6 years ago

@gre Ok. great. Yes, let's go through "temporary" path and build that feature in RN-webgl. And when RN will support native arrays we move it away.

Since your code works on that commit (I didn't test) I think I'll be able to do android implementation. I'll try that in next weeks when will have free time 👍

What about video? Is it possible to save effected video somehow?

gre commented 6 years ago

capturing to a video? haven't explored that yet, I have no experience in the subject, technically possible i guess, like probably would need to record the GL framebuffer.

kesha-antonov commented 6 years ago

Yes. I need to implement that too If you'll find or have some information about it (maybe links to useful articles) please post it here. I'll dive into source code in this weekend. Since I noob in OpenGL I need all useful info 😄

kesha-antonov commented 6 years ago

Maybe this would work? https://github.com/yzhong52/Save-OpenGL-Framebuffer-As-Video

gre commented 6 years ago

maybe? feels weird to need dep to opencv tho but maybe there is no other way?

kesha-antonov commented 6 years ago

As I said I am noob in OpenGL right now. I'll explore this question in weekend and hope will answer to that questions 👍

ghost commented 6 years ago

Sorry for the bump guys but if anybody has anything new on this, feedback welcome 😄

kesha-antonov commented 6 years ago

Hello! @kytwb Still couldn't create something useful. Waiting for this feature too

moeedshahid commented 6 years ago

CaptureFrame() returns (GLCanvas is unmounting)

"gl-react": "^2.2.4", "gl-react-native": "^2.48.0",

m stuck there ! can someone plz help i cant figure out how to get rid of this

gre commented 6 years ago

"gl-react": "^2.2.4", "gl-react-native": "^2.48.0",

for this library version please use repository https://github.com/gre/gl-react-native-v2 , discussion here is on the v3

moeedshahid commented 6 years ago

i m already using https://github.com/gre/gl-react-native-v2 and issue is in there sir ! For your information ! https://github.com/gre/gl-react-native-v2/issues/117

kesha-antonov commented 6 years ago

Hello! Any news? Almost year passed. @gre Do you have plans to work on this?

gre commented 6 years ago

I'll discuss with expo folks on how they intend to solve it in Expo and see what we can do to backport to react-native-webgl. also Expo have a new version of GLView, backed by opengl 3, so I might look at this as well. but it's tricky to maintain react-native-webgl on my own , with limited time

kesha-antonov commented 6 years ago

@gre Thanks for taking your time on this!

gre commented 6 years ago

BTW expo have now a solution for this https://docs.expo.io/versions/v27.0.0/sdk/gl-view#takesnapshotasyncoptions and when we'll figure out how to merge it back to react-native-webgl it will benefit for all ;)

ghost commented 6 years ago

@gre thanks for the update!

moeedshahid commented 6 years ago

you can use react-native-fs for this purpose !

here's the code

var path = RNFS.DocumentDirectoryPath + '/' + filename (the name you want to write the edited image into) ; var config = { quality: 0.8, type: 'jpeg', format: 'file', filePath: path } this.image.captureFrame(config) .then(response => { console.log(response) //response consist of the temporary path that can be used to upload the image on a server })

Regards !

On Wed, May 9, 2018 at 10:03 AM, Amine Mouafik notifications@github.com wrote:

@gre https://github.com/gre thanks for the update!

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/gre/gl-react/issues/93#issuecomment-387620836, or mute the thread https://github.com/notifications/unsubscribe-auth/Agip36YmRwFojujuWQK8ShwhsT8s07Y1ks5twnijgaJpZM4MxWCG .

kesha-antonov commented 6 years ago

@moeedshahid You can do this only in v2, right? You can see same code in the first comment

kesha-antonov commented 6 years ago

@gre Thanks for the update! Still waiting for this 🔥

moeedshahid commented 6 years ago

@kesha-antonov yes i have a lot trouble configuring it with v3 so i downgraded to v2 !

Jose4gg commented 6 years ago

@gre Do you have an ETA for this feature?

ParhamZare commented 6 years ago

Hi Can Apply Filter without Surface And GLIImage like pass image base64 , apply filter and return base64 filtered image ? because the crop function have problem decrease image quality thanks

yedeba commented 6 years ago

@kesha-antonov Hi, please, any example for capture() method in expo?. I'm not working. Thanks.

meinto commented 6 years ago

Did anyone implement it for react-native by now? :)

yedeba commented 6 years ago

How can I access to capture method declared in the GLViewNative class? capture = ( opt: * ): Promise<{ uri: string, localUri: string, width: number, height: number }> => { const { ref } = this; if (!ref) return Promise.reject(new Error("glView is unmounted")); return ref.takeSnapshotAsync(opt); };

yedeba commented 6 years ago

I already found out. In case someone helps: let result = await this.refs.surface.glView.capture();

JinHoSo commented 6 years ago

@gre Do you have an ETA for this feature?

alidawud commented 6 years ago

Any updates?

ankhanguit commented 6 years ago

Awsome @yedeba, i have used your way. it is successful. For who using Expo, this is my code:

import { Surface } from "gl-react-expo";

<Surface 
            ref={view => (this.imageFilter = view)} 
            style={styles.photoTakenSection}>
            <ImagePreview picture={picture} selected={filterSelected}/>
</Surface>

_uploadPhoto = async () => { let pictureSave = await this.imageFilter.glView.capture(); )

The result will have uri of picture, and then you can use it to display or upload on server.

yedeba commented 6 years ago

👍👍👍

gre commented 6 years ago

great 😝

dorthwein commented 6 years ago

Is there a non-expo solution for this? :(

gre commented 6 years ago

unfortunately for now this feature is only built-in in Expo and not yet backported to react-native-webgl

elfstyle commented 6 years ago

Hi! this feature worked on Tuesday but on Friday it started to return black pics. I even made test blank project for testing, but result was the same. What changed?

"gl-react-expo": "^3.16.3", "gl-react-image": "^3.1.1",

import React from 'react';
import {
  CameraRoll,
} from 'react-native';
import { Surface } from 'gl-react-expo'
import GLImage from 'gl-react-image'

export default class HomeScreen extends React.Component {

  handleOnLoad = async () => {
    const result = await this.SurfaceRef.glView.capture();
    console.log(result);
    CameraRoll.saveToCameraRoll(result.uri);
    console.log('done');
  }

  render() {
    return (
      <Surface
        ref={ref => this.SurfaceRef = ref}
        style={{ width: 300, height: 300 }}
        onLoad={this.handleOnLoad}
      >
        <GLImage
          source={{ uri: "http://i.imgur.com/tCatS2c.jpg" }}
        />
      </Surface>
    );
  }
}
elfstyle commented 6 years ago

Found out that Surface onLoad called handleOnLoad before render finished, if I call handleOnLoad manually, it works.

serhiipalash commented 6 years ago

@elfstyle try to add preload prop to the Surface https://github.com/gre/gl-react/issues/159#issuecomment-329705242

elfstyle commented 6 years ago

preload helped 👍

mopilo commented 5 years ago

any update on this issue ??

0plus1 commented 5 years ago

Hi @elfstyle , @yedeba , @ankhanguit ,

As experts of capturing using expo, is there a reason why my images are always 2400x2400? Is there a way to force a size, like with: https://docs.expo.io/versions/v31.0.0/sdk/gl-view#expoglviewtakesnapshotasyncgl-options

additionally I cannot seem to track down any documentation regarding glView.capture() is it a binding to what?

Thanks

moxxuk commented 5 years ago

Any news on the backporting for non-expo users?

david-saint commented 5 years ago

It's like from one issue to the other. I'm tired. I give up.

gre commented 4 years ago

This issue is now fixed in gl-react-native @ 4, the decision has been to upgrade to expo-gl implementation. https://github.com/gre/gl-react/blob/master/packages/gl-react-native/README.md

You can use the surface capture method.

ghost commented 4 years ago

I want to make an image edit app with image crop. To crop image i have used the ImageZoom, which works as I wanted. and I have used surface to capture the image. but the problem is I want to use ImageZoom inside the surface and desired that, surface should capture the zoomed image. is it possible?Here my code:

import { Surface } from 'gl-react-expo';
import ImageFilters from 'react-native-gl-image-filters';
import ImageZoom from 'react-native-image-pan-zoom';

<Surface style={{ width:300, height: 300}} ref={ref => (this.image = ref)}>
        <ImageZoom cropWidth={200} ref={ref=>{console.log(ref)}}  //Image Zoom is not working inside surface
                       cropHeight={200}
                       imageWidth={200}
                       imageHeight={200}> 
          {/* <Surface style={{ width:200, height: 200}} ref={ref => (this.image = ref)}> */}

            <ImageFilters {...this.state} 
                          width={200} 
                          height={200}
            >
              {{ uri: this.state.captureImageUrl }}
            </ImageFilters>
            {/* </Surface> */}
            </ImageZoom>
            </Surface>