ctx canvas image decrease width from bottom side - javascript

I have drawn the image in the canvas by using this below code in which I have combined the elements images with the folded cup image
canvas2(getFullElementImage);
function canvas2(getFullElementImage) {
var canvas = document.getElementById("finalCanvas");
var ctx = canvas.getContext("2d");
var productImg = new Image();
productImg.onload = function () {
var iw = productImg.width;
var ih = productImg.height;
console.log("height");
canvas.width = iw;
canvas.height = ih;
ctx.drawImage(productImg, 30, 0, productImg.width, productImg.height,
0, 0, iw, ih);
loadUpperIMage()
};
productImg.src = "https://res.cloudinary.com/faizykhan1212/image/upload/v1550583008/folded_cup_1.png"
function loadUpperIMage() {
var img = new Image();
img.src = getFullElementImage;
img.onload = function () {
var iw = img.width;
var ih = img.height;
// alert(iw)
var xOffset = 160, //left padding
yOffset = 110; //top padding
var a = 190.0; //image width
var b = 20; //round ness
var scaleFactor = iw / (4 * a);
// draw vertical slices
for (var X = 0; X < iw; X += 1) {
var y = b / a * Math.sqrt(a * a - (X - a) * (X - a)); // ellipsis equation
ctx.drawImage(img, X * scaleFactor, 0, iw / 3, ih, X + xOffset, y + yOffset, 1, 574);
}
};
}
};
This is how image is showing:
I want this to the decrease the width from the bottom so that this will fit to the cup with the left and the right corners.
Thanks

Maybe you can use webGL for examples like this.
This code is brilliant. I made some calibration for this part :
var xOffset = 174, //left padding
yOffset = 110; //top padding
var a = 180.0; //image width
var b = 80; //round ness
canvas2();
function canvas2() {
var canvas = document.getElementById("finalCanvas");
var ctx = canvas.getContext("2d");
var productImg = new Image();
productImg.onload = function () {
var iw = productImg.width;
var ih = productImg.height;
console.log("height");
canvas.width = iw;
canvas.height = ih;
ctx.drawImage(productImg, 30, 0, productImg.width, productImg.height,
0, 0, iw, ih);
loadUpperIMage()
};
productImg.src = "https://res.cloudinary.com/faizykhan1212/image/upload/v1550583008/folded_cup_1.png"
function loadUpperIMage() {
var img = new Image();
img.src = "https://res.cloudinary.com/faizykhan1212/image/upload/v1550655724/download-3.png";
img.onload = function () {
var iw = img.width;
var ih = img.height;
// alert(iw)
var xOffset = 174, //left padding
yOffset = 110; //top padding
var a = 180.0; //image width
var b = 80; //round ness
var scaleFactor = iw / (4 * a);
// draw vertical slices
for (var X = 0; X < iw; X += 1) {
var y = b / a * Math.sqrt(a * a - (X - a) * (X - a)); // ellipsis equation
ctx.drawImage(img, X * scaleFactor, 0, iw / 3, ih, X + xOffset, y + yOffset, 1, 574);
}
};
}
};
<canvas id="finalCanvas"></canvas>

Related

html canvas draw cylindrical view of the image by drawing vertical slices

