Crop the image using JavaScript - javascript

In my Angular 6 application I am making a file upload option and in preview the uploaded file needs to be displayed with auto cropping and auto resizing.
I have tried the following,
HTML:
<canvas id="canvas"></canvas>
<div style="display:none;">
<img id="source" [src]="url" width="300" height="227">
</div>
<input type='file' (change)="onSelectFile($event)">
File select functtion:
onSelectFile(event) {
if (event.target.files && event.target.files[0]) {
var reader = new FileReader();
reader.readAsDataURL(event.target.files[0]); // read file as data url
reader.onload = (event) => { // called once readAsDataURL is completed
this.url = event.target.result;
}
const canvas : any = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const image = document.getElementById('source');
ctx.drawImage(image, 33, 71, 104, 124, 21, 20, 87, 104);
}
}
In the above I have tried the following with the reference of link https://jsfiddle.net/8jwq3cs7/
const canvas : any = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const image = document.getElementById('source');
ctx.drawImage(image, 33, 71, 104, 124, 21, 20, 87, 104);
Before using the canvas the original image looks like this: https://mdn.mozillademos.org/files/5397/rhino.jpg
Whereas after using canvas it's like this: https://jsfiddle.net/8jwq3cs7/
But if I choose the image from choose file then I am unable to see the image after choosing...
Working example: https://stackblitz.com/edit/angular-file-upload-preview-uwpf8f
Even the solution with pure JavaScript alone would also be appreciable if not in the Angular way...
The requirement is, if I choose a file then the same file needs to be cropped and fit the size automatically in preview...
Kindly help me to achieve the result without jQuery or any library...

Here is a function to get the image as you are uploading using the choose file button
function readURL() {
const myimg = document.getElementById("myimg");
const input = document.getElementById("myfile");
if(input.files && input.files[0]) {
const reader = new FileReader();
reader.onload = e => {
console.log("changed");
myimg.src = e.target.result;
};
reader.readAsDataURL(input.files[0]);
}
}
document.querySelector('#myfile').addEventListener('change', () => {
readURL();
});
And the HTML will be
<img src="" id="myimg"><br>
<input type="file" id="myfile">
Here is a working fiddle
If you add a file the preview image will be updated.
You actually get a data url here. Use the data url to the load the image to the canvas then crop it. calling drawimg(e.target.result)
function drawimg(idata) {
const img = new Image();
img.onload = () => {
ctx.drawImage(img, 33, 71, 104, 124, 21, 20, 87, 104);
};
img.src = idata;
}
See working Fiddle: here

