p5js - pixelDensity() 在视网膜屏幕上没有帮助
p5js - pixelDensity() doesn't help on retina screens
我有一些代码可以从照片集生成拼贴画,我通过平均图像本身的像素颜色来实现这一点,最终,在某种操作之后,我只用平均颜色指向 (x,y)。
唯一的问题是,当我放大 视网膜屏幕(高于特定分辨率) 时,很明显这确实是屏幕上的一堆点,而不是一张完整的图像。
我想这与 pixelDensity() 有关,但经过大量实验后,它也没有帮助。
此处附有缩放裁剪示例 -
组合像素的主循环非常基本,看起来像这样 -
for (let y = 0; y <= imgOne.height; y++) {
for (let x = 0; x <= imgOne.width; x++) {
// Get the colors.
const colorOne = imgOne.get(x, y);
const colorTwo = imgTwo.get(x, y);
let avgRed = (red(colorOne) + red(colorTwo) ) / 2;
let avgGreen = (green(colorOne) + green(colorTwo)) / 2;
let avgBlue = (blue(colorOne) + blue(colorTwo) ) / 2;
stroke(avgRed,avgGreen,avgBlue);
point(x, y);
}
}
点函数专门画一个直径等于pixelDensity
的小圆。当您通过 CSS 变换或使用浏览器缩放功能放大 canvas 时,您将开始看到 sub-pixel 的人工制品。有两种方法可以确保您的颜色“点”是方形的并且即使在放大时也能完全填满平面:1) 使用 set()
函数明确绘制像素,2) 使用 square()
或rect()
函数刻意画一个正方形。 (理论上你也可以直接操作 pixels
数组,但这会复杂得多)。
这是一个演示原始问题以及不同解决方案的示例。
// only show a portion of the image.
const W = 120;
const H = 120;
let imgOne;
let imgTwo;
function preload() {
// "Recursive raytrace of a sphere" by Tim Babb is licensed under CC BY-SA 4.0
// https://creativecommons.org/licenses/by-sa/4.0/
imgOne = loadImage("https://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Recursive_raytrace_of_a_sphere.png/240px-Recursive_raytrace_of_a_sphere.png");
//
imgTwo = loadImage("https://upload.wikimedia.org/wikipedia/commons/thumb/3/31/Rainbow-gradient-fully-saturated.svg/240px-Rainbow-gradient-fully-saturated.svg.png");
}
function setup() {
createCanvas(W * 3, H);
noLoop();
}
function draw() {
background(220);
for (let y = 0; y < H; y++) {
for (let x = 0; x < W; x++) {
// Get the colors.
const colorOne = imgOne.get(x, y);
const colorTwo = imgTwo.get(x, y);
let avgRed = (red(colorOne) + red(colorTwo)) / 2;
let avgGreen = (green(colorOne) + green(colorTwo)) / 2;
let avgBlue = (blue(colorOne) + blue(colorTwo)) / 2;
stroke(avgRed, avgGreen, avgBlue);
point(x, y);
}
}
for (let y = 0; y < H; y++) {
for (let x = 0; x < W; x++) {
const colorOne = imgOne.get(x, y);
const colorTwo = imgTwo.get(x, y);
let avgRed = (red(colorOne) + red(colorTwo)) / 2;
let avgGreen = (green(colorOne) + green(colorTwo)) / 2;
let avgBlue = (blue(colorOne) + blue(colorTwo)) / 2;
set(x + W, y, color(avgRed, avgGreen, avgBlue));
}
}
updatePixels();
for (let y = 0; y < H; y++) {
for (let x = 0; x < W; x++) {
const colorOne = imgOne.get(x, y);
const colorTwo = imgTwo.get(x, y);
let avgRed = (red(colorOne) + red(colorTwo)) / 2;
let avgGreen = (green(colorOne) + green(colorTwo)) / 2;
let avgBlue = (blue(colorOne) + blue(colorTwo)) / 2;
fill(avgRed, avgGreen, avgBlue);
noStroke();
square(x + W * 2, y, 1);
}
}
}
// This work is licensed under a CC BY-SA 4.0 License.
// https://creativecommons.org/licenses/by-sa/4.0/
// Author: Paul Wheeler
html,
body {
margin: 0;
padding: 0;
}
canvas {
display: block;
transform-origin: top left;
transform: scale(4);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
为了重现问题,您需要先使用浏览器的缩放功能,然后运行 代码。我不确定为什么当您 运行 代码然后缩放时行为会有所不同。
我有一些代码可以从照片集生成拼贴画,我通过平均图像本身的像素颜色来实现这一点,最终,在某种操作之后,我只用平均颜色指向 (x,y)。 唯一的问题是,当我放大 视网膜屏幕(高于特定分辨率) 时,很明显这确实是屏幕上的一堆点,而不是一张完整的图像。 我想这与 pixelDensity() 有关,但经过大量实验后,它也没有帮助。
此处附有缩放裁剪示例 -
组合像素的主循环非常基本,看起来像这样 -
for (let y = 0; y <= imgOne.height; y++) {
for (let x = 0; x <= imgOne.width; x++) {
// Get the colors.
const colorOne = imgOne.get(x, y);
const colorTwo = imgTwo.get(x, y);
let avgRed = (red(colorOne) + red(colorTwo) ) / 2;
let avgGreen = (green(colorOne) + green(colorTwo)) / 2;
let avgBlue = (blue(colorOne) + blue(colorTwo) ) / 2;
stroke(avgRed,avgGreen,avgBlue);
point(x, y);
}
}
点函数专门画一个直径等于pixelDensity
的小圆。当您通过 CSS 变换或使用浏览器缩放功能放大 canvas 时,您将开始看到 sub-pixel 的人工制品。有两种方法可以确保您的颜色“点”是方形的并且即使在放大时也能完全填满平面:1) 使用 set()
函数明确绘制像素,2) 使用 square()
或rect()
函数刻意画一个正方形。 (理论上你也可以直接操作 pixels
数组,但这会复杂得多)。
这是一个演示原始问题以及不同解决方案的示例。
// only show a portion of the image.
const W = 120;
const H = 120;
let imgOne;
let imgTwo;
function preload() {
// "Recursive raytrace of a sphere" by Tim Babb is licensed under CC BY-SA 4.0
// https://creativecommons.org/licenses/by-sa/4.0/
imgOne = loadImage("https://upload.wikimedia.org/wikipedia/commons/thumb/3/32/Recursive_raytrace_of_a_sphere.png/240px-Recursive_raytrace_of_a_sphere.png");
//
imgTwo = loadImage("https://upload.wikimedia.org/wikipedia/commons/thumb/3/31/Rainbow-gradient-fully-saturated.svg/240px-Rainbow-gradient-fully-saturated.svg.png");
}
function setup() {
createCanvas(W * 3, H);
noLoop();
}
function draw() {
background(220);
for (let y = 0; y < H; y++) {
for (let x = 0; x < W; x++) {
// Get the colors.
const colorOne = imgOne.get(x, y);
const colorTwo = imgTwo.get(x, y);
let avgRed = (red(colorOne) + red(colorTwo)) / 2;
let avgGreen = (green(colorOne) + green(colorTwo)) / 2;
let avgBlue = (blue(colorOne) + blue(colorTwo)) / 2;
stroke(avgRed, avgGreen, avgBlue);
point(x, y);
}
}
for (let y = 0; y < H; y++) {
for (let x = 0; x < W; x++) {
const colorOne = imgOne.get(x, y);
const colorTwo = imgTwo.get(x, y);
let avgRed = (red(colorOne) + red(colorTwo)) / 2;
let avgGreen = (green(colorOne) + green(colorTwo)) / 2;
let avgBlue = (blue(colorOne) + blue(colorTwo)) / 2;
set(x + W, y, color(avgRed, avgGreen, avgBlue));
}
}
updatePixels();
for (let y = 0; y < H; y++) {
for (let x = 0; x < W; x++) {
const colorOne = imgOne.get(x, y);
const colorTwo = imgTwo.get(x, y);
let avgRed = (red(colorOne) + red(colorTwo)) / 2;
let avgGreen = (green(colorOne) + green(colorTwo)) / 2;
let avgBlue = (blue(colorOne) + blue(colorTwo)) / 2;
fill(avgRed, avgGreen, avgBlue);
noStroke();
square(x + W * 2, y, 1);
}
}
}
// This work is licensed under a CC BY-SA 4.0 License.
// https://creativecommons.org/licenses/by-sa/4.0/
// Author: Paul Wheeler
html,
body {
margin: 0;
padding: 0;
}
canvas {
display: block;
transform-origin: top left;
transform: scale(4);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
为了重现问题,您需要先使用浏览器的缩放功能,然后运行 代码。我不确定为什么当您 运行 代码然后缩放时行为会有所不同。