213 lines
10 KiB
JSON
213 lines
10 KiB
JSON
{
|
|
"format": "trakodag.web.presets",
|
|
"version": 1,
|
|
"name": "trakodag — artistic presets",
|
|
"description": "Pamiątkowy zestaw efektów. Załaduj plik przez 'Load project' i wybierz preset z listy.",
|
|
"presets": [
|
|
{
|
|
"name": "Sepia Vintage",
|
|
"description": "Ciepły sepia look + delikatna winieta — klasyczna pocztówka.",
|
|
"layers": [
|
|
{
|
|
"name": "sepia",
|
|
"visible": true,
|
|
"opacity": 1.0,
|
|
"code": "// klasyczna macierz sepia\nforEach((x, y, p) => {\n const r = p.r * 0.393 + p.g * 0.769 + p.b * 0.189;\n const g = p.r * 0.349 + p.g * 0.686 + p.b * 0.168;\n const b = p.r * 0.272 + p.g * 0.534 + p.b * 0.131;\n p.r = clamp(r);\n p.g = clamp(g);\n p.b = clamp(b);\n});\n"
|
|
},
|
|
{
|
|
"name": "vignette",
|
|
"visible": true,
|
|
"opacity": 1.0,
|
|
"code": "// ściemnienie krawędzi (radialne)\nconst cx = width / 2, cy = height / 2;\nconst maxD = hypot(cx, cy);\nforEach((x, y, p) => {\n const d = hypot(x - cx, y - cy) / maxD;\n const k = 1 - pow(d, 1.6) * 0.75;\n p.r = clamp(p.r * k);\n p.g = clamp(p.g * k);\n p.b = clamp(p.b * k);\n});\n"
|
|
},
|
|
{
|
|
"name": "grain",
|
|
"visible": true,
|
|
"opacity": 0.5,
|
|
"code": "// drobne ziarno filmu\nforEach((x, y, p) => {\n const n = randomInt(-15, 15);\n p.r = clamp(p.r + n);\n p.g = clamp(p.g + n);\n p.b = clamp(p.b + n);\n});\n"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"name": "CRT Scanlines",
|
|
"description": "Stary monitor / TV — boost kolorów + poziome linie skanowania + lekkie cieplejsze tony.",
|
|
"layers": [
|
|
{
|
|
"name": "boost",
|
|
"visible": true,
|
|
"opacity": 1.0,
|
|
"code": "// nasycenie i jasność jak na nasyconym CRT\nforEach((x, y, p) => {\n p.r = clamp(p.r * 1.12 + 4);\n p.g = clamp(p.g * 1.06 + 2);\n p.b = clamp(p.b * 1.10 + 4);\n});\n"
|
|
},
|
|
{
|
|
"name": "scanlines",
|
|
"visible": true,
|
|
"opacity": 1.0,
|
|
"code": "// co druga linia ciemniejsza\nforEach((x, y, p) => {\n if (y % 2 === 0) {\n p.r = (p.r * 0.55) | 0;\n p.g = (p.g * 0.55) | 0;\n p.b = (p.b * 0.55) | 0;\n }\n});\n"
|
|
},
|
|
{
|
|
"name": "rgb mask",
|
|
"visible": true,
|
|
"opacity": 0.6,
|
|
"code": "// maska RGB co 3 piksele w poziomie (jak fosfory)\nforEach((x, y, p) => {\n const m = x % 3;\n if (m === 0) { p.g = (p.g * 0.7) | 0; p.b = (p.b * 0.7) | 0; }\n else if (m === 1) { p.r = (p.r * 0.7) | 0; p.b = (p.b * 0.7) | 0; }\n else { p.r = (p.r * 0.7) | 0; p.g = (p.g * 0.7) | 0; }\n});\n"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"name": "Cyberpunk Glitch",
|
|
"description": "Losowe poziome przesunięcia + chromatyczna aberracja + neonowe ziarno.",
|
|
"layers": [
|
|
{
|
|
"name": "rgb split",
|
|
"visible": true,
|
|
"opacity": 1.0,
|
|
"code": "// chromatic aberration — R w lewo, B w prawo\nconst shift = 6;\nforEach((x, y, p) => {\n const r = prev.getPixel(x - shift, y).r;\n const b = prev.getPixel(x + shift, y).b;\n p.r = r;\n p.b = b;\n});\n"
|
|
},
|
|
{
|
|
"name": "glitch slices",
|
|
"visible": true,
|
|
"opacity": 1.0,
|
|
"code": "// losowe paski przesunięte w poziomie\nconst sliceCount = 30;\nfor (let s = 0; s < sliceCount; s++) {\n const yStart = randomInt(0, height - 1);\n const yEnd = min(height, yStart + randomInt(2, 14));\n const shift = randomInt(-40, 40);\n for (let y = yStart; y < yEnd; y++) {\n for (let x = 0; x < width; x++) {\n const sx = (x - shift + width) % width;\n const q = prev.getPixel(sx, y);\n setPixel(x, y, q.r, q.g, q.b, q.a);\n }\n }\n}\n"
|
|
},
|
|
{
|
|
"name": "neon tint",
|
|
"visible": true,
|
|
"opacity": 0.4,
|
|
"code": "// fioletowo-cyjanowe przesunięcie kolorów\nforEach((x, y, p) => {\n p.r = clamp(p.r + 25);\n p.b = clamp(p.b + 35);\n});\n"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"name": "Pixel Mosaic",
|
|
"description": "Pikselizacja blokowa — z każdego bloku bierzemy kolor środka.",
|
|
"layers": [
|
|
{
|
|
"name": "mosaic",
|
|
"visible": true,
|
|
"opacity": 1.0,
|
|
"code": "// rozmiar bloku w pikselach\nconst block = 14;\nfor (let y = 0; y < height; y += block) {\n for (let x = 0; x < width; x += block) {\n const c = prev.getPixel(x + (block >> 1), y + (block >> 1));\n for (let by = 0; by < block; by++) {\n for (let bx = 0; bx < block; bx++) {\n setPixel(x + bx, y + by, c.r, c.g, c.b, c.a);\n }\n }\n }\n}\n"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"name": "Neon Edges",
|
|
"description": "Wyciągnięcie krawędzi przez różnicę sąsiadów + mocne kolory na czarnym tle.",
|
|
"layers": [
|
|
{
|
|
"name": "edges",
|
|
"visible": true,
|
|
"opacity": 1.0,
|
|
"code": "// |sąsiad - piksel| dla każdego kanału\nforEach((x, y, p) => {\n const a = prev.getPixel(x, y);\n const b = prev.getPixel(x + 1, y);\n const c = prev.getPixel(x, y + 1);\n p.r = clamp((abs(a.r - b.r) + abs(a.r - c.r)) * 3);\n p.g = clamp((abs(a.g - b.g) + abs(a.g - c.g)) * 3);\n p.b = clamp((abs(a.b - b.b) + abs(a.b - c.b)) * 3);\n});\n"
|
|
},
|
|
{
|
|
"name": "neon boost",
|
|
"visible": true,
|
|
"opacity": 1.0,
|
|
"code": "// gdziekolwiek jest jakaś krawędź — pompuj nasycenie\nforEach((x, y, p) => {\n const m = max(p.r, max(p.g, p.b));\n if (m > 30) {\n p.r = clamp(p.r * 1.6);\n p.g = clamp(p.g * 1.6);\n p.b = clamp(p.b * 1.6);\n }\n});\n"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"name": "Dream Wave",
|
|
"description": "Sinusoidalne falowanie + pastelowe rozmycie — łagodny, oniryczny look.",
|
|
"layers": [
|
|
{
|
|
"name": "wave",
|
|
"visible": true,
|
|
"opacity": 1.0,
|
|
"code": "// poziome i pionowe falowanie\nfor (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n const dx = floor(sin(y * 0.04) * 10);\n const dy = floor(cos(x * 0.04) * 6);\n const p = prev.getPixel((x + dx + width) % width, (y + dy + height) % height);\n setPixel(x, y, p.r, p.g, p.b, p.a);\n }\n}\n"
|
|
},
|
|
{
|
|
"name": "soft glow",
|
|
"visible": true,
|
|
"opacity": 0.55,
|
|
"code": "// fake-blur: średnia z 4 losowych sąsiadów (tanie i działa)\nforEach((x, y, p) => {\n let r = 0, g = 0, b = 0;\n for (let i = 0; i < 4; i++) {\n const q = prev.getPixel(x + randomInt(-3, 3), y + randomInt(-3, 3));\n r += q.r; g += q.g; b += q.b;\n }\n p.r = (r >> 2);\n p.g = (g >> 2);\n p.b = (b >> 2);\n});\n"
|
|
},
|
|
{
|
|
"name": "pastel lift",
|
|
"visible": true,
|
|
"opacity": 0.6,
|
|
"code": "// dodaj odrobinę bieli, żeby wybielić cienie\nforEach((x, y, p) => {\n p.r = clamp(p.r + 30);\n p.g = clamp(p.g + 35);\n p.b = clamp(p.b + 40);\n});\n"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"name": "Posterize Pop",
|
|
"description": "Redukcja palety (5 poziomów na kanał) + boost nasycenia — pop-art.",
|
|
"layers": [
|
|
{
|
|
"name": "posterize",
|
|
"visible": true,
|
|
"opacity": 1.0,
|
|
"code": "// kwantyzacja kolorów\nconst levels = 5;\nconst step = 255 / (levels - 1);\nforEach((x, y, p) => {\n p.r = round(p.r / step) * step;\n p.g = round(p.g / step) * step;\n p.b = round(p.b / step) * step;\n});\n"
|
|
},
|
|
{
|
|
"name": "saturate",
|
|
"visible": true,
|
|
"opacity": 1.0,
|
|
"code": "// proste wzmocnienie nasycenia względem szarości\nforEach((x, y, p) => {\n const gray = (p.r + p.g + p.b) / 3;\n p.r = clamp(gray + (p.r - gray) * 1.6);\n p.g = clamp(gray + (p.g - gray) * 1.6);\n p.b = clamp(gray + (p.b - gray) * 1.6);\n});\n"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"name": "Film Noir",
|
|
"description": "Twarda czerń i biel z mocnym kontrastem + ziarno.",
|
|
"layers": [
|
|
{
|
|
"name": "grayscale",
|
|
"visible": true,
|
|
"opacity": 1.0,
|
|
"code": "// luminancja BT.601\nforEach((x, y, p) => {\n const g = (p.r * 0.299 + p.g * 0.587 + p.b * 0.114) | 0;\n p.r = p.g = p.b = g;\n});\n"
|
|
},
|
|
{
|
|
"name": "contrast",
|
|
"visible": true,
|
|
"opacity": 1.0,
|
|
"code": "// rozciągnięcie kontrastu wokół 128\nforEach((x, y, p) => {\n const v = clamp((p.r - 128) * 1.7 + 128);\n p.r = p.g = p.b = v;\n});\n"
|
|
},
|
|
{
|
|
"name": "grain",
|
|
"visible": true,
|
|
"opacity": 0.7,
|
|
"code": "// mocniejsze ziarno niż w sepii\nforEach((x, y, p) => {\n const n = randomInt(-25, 25);\n p.r = clamp(p.r + n);\n p.g = clamp(p.g + n);\n p.b = clamp(p.b + n);\n});\n"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"name": "Static Storm",
|
|
"description": "Burza statyki — losowe punkty białego/czarnego szumu rozsypane po obrazie.",
|
|
"layers": [
|
|
{
|
|
"name": "noise sprinkle",
|
|
"visible": true,
|
|
"opacity": 1.0,
|
|
"code": "// 8% pikseli — biały szum, 4% czarny\nforEach((x, y, p) => {\n const r = random1();\n if (r < 0.08) {\n const v = random256();\n p.r = p.g = p.b = v;\n } else if (r < 0.12) {\n p.r = p.g = p.b = 0;\n }\n});\n"
|
|
},
|
|
{
|
|
"name": "horizontal lines",
|
|
"visible": true,
|
|
"opacity": 0.6,
|
|
"code": "// losowe całe linie do bieli\nfor (let i = 0; i < 6; i++) {\n const y = randomInt(0, height - 1);\n for (let x = 0; x < width; x++) {\n setPixel(x, y, 220, 220, 220, 255);\n }\n}\n"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"name": "Mirror Kaleidoscope",
|
|
"description": "Pionowe lustro + przesunięcie sinusoidalne — efekt kalejdoskopu.",
|
|
"layers": [
|
|
{
|
|
"name": "mirror",
|
|
"visible": true,
|
|
"opacity": 1.0,
|
|
"code": "// odbijamy lewą połówkę na prawą\nfor (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n const sx = x < width / 2 ? x : (width - 1 - x);\n const q = prev.getPixel(sx, y);\n setPixel(x, y, q.r, q.g, q.b, q.a);\n }\n}\n"
|
|
},
|
|
{
|
|
"name": "sine flow",
|
|
"visible": true,
|
|
"opacity": 1.0,
|
|
"code": "// powolny przepływ\nfor (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n const dx = floor(sin(y * 0.08) * 18);\n const q = prev.getPixel((x + dx + width) % width, y);\n setPixel(x, y, q.r, q.g, q.b, q.a);\n }\n}\n"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|