createGraphics on mobile device

so working with createGraphics and hi DPI screens is a known issue which apparently has been fixed. However, I still have some struggles with working with Graphics on mobile devices.

I have this code where stuff is drawn on a graphics layer and there is a button to save said graphics layer. However, I haven’t found any possibility to display the graphics layer on the canvas in high resolution (so setting pixelDensity to 1 is not an option). It’s always cropped when displaying with the image() function. Weirdly, when I save graphics with save(), the whole graphics canvas is saved. Am I doing something wrong?

var buttonTxt = ["back", "save", "next"];
var strokeWght = 4;
var textS = 24;
var timeSt;
var buttons = [];
var graphL;


function setup() {
	createCanvas(windowWidth, windowHeight);
	colorMode(HSB, 360, 100, 100, 100);
	graphL = createGraphics(windowWidth, windowHeight);
	//graphL.scale(1/pixelDensity());
	graphL.colorMode(HSB, 360, 100, 100, 100);
	
	textSize(textS);
	
	textClr = color(0, 0, 0); 
	strokeClr = color(0, 0, 0);
	bgClr = color(0, 0, 100);
	
	for (var i=0; i<3; i++) {
		buttons[i] = new Button(i);
	}
}

function draw() {


	graphL.rectMode(CORNER);
	graphL.background(180, 100, 100);
	graphL.fill(0, 100, 100);
	graphL.strokeWeight(10);
	graphL.rect(windowWidth*.1, windowHeight*.1, windowWidth*.8, windowHeight*.8);
	
	graphL.textSize(16);
	graphL.fill(0, 0, 100);
	graphL.stroke(0, 0, 0);
	graphL.strokeWeight(1);
	graphL.text("windowWidth: " + windowWidth + "\ngraphL.width: " + graphL.width  + "\npixelDensity: " + pixelDensity() +	"\ngraphL.pixelDensity: " + graphL.pixelDensity(), 50, 70);

	image(graphL, 0, 0);
	buttons[1].show();
	
	var dd=day();
	var mm=month();
	var yy=year();
	var hh=hour();
	var mi=minute();
	var ss=second();
	timeSt = nf(yy, 4) + nf(mm, 2) + nf(dd, 2) + nf(hh, 2) + nf(mi, 2) + nf(ss, 2);
}


function saveCnv() {
	save(graphL, "layer" + timeSt + ".png");
}


class Button {
	constructor(indexB) {
		this.indexB = indexB;
		this.x = (width/6)*(this.indexB*2+1);
		this.y = windowHeight*.9;
		this.w = 70;
		this.h = 40;
		this.textMarg = 10;
	}
	show() {
		rectMode(CENTER);
		stroke(strokeClr);
		fill(bgClr);
		strokeWeight(strokeWght);
		rect(this.x, this.y, this.w, this.h);
		
		textAlign(LEFT);
		textSize(textS);
		noStroke();
		fill(textClr);
		text(buttonTxt[this.indexB], this.x-(this.w/2)+this.textMarg, this.y+(textS/2));
	}
	clicked() {
		if (mouseX>=this.x-(this.w/2)&&mouseY>=this.y-(this.h/2)&&mouseX<=this.x+(this.w/2)&&mouseY<=this.y+(this.h/2)) {
			return(this.indexB);
		}
	}
}

function mouseClicked() {
	for (var i=0; i<buttons.length; i++){
		buttons[i].clicked();
		if (buttons[i].clicked()==1) {
			saveCnv();
		}
	}
}

This results in the following:
screenshot:

saved Image:

When I scale the graphics layer to

	graphL.scale(1/pixelDensity());

it gets blurry.

I’d appreciate any help! Thank you

1 Like

I don’t have a mobile to test on, but perhaps this information is useful for narrowing down the issue. I’m testing on a laptop with pixelDensity 3. On this device both the screen and the saved image are displayed properly (so no cropped results).

When I run the program it shows a windowWidth of 851 pixels. Once I save it however it gets multiplied by the pixelDensity, giving me an image file of 2553 pixels wide. Perhaps this is the same for your saved image; could you check whether your saved image on your mobile is (360 x 4 =) 1440 pixels wide?
If so, what’s being displayed on your canvas is an unscaled 1440px graphics, while the sketch interprets your screen as a 360px wide display.

In the link you provided BenjaminHabert suggests using copy() instead of image() for drawing the graphic on your canvas. Have you tried that?

1 Like

Thanks for trying it out.
Yes, the saved image is 1440p. But even though the sketch thinks it’s a 360p screen, it should know about the screen’s pixelDensity, so I don’t understand why it’s rendering the image too big…

Anyways, I tried the copy function, and oddly enough, that worked when specifying the target width and height. Thanks for pointing that answer out, I thought I’d tried that already :relieved:

The problem with copy() (and also with image) was the low fps in my sketch, so now I just draw it on the default canvas and when “save” is pressed, draw the image again on my graphics layer, which is then saved.

1 Like