How do I use a captured image with react-native-camera - reactjs

I can get the react-native-camera module to access the camera and save an image. However, I can't figure out how to display this image to the user.
What I'm trying:
Here I take the picture. This generates what looks to be a .jpg file in assets-library://....
_takePicture() {
var self = this;
this.refs.cam.capture(function(err, data) {
this.setState({photo: data});
console.log(err, data);
// data is "assets-library://asset/asset.JPG?id=########-####-####-####-##########&ext=JPG"
console.log('just took a picture');
});
}
However, If I try to render the image:
render: function() {
return(
<Image style={styles.image} source={{uri: this.state.photo}}/>
);
}
I get this error:
No suitable image URL loader found for assets-library://asset/asset.JPG?id=.......
How can I take a photo, save it to the current state of my application, and render it?

The solution was to enable the save to disk option vs. the save to cameraRoll option:
<Camera
captureTarget={Camera.constants.CaptureTarget.disk}
// Rest of Camera options here
/>

So, I was using the #YPCrumble answer for some time.
But now I have to save the image in my camera roll.
If anyone want to continue saving in camera roll, you have to manually link RTCCameraRoll library.
Documentation to link library here:
https://facebook.github.io/react-native/docs/linking-libraries-ios.html#manual-linking
It is so simple:
You can find the RCTImage.xcodeproj in your
node_modules/react-native/Libraries/CameraRoll
Drag and drop this file inside Libraries folder in your XCode project.
After that, click in your main project, and find in the right pane
"Build Phases".
Inside "Link Binary With Libraries", drag and drop the file called
"libRCTCameraRoll.a" from left pane -> Libraries ->
RTCCameraRoll.xcodeproj -> Products

Related

React Avatar Editor

