split huge image into tiles, load tiles as grayscale images
This commit is contained in:
+2
-1
@@ -11,6 +11,7 @@ yarn.lock
|
|||||||
.env.*.local
|
.env.*.local
|
||||||
|
|
||||||
# IDE
|
# IDE
|
||||||
|
.zed/
|
||||||
.vscode/
|
.vscode/
|
||||||
.idea/
|
.idea/
|
||||||
*.swp
|
*.swp
|
||||||
@@ -28,4 +29,4 @@ logs/
|
|||||||
*.log
|
*.log
|
||||||
|
|
||||||
# OS
|
# OS
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
|||||||
+3
-1
@@ -14,6 +14,7 @@ out/
|
|||||||
.env.*.local
|
.env.*.local
|
||||||
|
|
||||||
# IDE
|
# IDE
|
||||||
|
.zed/
|
||||||
.vscode/
|
.vscode/
|
||||||
.idea/
|
.idea/
|
||||||
*.swp
|
*.swp
|
||||||
@@ -28,4 +29,5 @@ Thumbs.db
|
|||||||
.cache/
|
.cache/
|
||||||
|
|
||||||
# big assets
|
# big assets
|
||||||
assets/scans/
|
assets/scans/
|
||||||
|
assets/img/
|
||||||
|
|||||||
+59
-23
@@ -1,5 +1,6 @@
|
|||||||
import p5 from "p5";
|
import p5 from "p5";
|
||||||
import io from "socket.io-client";
|
import io from "socket.io-client";
|
||||||
|
import UPNG from "upng-js";
|
||||||
const socket = io("http://localhost:3000");
|
const socket = io("http://localhost:3000");
|
||||||
|
|
||||||
const params = {
|
const params = {
|
||||||
@@ -35,32 +36,65 @@ const realText = poem.split(" ").filter((t) => t.length > 0);
|
|||||||
|
|
||||||
const sketch = (p) => {
|
const sketch = (p) => {
|
||||||
let sobel;
|
let sobel;
|
||||||
|
const imageW = 37418,
|
||||||
|
imageH = 27178;
|
||||||
|
const tileW = 8192;
|
||||||
|
const tileH = 4096;
|
||||||
|
const tileCols = Math.ceil(imageW / tileW);
|
||||||
|
const tileRows = Math.ceil(imageH / tileH);
|
||||||
|
const tileCount = tileCols * tileRows;
|
||||||
|
const tiles = [];
|
||||||
p.setup = async () => {
|
p.setup = async () => {
|
||||||
// bg = await p.loadImage("assets/scans/1200dpi 16bit grayscale.png");
|
// bg = await p.loadImage("assets/scans/1200dpi 16bit grayscale.png");
|
||||||
bg = await p.loadImage("assets/scans/portable.png");
|
const promises = [];
|
||||||
|
let n_downloaded = 0;
|
||||||
|
for (let row = 0; row < tileRows; row++) {
|
||||||
|
for (let column = 0; column < tileCols; column++) {
|
||||||
|
const x = column * tileW;
|
||||||
|
const y = row * tileH;
|
||||||
|
const w = Math.min(tileW, imageW - x);
|
||||||
|
const h = Math.min(tileH, imageH - y);
|
||||||
|
promises.push(
|
||||||
|
fetch(
|
||||||
|
`assets/img/tiles/37418x27178_3200dpi_16bit_grayscale/tile_x${x}_y${y}_w${w}_h${h}.png`,
|
||||||
|
)
|
||||||
|
.then((res) => res.arrayBuffer())
|
||||||
|
.then((buffer) => {
|
||||||
|
// divide width by 2 because we are colorpacking
|
||||||
|
const p5img = p.createImage(w / 2, h);
|
||||||
|
p5img.loadPixels();
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`p5img.pixels.length: ${p5img.pixels.length}, p5img.width: ${p5img.width}, p5img.height: ${p5img.height}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
const img = UPNG.decode(buffer);
|
||||||
|
console.log(
|
||||||
|
`img.data.length: ${img.data.length}, img.width: ${img.width}, img.height: ${img.height}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
// BEWARE: weird things happening with dimension of the loaded image (4096 values too many)
|
||||||
|
for (let i = 0; i < w * h * 4; i++) {
|
||||||
|
p5img.pixels[i] = img.data[i];
|
||||||
|
}
|
||||||
|
tiles[row * tileCols + column] = img;
|
||||||
|
n_downloaded++;
|
||||||
|
console.log(
|
||||||
|
`Downloaded ${n_downloaded} / ${tileCount} (${Math.round((n_downloaded / tileCount) * 100)}%) tiles`,
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await Promise.all(promises);
|
||||||
p.createCanvas(p.windowWidth, p.windowHeight, p.WEBGL);
|
p.createCanvas(p.windowWidth, p.windowHeight, p.WEBGL);
|
||||||
sobel = p.createFilterShader(`
|
const shaderFile = await fetch("shader/sobel.frag");
|
||||||
precision highp float;
|
const shaderText = await shaderFile.text();
|
||||||
|
sobel = p.createFilterShader(shaderText);
|
||||||
// x,y coordinates, given from the vertex shader
|
console.log(
|
||||||
varying vec2 vTexCoord;
|
"Max texture size:",
|
||||||
|
p._renderer.GL.getParameter(p._renderer.GL.MAX_TEXTURE_SIZE),
|
||||||
// the canvas contents, given from filter()
|
);
|
||||||
uniform sampler2D tex0;
|
|
||||||
// other useful information from the canvas
|
|
||||||
uniform vec2 texelSize;
|
|
||||||
uniform vec2 canvasSize;
|
|
||||||
// a custom variable from this sketch
|
|
||||||
uniform float pulse;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
// get the color at current pixel
|
|
||||||
vec4 color = texture2D(tex0, vTexCoord);
|
|
||||||
// set the output color
|
|
||||||
color.b = 1.0;
|
|
||||||
color *= pulse;
|
|
||||||
gl_FragColor = vec4(color.rgb, 1.0);
|
|
||||||
}`);
|
|
||||||
// const stream = c.elt.captureStream(60);
|
// const stream = c.elt.captureStream(60);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -125,6 +159,8 @@ const sketch = (p) => {
|
|||||||
p.fill(0, 0, 0, params.textAlpha);
|
p.fill(0, 0, 0, params.textAlpha);
|
||||||
p.text(word, bounds.x, bounds.y + p.textAscent());
|
p.text(word, bounds.x, bounds.y + p.textAscent());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function drawTiles(x, y, width, height) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
new p5(sketch);
|
new p5(sketch);
|
||||||
|
|||||||
@@ -7,7 +7,8 @@
|
|||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"p5": "^2.2.2",
|
"p5": "^2.2.2",
|
||||||
"socket.io-client": "^4.8.3"
|
"socket.io-client": "^4.8.3",
|
||||||
|
"upng-js": "^2.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"lil-gui": "^0.21.0",
|
"lil-gui": "^0.21.0",
|
||||||
|
|||||||
Executable
+36
@@ -0,0 +1,36 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
INPUT="$1"
|
||||||
|
OUTPUT_DIR="tiles"
|
||||||
|
|
||||||
|
#Create OUTPUT_DIR if it doesn't exist
|
||||||
|
mkdir -p "$OUTPUT_DIR"
|
||||||
|
|
||||||
|
#Get image dimensions
|
||||||
|
WIDTH=$(identify -format "%w" "$INPUT")
|
||||||
|
HEIGHT=$(identify -format "%h" "$INPUT")
|
||||||
|
echo "Image dimensions: $WIDTH x $HEIGHT"
|
||||||
|
|
||||||
|
#Tile dimensions
|
||||||
|
TILE_WIDTH=8192
|
||||||
|
TILE_HEIGHT=4096
|
||||||
|
|
||||||
|
echo "Cutting image into tiles of ${TILE_WIDTH}x${TILE_HEIGHT}..."
|
||||||
|
|
||||||
|
# Loop over vertical and horizontal positions
|
||||||
|
count=0
|
||||||
|
for (( y=0; y<HEIGHT; y+=TILE_HEIGHT )); do
|
||||||
|
for (( x=0; x<WIDTH; x+=TILE_WIDTH )); do
|
||||||
|
|
||||||
|
W=$(($TILE_WIDTH < $((WIDTH - x)) ? $TILE_WIDTH : $((WIDTH - x))))
|
||||||
|
H=$(($TILE_HEIGHT < $((HEIGHT - y)) ? $TILE_HEIGHT : $((HEIGHT - y))))
|
||||||
|
|
||||||
|
# Filename encodes position: tile_x<x>_y<y>_w<W>_h<H>.png
|
||||||
|
TILE_FILE="$OUTPUT_DIR/tile_x${x}_y${y}_w${W}_h${H}.png"
|
||||||
|
echo "Creating $TILE_FILE"
|
||||||
|
convert "$INPUT" -crop "${TILE_WIDTH}x${TILE_HEIGHT}+${x}+${y}" +repage "$TILE_FILE"
|
||||||
|
((count++))
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Done. $count tiles created."
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
precision highp float;
|
||||||
|
|
||||||
|
// x,y coordinates, given from the vertex shader
|
||||||
|
varying vec2 vTexCoord;
|
||||||
|
|
||||||
|
// the canvas contents, given from filter()
|
||||||
|
uniform sampler2D tex0;
|
||||||
|
// other useful information from the canvas
|
||||||
|
uniform vec2 texelSize;
|
||||||
|
uniform vec2 canvasSize;
|
||||||
|
// a custom variable from this sketch
|
||||||
|
uniform float pulse;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
// Sample neighboring pixels
|
||||||
|
float tl = texture2D(tex0, vTexCoord + vec2(-texelSize.x, -texelSize.y)).r;
|
||||||
|
float l = texture2D(tex0, vTexCoord + vec2(-texelSize.x, 0.0)).r;
|
||||||
|
float bl = texture2D(tex0, vTexCoord + vec2(-texelSize.x, texelSize.y)).r;
|
||||||
|
|
||||||
|
float t = texture2D(tex0, vTexCoord + vec2(0.0, -texelSize.y)).r;
|
||||||
|
float b = texture2D(tex0, vTexCoord + vec2(0.0, texelSize.y)).r;
|
||||||
|
|
||||||
|
float tr = texture2D(tex0, vTexCoord + vec2(texelSize.x, -texelSize.y)).r;
|
||||||
|
float r = texture2D(tex0, vTexCoord + vec2(texelSize.x, 0.0)).r;
|
||||||
|
float br = texture2D(tex0, vTexCoord + vec2(texelSize.x, texelSize.y)).r;
|
||||||
|
|
||||||
|
// Sobel kernels
|
||||||
|
float gx = -tl - 2.0 * l - bl + tr + 2.0 * r + br;
|
||||||
|
float gy = -tl - 2.0 * t - tr + bl + 2.0 * b + br;
|
||||||
|
|
||||||
|
float edge = length(vec2(gx, gy));
|
||||||
|
|
||||||
|
gl_FragColor = vec4(vec3(edge), 1.0);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user