Here is how I implemented it in my case:
onSelectFile(event) {
if (event.target.files && event.target.files[0]) {
var reader = new FileReader();
reader.readAsDataURL(event.target.files[0]); // read file as data url
reader.onload = (event) => { // called once readAsDataURL is completed
console.log(event);
this.url = event.target.result;
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const image = new Image();
image.src = this.url;
ctx.drawImage(image, 33, 71, 104, 124, 21, 20, 87, 104);
}
The working stackblitz demo is here : https://stackblitz.com/edit/angular-file-upload-preview-qrrgx5
Hope it helps and this is what you want.

I'm a bit late to the party on this one, but I was facing a very similar issue myself yesterday, but instead using NodeJS.
My solution in the end was to break down the image into its RGBA values and check each row and column of the image to find where the image itself actually starts in comparison to the BG.
In my case, I'm working with images that are around 1500px*500px, with my solution taking around 150-250ms per image to read in the file, break down its pixels, calculate the cropping positions and to write the cropped file back to disk.
Since I couldn't find any nice libraries online to handle this, I've made my own and published it to NPM in case anyone else comes across the same issue and needs some help! :-)
https://www.npmjs.com/package/developyn-autocrop

<html>
<head>
<style>
#preview {
background: red;
border: 1px solid green;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="http://jcrop-cdn.tapmodo.com/v0.9.12/js/jquery.Jcrop.min.js"></script>
<link rel="stylesheet" href="http://jcrop-cdn.tapmodo.com/v0.9.12/css/jquery.Jcrop.css" type="text/css" />
<script type="text/javascript">
$(document).delegate(':file', 'change', function() {
picture(this);
console.log('running');
});
//$(document).delegate(':form', 'change', function() {
var picture_width;
var picture_height;
var crop_max_width = 300;
var crop_max_height = 300;
function picture(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$("#jcrop, #preview").html("").append("<img src=\""+e.target.result+"\" alt=\"\" />");
picture_width = $("#preview img").width();
picture_height = $("#preview img").height();
$("#jcrop img").Jcrop({
onChange: canvas,
onSelect: canvas,
boxWidth: crop_max_width,
boxHeight: crop_max_height
});
}
reader.readAsDataURL(input.files[0]);
}
}
function canvas(coords){
var imageObj = $("#jcrop img")[0];
var canvas = $("#canvas")[0];
canvas.width = coords.w;
canvas.height = coords.h;
var context = canvas.getContext("2d");
context.drawImage(imageObj, coords.x, coords.y, coords.w, coords.h, 0, 0, canvas.width, canvas.height);
png();
}
function png() {
var png = $("#canvas")[0].toDataURL('image/png');
$("#png").val(png);
}
function dataURLtoBlob(dataURL) {
var BASE64_MARKER = ';base64,';
if(dataURL.indexOf(BASE64_MARKER) == -1) {
var parts = dataURL.split(',');
var contentType = parts[0].split(':')[1];
var raw = decodeURIComponent(parts[1]);
return new Blob([raw], {type: contentType});
}
var parts = dataURL.split(BASE64_MARKER);
var contentType = parts[0].split(':')[1];
var raw = window.atob(parts[1]);
var rawLength = raw.length;
var uInt8Array = new Uint8Array(rawLength);
for(var i = 0; i < rawLength; ++i) {
uInt8Array[i] = raw.charCodeAt(i);
}
return new Blob([uInt8Array], {type: contentType});
}
</script>
</head>
<body>
<form id="form">
<h2>Image file select</h2>
<input id="file" type="file" onchange="imageLoad()" />
<h2>Uploaded Image</h2>
<div id="jcrop"></div>
<h2>Cropped Image</h2>
<canvas id="canvas"></canvas>
<input id="png" type="hidden" />
<h2>Submit form</h2>
<input type="submit" value="Upload form data and image" />
</form>
</body>
</html>

// Set constraints for the video stream
var constraints = { video: { facingMode: "user" }, audio: false };
// Define constants
const cameraView = document.querySelector("#camera--view"),
cameraOutput = document.querySelector("#camera--output"),
cameraSensor = document.querySelector("#camera--sensor"),
cameraTrigger = document.querySelector("#camera--trigger")
// Access the device camera and stream to cameraView
function cameraStart() {
navigator.mediaDevices
.getUserMedia(constraints)
.then(function(stream) {
track = stream.getTracks()[0];
cameraView.srcObject = stream;
})
.catch(function(error) {
console.error("Oops. Something is broken.", error);
});
}
// Take a picture when cameraTrigger is tapped
cameraTrigger.onclick = function() {
cameraSensor.width = cameraView.videoWidth;
cameraSensor.height = cameraView.videoHeight;
cameraSensor.getContext("2d").drawImage(cameraView, 0, 0);
cameraOutput.src = cameraSensor.toDataURL("image/webp");
cameraOutput.classList.add("taken");
};
// Start the video stream when the window loads
window.addEventListener("load", cameraStart, false);
html, body{
margin: 0;
padding: 0;
height: 100%;
width: 100%;
}
#camera, #camera--view, #camera--sensor, #camera--output{
position: fixed;
height: 100%;
width: 100%;
object-fit: cover;
}
#camera--view, #camera--sensor, #camera--output{
transform: scaleX(-1);
filter: FlipH;
}
#camera--trigger{
width: 200px;
background-color: black;
color: white;
font-size: 16px;
border-radius: 30px;
border: none;
padding: 15px 20px;
text-align: center;
box-shadow: 0 5px 10px 0 rgba(0,0,0,0.2);
position: fixed;
bottom: 30px;
left: calc(50% - 100px);
}
.taken{
height: 100px!important;
width: 100px!important;
transition: all 0.5s ease-in;
border: solid 3px white;
box-shadow: 0 5px 10px 0 rgba(0,0,0,0.2);
top: 20px;
right: 20px;
z-index: 2;
}
<html lang=”en”>
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Name of your awesome camera app -->
<title>Camera App</title>
<!-- Link to your main style sheet-->
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- Camera -->
<main id="camera">
<!-- Camera sensor -->
<canvas id="camera--sensor"></canvas>
<!-- Camera view -->
<video id="camera--view" autoplay playsinline></video>
<!-- Camera output -->
<img src="//:0" alt="" id="camera--output">
<!-- Camera trigger -->
<button id="camera--trigger">Take a picture</button>
</main>
<!-- Reference to your JavaScript file -->
<script src="app.js"></script>
</body>
</html>

