#### Howdy, Stranger!

We are about to switch to a new forum software. Until then we have removed the registration on this forum.

# Set size in cm/mm?

edited January 2018

If I recall correctly all size parameters are in pixels. Is it possible, if one wants, to define them in terms of cm or mm? You would need the pixel density of the monitor, right? Is that possible to get in Processing?

As a side note, it is quite difficult to google solutions specific to Processing since the name is such a commonly used word. I suppose I should have done the site:processing.org thing..

Tagged:

## Answers

• Here's a bit of a hacky solution (however this approach only works if you redraw your screen every frame).

Here we scale a 20x20 pixel grid up to a 200x200 pixel grid. If you need it in cm, you will need to get the screens DPI (pixels per inch) and convert it to cm. Average screen DPI I think is 72 and you can test whether the screen is high-dpi by calling https://processing.org/reference/displayDensity_.html

``````void setup() {
size(200,200);
}

void draw() {
//you can draw everything you like on a smaller scale, say 20x20 pixels
background(255); //background color
int smallW = 20, smallH = 20;
stroke(255,0,0);
fill(0,0,255);
rect(5,5,10,10);

//and then read the pixels
loadPixels();
color[] pix = pixels;
println(pix.length);

//and then scale it up to 200x200
background(255); //clear the screen
noStroke();
for(int i = 0; i < smallH; ++i) {
for(int j = 0; j < smallW; ++j) {
fill(pix[i*width+j]);
rect((float)j/smallW * width, (float)i/smallH * height, 1./smallW * width, 1./smallH * height);
}
}
}
``````
• edited January 2018

In order to fix visual glitches, in case smallW is not a multiple of width you can use the following code (it basically ceils and floors the correct values):

``````void setup() {
size(200,200);
}

void draw() {
//you can draw everything you like on a smaller scale, say 20x20 pixels
background(255); //background color
int smallW = 21, smallH = 21;
stroke(255,0,0);
fill(0,0,255);
point(0,0);
point(20,20);
rect(5,5,10,10);

//and then read the pixels
loadPixels();
color[] pix = pixels;
println(pix.length);
//and then scale it up to 200x200
background(255); //clear the screen
noStroke();
for(int i = 0; i < smallH; ++i) {
for(int j = 0; j < smallW; ++j) {
fill(pix[i*width+j]);
rect(floor((float)j/smallW * width), floor((float)i/smallH * height), ceil(1./smallW * width), ceil(1./smallH * height));
}
}
}
``````
• Average screen DPI I think is 72 and you can test whether the screen is high-dpi by calling https://processing.org/reference/displayDensity_.html

Is DPI limited to a set of values? Or can it vary freely from monitor to monitor?

• https://en.wikipedia.org/wiki/Dots_per_inch#Computer_monitor_DPI_standards

This is OS specific, and device specific, and complex. You can get a general hint about being on a single or double density display to get you in the right ballpark, but you need to know more to say anything about the physical display size vs pixels (or scaled virtual pixels). If you don't know the actual physical screen dimensions, find the OS at a minimum.

• Thanks for the answer, I've resolved the dpi problem. The program is going to run only on one computer, so I just used the screen size and the resolution to calculate the dpi. The problem is that the dpi was in decimals, 96.11 or something like this. Converting this to dots per mm gives 3.78 pixels per mm. Since height and width values are integers in the resize function, it seems that it is impossible to resize and image into something that is exactly, for example, 10 mm, since that would mean resizing that parameter to 37.8 pixels. Is there any way to obtain an exact resizing in terms of mm? Thanks.

• You can't resize the window to 96.11, but you can absolute draw a PImage as 96.11 pixels wide. You can also position by fractions of a pixel. Floats are built in all the way down.

That said, rounding to the nearest pixel is probably what you want to do for large objects -- I''m not sure how much 0.27 millimeters really matters on a 10mm image. For small ones, just give the correct fractional size, e.g.

``````translate(96.1, 96.1); // move 1x1mm
image(img, 0, 0, 961.1, 961.1); // display 10x10mm
``````

Note that this inline resizing form of `image()` is very processor intensive -- better to resize just once and then use a simple img() to display. You can also do this by drawing to a transparent PGraphics that is rounded up e.g. 2 pixels -- that leaves you space for an antialiasing edge and transparency.

• I used this before when creating pdf's from processing:

``````  import processing.pdf.*;

void settings() {
size((int)mm(170),(int)mm(210));
}

void draw() {
beginRecord(PDF, "output.pdf");

strokeWeight(mm(3));
rect(mm(10), mm(10), mm(150), mm(10));

endRecord();
exit();
}

static final float MM_TO_PIXEL_RATIO = 0.3527778f;

public float mm(float wantedMM) {
return wantedMM / MM_TO_PIXEL_RATIO;
}
``````

When opening them in illustrator they have the correct size.

Now if I still would need it I would use something like this:

``````import processing.pdf.*;

void settings() {
size(170, 210);
}

void draw() {
beginRecord(PDF, "output.pdf");

strokeWeight(3);
rect(10, 10, 150, 10);

endRecord();
exit();
}

void size(int w, int h) {
super.size(round(mm(w)), round(mm(h)));
}

void rect(float a, float b, float c, float d) {
super.rect(mm(a), mm(b), mm(c), mm(d));
}

void strokeWeight(float s) {
super.strokeWeight(mm(s));
}

static final float MM_TO_PIXEL_RATIO = 0.3527778f;

public float mm(float wantedMM) {
return wantedMM / MM_TO_PIXEL_RATIO;
}
``````

Maybe even add an option so you can switch between using pixels and mm.

• Note that this inline resizing form of image() is very processor intensive -- better to resize just once and then use a simple img() to display.

This is basically what I am doing. The problem is that according to the IDE the resize function only takes int values.

• Right -- that is true, because the output of resize() is a new pixel grid, so its width and height must be ints. So if you want a fractional resize:

You can also do this by drawing to a transparent PGraphics that is rounded up e.g. 2 pixels -- that leaves you space for an antialiasing edge and transparency.

You then draw -- once -- to this int-based PGraphics pg using float-based width and height, `pg.image(img, 0, 0, floatwidth, floatheight)` where `floatwidth` / `floatheight` are less than `pg.width` / `pg.height` (you rounded up when you created `pg`).

Now you have a PGraphics image that is pre-resized to a fraction of a pixel. It has a soft edge on the right and/or bottom. You can further draw this image at a fractional pixel location -- for example with `image(pg, 100.5, 100.5)` -- without resizing.

Sign In or Register to comment.