Is it possible to move an image (or image object) without clearing the whole background?
I wish to create an app that allows the user to "paint", using a device that is not the mouse. I would like to have a cursor to follow the users movement with the input device, without having to clear the already painted picture.
Is this possible? And how?
It depends how you handle drawing.
I would suggest using PImage as a canvas to draw into and another PImage to store the pixels of your brush. The 'brush' can be a loaded image, or at the start of your sketch you could make the brush using drawing commands, then store those as a PImage using get().
You will need to clear everything because you want to draw your cursor, but you will also draw your canvas, and you'll store 'brush strokes' only when the mouse is pressed (or some device specific method) by using the copy() or the blend() function (depending on your brush PNG - with or without transparency, etc.)
Here's a quick sketch to illustrate this:
PImage canvas;
PImage brush;
void setup(){
size(800,800);
stroke(128);
smooth();
canvas = createImage(width,height,ARGB);
brush = loadImage("brush.png");
}
void draw(){
background(255);
image(canvas,0,0);
//draw cursor
line(mouseX-5,mouseY-5,mouseX+5,mouseY+5);
line(mouseX+5,mouseY-5,mouseX-5,mouseY+5);
//blend brush pixels into canvas if mouse is pressed
if(mousePressed) canvas.blend(brush, 0, 0, brush.width, brush.width, (int)(mouseX-brush.width*.5), (int)(mouseY-brush.height*.5), brush.width, brush.width,MULTIPLY);
}
Note that you need an image into your sketch's data folder.
You can try it here:
You can run a javascript version bellow:
var canvas;
var brush;
function setup(){
createCanvas(800,800);
stroke(128);strokeWeight(3);
smooth();
canvas = createImage(width,height);
brush = getGradientImg(64,64,random(360),random(100),85);
}
function draw(){
background(255);
image(canvas,0,0);
//draw cursor
line(mouseX-5,mouseY-5,mouseX+5,mouseY+5);
line(mouseX+5,mouseY-5,mouseX-5,mouseY+5);
//blend brush pixels into canvas if mouse is pressed
if(isMousePressed) canvas.blend(brush, 0, 0, brush.width, brush.width, (int)(mouseX-brush.width*.5), (int)(mouseY-brush.height*.5), brush.width, brush.width,MULTIPLY);
//image(brush,mouseX,mouseY);
}
//*
function getGradientImg(w,h,hue,satMax,brightness){
push();//isolate drawing styles such as color Mode
colorMode(HSB,360,100,100);
var gradient = createImage(w,h);//create an image with an alpha channel
var np = w * h;//total number of pixels
var np4 = np*4;
var cx = floor(gradient.width * 0.5);//center on x
var cy = floor(gradient.height * 0.5);//center on y
gradient.loadPixels();
for(var i = 0 ; i < np4; i+=4){//for each pixel
var id4 = floor(i * .25);
var x = id4%gradient.width;//compute x from pixel index
var y = floor(id4/gradient.width);//compute y from pixel index
var d = dist(x,y,cx,cy);//compute distance from centre to current pixel
//map the saturation and transparency based on the distance to centre
gradient.pixels[i] = hue;
gradient.pixels[i+1] = map(d,0,cx,satMax,0);
gradient.pixels[i+2] = brightness;
gradient.pixels[i+3] = map(d,0,cx,255,0);
}
gradient.updatePixels();//finally update all the pixels
pop();
console.log(gradient);
return gradient;
}
//*/
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.4.4/p5.min.js"></script>
Related
I have a simple ellipse, moving across the screen, is there any simple code I could implement to have this ellipse draw a trail behind it that has its alpha fade over time to a certain extent? I still want the trail visible in the end but less bright than the casting ellipse.
You could also do something like this:
let positions = [];
function draw(){
positions.push(mouseX);
positions.push(mouseY);
for(let i in positions){
let x = positions[i];
let y = positions[i + 1];
fill(255, 255 - i * 10); noStroke();
ellipse(mouseX, mouseY, x, y)
}
if(positions.length > 20){
positions.shift();
positions.shift();
}
}
Assuming the ellipse is the only thing being drawn then there is a simple solution which is to, instead of drawing a fully opaque background on each frame, draw a semi-transparent background:
function setup() {
createCanvas(windowWidth, windowHeight);
}
function draw() {
background(0, 35);
ellipse(mouseX, mouseY, 20, 20);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
However, there are some caveats, namely that for certain colors/transparency levels you will be left with permanent "ghost" of the trails due to some weird alpha blending math anomalies.
I am developing a endless game, and want to take a Snapshot when the player Dies. I've almost done that using Texture2D. i have done Load Texture in image programmatically. but want to set border to the image. How can i do that.? how can i set border to that image at Run-time.?
This Code For Load Texture To the Image at Run-time when my player Dies.
void LoadImage(){
byte[] bytes = File.ReadAllBytes (Application.dataPath +"/GameOverScreenShot" + "/BirdDiedScreenShot.png");
Texture2D texture = new Texture2D (900, 900, TextureFormat.RGB24, false);
texture.filterMode = FilterMode.Trilinear;
texture.LoadImage (bytes);
Sprite sprite = Sprite.Create (texture, new Rect (0, 0, 700, 380), new Vector2 (0.5f, 0.0f), 1.0f);
imgObject.GetComponent<UnityEngine.UI.Image> ().sprite = sprite;
}
i want to Set Border to that image at Run-time. any one can help i really appreciate. thanks in Advance.
Do this after you load the image into the Texture2D variable and this will change the border of the image to whatever color you want.
//color should be a variable that holds the color of the border you want.
for (int i = 0; i< texture.width; i++){
texture.SetPixel(i, 0, color); //top border
texture.SetPixel(i, texture.height - 1, color); //bottom border
}
for (int j = 0; j < texture.height; j++){
texture.SetPixel(0, j, color); // left border
texture.SetPixel(texture.width - 1, j, color); //right border
}
texture.Apply();
This will replace any pixels on the edge of your original image so if you need those edge pixels you will need to look for another solution. Also, texture.Apply takes a while to run so if you need to constantly apply this border you may experience slowdown but you mentioned it is only when the player dies so this should not be an issue.
I have stuck up in a problem. This question is with respect to processing. I have to draw a scratch on an image using this function
line(pmouseX, pmouseY, mouseX, mouseY);
How do I achieve this? I mean, wherever I draw a scratch, pixel corresponding to that image has to be updated.
Thanks for any assistance
I'm not sure what kind of effect do you want to achieve so here is basic usage of drawing line according to mouse position.
PImage img; //global variable for storing image
void setup(){
img = loadImage("image.jpg"); //loading image
size(img.width, img.height); //setting size of sketch
}
void draw(){
image(img, 0, 0); //each time redraw background with Image
line(pmouseX, pmouseY, mouseX, mouseY); //draw line acc to mouse
}
If you want to draw big line just move image() function into setup().
If you want more complicated lines you will have to use mouse events.
I'm trying to figure out how to convert the mouse position (screen coordinates) to the corresponding point on the underlying transformed image drawn on a direct2d surface.
the code here should be considered pseudo code as i'm using a modified c++/CLI wrapper around direct2d for c#, you won't be able to compile this in anything but my own project.
Render()
{
//The transform matrix combines a rotation, followed by a scaling then a translation
renderTarget.Transform = _rotate * _scale * _translate;
RectF imageBounds = new RectF(0, 0, _imageSize.Width, _imageSize.Height);
renderTarget.DrawBitmap(this._image, imageBounds, 1, BitmapInterpolationMode.Linear);
}
Zoom(float zoomfactor, PointF mousepos)
{
//mousePos is in screen coordinates. I need to convert it to image coordinates.
Matrix3x2 t = _translate.Invert();
Matrix3x2 s = _scale.Invert();
Matrix3x2 r = _rotate.Invert();
PointF center = (t * s * r).TransformPoint(mousePos);
_scale = Matrix3x2.Scale(zoomfactor, zoomfactor, center);
}
This is incorrect, the scale center starts moving around wildly when the zoomfactor increases or decreases smoothly, the resulting zoom function is not smooth and flickers a lot even though the mouse pointer is immobile on the center of the client surface. I tried all the combinations I could think of but could not figure it out.
If I set the scale center point as (imagewidth/2, imageheight/2), the resulting zoom is smooth but is always centered on the image center, so I'm pretty sure the flicker isn't due to some other buggy part of the program.
Thanks.
I finally got it right
this gives me perfectly smooth (incremental?, relative?) zooming centered on the client center
(I abandoned the mouse position idea since I wanted to use mouse movement input to drive the zoom)
protected float zoomf
{
get
{
//extract scale factor from scale matrix
return (float)Math.Sqrt((double)((_scale.M11 * _scale.M11)
+ (_scale.M21 * _scale.M21)));
}
}
public void Zoom(float factor)
{
factor = Math.Min(zoomf, 1) * 0.006f * factor;
factor += 1;
Matrix3x2 t = _translation;
t.Invert();
PointF center = t.TransformPoint(_clientCenter);
Matrix3x2 m = Matrix3x2.Scale(new SizeF(factor, factor), center);
_scale = _scale * m;
Invalidate();
}
Step1: Put android:scaleType="matrix" in ImageView XML file
Step 2: Convert screen touch points to Matrix value.
Step 3: Divide each matrix value with Screen density parameter to
get same coordinate value in all screens.
**XML**
<ImageView
android:id="#+id/myImage"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="matrix"
android:src="#drawable/ga"/>
**JAVA**
#Override
public boolean onTouchEvent(MotionEvent event) {
float[] point = new float[]{event.getX(), event.getY()};
Matrix inverse = new Matrix();
getImageMatrix().invert(inverse);
inverse.mapPoints(point);
float density = getResources().getDisplayMetrics().density;
int[] imagePointArray = new int[2];
imagePointArray[0] = (int) (point[0] / density);
imagePointArray[1] = (int) (point[1] / density);
Rect rect = new Rect( imagePointArray[0] - 20, imagePointArray[1] - 20, imagePointArray[0] + 20, imagePointArray[1] + 20);//20 is the offset value near to the touch point
boolean b = rect.contains(267, 40);//267,40 are the predefine image coordiantes
Log.e("Touch inside ", b + "");
return true;
}
http://deepschool.kd.io/Pages/Experiments/draw.htm
This is a Image editor I am working on, But it has a bug. Let's say you have created an image a 15x Zoom, when you change the zoom, the image is lost. Why is this? and what is the Remedy?
HTML:
Zoom:
<input type="number" id="zoom" min="1" max="50" onchange="zoomy()">
JS:
var zoomy = function() {
var zoomamount = zoom.value
var canvassize = zoomamount * 16
c.width = canvassize
c.height = canvassize
};
Thanks In Advance
If you want to zoom into canvas, it means you have to redraw it with zoom.
So instead of drawing pixels on click right onto canvas, which is made of pure pixels... You need to first create some representation of your grid of pixels.
var gridOfPixels = [];
Let's say you are ok with static size for now. Make it 8x8 pixels. At start you want to initialize your array:
for (var i=0; i < 8*8; i++) gridOfPixels[i] = 0;
So the grid canvas is ready, now we need to draw it.
function renderGrid() {
for (var y=0; y < 8; y++)
for (var x=0; x < 8; x++)
renderPixel( x, y, gridOfPixels[x+y*8] );
}
You already know how to renderPixel - calculate the rectangle position (posX = x*pixWidth, posY*pixHeight), where pixWidth is canvasWidth/8, etc.. Now you draw all your pixels, using the third parameter for the color.
To finish, you have to connect onclick to put a pixel on grid, and then call renderGrid so the user sees the change.
$('#my-canvas').click(function(e) {
var x = ...;
var y = ...; // calculate the position of pixels from mouse position inside canvas
// dont forget to check that x,y are in the 0-7 range
// dont forget to convert x,y to whole number using parseInt()
gridOfPixels[x+y*8] = 1;
renderGrid(); // update the grid canvas
});
Now, every time you resize the canvas or change some variables, the original canvas content will be saved in your grid, and you can renderGrid() any time you need to. You could even do it in realtime, animating the color of the pixels, etc..
Have fun. :)