Related

Adjusting the brightness of an image using canvas context in Microsoft Edge

I am building an application where I need to be able to capture a frame-grab from a web camera and upload it to the application. To do this, I am using WebRTC to capture the image from the video stream, write it to a canvas, and then grab the data and upload it. This works fine for the most part. However, I needed to give the user a way to adjust the brightness. To accomplish this, I added a slider to the page with the video stream on it, that applies "style.webkitFilter = 'brightness(X%)'" when adjusted. Again, this works fine, but did not adjust the brightness of the captured image, just the displayed video stream. The javascript function I use to actually capture the image is:
function takepicture() {
var context = canvas.getContext('2d');
var b = document.getElementById('txtBrightness').value;
if (width && height) {
canvas.width = width;
canvas.height = height;
context.filter = 'brightness(' + b + '%)';
context.drawImage(video, 0, 0, width, height);
var data = canvas.toDataURL();
//photo.setAttribute('src', data);
//alert(data);
document.getElementById('Image').value = data;
//$("#Image").val(data);
$("#form1").submit();
} else {
clearphoto();
}
}
This works in Chrome, Firefox, and the Chromium based version of Edge, however, it does NOT work in the EdgeHTML versions of Edge. In those versions of Edge, the video stream is correctly displayed with the adjusted brightness, but the captured image does not have the brightness adjusted. Is there a workaround to make context filters work with the EdgeHTML versions of the Edge browser?
From the CanvasRenderingContext2D.filter, it seems that CanvasRenderingContext2D.filter not support Microsoft Edge browser (EdgeHtml version).
As a workaround, you could try to use Konva plugin to apply filter to an image.
Sample code as below:
<head>
<meta charset="utf-8" />
<title></title>
<script src="https://unpkg.com/konva#4.1.3/konva.min.js"></script>
<meta charset="utf-8" />
<title>Konva Brighten Image Demo</title>
<style>
body {
margin: 0;
padding: 0;
overflow: hidden;
background-color: #f0f0f0;
}
#slider {
position: absolute;
top: 20px;
left: 20px;
}
</style>
</head>
<body>
<div id="container"></div>
<input id="slider" type="range" min="-1" max="1" step="0.05" value="0" />
<script>
function loadImages(sources, callback) {
var images = {};
var loadedImages = 0;
var numImages = 0;
for (var src in sources) {
numImages++;
}
for (var src in sources) {
images[src] = new Image();
images[src].onload = function () {
if (++loadedImages >= numImages) {
callback(images);
}
};
images[src].src = sources[src];
}
}
function buildStage(images) {
var stage = new Konva.Stage({
container: 'container',
width: window.innerWidth,
height: window.innerHeight
});
var layer = new Konva.Layer();
var lion = new Konva.Image({
image: images.lion,
x: 80,
y: 30,
draggable: true
});
lion.cache();
lion.filters([Konva.Filters.Brighten]);
layer.add(lion);
stage.add(layer);
var slider = document.getElementById('slider');
slider.oninput = function () {
lion.brightness(slider.value);
layer.batchDraw();
};
}
var sources = {
lion: '/images/lion.png'
};
loadImages(sources, buildStage);
</script>
</body>
The output like this:

Cant get firebase to stop overriding old pictures when I upload them in javascript/jquery

Firebase overirdes my old pictures each time I upload the new picture, I want it to save my old pictures
<!DOCTYPE html>
<html>
<head>
<title>Firebase Storage</title>
</head>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="form1" runat="server">
<input type='file' id="imgInp" />
<img id="blah" src="#" alt="your image" />
<button type="submit" onclick="window.open('#blah')">Download!</button>
</form>
<a download="new-image.png" id="download">Download</a>
<label>Image File:</label>
<br/>
<button onclick="myFunction()">Click me</button>
<button onclick="myFunctiondown()">Click me</button>
<button onclick="myFunctionleft()">Click me</button>
<button onclick="myFunctionleft2()">Click me</button>
<button onclick="myFunctiontext()">Click me</button>
<input type="file" id="imageLoader" name="imageLoader" />
<h1>Example of using <code><canvas></code></h1>
<p>This example shows how a photo is loaded in a <code><canvas></code> tag and then flipped.</p>
<p>Click on the photo to flip (provided, of course, that your browser supports <code><canvas></code>)</p>
<canvas id="canvas" style="border:1px red solid;"></canvas>
<a download="new-image.png" id="download">Download</a>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="add-download-btn.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://www.gstatic.com/firebasejs/5.8.0/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/5.8.0/firebase-storage.js"></script>
<h1>Firebase Storage</h1>
<input type="file" id="fileButton">
<div id="image" style=""></div>
<script src="https://www.gstatic.com/firebasejs/5.8.6/firebase.js"></script>
<style>
img {
height: 200px;
width: 200px;
}
#image{
height:250px;
width:250px;
float:left;
}
#dwnld{
float:left;
}
.button {
appearance: button;
-moz-appearance: button;
-webkit-appearance: button;
text-decoration: none; font: menu; color: ButtonText;
display: inline-block; padding: 2px 8px;
font-size: 15px;
}
.btn {
padding: 5px 10px;
font-size: 16px;
border-radius: 3px;
border: solid 1px #C0392B;
background-color: #E74C3C;
text-decoration: none;
color: white;
}
.btn:hover {
opacity: .9;
}
.btn:active {
opacity: 1;
}
canvas {
height: 50vh;
}
</style>
<script>
// Initialize Firebase
var config = {
apiKey: "AIzaSyAMEuYur7_ExqF92Os02kRlZbSXIHdfDjE",
authDomain: "danniauth.firebaseapp.com",
databaseURL: "https://danniauth.firebaseio.com",
projectId: "danniauth",
storageBucket: "danniauth.appspot.com",
messagingSenderId: "279422179745"
};
firebase.initializeApp(config);
</script>
<script>
//$(document).ready(function () {
// $("#blah").click(function () {
// $("img").animate({
// height: '+=5px',
// width: '+=5px'
// });
// var button = document.getElementById('download');
// button.setAttribute( 'href', can.toDataURL('image/png', 1) );
// });
// });
var imageLoader = document.getElementById('imageLoader');
imageLoader.addEventListener('change', handleImage, false);
var can = document.getElementById('canvas');
var ctx = can.getContext('2d');
var img = new Image();
function handleImage(e) {
var reader = new FileReader();
reader.onload = function(event) {
img.onload = function() {
can.width = img.width;
can.height = img.height;
ctx.drawImage(img, 0, 0, img.width, img.height);
ctx.save();
}
img.src = event.target.result;
}
reader.readAsDataURL(e.target.files[0]);
}
function myFunction() {
console.log('here');
can.width = img.width;
can.height = img.height;
ctx.translate(img.width - 500, img.height - 505);
ctx.rotate(Math.PI/2);
ctx.translate(-(img.width - 500), -(img.height - 505));
ctx.drawImage(img, 60, 60, img.width, img.height);
var button = document.getElementById('download');
button.setAttribute( 'href', can.toDataURL('image/png', 1) );
};
function myFunctiondown() {
console.log('here');
can.width = img.width;
can.height = img.height;
ctx.translate(img.width - 1, img.height - 1);
ctx.rotate(Math.PI);
// ctx.translate(-(img.width - 500), -(img.height - 505));
ctx.drawImage(img, 0, 0, img.width, img.height);
var button = document.getElementById('download');
button.setAttribute( 'href', can.toDataURL('image/png', 1) );
};
function myFunctionleft() {
console.log('here');
can.width = img.width;
can.height = img.height;
ctx.translate(img.width - 500, img.height - 500);
ctx.rotate(Math.PI/360);
ctx.translate(-(img.width - 500), -(img.height - 505));
ctx.drawImage(img, 0, 0, img.width, img.height);
var button = document.getElementById('download');
button.setAttribute( 'href', can.toDataURL('image/png', 1) );
};
function myFunctionleft2() {
console.log('here');
can.width = img.width;
can.height = img.height;
ctx.translate(img.width - 500, img.height - 500);
ctx.rotate(270 * Math.PI / 180);
ctx.translate(-(img.width - 500), -(img.height - 505));
ctx.drawImage(img, 164, 164, img.width, img.height);
var button = document.getElementById('download');
button.setAttribute( 'href', can.toDataURL('image/png', 1) );
};
//////////////////////////////
// function readURL(input) {
// if (input.files && input.files[0]) {
// var reader = new FileReader();
// reader.onload = function(e) {
// $('#blah').attr('src', e.target.result);
// }
// reader.readAsDataURL(input.files[0]);
// }
//}
//$("#imgInp").change(function() {
// readURL(this);
//});
//$('#download').attr('scr', e.target.result())
/*
*
* Create a variable to reference the upload button.
*
*/
var fileButton = $('#fileButton' );
/*
*
* Add a change event listener the upload button.
*
*/
fileButton.change(function(event){
// ImageTools.resize(this.files[0], {
// width: 320, // maximum width
// height: 240 // maximum height
// }, function(blob, didItResize) {
// didItResize will be true if it managed to resize it, otherwise false (and will return the original file as 'blob')
// document.getElementById('image').src = window.URL.createObjectURL(blob);
// you can also now upload this blob using an XHR.
// });
/*
* Create a variable and get the relevant file objec
*/
var file = event.target.files[0];
/*
* Create a Firebase reference for a new image.
*user/number.jpg
*/ //+ new Date().getTime() + file.name).put(file);
var ref = firebase.storage().ref('/images/testing.jpg');
var user = firebase.auth().currentUser;
var storageRef = firebase.storage().ref("user");
var userRef = storageRef.child(user.uid);
firebase.auth().onAuthStateChanged(function(user) {
if( user )
{
$('.unauthed').hide();
$('.authed').show();
console.log(user.uid);
}
else
{
}
});
/*
* Upload the file using the Firebase reference.
*/
userRef.put(file);
ref.put(file);
/*
* Retrieve the full URL of the uploaded file and place it into an IMG tag
* in the DIV with the id of IMAGE.
*$('#image').width(100);
*/
ref.getDownloadURL().then(function(url){
$('#image').html('<img src="'+url+'">');
});
});
</script>
</body>
</html>
Currently you upload files with:
userRef.put(file);
ref.put(file);
Every time you run this code, it adds the data to the exact same location, overwriting whatever you previously wrote at that location.
To store multiple files, you'll need to create a new unique StorageReference each time you want to upload a file. A simple way to do that would be to use the timestamp in the file name:
userRef.child(Date.now()).put(file);
This means that each file is stored in a "folder" for the user, and then with the current timestamp under there.

