I'm building a mobile website which lets users upload photos from their camera.
I can get images from the users albums, and I can get images when the user takes a photo in iOS6 on iPhone4 and Android 4, but when the user takes a photo with an iPhone5 (also using iOS6), I get nothing. I can get the image from the users photo albums, but not when taking a photo.
here's the code and jsfiddle below
$('input#file_api').change(function(evt){
var image = evt.target.files[0];
var reader = new FileReader();
reader.onerror = (function(){alert('error reading file')});
reader.onload = (function(theFile) {
return function(e) {
// Render thumbnail.
var tempImg = new Image();
tempImg.src = reader.result;
tempImg.onload = function(){
var canvas = document.createElement('canvas');
canvas.width=tempImg.width;
canvas.height=tempImg.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(tempImg,0,0);
$('body').append(canvas);
})(image);
reader.readAsDataURL(image);
I've got an example here http://jsfiddle.net/8DJUy/4/
If you use the file picker to get a photo, it will append the photo to the page.
If you take a photo with an iPhone5, it won't append anything. But at the same time, it doesn't error out either.
Any suggestions on how to get around this?
I can't quite figure out what the problem is with grabbing the photo.
The reason I'm grabbing the photos like this is that the file sizes are quite large when uploaded directly from the phone, and the use case does not require high resolution images, so I'm using the canvas to resize the image before uploading it.
Try this instead:
ctx.drawImage(tempImg, 0, 0, canvas.width, canvas.height);
Related
I am using ESRI basemaps with Mapbox-GL-JS. I am trying to capture a screenshot of the map using the following code:
this.map.getCanvas().toBlob(function (blob) {
canvasContext.strokeStyle = '#CCCCCC';
canvasContext.strokeRect(leftPosition, topPosition, width, height);
var img = new Image();
img.setAttribute("crossOrigin", "anonymous");
var srcURL = URL.createObjectURL(blob);
img.onload = function () {
canvasContext.drawImage(img, leftPosition, topPosition, width, height);
URL.revokeObjectURL(srcURL);
};
img.src = srcURL;
});
I am not able to figure out why the attribution on the Map is not getting captured in the screenshot. I understand that here I am just trying to get the canvas of the map. I even tried adding text elements to the map canvas and that doesn't work either. I have markers & routes, which get in the image correctly. I also tried using the Mapbox basemap and try the same, but faced the same issue.
Any help is highly appreciated!
map.getCanvas() will only return the Map's canvas not any of the HTML Elements which sit over the map like the controls, Mapbox logo or attribution text. Sam Murphy has been working on an example showing how to capture the Map including the Logo and Attribution text to an image which you can see at https://github.com/mapbox/mapbox-gl-js/pull/6518/files.
Since we can't easily capture an HTML Element to an image in JavaScript the attribution text is re-created in a canvas drawn into the Image.
I need to dynamically add groups of multiple groups of images to the canvas, these "multi-group" will react differently depending on which of he contained groups has been dragged over by another group. I need these multi-groups to be able to be selected, rotated and dragged around the screen.
Ive chosen to use FabricJS and create images using fabric.Image.fromURL, manipulate, then add them to the canvas in a callback function. To add multiple images to a group, you nest more images in cascading callback functions as shown in this tutorial
I cant find a way to get a reference to a group of images created this way so I can add another group of images. Declaring a variable before any calls to fabric.Image.fromURL and trying to assign a reference to a created image doesnt work. The only way Ive got something working is a horrible desparate hack of adding such a group to the canvas then setting it as the active object then creating a new group and adding that active object to the group, this is soooo wrong and I dont think it will work for 3 groups. Heres my last coding attempt;
fabric.Image.fromURL('images/icon_station.png', function(img) {
var img1 = img;
fabric.Image.fromURL('images/icon_curve.png', function(img) {
img.set({left: 64,top: 64,angle: -90});
var img2 = img;
fabric.Image.fromURL('images/icon_curve.png', function(img) {
var img3 = img;
var tile_loop = new fabric.Group([img1, img2, img3]);
tile_loop.set({left: 0, top: 0, height: 64, width: 64});
canvas.add(tile_loop).setActiveObject(tile_loop);
});
});
});
fabric.Image.fromURL('images/icon_station.png', function(img) {
img.set({left: 64,top: 64});
var img1 = img;
fabric.Image.fromURL('images/icon_straight.png', function(img) {
img.set({left: 64,top: 64});
var img2 = img;
fabric.Image.fromURL('images/icon_curve.png', function(img) {
img.set({left: 64,top: 64});
var img3 = img;
var tile_loop = new fabric.Group([img1,img2,img3,canvas.getActiveObject()]);
tile_loop.set({left: 128, top: 128, height: 128, width: 128});
canvas.add(tile_loop);
});
});
});
The only other way Ive seen is to load images into html tags and create them in fabric from the tags, like this
var imgElement = document.getElementById('my-img');
var imgInstance = new fabric.Image(imgElement, {left: 100,top: 100});
canvas.add(imgInstance);
but that seems like a last resort work around, I would prefer to load images up directly in fabricjs.
Ive tried to do this in Phaser but it doesnt do groups of groups, Fabric has all the other stuff I need so I would like to stay with it, its a shame it does these weird ways of handling images.
Any help is much appreciated, if all else fails Ill use the last resort, it would be great to find a clever correct way.
I created an example in JSFiddle;
http://jsfiddle.net/d7bjbpfb/
I have a canvas on one page that is built using fabricjs
can i send that canvas to another page so that it retains all its objects as it is with all their properties and attributes to be same aswell.
Sure you can, just export your canvas to JSON
var canvas = new fabric.Canvas('c');
data = JSON.stringify(canvas)
Now you can send that data using a post request or store it in a database or whatever you want.
canvas.loadFromJSON(data, canvas.renderAll.bind(canvas));
Example: http://jsfiddle.net/P9cEf/3/
The example uses two canvases one page, but the concept is the same.
Edit:
To download the image client side
var canvas1 = document.getElementById("c");
var image = canvas1.toDataURL("image/png").replace("image/png", "image/octet-stream");
window.location.href = image;
Not sure what would be causing this, but when I upload some images to my remote server via FileTransfer(), the images sometimes show up either sideways or upside down. However, when I view the images locally on the iPhone, they are positioned in the correct way.
For example, when I select an image like this to upload: http://sharefa.st/view/WBe2QNSK8r8z
It will turn out like this: http://sharefa.st/view/EWdW1Z4G8r8z
I am using the local path to transfer the file, so I don't understand why the image would rotate "randomly".
Here is my upload function:
function uploadPhoto() {
var options = new FileUploadOptions();
options.fileKey = 'file';
options.fileName = imgURI.substr(imgURI.lastIndexOf('/')+1);
options.mimeType = 'image/jpeg';
var params = new Object();
if(logged_in == true) {
params.unique_id = app_unique_id;
params.secret_key = user_secret_key;
}
options.params = params;
loadingStart();
var ft = new FileTransfer();
ft.upload(imgURI, 'http://' + remote_server + '/API/upload', uploadDetails, fail, options);
}
imgURI value looks like this:
file://localhost/var/mobile/Applications/<snip>/tmp/photo_015.jpg
Any insight is appreciated.
Thanks to Humanoidism pointing out that the issue was in fact with the iPhone, and the way it stored images, I was able to figure out a solutuion.
To upload photos in the correct orientation you must add the correctOrientation setting to the options array in getPicture(), and set it to true.
Here are two examples:
function capturePhoto() {
navigator.camera.getPicture(onPhotoDataSuccess, onFail, { quality: 30, correctOrientation: true });
}
function getPhoto(source) {
navigator.camera.getPicture(onPhotoURISuccess, onFail, { quality: 30,
destinationType: destinationType.FILE_URI,
sourceType: source,
correctOrientation: true });
}
The problem is not PhoneGap but iPhone. The iPhone was designed to be used as a wide lens camera. Turn the phone sideways when taking pictures or capturing video if you intend to view them on desktop. Your phone will display them correctly, because it "knows" how you took them, but the computer that you're viewing it on dosen't.
What you could do to prevent this is to rotate the picture before the upload. This is not a recommended fix but at least people on desktop computers will be able to see it. Though when viewing them on iPhone they'll be rotated - maybe a check for mobile devices wether or not to rotate the image could come in handy - but still again, not recommended.
var img = new Image();
img.src = '/images/backdrop.jpg';
ctx.drawImage(img,0,0);
I wanted to load an image from local disk on to canvas using dialog box mechanism rather than the path directly specified as in above example. I tried different sorts using JavaScript but in vain, even tried using the input type as file. What else can I try?
Take a look here:
https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Using_images
It's important to have drawImage call after the image has loaded:
var img = new Image();
img.onload = function() {
var ctx = document.getElementById('ctx').getContext('2d');
ctx.drawImage(img, 0, 0);
}
img.src = 'images/backdrop.jpg';
Also, note that you probably want to use images/backdrop.jpg instead of /images/backdrop.jpg (note there's no slash in front), as using the latter would get the image from root directory, I would assume that's probably not where your images are.
As far as loading from a dialog box, you can replace the last line from the above with something like this:
var name = prompt("Enter the name of the file", "backdrop.jpg");
img.src = 'images/' + name;
This way, the user would be able to enter the name of the image file to load it. Of course, you need to have that file in your images folder.
Hope this helps.