I have an image in a tag
var img = new Image();
ctx.drawImage(img,0,0,img.width,img.height);
ecc...
How is possible to change the Brightness and Contrast of this image with javascript?
Tnx
There's at least one javascript library I know of which can do this, Pixastic
Usage might look like this.
Pixastic.process(canvas, 'brightness',
{
'brightness': 60,
'contrast': 0.5,
'leaveDOM': true
},
function(img) {
ctx.drawImage(img, 0, 0);
}
);
The library is kind of intended to work with images within your page and it replaces them with canvas elements which contain the rendered result.
But in the code above I've passed in a canvas element rather than an image and included the 'leaveDOM' property to prevent the pixastic library from swapping your canvas in the DOM for the one it creates.
To display the results I've included the callback function which just does ctx.drawImage to put the contents into your original canvas.
Hope that makes sense.
You can check the documentation for more examples. Pixastic Documentation
In my experience, fabric.js is the best javascript library for performing this. Check out Fabric JS and how to do image filtering at: http://fabricjs.com/image-filters
you can try this , see comment
<script type="application/javascript">
function clickMeEvent(obj)
{
if (obj.style.opacity=="0.9")
{
obj.style.opacity="0.7";
}
else if (obj.style.opacity=="0.7")
{
obj.style.opacity="0.5";
}
else if (obj.style.opacity=="0.5")
{
obj.style.opacity="0.3";
}
else if (obj.style.opacity=="0.3")
{
obj.style.opacity="0.1";
}
else
{
obj.style.opacity="0.0";
}
}
</script>
You can try this (c# code):
Bitmap originalImage;
Bitmap adjustedImage;
double brightness = 1.0f; // no change in brightness
double constrast = 2.0f; // twice the contrast
double gamma = 1.0f; // no change in gamma
float adjustedBrightness = brightness - 1.0f;
float[][] ptsArray ={
new float[] {contrast, 0, 0, 0, 0}, // scale red
new float[] {0, contrast, 0, 0, 0}, // scale green
new float[] {0, 0, contrast, 0, 0}, // scale blue
new float[] {0, 0, 0, 1.0f, 0}, // don't scale alpha
new float[] {adjustedBrightness, adjustedBrightness, adjustedBrightness, 0, 1}};
imageAttributes = new ImageAttributes();
imageAttributes.ClearColorMatrix();
imageAttributes.SetColorMatrix(new ColorMatrix(ptsArray), ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
imageAttributes.SetGamma(gamma, ColorAdjustType.Bitmap);
Graphics g = Graphics.FromImage(adjustedImage);
g.DrawImage(originalImage, new Rectangle(0,0,adjustedImage.Width,adjustedImage.Height)
,0,0,bitImage.Width,bitImage.Height,
GraphicsUnit.Pixel, imageAttributes);
Related
I am a super early user of coding from Italy.
I came up with an idea to promote a company logo on their website and I almost reached the goal so I am sharing this problem.
The idea is to obtain a sort of clipping mask effect when the mouse/cursor move on the image
I've made so far a code that does the work with a still ellipse.
When I set the position parameters of the ellipse as mouseX and mouseY the effect does not work if not just a bit of a glitch at the start.
How can I make it work as intended?
Here you can find the link of what I have now:
https://editor.p5js.org/francesco.ficini.designer/full/FLBuhggW-
Here the code:
let img;
let imgbg2;
let maskImage;
function preload() {
img = loadImage("NeroP.jpg");
imgbg2 = loadImage("RossoP.jpg");
}
function setup() {
createCanvas(400, 225);
img.mask(img);
}
function draw() {
background(imgbg2, 0, 0);
//Immages
image(imgbg2, 0, 0);
image(img,0,0);
// Ellipse Mask
maskImage = createGraphics(400, 225);
maskImage.ellipse(200, 100, 50, 50);
imgbg2.mask(maskImage);
image(imgbg2, 0, 0);
}
The thing about the p5.Image.mask function is that it modifies the image that is being masked. Which means that any pixels that are cleared by the mask are gone for good. So if you want to dynamically change the mask you will need to make a copy of the original and re-apply the modified mask any time it changes.
Additionally you will want to avoid creating images and graphics objects in your draw() function because this can result in excessive memory allocation. Instead create a single set of graphics/images and re-use them.
let img;
let imgbg2;
let maskImage;
let maskResult;
function preload() {
img = loadImage("https://www.paulwheeler.us/files/NeroP.jpeg");
imgbg2 = loadImage("https://www.paulwheeler.us/files/RossoP.jpeg");
}
function setup() {
createCanvas(400, 225);
// Create graphics and image buffers in setup
maskImage = createGraphics(imgbg2.width, imgbg2.height);
maskResult = createImage(imgbg2.width, imgbg2.height);
}
function mouseMoved() {
if (maskResult) {
maskImage.clear();
// Ellipse
maskImage.ellipse(mouseX, mouseY, 50, 50);
// Copy the original imgbg2 to the maskResult image
maskResult.copy(
imgbg2,
0, 0, imgbg2.width, imgbg2.height,
0, 0, imgbg2.width, imgbg2.height
);
// apply the mask to maskResult
maskResult.mask(maskImage);
}
}
function draw() {
//Immagini
image(img, 0, 0);
// draw the masked version of the image
image(maskResult, 0, 0);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
The game I'm creating doesn't require any physics, however you are able to interact when hovering over/clicking on the sprite by using sprite.setInteractive({cursor: "pointer"});, sprite.on('pointermove', function(activePointer) {...}); and similar. However I noticed two issues with that:
The sprite has some area which are transparent. The interactive functions will still trigger when clicking on those transparent areas, which is unideal.
When playing a sprite animation, the interactive area doesn't seem to entirely (at all?) change, thus if the sprite ends on a frame bigger than the previous, there end up being small areas I can't interact with.
One option I thought of was to create a polygon over my sprite, which covers the area I want to be interactive. However before I do that, I simply wanted to ask if there are simpler ways to fix these issues.
Was trying to find an answer for this myself just now..
Think Make Pixel Perfect is what you're looking for.
this.add.sprite(x, y, key).setInteractive(this.input.makePixelPerfect());
https://newdocs.phaser.io/docs/3.54.0/focus/Phaser.Input.InputPlugin-makePixelPerfect
This might not be the best solution, but I would solve this problem like this. (If I don't want to use physics, and if it doesn't impact the performance too much)
I would check in the event-handler, if at the mouse-position the pixel is transparent or so, this is more exact and less work, than using bounding-boxes.
You would have to do some minor calculations, but it should work well.
btw.: if the origin is not 0, you would would have to compensate in the calculations for this. (in this example, the origin offset is implemented)
Here is a demo, for the click event:
let Scene = {
preload ()
{
this.load.spritesheet('brawler', 'https://labs.phaser.io/assets/animations/brawler48x48.png', { frameWidth: 48, frameHeight: 48 });
},
create ()
{
// Animation set
this.anims.create({
key: 'walk',
frames: this.anims.generateFrameNumbers('brawler', { frames: [ 0, 1, 2, 3 ] }),
frameRate: 8,
repeat: -1
});
// create sprite
const cody = this.add.sprite(200, 100).setOrigin(0);
cody.play('walk');
cody.setInteractive();
// just info text
this.mytext = this.add.text(10, 10, 'Click the Sprite, or close to it ...', { fontFamily: 'Arial' });
// event to watch
cody.on('pointerdown', function (pointer) {
// calculate x,y position of the sprite to check
let x = (pointer.x - cody.x) / (cody.displayWidth / cody.width)
let y = (pointer.y - cody.y) / (cody.displayHeight / cody.height);
// just checking if the properties are set
if(cody.anims && cody.anims.currentFrame){
let currentFrame = cody.anims.currentFrame;
let pixelColor = this.textures.getPixel(x, y, currentFrame.textureKey, currentFrame.textureFrame);
// alpha > 0 a visible pixel of the sprite, is clicked
if(pixelColor.a > 0) {
this.mytext.text = 'Hit';
} else {
this.mytext.text = 'No Hit';
}
// just reset the textmessage
setTimeout(_ => this.mytext.text = 'Click the Sprite, or close to it ...' , 1000);
}
}, this);
}
};
const config = {
type: Phaser.AUTO,
width: 400,
height: 200,
scene: Scene
};
const game = new Phaser.Game(config);
<script src="https://cdn.jsdelivr.net/npm/phaser#3.55.2/dist/phaser.js"></script>
I have a video that's streaming parts of a video into a MediaSource and playing it. I have a canvas that I want to draw the video on an then overlay some effects. However, in my handler, the call to drawImage, while it works, it only appears to copy a single pixel. The video itself plays fine.
I have a screenshot from my app, which has the source video next to the destination canvas element:
As you can sorta see, the solid color of the canvas is the color of the very first pixel of the source video.
The actual code in question looks similar to this:
startWatch() {
this.timer = setInterval(this.copyFrame.bind(this), 1000 / this.fps)
}
copyFrame() {
const { width, height } = this.video.getBoundingClientRect()
// I've tried the 3, 5, and 9 argument versions of this function
// width is 300 and height is 168.75.
this.ctx.drawImage(this.video, 0, 0, width, height, 0, 0, width, height)
}
(where this.video is a video element)
This code does "work" in that the canvas's color does update over time as the video plays. But it's always just the initial pixel. So the timing loop works, but the drawImage call isn't doing what I expect.
(1) Using const { width, height } may not be correct. Check the values you are given.
What happens if you console.log the width or height values, are they correct/expected numbers?
(2) "...But the drawImage call isn't doing what I expect."
ctx.drawImage( someElement, 0, 0, A1, A2, 0, 0, B1, B2 );
Consider the above code,
The first width/height (A1/A2) is for how much of the input to draw (it must match size of input's own width/height, otherwise cropping or margins will occur). Eg: A1 == 720 if input video is 720 pixels wide.
The second width/height (B1/B2) is for how much resize of the output to draw. Usually you want to fill entire canvas area so use canvas dimensions (aspect ratio is left to coder to implement as preferred).
In your shown code, your const { width, height } is either
Giving too small a number for A1/A2 params (it samples one pixel)
Giving too large a number for B1/B2 params (it stretches output so large that one pixel fills the canvas).
Possible solutions:
Try (if you must use bounding rectangle):
function copyFrame()
{
//# width is 300 and height is 168.75.
//const { width, height } = this.video.getBoundingClientRect()
let myRect = this.video.getBoundingClientRect();
this.ctx.drawImage( this.video, 0, 0,
this.video.videoWidth, this.video.videoHeight,
0, 0, myRect.width, myRect.height);
}
Alternativey you could just draw the picture into canvas size:
function copyFrame()
{
//# assuming your Canvas is called "this.cnvs"
this.ctx.drawImage( this.video, 0, 0,
this.video.videoWidth, this.video.videoHeight,
0, 0, this.cnvs.width, this.cnvs.height);
}
For aspect ratio you can use the below formula (swap all width & height references for a new drawn_width)
myRatio = ( vid_height / vid_width );
drawn_height = ( myCanvas_width * myRatio );
I have this image in my website, is a png.I want to know if there is anyway with HTML5 , javascript or css to change the color of the image? At least the image change to white (invert color black to white, not the transparency).
Thanks in advance
You cannot do this in plain HTML or CSS. You can do this with JS/HTML Canvas, but there is probably a much easier and more compatible solution than JS/HTML Canvas for performing image manipulation.
Depending on what you are trying to do, you may just want to create a second image that you swap out with the first. There are also some decent image manipulation packages in server-side languages like PHP, if you need to do something more dynamic.
If you are set on using js, the code below is modified from your example.
Using your example:
window.onload = function(){
var imageObj = new Image();
imageObj.onload = function(){
drawImage(this);
};
imageObj.src = "darth-vader.jpg";
};
function drawImage(imageObj){
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var destX = 69; //update these to set the image position
var destY = 50;
context.drawImage(imageObj, destX, destY);
var imageData = context.getImageData(0, 0, canvas.width, canvas.height);
var data = imageData.data;
for (var i = 0, n = data.length; i < n; i += 4) {
if(data[i] == 0 && data[i+1] == 0 && data[i+2] ==0){ //if black, ie. red, green, and blue are all 0
//switch to white
data[i] = 255; //red
data[i+1] = 255; //green
data[i+2] = 255; //blue
}
// i+3 is alpha (the fourth element)
}
// overwrite original image
context.putImageData(imageData, 0, 0);
}
You haven't explained why you aren't just using Photoshop to do it, but I assume you have your reasons.
Well wanted to support all... but for
now Firefox, Chrome will be nice.
Latest versions , would be nice ... I
guess with canvas HTML5 is possible.
I'm not sure how well it works with transparent .pngs, but you could try Pixastic.
Here's a demo of the "Invert" effect: http://www.pixastic.com/lib/docs/actions/invert/
You've lucked out with the browser support for "Invert" - it works in even IE:
Although a few of the effects in
Pixastic are simulated in IE with
proprietary filters, most actions and
effects will not work without a canvas
enabled browser. Please consider using
either Firefox, Opera or Safari
I can make a obj to use the canvas to draw like this:
MyObj.myDiv = new Canvas($("effectDiv"), Setting.width, Setting.height);
Then, I use this to draw a rectangle on the canvas:
var c = new Rectangle(80, 80,
{
fill: [220, 40, 90]
}
);
var move = new Timeline;
move.addKeyframe(0,
{
x: 0,
y: 0
}
);
c.addTimeline(move);
MyObj.myDiv.append(c);
But after I draw the rectangle, I want clear the canvas, but I don't know which method and how to do this... ...
O...one more thing:
it is the CAKE's web site:
Link
Clearing the canvas:
canvas.clear = true; // makes the canvas clear itself on every frame
canvas.fill = somecolor; // fills the canvas with some color on every frame
// with canvas.clear = false and low-opacity fill, fancy motion blur effect
Removing the rectangle from the canvas:
rectangle.removeSelf();
or
canvas.removeChild(rectangle);
You can try this method:
MyObj.myDiv.clearRect(0, 0, canvas.width, canvas.height);
Which effectively colours the entire canvas in the background colour.
Easiest way is:
MyObj.myDiv.width = MyObj.myDiv.width;
I found that resizing the canvas works like magic, even if you're not really changing the size:
canvas.width = canvas.width