Change canvas shape

What I'd like to achieve: I need to load different images in different canvas, move and resize them and show a preview. I'm using fabricJs. With rectangular canvas everything works fine, the problem is when I want to concatenate canvas with a diagonal section. Something like this:
I tried something with the transform property in CSS, but then I could no longer interract with the canvas. Any idea on how to do this? Or is there a way to have only one canvas with something like sections?
What I have right now (only part of the code to interract with the canvas, the preview it's another canvas where I draw again everything):
$( document ).ready(function() {
addImage('canvas1', 'imageLoader1');
addImage('canvas2', 'imageLoader2');
});
function addImage(canvas, input) {
var canvas = new fabric.Canvas(canvas);
document.getElementById(input).addEventListener('change', function (e) {
var file = e.target.files[0];
var reader = new FileReader();
reader.onload = function (f) {
var data = f.target.result;
fabric.Image.fromURL(data, function (img) {
var oImg = img.set({
left: 0,
top: 0,
angle: 00,
width: 100,
height: 100
}).scale(0.9);
canvas.add(oImg).renderAll();
var a = canvas.setActiveObject(oImg);
var dataURL = canvas.toDataURL({
format: 'png',
quality: 0.8
});
});
};
reader.readAsDataURL(file);
});
}
.container {
width: 544px;
}
.canvas-container {
float: left;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.12/fabric.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div class="container">
<canvas id="canvas1" width="272px" height="465px"></canvas>
<canvas id="canvas2" width="272px" height="465px" style="float: left;"></canvas>
</div>
<div>
<input type="file" id="imageLoader1" name="imageLoader1"/>
<input type="file" id="imageLoader2" name="imageLoader1"/>
</div>
</body>
In reply to #Observer comment:
clipTo is deprecated since v2.0.0. You could achieve this with clipPath (which is more powerful and more flexible than clipTo since it accepts a fabric.Object):
const canvas = new fabric.Canvas("canvas", {backgroundColor: "#d3d3d3"})
const container = new fabric.Rect({
width: 200,
height: 200,
left: 100,
top: 100,
})
const obj = new fabric.Circle({
radius: 50,
left: 150,
top: 150,
fill: "blue"
})
canvas.clipPath = container
canvas.add(obj)
canvas.requestRenderAll()
#canvas {
background: #e8e8e8;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/4.0.0-beta.5/fabric.min.js"></script>
<canvas id="canvas" width="400" height="400"></canvas>

webcam photo saving to hard disk using php script is not working

This code is not working to save the photo on hard disk, so can anybody please tell me which code will used to save a photo to hard disk.
<html>
<head>
<div id="my_camera" style="width:520px; height:440px;margin-left:180px;"></div>
<div id="my_result" style="position:absolute;margin-left:740px;margin-top:-440px;"></div>
<script src="cam/webcam.js"></script>
<script type="text/javascript">
Webcam.attach('#my_camera');
function take_snapshot() {
Webcam.set({
width: 320,
height: 240,
dest_width: 640,
dest_height: 480,
image_format: 'jpg',
jpeg_quality: 90,
force_flash: false,
flip_horiz: true,
fps: 45
});
Webcam.snap(function(data_uri) {
document.getElementById('my_result').innerHTML = '<img src="' + data_uri + '"/>';
});
}
</script>
Take Snapshot
</head>
</html>
<?php
move_uploaded_file($_FILES['webcam']['tmp_name'], 'webcam.jpg');
?>
You need to post the captured image to php, for that you can use jquery .ajax(), here's a complete example:
upload.php
<?php
$img = !empty($_REQUEST['imgBase64']) ? $_REQUEST['imgBase64'] : die("No image was posted");
$imgName = $_REQUEST['imgName'];
$img = str_replace('data:image/png;base64,', '', $img);
$img = str_replace(' ', '+', $img);
$fileData = base64_decode($img);
//saving
file_put_contents($imgName, $fileData);
Now the js/jquery, css and html:
(function() {
// The width and height of the captured photo. We will set the
// width to the value defined here, but the height will be
// calculated based on the aspect ratio of the input stream.
var width = 320; // We will scale the photo width to this
var height = 0; // This will be computed based on the input stream
// |streaming| indicates whether or not we're currently streaming
// video from the camera. Obviously, we start at false.
var streaming = false;
// The various HTML elements we need to configure or control. These
// will be set by the startup() function.
var video = null;
var canvas = null;
var photo = null;
var startbutton = null;
function startup() {
video = document.getElementById('video');
canvas = document.getElementById('canvas');
photo = document.getElementById('photo');
startbutton = document.getElementById('startbutton');
navigator.getMedia = (navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia);
navigator.getMedia({
video: true,
audio: false
},
function(stream) {
if (navigator.mozGetUserMedia) {
video.mozSrcObject = stream;
} else {
var vendorURL = window.URL || window.webkitURL;
video.src = vendorURL.createObjectURL(stream);
}
video.play();
},
function(err) {
console.log("An error occured! " + err);
}
);
video.addEventListener('canplay', function(ev) {
if (!streaming) {
height = video.videoHeight / (video.videoWidth / width);
// Firefox currently has a bug where the height can't be read from
// the video, so we will make assumptions if this happens.
if (isNaN(height)) {
height = width / (4 / 3);
}
video.setAttribute('width', width);
video.setAttribute('height', height);
canvas.setAttribute('width', width);
canvas.setAttribute('height', height);
streaming = true;
}
}, false);
startbutton.addEventListener('click', function(ev) {
takepicture();
ev.preventDefault();
}, false);
clearphoto();
}
// Fill the photo with an indication that none has been
// captured.
function clearphoto() {
var context = canvas.getContext('2d');
context.fillStyle = "#AAA";
context.fillRect(0, 0, canvas.width, canvas.height);
var data = canvas.toDataURL('image/png');
photo.setAttribute('src', data);
}
// Capture a photo by fetching the current contents of the video
// and drawing it into a canvas, then converting that to a PNG
// format data URL. By drawing it on an offscreen canvas and then
// drawing that to the screen, we can change its size and/or apply
// other changes before drawing it.
function takepicture() {
var context = canvas.getContext('2d');
if (width && height) {
canvas.width = width;
canvas.height = height;
context.drawImage(video, 0, 0, width, height);
var data = canvas.toDataURL('image/png');
photo.setAttribute('src', data);
$.ajax({
type: "POST",
url: "upload.php",
data: {
imgBase64: data,
imgName: "webcam.png"
}
}).done(function(o) {
console.log('saved');
});
} else {
clearphoto();
}
}
// Set up our event listener to run the startup process
// once loading is complete.
window.addEventListener('load', startup, false);
})();
#video {
border: 1px solid black;
box-shadow: 2px 2px 3px black;
width:320px;
height:240px;
}
#photo {
border: 1px solid black;
box-shadow: 2px 2px 3px black;
width:320px;
height:240px;
}
#canvas {
display:none;
}
.camera {
width: 340px;
display:inline-block;
}
.output {
width: 340px;
display:inline-block;
}
#startbutton {
display:block;
position:relative;
margin-left:auto;
margin-right:auto;
bottom:32px;
background-color: rgba(0, 150, 0, 0.5);
border: 1px solid rgba(255, 255, 255, 0.7);
box-shadow: 0px 0px 1px 2px rgba(0, 0, 0, 0.2);
font-size: 14px;
font-family: "Lucida Grande", "Arial", sans-serif;
color: rgba(255, 255, 255, 1.0);
}
.contentarea {
font-size: 16px;
font-family: "Lucida Grande", "Arial", sans-serif;
width: 760px;
}
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<meta charset='utf-8'>
</head>
<body>
<div class="contentarea">
<div class="camera">
<video id="video">Video stream not available.</video>
<button id="startbutton">Take photo</button>
</div>
<canvas id="canvas">
</canvas>
<div class="output">
<img id="photo" alt="The screen capture will appear in this box.">
</div>
</div>
</body>
</html>
Based on :
https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Taking_still_photos
https://stackoverflow.com/a/13198699/797495
https://stackoverflow.com/a/31128229/797495
Note:
I've tested the code on my server and it works as intended.