I am using below code to draw a cylindrical view of the image by drawing vertical slices of the image:
DrawMug(canvasId, cupImg, rotate, scale) {
var canvas: any = document.getElementById(canvasId);
var ctx = canvas.getContext("2d");
var productImg = new Image();
productImg.onload = () => {
var iw = productImg.width;
var ih = productImg.height;
console.log("height");
canvas.width = iw;
canvas.height = ih;
ctx.drawImage(productImg, 0, 0, productImg.width, productImg.height, 0, 0, iw, ih);
this.loadUpperIMage(ctx, rotate, scale);
};
productImg.src = cupImg;
}
loadUpperIMage(ctx: any, rotate: number, scale: number) {
var img = new Image();
img.src = this.designImgUrl;
img.onload = function() {
var iw = img.width;
var ih = img.height;
var xOffset = 100, //left padding
yOffset = 110; //top padding
var a = 75.0; //image width
var b = 12.0; //round ness
var scaleFactor = iw / (scale * a);
// draw vertical slices (increasing X by 1)
for (var X = 0; X < iw; X += 1) {
var y = b / a * Math.sqrt(a * a - (X - a) * (X - a)); // ellipsis equation
ctx.drawImage(img, (X * scaleFactor), 0, (iw / rotate), ih, X + xOffset, y + yOffset, 1, 174);
}
};
}
It draws the image but the edges doesn't look good as below:
I tried resolving it by decreasing the vertical slice width by replacing the for loop as below
// draw vertical slices (increasing X by 0.1)
for (var X = 0; X < iw; X += 0.1) {
var y = b / a * Math.sqrt(a * a - (X - a) * (X - a)); // ellipsis equation
ctx.drawImage(img, (X * scaleFactor), 0, (iw / rotate), ih, X + xOffset, y + yOffset, 0.1, 174);
}
it fixes the edges but it distorts the image as below, probably because here I am taking destination width as 0.1 but, I am not sure how do I set source width accordingly.
Fiddle
https://jsfiddle.net/au8f6d51/

Why this pixelation animation is jolty

I have the following multi-step pixelation animation. It animates from low-to-high pixelation very slowly to show you that it jolts in between some of the steps, as if the image is slightly moved between renderings. I can't figure out why this is happening or how to make it appear as if the image is staying in one place.
var c = document.createElement('canvas')
c.style.display = 'flex'
c.style.width = '100vw'
c.style.height = '100vh'
c.style['image-rendering'] = 'pixelated'
document.body.appendChild(c)
var x = c.getContext('2d')
x.webkitImageSmoothingEnabled = false
x.mozImageSmoothingEnabled = false
x.msImageSmoothingEnabled = false
x.imageSmoothingEnabled = false
var src = c.getAttribute('data-draw')
var small = `https://upload.wikimedia.org/wikipedia/commons/thumb/c/c5/M101_hires_STScI-PRC2006-10a.jpg/307px-M101_hires_STScI-PRC2006-10a.jpg`
var large = `https://upload.wikimedia.org/wikipedia/commons/thumb/c/c5/M101_hires_STScI-PRC2006-10a.jpg/1280px-M101_hires_STScI-PRC2006-10a.jpg`
// c.width = c.clientWidth
// c.height = c.clientHeight
var stack = []
var start = false
var place = 0
function queue(image, ratio, width, height) {
stack.push({ image, ratio, width, height })
if (start) return
start = true
setTimeout(proceed, 0)
}
function proceed() {
let point = stack.shift()
let w
let h
if (point.ratio) {
w = c.width = c.clientWidth * point.ratio
h = c.height = c.clientHeight * point.ratio
} else {
w = point.width
h = point.height
}
if (!stack.length) {
x.webkitImageSmoothingEnabled = true
x.mozImageSmoothingEnabled = true
x.msImageSmoothingEnabled = true
x.imageSmoothingEnabled = true
c.classList.remove('px')
}
drawImageProp(x, point.image, 0, 0, w, h)
if (stack.length) {
setTimeout(proceed, 1000)
}
}
var s = new Image()
s.onload = function(){
queue(s, 0.01)
queue(s, 0.03)
var i = new Image()
i.onload = function(){
queue(i, 0.03)
queue(i, 0.11)
queue(i, 1)
}
i.src = large
}
s.src = small
function drawImageProp(ctx, img, x, y, w, h, offsetX, offsetY) {
if (arguments.length === 2) {
x = y = 0;
w = ctx.canvas.width;
h = ctx.canvas.height;
}
// default offset is center
offsetX = typeof offsetX === "number" ? offsetX : 0.5;
offsetY = typeof offsetY === "number" ? offsetY : 0.5;
// keep bounds [0.0, 1.0]
if (offsetX < 0) offsetX = 0;
if (offsetY < 0) offsetY = 0;
if (offsetX > 1) offsetX = 1;
if (offsetY > 1) offsetY = 1;
var iw = img.width,
ih = img.height,
r = Math.min(w / iw, h / ih),
nw = iw * r, // new prop. width
nh = ih * r, // new prop. height
cx, cy, cw, ch, ar = 1;
// decide which gap to fill
if (nw < w) ar = w / nw;
if (Math.abs(ar - 1) < 1e-14 && nh < h) ar = h / nh; // updated
nw *= ar;
nh *= ar;
// calc source rectangle
cw = iw / (nw / w);
ch = ih / (nh / h);
cx = (iw - cw) * offsetX;
cy = (ih - ch) * offsetY;
// make sure source rectangle is valid
if (cx < 0) cx = 0;
if (cy < 0) cy = 0;
if (cw > iw) cw = iw;
if (ch > ih) ch = ih;
// fill image in dest. rectangle
ctx.drawImage(img, cx, cy, cw, ch, x, y, w, h);
}
Even in between the last two steps it shifts slightly. Wondering what's going wrong and how to fix it.
FYI, there are two images, a small one and a big one, both the same thing. It first loads the small image at low resolution, then loads the large one. While the large one is loading, it does a few animation steps using the small image to start the animation. Then once the large one is done, it picks up where the small one left off and does a few more animation steps using the large image.

