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
|
||||
|
||||
# IDE
|
||||
.zed/
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
@@ -28,4 +29,4 @@ logs/
|
||||
*.log
|
||||
|
||||
# OS
|
||||
Thumbs.db
|
||||
Thumbs.db
|
||||
|
||||
+3
-1
@@ -14,6 +14,7 @@ out/
|
||||
.env.*.local
|
||||
|
||||
# IDE
|
||||
.zed/
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
@@ -28,4 +29,5 @@ Thumbs.db
|
||||
.cache/
|
||||
|
||||
# big assets
|
||||
assets/scans/
|
||||
assets/scans/
|
||||
assets/img/
|
||||
|
||||
+59
-23
@@ -1,5 +1,6 @@
|
||||
import p5 from "p5";
|
||||
import io from "socket.io-client";
|
||||
import UPNG from "upng-js";
|
||||
const socket = io("http://localhost:3000");
|
||||
|
||||
const params = {
|
||||
@@ -35,32 +36,65 @@ const realText = poem.split(" ").filter((t) => t.length > 0);
|
||||
|
||||
const sketch = (p) => {
|
||||
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 () => {
|
||||
// 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);
|
||||
sobel = p.createFilterShader(`
|
||||
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() {
|
||||
// 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 shaderFile = await fetch("shader/sobel.frag");
|
||||
const shaderText = await shaderFile.text();
|
||||
sobel = p.createFilterShader(shaderText);
|
||||
console.log(
|
||||
"Max texture size:",
|
||||
p._renderer.GL.getParameter(p._renderer.GL.MAX_TEXTURE_SIZE),
|
||||
);
|
||||
// const stream = c.elt.captureStream(60);
|
||||
};
|
||||
|
||||
@@ -125,6 +159,8 @@ const sketch = (p) => {
|
||||
p.fill(0, 0, 0, params.textAlpha);
|
||||
p.text(word, bounds.x, bounds.y + p.textAscent());
|
||||
}
|
||||
|
||||
function drawTiles(x, y, width, height) {}
|
||||
};
|
||||
|
||||
new p5(sketch);
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"p5": "^2.2.2",
|
||||
"socket.io-client": "^4.8.3"
|
||||
"socket.io-client": "^4.8.3",
|
||||
"upng-js": "^2.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"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