I have a react component which uses DropZone.
Actions are like this:
Add image to DropZone Area.
Image added is uploaded using PHP and a URL is sent back to next step.
This step show the React Avatar Editor holding the URL to the uploaded image.
I have set up the Avatar area/component like this:
setEditorRef = (editor) => this.editor = editor
<AvatarEditor
ref={this.setEditorRef}
image={this.state.image} // URL to uploaded image
scale={this.state.scale}
position={this.state.position}
onPositionChange={this.handlePositionChange}
style={{width: '310px', height: '263px'}}
border={10}
color={[255, 255, 255, 0.8]} // RGBA
rotate={this.state.rotate}
/>
What I need (AFTER dragging the image around, scaling it or rotating) is to send the image within the canvas to a php script, and save it. I know how to do this, but I cannot figure out how to access the image "constrained" by the canvas?
I've tried Avatar Editor's solutions (mentioned on the github).
this.editor.getImageScaledToCanvas().toDataURL('image/jpeg', 1);
and
this.editor.getImage();
But using axios and
let formData = new FormData();
formData.append('file', linkToCanvas);
does not work. (LinkToCanvas) should be the image held by the Avatar Canvas.
I also have the following issue after Image upload (solving this one enables me to solve the first issue as well, as I know the orientation of the image shown):
When uploading (4mb+) image files, I strip the EXIF information, save the image and returns a URL to Avatar Editor pointing to the new image.
If the image is vertical - Avatar shows the image horizontally (even when removing the EXIF info from the jpegs). Any way to force React to load an image 1-to-1, as it is stored on my server?
Any help is HIGHLY appreciated, as I've been struggling with this for a week now :-(
I know it's a long question. But I'm hoping for a short answer.
Thanks
The problem is that editor is not added to references.
To fix this, declare editor before constructor
...
import AvatarEditor from 'react-avatar-editor';
class YourClassName extends React.Component<any, any> {
editor: AvatarEditor;
constructor(props: Props) {
...
change setEditorFunction to this
setEditorRef = (editor: any) => {
if (editor) {
this.editor = editor;
const img = this.editor.getImageScaledToCanvas().toDataURL();
console.log(img);
}
}
And the last step change reference in component
<AvatarEditor
image={this.state.image}
width={this.state.width}
height={this.state.height}
color={[0, 0, 0, 0.6]}
scale={this.state.scale}
rotate={this.state.rotate}
position={this.state.position}
borderRadius={this.state.borderRadius}
ref={(ref) => this.setEditorRef(ref)}
onLoadSuccess={this.loadSuccess}
/>
A workaround but maybe not the best solution to Avatar Editor forcing rotate on jpgs. I use php to detect EXIF data. Rotate if this is needed. Then create a png from the jpg. Then save it and unlink “old jpg”. And finally return its location to my react script.
This solves the rotation problem. So now I can crop/rotate the image on the canvas and using the
getCroppingRect()
I can retrieve x, y, width and height and handle crop serverside. Finally enabling me to store the crop area.
However a new problem is now issued, as the editor rotates the image around its canvas center, so even if I can retrieve coordinates for the cropscript, as well as the rotation angle, its still misplaced, as php’s rotateimage rotates on the image center.
Anyone know how to rotate an image on a canvas around the image center?

Meteor FS link leads to 404 Error

I am currently developing a Meteor React app, which is using the ostrio:files package to store audio files in a collection named Files. In another (regular mongo) collection, I am using the following code in the transform function to "join" the document with the link to the audio file:
transform: function(doc){
let curAudio = doc.audio;
let audioFile = Files.collection.findOne({_id: curAudio.file_id});
if(audioFile){
curAudio.audioLink = Files.link(audioFile);
curAudio.audioLength = audioFile.meta.length;
curAudio.audioSize = audioFile.size;
doc.audio = curAudio;
}
return doc;
}
This seems to work just fine, as the resulting audio.audioLink is something like
http://localhost:3000/cdn/storage/files/8Q7WwEXyJSkNWwFQa/original/8Q7WwEXyJSkNWwFQa.m4a
But when I try to do something like this
<audio controls preload="none" style={{width: "480px"}}>
<source src={track.audioLink} type="audio/mp4"/>
<p>Your browser does not support HTML5 audio.</p>
</audio>
To be able to play the file, everything works until I click the play button of the HTML5 player. Then, chrome outputs to the console, that the server returned 404 when the file was supposed to be loaded. I tested putting the link into the adress bar, here the server response is just
File Not Found :(
Does anyone have an idea how to fix this?
I found the answer:
My local Ubuntu installation was apparently configured to store uploaded files in /tmp, which didn't caus problems until I restarted the system or cleared my temporary files otherwise. Having the server recreate the DB fixed the problem.

How to UPLOAD a file into my JS application?

I am working on extjs 4.2 application. Trying to create a menu toolbar where I can add and delete files. For example:
When I press Open, I want to see the file browser window. And when I finish choosing the file and click "open", I will see something like this:
I know that I need to use onItemClick() function to open the browser. But I have no idea how to call that window. Also how can you program so only certain file extensions can be chosen.
I am guessing that once you press "open" on the file browser window, the file tree in the left panel will dynamically add that file. But have no idea how can I connect "open" to my tree.
Just to clarify - this is going to be user based app, it is not going to be a webapp. This will be opened in user's browser and that is it. No need to get some info from server or send something to client.
EDIT: I have been able to solve the part where you click on Open the file browser dialog pops up. Then when I select a file and press "open", it displays a message box with file's name.
Here is the code for that part:
var item = Ext.create('Ext.form.field.File', {
buttonOnly: true,
buttonText: 'Open',
hideLabel: true,
listeners: {
'change': function(fb, v){
Ext.Msg.alert('Status', v);
}
}
});
var mainmenu = Ext.create('Ext.menu.Menu', {
width: 200,
margin: '0 0 10 0',
items: [item]
});
Now the problem is that I need to get the FULL PATH of the file. This message only shows file's name. Any help?
Using files on the web can be tricky, so you're going to have to be patient, diligent, and be prepared for some self-learning.
A. If you want to be compatible with all browsers, you need to upload the file to a server, and have the server return info about the file. Or you can try Sencha Desktop Packager, flash, or signed Java Applets.
If you are okay with only modern browsers, you will need to read and learn the HTML5 File API. Here's a start:
https://developer.mozilla.org/en-US/docs/Web/API/FileReader?redirectlocale=en-US&redirectslug=DOM%2FFileReader
B. Start with a filefield button for now, and add it as a menuitem later, just to keep things simple. You will want to listen to the filefield's change event if you want to read the file.
C. To restrict file types (only modern browsers allow this), you'll need to do something like this (audio/* is just an example):
{
xtype:'filefield',
listeners:{
afterrender:function(cmp){
cmp.fileInputEl.set({
accept:'audio/*'
});
}
}
}
D. After you get the file, you will want to add it's info to the tree's TreeStore.

how to clear the file name list after fineUploader (3.5) uploads file

I download fine uploader 3.5, created http handler for a file upload function in my little website . the website is done by asp.net ajax and jquery. it runs at IE9. every time I upload a file, there is a list of file names shown below the load button. if I don't want thme, what should I do?
my code is like this:
html: ...
'<tr><td><div id="jquery-wrapped-fine-uploader"></div></td></tr>...
'ajax/jquery:...
'$('#jquery-wrapped-fine-uploader').fineUploader({
'request: { endpoint: 'xxx.ashx' }
'})
'$('#jquery-wrapped-fine-uploader').on("complete",
'function (event, id, fileName, responseJSON) {
' alert("UPLOAD SUCCESS");
' $.ajax({some ajax calls here});
' })
// WHERE TO PUT this TO CLEAR the UPLOADED FILE LIST??? $('#jquery-wrapped-fine-uploader').fineUploader('reset');
XXX.ashx:
'... public void ProcessRequest (HttpContext context) {
'do some http request work..
'context.Response.ContentType = "text/plain";
'context.Response.Write("{\"success\":true}");
'}
My question is:
I want to completely remove the uploaded file list which shows automatically in green color ( or red if they fail), in order to clear them, I tried to put: $('#jquery-wrapped-fine-uploader').fineUploader('reset'); right after .on('complete'), it's not working, also #jquery-wrapped-fine-uploader seems cached all the time. please help on this.
If you don't want to see the file list at all, you should be using FineUploaderBasic mode instead of using FineUploader mode and then removing all elements in the pre-built UI. FineUploaderBasic mode gives you access to the API, options, and callbacks, but assumes you will be creating your own UI. In other words, FineUploaderBasic mode does not create any DOM elements (except the opaque file input element as a child of your button container, if you supply one). This is all explained (in a great amount of detail) in the documentation.
Start here: http://docs.fineuploader.com

Opened file gets cached in titanium. Cant view replaced file content while app is running

I am facing a slight issue while editing a file.
I am saving a file (image) with a certain name on ios using the code below.
But the problem is that when i replace the image stored in a file (eg temp.jpg) the app still picks up the previous image when i open the file. However the new image can be seen in the explorer.
If i restart the app the new image appears while opening the image.
var folder = Ti.Filesystem.getFile(Ti.Filesystem.externalStorageDirectory, 'DocImages');
// DocImages is a folder for files
// ImageVar contains the blob for the new image from camera or gallery
// docImgModel is the model class containing the name and image path of the image
if(imageVar !== null && imageVar !== undefined){
if (docImgModel.imagePath !== null && docImgModel.imagePath !== undefined){
tempFile = Ti.Filesystem.getFile(docImgModel.imagePath);
if (tempFile.exists()) {
tempFile.deleteFile(); // deleting already existing file
}}
// in case of changing the image stored in a file(the case in which i have a
// problem) the imgFile(below) is same as docImgModel.imagePath (above)
imgFile = Ti.Filesystem.getFile(Ti.Filesystem.externalStorageDirectory + 'DocImages/', filenameWithExtension); // creating a new file
// writing image to file
imgFile.write(imageVar);
Ti.API.info('new image saved');
}
}
I was wondering if titanium saves cache of the file already opened and is hence not able to show the new image.
If not, is there anything else i am doing wrong or something i could do to make it work.
I just want to show the new saved image. Is there any way to do it.
Thanks.
I haven't worked with opening files from the device, but I ran into a similar issue when trying to update data on my screen. If you are saying when you open the app and it loads the correct image comes up, then the code that you use to load the image appears correct and working. I assume that is the code you posted above. Even that appears to be a code fragment of a more complete file.
You didn't post any UI code, which is probably where your real problem is coming from. You have an object, a view of some sort I'm guessing, that is already rendered using the old image before you load the new image. So debugging, you might see the new image's data loaded in the code above, but the UI element hasn't been assigned or updated correctly.
As a test, I would suggest that you put some test code into your app that allows you to destroy your UI elements and recreate them, you will probably see the picture come up properly in that case.
According to this post: http://developer.appcelerator.com/question/31181/simple-image-refresh
Just assigning the image you loaded to the url of the image should update it. Your example code doesn't show the image object that you are attempting to update and how that communication is made from the code that is loading the image.
// this sets the background color of the master UIView (when there are no windows/tab groups on it)
Titanium.UI.setBackgroundColor('#000');
// create tab group
var tabGroup = Titanium.UI.createTabGroup();
var image1 = 'image1.png';
var image2 = 'image2.png';
//
// create base UI tab and root window
//
var win1 = Titanium.UI.createWindow({
title:'Tab 1',
backgroundColor:'#fff'
});
var tab1 = Titanium.UI.createTab({
icon:'KS_nav_views.png',
title:'Tab 1',
window:win1
});
var img = Titanium.UI.createImageView({
width:100,
height:100,
top:50,
left:110,
url:image1
});
win1.add(img);
var btn = Titanium.UI.createButton({
title:'load',
width:100,
height:35,
top:50,
left:0
});
function switchImage(){
if(img.url == image1){
img.url = image2;
} else {
img.url = image1;
}
}
btn.addEventListener('click',function(){
switchImage();
});
setInterval(switchImage,3000);
win1.add(btn);
//
// add tabs
//
tabGroup.addTab(tab1);
// open tab group
tabGroup.open();

Resources