Bar chart in javascript

The following code is my attempt to create a bar chart with javascript and the html 5 canvas:
var canvas = $("#chart");
var ctx = canvas.getContext("2d");
ctx.strokeFill = "green";
var margin = 5;
var bWidth = (canvas.width - (margin * results.length)) / results.length;
var max = results.sort()[results.length - 1];
var yScale = canvas.height / max;
for (result of results)
{
ctx.strokeRect();
}
The data I am trying to visualize looks like this:
[{"choice": "Yes", votes: 2}, {"choice": "No", votes: 1}, {"choice":"maybe", votes: 3}]
The questions are:
How can I compute the x and y axes for each element?
How can I print the choices under the bars?
There can be up to 20 choices and each can be up to 200 characters. How could this be handled?
After additional research the following is the solution:
var results = extractResults($("#results"));
var canvas = $("#chart");
var ctx = canvas.getContext("2d");
var margin = canvas.width * 0.005;
var bWidth = (canvas.width - (margin * results.length)) / results.length;
var max = Math.max.apply( Math, results );
var yScale = canvas.height / max;
var currX = margin;
ctx.font = "20px Arial"
for (i = 0; i < results.length; i++)
{
var bHeight = yScale * results[i];
ctx.fillStyle = "green";
ctx.fillRect(currX, canvas.height - bHeight, bWidth, bHeight);
ctx.fillStyle = "black";
ctx.fillText(i + 1, currX + bWidth / 2, canvas.height - canvas.height * 0.05, bWidth / 2);
currX += bWidth + margin;
}

Wrap images on papercup(background image)