Write custom text on image canvas with fabric.js and HTML5

I am using HTML5 and fabric.js for uploading multiple images. I want to add custom text on this image canvas. Right now I am uploading multiple images into canvas one by one. After uploading images I want to add custom text on canvas.
var canvas = new fabric.Canvas('canvas');
document.getElementById('file').addEventListener("change",function (e) {
var file = e.target.files[0];
var reader = new FileReader();
console.log("reader " + reader);
reader.onload = function (f) {
var data = f.target.result;
fabric.Image.fromURL(data, function (img) {
var oImg = img.set({left: 70, top: 100, width: 250, height: 200, angle: 0}).scale(0.9);
canvas.add(oImg).renderAll();
var a = canvas.setActiveObject(oImg);
var dataURL = canvas.toDataURL({format: 'png', quality: 0.8});
});
};
reader.readAsDataURL(file);
});
document.querySelector('#txt').onclick = function (e) {
e.preventDefault();
canvas.deactivateAll().renderAll();
document.querySelector('#preview').src = canvas.toDataURL();
};
canvas{
border: 1px solid black;
}
<script src="https://rawgit.com/kangax/fabric.js/master/dist/fabric.min.js"></script>
<input type="file" id="file">
<canvas id="canvas" width="750" height="550"></canvas>
Click Me!!<br />
<img id="preview" />
https://jsfiddle.net/varunPes/vb1weL93/
I have seen some links:
http://fancyproductdesigner.com/product/t-shirt/ - The expected result.
http://jsfiddle.net/EffEPi/qpJTz/
Update
I need that the user can choose the text's color and the font-family.
After clicking on Click Me!! button, the custom text and image should come together in one image.
You can use IText like this:
canvas.add(new fabric.IText('Tap and Type', {
fontFamily: 'arial black',
left: 100,
top: 100,
}));
And the full code:
var canvas = new fabric.Canvas('canvas');
document.getElementById('file').addEventListener("change", function (e) {
var file = e.target.files[0];
var reader = new FileReader();
console.log("reader " + reader);
reader.onload = function (f) {
var data = f.target.result;
fabric.Image.fromURL(data, function (img) {
var oImg = img.set({left: 70, top: 100, width: 250, height: 200, angle: 0}).scale(0.9);
canvas.add(oImg).renderAll();
canvas.setActiveObject(oImg);
});
};
reader.readAsDataURL(file);
});
$('#fill').change(function(){
var obj = canvas.getActiveObject();
if(obj){
// old api
// obj.setFill($(this).val());
obj.set("fill", this.value);
}
canvas.renderAll();
});
$('#font').change(function(){
var obj = canvas.getActiveObject();
if(obj){
// old api
// obj.setFontFamily($(this).val());
obj.set("fontFamily", this.value);
}
canvas.renderAll();
});
function addText() {
var oText = new fabric.IText('Tap and Type', {
left: 100,
top: 100 ,
});
canvas.add(oText);
oText.bringToFront();
canvas.setActiveObject(oText);
$('#fill, #font').trigger('change');
}
document.querySelector('#txt').onclick = function (e) {
e.preventDefault();
canvas.deactivateAll().renderAll();
document.querySelector('#preview').src = canvas.toDataURL();
};
canvas{
border: 1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.3.6/fabric.min.js"></script>
<input type="file" id="file">
<input type="color" value="blue" id="fill" />
<select id="font">
<option>arial</option>
<option>tahoma</option>
<option>times new roman</option>
</select>
<button onclick="addText()">Add Custom Text</button>
<br />
<canvas id="canvas" width="750" height="550"></canvas>
Click Me!!
<br />
<img id="preview" />
Update:
To keep the text always in the front you need to use .bringToFront() function. (Thanks to #Amit Sharma in Fabric.js - problem with drawing multiple images zindex)
http://jsbin.com/qicesa/edit?html,css,js,output

Categories

Resources