I want to wrap images and text on sample papercup.
When a image is uploaded on canvas, I want to wrap it around the background image of papercup whose position is fixed at all times.
I am using Fabric JS for the html5 canvas tool.
Here is my code but there it only shows 1pixel of image, also when I click the image to drag and drop ,it VANISHES.
HTML:
<div id="container">
<input type="file" id="imageLoader" name="imageLoader" />
Remove:<input type="button" value="remove" id="imageRemove" name="imageRemove" onClick="handleRemove()"/>
<canvas id="canvas" width="500" height="400" style="width:1000px;height:500px;margin-left:5%;" ></canvas>
</div>
JS:
var offsetY=[0,1,2,3,4,5,6,5,4,3,2,1,0];
var canvas = new fabric.Canvas('canvas', {
backgroundColor: 'rgb(240,240,240)'
});
var imageLoader = document.getElementById('imageLoader');
imageLoader.addEventListener('change', handleImage, false);
function handleImage(e) {
var reader = new FileReader();
reader.onload = function (event) {
var image = new Image();
image.onload = function () {
var width = image.width,
height = image.height;
var context = $("canvas")[0].getContext("2d");
for(var x=0;x<offsetY.length;x++){
context.drawImage(image,
x,0,1,image.height,
x,offsetY[x],1,image.height);
}
};
image.src = event.target.result;
}
reader.readAsDataURL(e.target.files[0]);
}
function handleRemove() {
canvas.clear().renderAll();
}
I am new at html5 canvas,please help.
http://jsfiddle.net/kNEaX/217/
You can draw a user image like this:
On to this paper cup:
With results like this:
Using this example code:
Modify this example to fit your needs. Good luck with your project!
var faceCanvas = document.getElementById('face');
var faceCtx = faceCanvas.getContext('2d');
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var cw, ch;
$myslider = $('#myslider');
$myslider.val(50);
var PI = Math.PI;
var cupTop = 78;
var cupBottom = 295;
var dxx = 19;
var dyy = 34;
var l = {
x0: 41,
y0: cupTop,
x1: 74,
y1: cupBottom
};
var r = {
x0: 249,
y0: cupTop,
x1: 218,
y1: cupBottom
};
var t = {
x0: l.x0,
y0: l.y0,
x1: l.x0 + dxx,
y1: r.y0 + dyy,
x2: r.x0 - dxx,
y2: r.y0 + dyy,
x3: r.x0,
y3: r.y0
};
var b = {
x0: l.x1,
y0: l.y1,
x1: l.x1 + dxx,
y1: r.y1 + dyy,
x2: r.x1 - dxx,
y2: r.y1 + dyy,
x3: r.x1,
y3: r.y1
};
var topOffset = 40;
var imgCount = 2;
var cup = new Image();
cup.crossOrigin = 'anonymous';
cup.onload = start;
var pic = new Image();
pic.crossOrigin = 'anonymous';
pic.onload = start;
cup.src = 'https://image.ibb.co/iKJvyc/VENFv.png';
pic.src = 'https://image.ibb.co/dJHG4H/Pu7aY.jpg';
function start() {
if (--imgCount > 0) {
return;
}
cw = canvas.width = faceCanvas.width = cup.width;
ch = canvas.height = faceCanvas.height = cup.height;
draw();
face();
$myslider.change(function() {
var value = parseInt($(this).val()) / 100;
topOffset = (l.y1 - l.y0 - pic.height) * value;
draw();
face();
});
}
function face() {
//
var lm = (l.y1 - l.y0) / (l.x1 - l.x0);
var lb = l.y1 - (lm * l.x1);
//
var rm = (r.y1 - r.y0) / (r.x1 - r.x0);
var rb = r.y1 - (rm * r.x1);
faceCtx.clearRect(0, 0, faceCanvas.width, faceCanvas.height);
for (var y = 0; y < pic.height; y++) {
var yy = cupTop + topOffset + y;
var leftX = (yy - lb) / lm;
var rightX = (yy - rb) / rm;
var width = rightX - leftX;
faceCtx.drawImage(
pic,
0, y, pic.width, 1,
leftX, yy, width, 1
);
}
var yy = cupTop + topOffset;
var p0 = {
x: (yy - lb) / lm,
y: cupTop + topOffset
};
var p3 = {
x: (yy - rb) / rm,
y: cupTop + topOffset
};
var p1 = {
x: p0.x + dxx,
y: p0.y + dyy
};
var p2 = {
x: p3.x - dxx,
y: p3.y + dyy
};
var points = calcPointsOnBezier(p0, p1, p2, p3);
for (var x in points) {
var y = points[x];
ctx.drawImage(faceCanvas, x, 0, 1, ch, x, y - yy, 1, ch);
}
}
function calcPointsOnBezier(p0, p1, p2, p3) {
var points = {};
for (var x = parseInt(p0.x); x < parseInt(p3.x + 1); x++) {
points[x] = p0.y;
}
for (var i = 0; i < 1000; i++) {
var t = i / 1000;
var pt = getCubicBezierXYatT(p0, p1, p2, p3, t);
points[parseInt(pt.x)] = parseInt(pt.y);
}
return (points);
}
function draw() {
ctx.strokeStyle = 'gold';
ctx.clearRect(0, 0, cw, ch);
ctx.drawImage(cup, 0, 0);
// diagnostic();
}
function diagnostic() {
ctx.beginPath();
ctx.moveTo(l.x0, l.y0);
ctx.lineTo(l.x1, l.y1);
ctx.moveTo(r.x0, r.y0);
ctx.lineTo(r.x1, r.y1);
ctx.lineWidth = 3;
ctx.stroke();
ctx.beginPath();
ctx.moveTo(t.x0, t.y0);
ctx.bezierCurveTo(t.x1, t.y1, t.x2, t.y2, t.x3, t.y3);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(b.x0, b.y0);
ctx.bezierCurveTo(b.x1, b.y1, b.x2, b.y2, b.x3, b.y3);
ctx.stroke();
}
function getCubicBezierXYatT(startPt, controlPt1, controlPt2, endPt, T) {
var x = CubicN(T, startPt.x, controlPt1.x, controlPt2.x, endPt.x);
var y = CubicN(T, startPt.y, controlPt1.y, controlPt2.y, endPt.y);
return ({
x: x,
y: y
});
}
// cubic helper formula at T distance
function CubicN(T, a, b, c, d) {
var t2 = T * T;
var t3 = t2 * T;
return a + (-a * 3 + T * (3 * a - a * T)) * T +
(3 * b + T * (-6 * b + b * 3 * T)) * T +
(c * 3 - c * 3 * T) * t2 +
d * t3;
}
body {
background-color: ivory;
}
canvas {
border: 1px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
Vertical Position:<input id=myslider type=range min=0 max=100 value=50><br>
<canvas id="canvas" width=300 height=300></canvas>
<canvas id="face" width=300 height=300 hidden></canvas>
ADDITIONAL NOTE: The example above creates the effect on an Html Canvas element
That's done because the effect requires the context.drawImage method which is available in the native Canvas element.
Once you create your effect using native canvas, you can easily use that native canvas as an image source to create a FabricJS Image object (fabric.Image accepts an html canvas as an image source):
// get a reference to the html canvas with the
// "image around mug" effect
var canvas=document.getElementById("canvas");
// create a fabric.Image using that html canvas
// as an image source
var c=new fabric.Canvas('c');
var myFabricImage=new fabric.Image(canvas, {
left: 50,
top: 50,
});
c.add(myFabricImage);

Obtaining color pixel of an image in JavaScript canvas

I'm a little stuck trying to get the pixel color of an image. I need to get the RGB value of a pixel, jump three and store it in an array, but my console always returns [0, 0, 0...].
You have any idea how to do this in a better way?
My code looks like this:
function captureImageData( image )
{
var cnv = document.createElement( 'canvas' );
cnv.width = image.width;
cnv.height = image.height;
var ctx = cnv.getContext( '2d' );
ctx.drawImage( image, 0, 0 );
var imageData = ctx.getImageData( 0, 0, 200, 100 );
var data = imageData.data;
var height = imageData.height;
var width = imageData.width;
for ( var y = 0; y < 100; y += 2 )
{
for ( var x = 0; x < 200; x += 2 )
{
red.push(data[( y * imageData.width + x ) * 4 + 0]);
green.push(data[( y * imageData.width + x ) * 4 + 1]);
blue.push(data[( y * imageData.width + x ) * 4 + 2]);
alpha.push(data[( y * imageData.width + x ) * 4 + 3]);
}
}
console.log( red );
}
How are you passing the image to the function? Try the following, it works fine for me.
Live Demo
var red = [],
green = [],
blue = [],
alpha = [];
function captureImageData(image) {
var cnv = document.createElement('canvas');
cnv.width = image.width;
cnv.height = image.height;
var ctx = cnv.getContext('2d');
ctx.drawImage(image, 0, 0);
var imageData = ctx.getImageData(0, 0, 200, 100);
var data = imageData.data;
var height = imageData.height;
var width = imageData.width;
var index = 0;
for (var y = 0; y < 100; y += 2) {
for (var x = 0; x < 200; x += 2) {
index = (y * imageData.width + x) * 4;
red.push(data[index]);
green.push(data[index + 1]);
blue.push(data[index + 2]);
alpha.push(data[index + 3]);
}
}
// log out any pixel here
console.log(red[1]);
}
var image = new Image();
image.crossOrigin = true;
image.src = "http://i.imgur.com/LdmrhlK.jpg";
image.onload = function () {
captureImageData(this);
}

Categories

Resources