<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PRISMA EVO X | Modern Pro</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;800&family=JetBrains+Mono:wght@400;700&family=swap" rel="stylesheet">
<style>
:root {
--accent: #FFFFFF;
--bg: #0a0a0c;
--panel: rgba(20, 20, 25, 0.8);
--border: rgba(255, 255, 255, 0.08);
--text: #e0e0e0;
--subtext: #888;
}
body {
margin: 0;
height: 100vh;
display: flex;
background: var(--bg);
color: var(--text);
font-family: 'Inter', sans-serif;
overflow: hidden;
}
/* --- SIDEBAR --- */
.sidebar {
width: 600px;
background: var(--panel);
backdrop-filter: blur(20px);
border-right: 1px solid var(--border);
display: flex;
flex-direction: column;
z-index: 100;
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}
.header {
padding: 40px 30px;
background: linear-gradient(to bottom, rgba(0,0,0,0.2), transparent);
}
/* Logo Ayarı */
.header img {
max-width: 180px;
height: auto;
display: block;
}
.header .version {
font-family: 'JetBrains Mono';
font-size: 9px;
color: var(--subtext);
margin-top: 8px;
display: block;
letter-spacing: 2px;
}
.scroll {
flex: 1;
overflow-y: auto;
padding: 0 25px 40px;
mask-image: linear-gradient(to bottom, transparent, black 5%, black 95%, transparent);
}
.scroll::-webkit-scrollbar { width: 4px; }
.scroll::-webkit-scrollbar-thumb { background: var(--border); border-radius: 10px; }
/* --- GRID & BUTTONS --- */
.cat-title {
font-size: 16px;
color: var(--subtext);
margin: 35px 0 15px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 1.5px;
display: flex;
align-items: center;
gap: 10px;
}
.cat-title::after {
content: '';
flex: 1;
height: 1px;
background: var(--border);
}
.grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 10px;
}
.btn {
background: rgba(255,255,255,0.03);
border: 1px solid var(--border);
color: #ccc;
font-size: 16px;
padding: 12px 10px;
cursor: pointer;
transition: all 0.25s ease;
border-radius: 8px;
text-align: center;
font-family: 'Inter';
}
.btn:hover {
background: rgba(255,255,255,0.08);
border-color: var(--accent);
color: #fff;
transform: translateY(-2px);
}
.btn.active {
background: var(--accent);
color: #000;
font-weight: 700;
border-color: var(--accent);
box-shadow: 0 8px 20px rgba(0, 2, 4, 0.1);
}
/* --- VIEWPORT --- */
.viewport {
flex: 1;
display: flex;
flex-direction: column;
padding: 40px;
position: relative;
background: radial-gradient(circle at center, #16161a 0%, #0a0a0c 100%);
}
.main-controls {
margin-bottom: 30px;
display: flex;
justify-content: flex-end;
align-items: center;
gap: 10px;
}
/* Mobil Logo Stili */
.mobile-logo {
display: none; /* Masaüstünde gizli */
max-width: 240px;
height: auto;
margin-right: auto; /* Sola yaslar */
}
canvas {
max-width: 100%;
max-height: 65vh;
border-radius: 16px;
background: #000;
box-shadow: 0 30px 60px rgba(0,0,0,0.5);
transition: all 0.5s cubic-bezier(0.16, 1, 0.3, 1);
object-fit: contain;
margin: auto;
display: none;
}
.file-btn {
background: transparent;
border: 1px solid var(--border);
color: var(--text);
padding: 12px 28px;
cursor: pointer;
font-weight: 600;
font-size: 13px;
border-radius: 50px;
transition: 0.3s;
display: inline-flex;
align-items: center;
gap: 8px;
}
.file-btn:hover {
transform: scale(1.05);
box-shadow: 0 0 30px rgba(255,255,255,0.2);
border-color: var(--accent);
}
.action-btns {
display: none;
gap: 10px;
flex: 1;
justify-content: flex-end;
}
#up { display: none; }
.upload-area {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 80%;
max-width: 600px;
height: 300px;
border: 2px dashed #999;
border-radius: 20px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
color: var(--subtext);
cursor: pointer;
transition: 0.3s;
}
.upload-area:hover {
border-color: var(--accent);
background: rgba(255,255,255,0.2);
color: #fff;
}
.upload-area svg {
width: 48px;
height: 48px;
margin-bottom: 20px;
}
#loader {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
padding: 20px 40px;
background: rgba(0,0,0,0.8);
backdrop-filter: blur(10px);
border-radius: 12px;
font-family: 'JetBrains Mono';
letter-spacing: 2px;
border: 1px solid var(--accent);
display: none;
z-index: 200;
}
.stats {
font-family: 'JetBrains Mono';
font-size: 10px;
color: var(--subtext);
margin-top: 10px;
}
.mobile-toggle {
display: none;
position: fixed;
bottom: 72px;
right: 25px;
background: var(--accent);
width: 80px;
height: 80px;
border-radius: 50%;
z-index: 1000;
border: none;
box-shadow: 0 10px 30px rgba(0, 2, 4, 0.4);
cursor: pointer;
}
@media (max-width: 768px) {
.sidebar {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 80vh;
transform: translateY(100%);
border-radius: 30px 30px 0 0;
border-top: 1px solid var(--border);
}
.sidebar.open { transform: translateY(0); }
.viewport { padding: 20px; }
.mobile-toggle { display: flex; align-items: center; justify-content: center; }
canvas { max-height: 40vh; }
.upload-area { width: 90%; height: 250px; }
/* Mobilde logoyu görünür yap */
.mobile-logo { display: block; }
.main-controls { justify-content: space-between; }
}
</style>
</head>
<body>
<button class="mobile-toggle" onclick="toggleMenu()">
<svg width="40" height="40" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="SVGRepo_iconCarrier">
<path d="M3.84453 3.84453C2.71849 4.97056 2.71849 6.79623 3.84453 7.92226L5.43227 9.51C5.44419 9.49622 5.45669 9.48276 5.46978 9.46967L9.46978 5.46967C9.48284 5.45662 9.49625 5.44415 9.50999 5.43226L7.92226 3.84453C6.79623 2.71849 4.97056 2.71849 3.84453 3.84453Z" fill="#121212"></path>
<path d="M10.5679 6.49012C10.556 6.50386 10.5435 6.51728 10.5304 6.53033L6.53044 10.5303C6.51735 10.5434 6.5039 10.5559 6.49011 10.5678L16.0777 20.1555C17.2038 21.2815 19.0294 21.2815 20.1555 20.1555C21.2815 19.0294 21.2815 17.2038 20.1555 16.0777L10.5679 6.49012Z" fill="#121212"></path>
<path d="M16.1 2.30719C16.261 1.8976 16.8385 1.8976 16.9994 2.30719L17.4298 3.40247C17.479 3.52752 17.5776 3.62651 17.7022 3.67583L18.7934 4.1078C19.2015 4.26934 19.2015 4.849 18.7934 5.01054L17.7022 5.44252C17.5776 5.49184 17.479 5.59082 17.4298 5.71587L16.9995 6.81115C16.8385 7.22074 16.261 7.22074 16.1 6.81116L15.6697 5.71587C15.6205 5.59082 15.5219 5.49184 15.3973 5.44252L14.3061 5.01054C13.898 4.849 13.898 4.26934 14.3061 4.1078L15.3973 3.67583C15.5219 3.62651 15.6205 3.52752 15.6697 3.40247L16.1 2.30719Z" fill="#121212"></path>
<path d="M19.9672 9.12945C20.1281 8.71987 20.7057 8.71987 20.8666 9.12945L21.0235 9.5288C21.0727 9.65385 21.1713 9.75284 21.2959 9.80215L21.6937 9.95965C22.1018 10.1212 22.1018 10.7009 21.6937 10.8624L21.2959 11.0199C21.1713 11.0692 21.0727 11.1682 21.0235 11.2932L20.8666 11.6926C20.7057 12.1022 20.1281 12.1022 19.9672 11.6926L19.8103 11.2932C19.7611 11.1682 19.6625 11.0692 19.5379 11.0199L19.14 10.8624C18.732 10.7009 18.732 10.1212 19.14 9.95965L19.5379 9.80215C19.6625 9.75284 19.7611 9.65385 19.8103 9.5288L19.9672 9.12945Z" fill="#121212"></path>
<path d="M5.1332 15.3072C5.29414 14.8976 5.87167 14.8976 6.03261 15.3072L6.18953 15.7065C6.23867 15.8316 6.33729 15.9306 6.46188 15.9799L6.85975 16.1374C7.26783 16.2989 7.26783 16.8786 6.85975 17.0401L6.46188 17.1976C6.33729 17.2469 6.23867 17.3459 6.18953 17.471L6.03261 17.8703C5.87167 18.2799 5.29414 18.2799 5.1332 17.8703L4.97628 17.471C4.92714 17.3459 4.82852 17.2469 4.70393 17.1976L4.30606 17.0401C3.89798 16.8786 3.89798 16.2989 4.30606 16.1374L4.70393 15.9799C4.82852 15.9306 4.92714 15.8316 4.97628 15.7065L5.1332 15.3072Z" fill="#121212"></path>
</g>
</svg>
</button>
<div class="sidebar" id="sidebar">
<div class="header">
<img src="https://armzoyxigtzenavvvtzu.supabase.co/storage/v1/object/public/brands/pilight.png" alt="PRISMA EVO X">
<span class="version">ULTIMATE PIPELINE ENGINE 2026</span>
<div class="stats" id="stats">Engines: Loading...</div>
</div>
<div class="scroll">
<div id="menu"></div>
</div>
</div>
<div class="viewport">
<div class="main-controls">
<img class="mobile-logo" src="https://armzoyxigtzenavvvtzu.supabase.co/storage/v1/object/public/brands/pilight.png" alt="PRISMA EVO X">
<input type="file" id="up" accept="image/*">
<div class="action-btns" id="action-btns">
<label class="file-btn" for="up">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M23 4v6h-6M1 20v-6h6M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"/></svg>
NEW IMAGE
</label>
<button class="file-btn" onclick="downloadImg()">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M7 10l5 5 5-5M12 15V3"/></svg>
EXPORT
</button>
</div>
</div>
<label class="upload-area" for="up" id="upload-label">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M17 8l-5-5-5 5M12 3v12"/></svg>
<span>UPLOAD IMAGE</span>
</label>
<div id="loader">PROCESSING...</div>
<canvas id="cv"></canvas>
</div>
<script>
function toggleMenu() {
const sb = document.getElementById('sidebar');
sb.classList.toggle('open');
}
const cv=document.getElementById("cv"), ctx=cv.getContext("2d",{willReadFrequently:true});
let img=null, currentStyle="Normal", origData=null;
const Ops = {
gray: (d) => { for(let i=0;i<d.data.length;i+=4){ let v=d.data[i]*0.3+d.data[i+1]*0.59+d.data[i+2]*0.11; d.data[i]=d.data[i+1]=d.data[i+2]=v; } },
invert: (d) => { for(let i=0;i<d.data.length;i+=4){ d.data[i]=255-d.data[i]; d.data[i+1]=255-d.data[i+1]; d.data[i+2]=255-d.data[i+2]; } },
thresh: (d, val=128) => { for(let i=0;i<d.data.length;i+=4){ let v=(d.data[i]+d.data[i+1]+d.data[i+2])/3 > val ? 255 : 0; d.data[i]=d.data[i+1]=d.data[i+2]=v; } },
posterize: (d, levels=4) => { let step=255/levels; for(let i=0;i<d.data.length;i+=4){ d.data[i]=Math.round(d.data[i]/step)*step; d.data[i+1]=Math.round(d.data[i+1]/step)*step; d.data[i+2]=Math.round(d.data[i+2]/step)*step; } },
noise: (d, amt=30) => { for(let i=0;i<d.data.length;i+=4){ let n=(Math.random()-0.5)*amt; d.data[i]+=n; d.data[i+1]+=n; d.data[i+2]+=n; } },
tint: (d, r, g, b, str=1) => { for(let i=0;i<d.data.length;i+=4){ d.data[i]+=(r-d.data[i])*str; d.data[i+1]+=(g-d.data[i+1])*str; d.data[i+2]+=(b-d.data[i+2])*str; } },
channelSwap: (d, c1, c2, c3) => {
const map = {r:0, g:1, b:2};
let t = new Uint8ClampedArray(d.data);
for(let i=0;i<d.data.length;i+=4){ d.data[i]=t[i+map[c1]]; d.data[i+1]=t[i+map[c2]]; d.data[i+2]=t[i+map[c3]]; }
},
scanlines: (d, str=0.5, size=2) => { let w=d.width; for(let i=0;i<d.data.length;i+=4){ let y=Math.floor((i/4)/w); if(y%size===0){ d.data[i]*=str; d.data[i+1]*=str; d.data[i+2]*=str; } } },
vignette: (d, str=1) => { let w=d.width, h=d.height, cx=w/2, cy=h/2, max=Math.sqrt(cx*cx+cy*cy); for(let i=0;i<d.data.length;i+=4){ let x=(i/4)%w, y=Math.floor((i/4)/w), dist=Math.sqrt((x-cx)**2+(y-cy)**2), r=1-(dist/max)*str; d.data[i]*=r; d.data[i+1]*=r; d.data[i+2]*=r; } },
pixelate: (d, size=5) => {
let w=d.width, h=d.height;
let temp = new Uint8ClampedArray(d.data);
for(let y=0; y<h; y+=size){
for(let x=0; x<w; x+=size){
let i=(y*w+x)*4, r=temp[i], g=temp[i+1], b=temp[i+2];
for(let dy=0; dy<size && y+dy<h; dy++){
for(let dx=0; dx<size && x+dx<w; dx++){
let idx = ((y+dy)*w + (x+dx))*4;
d.data[idx]=r; d.data[idx+1]=g; d.data[idx+2]=b;
}
}
}
}
},
chromatic: (d, off=5) => { let t=new Uint8ClampedArray(d.data); for(let i=0;i<d.data.length;i+=4){ d.data[i]=t[i+off*4]||t[i]; d.data[i+2]=t[i-off*4]||t[i+2]; } },
duotone: (d, dark, light) => {
Ops.gray(d);
for(let i=0;i<d.data.length;i+=4){
let lum = d.data[i]/255;
d.data[i] = dark[0] + lum*(light[0]-dark[0]);
d.data[i+1] = dark[1] + lum*(light[1]-dark[1]);
d.data[i+2] = dark[2] + lum*(light[2]-dark[2]);
}
},
convolve: (d, m) => {
let side=Math.round(Math.sqrt(m.length)), half=Math.floor(side/2), src=new Uint8ClampedArray(d.data), sw=d.width, sh=d.height;
for(let y=0; y<sh; y++){
for(let x=0; x<sw; x++){
let r=0,g=0,b=0;
for(let cy=0; cy<side; cy++){
for(let cx=0; cx<side; cx++){
let scy=y+cy-half, scx=x+cx-half;
if(scy>=0 && scy<sh && scx>=0 && scx<sw){
let off=(scy*sw+scx)*4, wt=m[cy*side+cx];
r+=src[off]*wt; g+=src[off+1]*wt; b+=src[off+2]*wt;
}
}
}
let i=(y*sw+x)*4;
d.data[i]=r; d.data[i+1]=g; d.data[i+2]=b;
}
}
},
sobel: (d) => {
Ops.gray(d);
let src=new Uint8ClampedArray(d.data), w=d.width, h=d.height;
for(let y=1; y<h-1; y++){
for(let x=1; x<w-1; x++){
let px = (dx,dy) => src[((y+dy)*w + (x+dx))*4];
let gx = -px(-1,-1) + px(1,-1) - 2*px(-1,0) + 2*px(1,0) - px(-1,1) + px(1,1);
let gy = -px(-1,-1) - 2*px(0,-1) - px(1,-1) + px(-1,1) + 2*px(0,1) + px(1,1);
let val = Math.sqrt(gx*gx + gy*gy);
let i = (y*w+x)*4;
d.data[i]=d.data[i+1]=d.data[i+2]=val;
}
}
},
glitch: (d, block, shift) => {
let w=d.width, t=new Uint8ClampedArray(d.data);
for(let i=0;i<d.data.length;i+=4){
let y = Math.floor((i/4)/w);
if(y%block < block/2) {
let s = shift*4;
d.data[i]=t[i+s]||t[i]; d.data[i+1]=t[i+1+s]||t[i+1]; d.data[i+2]=t[i+2+s]||t[i+2];
}
}
},
bayer: (d) => {
Ops.gray(d);
const matrix = [[0,8,2,10],[12,4,14,6],[3,11,1,9],[15,7,13,5]];
for(let i=0;i<d.data.length;i+=4){
let x=(i/4)%d.width, y=Math.floor((i/4)/d.width);
let thresh = (matrix[x%4][y%4]/16)*255;
let v = d.data[i] > thresh ? 255 : 0;
d.data[i]=d.data[i+1]=d.data[i+2]=v;
}
},
colorFilter: (d, m) => {
let t=new Uint8ClampedArray(d.data);
for(let i=0;i<d.data.length;i+=4){
d.data[i] = t[i]*m[0] + t[i+1]*m[1] + t[i+2]*m[2];
d.data[i+1] = t[i]*m[3] + t[i+1]*m[4] + t[i+2]*m[5];
d.data[i+2] = t[i]*m[6] + t[i+1]*m[7] + t[i+2]*m[8];
}
},
solarize: (d) => { for(let i=0;i<d.data.length;i+=4){ d.data[i]=d.data[i]>127?255-d.data[i]:d.data[i]; d.data[i+1]=d.data[i+1]>127?255-d.data[i+1]:d.data[i+1]; d.data[i+2]=d.data[i+2]>127?255-d.data[i+2]:d.data[i+2]; } },
distort: (d, amt=10) => {
let w=d.width, h=d.height, t=new Uint8ClampedArray(d.data);
for(let y=0; y<h; y++){
for(let x=0; x<w; x++){
let nx = x + Math.sin(y/10)*amt;
if(nx>=0 && nx<w){
let i=(y*w+x)*4, ni=(y*w+Math.floor(nx))*4;
d.data[i]=t[ni]; d.data[i+1]=t[ni+1]; d.data[i+2]=t[ni+2];
}
}
}
},
kaleidoscope: (d, segments=6) => {
let w=d.width, h=d.height, t=new Uint8ClampedArray(d.data), cx=w/2, cy=h/2;
for(let y=0; y<h; y++){
for(let x=0; x<w; x++){
let dx=x-cx, dy=y-cy, r=Math.sqrt(dx*dx+dy*dy), a=Math.atan2(dy,dx);
a = Math.abs(((a % (Math.PI*2/segments)) - Math.PI/segments));
let nx=Math.floor(cx+Math.cos(a)*r), ny=Math.floor(cy+Math.sin(a)*r);
if(nx>=0 && nx<w && ny>=0 && ny<h){
let i=(y*w+x)*4, ni=(ny*w+nx)*4;
d.data[i]=t[ni]; d.data[i+1]=t[ni+1]; d.data[i+2]=t[ni+2];
}
}
}
},
liquid: (d) => {
let w=d.width, h=d.height, t=new Uint8ClampedArray(d.data);
for(let y=0; y<h; y++){
for(let x=0; x<w; x++){
let offX = Math.sin(y/20)*15, offY = Math.cos(x/20)*15;
let nx=Math.floor(x+offX), ny=Math.floor(y+offY);
if(nx>=0 && nx<w && ny>=0 && ny<h){
let i=(y*w+x)*4, ni=(ny*w+nx)*4;
d.data[i]=t[ni]; d.data[i+1]=t[ni+1]; d.data[i+2]=t[ni+2];
}
}
}
},
rain: (d) => {
for(let i=0; i<d.data.length; i+=Math.floor(Math.random()*200+100)){
for(let j=0; j<40; j++) { if(d.data[i+j*d.width*4]) d.data[i+j*d.width*4]+=100; }
}
},
fractalSplit: (d) => {
let w=d.width, h=d.height, t=new Uint8ClampedArray(d.data);
let s = Math.floor(w/2);
for(let i=0; i<d.data.length; i+=4){
let x=(i/4)%w, y=Math.floor((i/4)/w);
let ni = ((y%s)*w + (x%s))*4;
d.data[i]=t[ni]; d.data[i+1]=t[ni+1]; d.data[i+2]=t[ni+2];
}
}
};
const effectCategories = {
"Art & Sketch": [
{ id:"Pencil_Sketch", p: [ (d)=>Ops.sobel(d), (d)=>Ops.invert(d), (d)=>Ops.tint(d,240,240,240,0.2) ] },
{ id:"Chalkboard", p: [ (d)=>Ops.sobel(d), (d)=>Ops.noise(d,50), (d)=>Ops.tint(d,30,50,40,0.5) ] },
{ id:"Pop_Art_Andy", p: [ (d)=>Ops.posterize(d,3), (d)=>Ops.channelSwap(d,'g','b','r'), (d)=>Ops.tint(d,255,200,0,0.2) ] },
{ id:"Comic_Book", p: [ (d)=>Ops.posterize(d,4), (d)=>Ops.convolve(d, [0,-1,0,-1,5,-1,0,-1,0]), (d)=>Ops.noise(d,15) ] },
{ id:"Pointillism_Dither", p: [ (d)=>Ops.bayer(d), (d)=>Ops.tint(d,50,30,10,0.5) ] },
{ id:"Manga_Studio", p: [ (d)=>Ops.gray(d), (d)=>Ops.thresh(d,100), (d)=>Ops.noise(d,80), (d)=>Ops.scanlines(d,0.8,4) ] },
{ id:"Oil_Paint_Sim", p: [ (d)=>Ops.posterize(d,5), (d)=>Ops.convolve(d, [1/9,1/9,1/9,1/9,1/9,1/9,1/9,1/9,1/9]), (d)=>Ops.convolve(d, [0,-1,0,-1,5,-1,0,-1,0]) ] },
{ id:"Stain_Art", p: [ (d)=>Ops.thresh(d,128), (d)=>Ops.invert(d), (d)=>Ops.pixelate(d,3) ] },
{ id:"Color_Print", p: [ (d)=>Ops.channelSwap(d,'b','r','g'), (d)=>Ops.posterize(d,3), (d)=>Ops.bayer(d) ] },
{ id:"Pastel_Dream", p: [ (d)=>Ops.posterize(d,6), (d)=>Ops.tint(d,255,200,200,0.3) ] },
{ id:"Gravure_Print", p: [ (d)=>Ops.gray(d), (d)=>Ops.sobel(d), (d)=>Ops.thresh(d,50), (d)=>Ops.invert(d) ] },
{ id:"Mosaic_Glass", p: [ (d)=>Ops.pixelate(d,8), (d)=>Ops.convolve(d, [0,-1,0,-1,5,-1,0,-1,0]) ] },
{ id:"Street_Wall", p: [ (d)=>Ops.posterize(d,2), (d)=>Ops.noise(d,60), (d)=>Ops.tint(d,100,100,100,0.5) ] }
],
"Retro Tech": [
{ id:"Gameboy_Classic", p: [ (d)=>Ops.pixelate(d,4), (d)=>Ops.duotone(d, [15,56,15], [155,188,15]) ] },
{ id:"Virtual_Boy", p: [ (d)=>Ops.pixelate(d,3), (d)=>Ops.duotone(d, [20,0,0], [255,0,0]), (d)=>Ops.scanlines(d,0.5,2) ] },
{ id:"Commodore_64", p: [ (d)=>Ops.pixelate(d,5), (d)=>Ops.posterize(d,2), (d)=>Ops.tint(d,100,100,200,0.4) ] },
{ id:"Old_CRT_TV", p: [ (d)=>Ops.chromatic(d,3), (d)=>Ops.scanlines(d,0.6,3), (d)=>Ops.vignette(d,1.5), (d)=>Ops.noise(d,20) ] },
{ id:"VHS_Tape", p: [ (d)=>Ops.glitch(d,10,5), (d)=>Ops.channelSwap(d,'r','b','g'), (d)=>Ops.noise(d,30) ] },
{ id:"Apple_II_Monitor", p: [ (d)=>Ops.duotone(d, [0,0,0], [51,255,51]), (d)=>Ops.scanlines(d,0.7,2) ] },
{ id:"CGA_Graphics", p: [ (d)=>Ops.posterize(d,2), (d)=>Ops.channelSwap(d,'r','g','b'), (d)=>Ops.tint(d,255,85,255,0.5) ] },
{ id:"Time_Out_Disk", p: [ (d)=>Ops.pixelate(d,2), (d)=>Ops.glitch(d,50,-10), (d)=>Ops.gray(d) ] },
{ id:"Teletext", p: [ (d)=>Ops.pixelate(d,6), (d)=>Ops.posterize(d,2), (d)=>Ops.thresh(d,100) ] },
{ id:"Old_Camera", p: [ (d)=>Ops.sepia=Ops.colorFilter(d,[0.39,0.76,0.18, 0.34,0.68,0.16, 0.27,0.53,0.13]), (d)=>Ops.noise(d,40), (d)=>Ops.vignette(d,1.8) ] },
{ id:"Daguerreotype", p: [ (d)=>Ops.gray(d), (d)=>Ops.noise(d,60), (d)=>Ops.vignette(d,2), (d)=>Ops.convolve(d, [0,-1,0,-1,5,-1,0,-1,0]) ] },
{ id:"Pinhole", p: [ (d)=>Ops.vignette(d,2.5), (d)=>Ops.tint(d,50,30,10,0.3), (d)=>Ops.convolve(d, [1/9,1/9,1/9,1/9,1/9,1/9,1/9,1/9,1/9]) ] }
],
"Sci-Fi": [
{ id:"Thermal_Vision", p: [ (d)=>Ops.gray(d), (d)=>Ops.colorFilter(d, [2,0,0, 0,1.5,0, 0,0,0.5]) ] },
{ id:"Night_Vision", p: [ (d)=>Ops.gray(d), (d)=>Ops.duotone(d,[0,20,0],[50,255,50]), (d)=>Ops.noise(d,40), (d)=>Ops.vignette(d,1) ] },
{ id:"X_Ray_Machine", p: [ (d)=>Ops.invert(d), (d)=>Ops.duotone(d,[0,10,30],[200,255,255]), (d)=>Ops.sobel(d) ] },
{ id:"Predator_Vision", p: [ (d)=>Ops.solarize(d), (d)=>Ops.posterize(d,4), (d)=>Ops.tint(d,255,0,0,0.4) ] },
{ id:"Matrix_System", p: [ (d)=>Ops.sobel(d), (d)=>Ops.duotone(d,[0,0,0],[0,255,0]), (d)=>Ops.scanlines(d,0.5,2) ] },
{ id:"Sonar_Radar", p: [ (d)=>Ops.gray(d), (d)=>Ops.thresh(d,150), (d)=>Ops.duotone(d,[0,0,0],[0,150,255]), (d)=>Ops.vignette(d,2) ] },
{ id:"Cyborg_Eye", p: [ (d)=>Ops.chromatic(d,10), (d)=>Ops.tint(d,255,0,0,0.6), (d)=>Ops.scanlines(d,0.8,4) ] },
{ id:"Hacker_Terminal", p: [ (d)=>Ops.pixelate(d,2), (d)=>Ops.duotone(d,[0,0,0],[0,255,0]) ] },
{ id:"Infrared_IR", p: [ (d)=>Ops.invert(d), (d)=>Ops.channelSwap(d,'b','r','g') ] },
{ id:"Space_Scanner", p: [ (d)=>Ops.sobel(d), (d)=>Ops.invert(d), (d)=>Ops.colorFilter(d,[0,1,0, 0,0,1, 1,0,0]) ] },
{ id:"Radioactive", p: [ (d)=>Ops.solarize(d), (d)=>Ops.tint(d,100,255,50,0.5), (d)=>Ops.noise(d,50) ] },
{ id:"Biometric_Scan", p: [ (d)=>Ops.bayer(d), (d)=>Ops.duotone(d,[0,0,50],[0,255,255]) ] }
],
"Glitch & Distortion": [
{ id:"Data_Bend", p: [ (d)=>Ops.glitch(d,20,15), (d)=>Ops.chromatic(d,8) ] },
{ id:"Signal_Loss", p: [ (d)=>Ops.glitch(d,2,-20), (d)=>Ops.noise(d,50), (d)=>Ops.scanlines(d,0.2,2) ] },
{ id:"Chromatic_Aberration", p: [ (d)=>Ops.chromatic(d,15), (d)=>Ops.glitch(d,100,-10), (d)=>Ops.pixelate(d,2) ] },
{ id:"Ghost_Frequency", p: [ (d)=>Ops.solarize(d), (d)=>Ops.glitch(d,5,5), (d)=>Ops.tint(d,200,200,255,0.4) ] },
{ id:"Acid_Trip", p: [ (d)=>Ops.channelSwap(d,'g','b','r'), (d)=>Ops.solarize(d), (d)=>Ops.glitch(d,30,10) ] },
{ id:"Memory_Leak", p: [ (d)=>Ops.pixelate(d,10), (d)=>Ops.glitch(d,50,20), (d)=>Ops.posterize(d,3) ] },
{ id:"Corrupted_Tape", p: [ (d)=>Ops.noise(d,100), (d)=>Ops.scanlines(d,0.1,5), (d)=>Ops.chromatic(d,5) ] },
{ id:"Cyber_Wreck", p: [ (d)=>Ops.sobel(d), (d)=>Ops.glitch(d,15,30), (d)=>Ops.tint(d,255,0,255,0.5) ] },
{ id:"Broken_Screen", p: [ (d)=>Ops.glitch(d,200,-50), (d)=>Ops.glitch(d,10,20) ] }
],
"Atmospheric": [
{ id:"Extreme_Infrared", p: [ (d)=>Ops.invert(d), (d)=>Ops.channelSwap(d,'b','r','g'), (d)=>Ops.tint(d,255,0,50,0.4) ] },
{ id:"Anamorphic_Flare", p: [ (d)=>Ops.distort(d,5), (d)=>Ops.chromatic(d,12), (d)=>Ops.scanlines(d,0.8,4) ] },
{ id:"Vaporwave_Pink", p: [ (d)=>Ops.duotone(d,[0,255,255],[255,0,255]), (d)=>Ops.noise(d,20), (d)=>Ops.vignette(d,1.2) ] },
{ id:"Synthwave_Grid", p: [ (d)=>Ops.duotone(d,[20,0,40],[255,0,150]), (d)=>Ops.scanlines(d,0.4,3), (d)=>Ops.convolve(d,[0,-1,0,-1,5,-1,0,-1,0]) ] },
{ id:"ASCII_Matrix", p: [ (d)=>Ops.pixelate(d,6), (d)=>Ops.gray(d), (d)=>Ops.duotone(d,[0,0,0],[0,255,0]), (d)=>Ops.bayer(d) ] },
{ id:"Datamoshing_V1", p: [ (d)=>Ops.glitch(d,5,40), (d)=>Ops.pixelate(d,3), (d)=>Ops.chromatic(d,10) ] },
{ id:"Cyber_Rain", p: [ (d)=>Ops.rain(d), (d)=>Ops.tint(0,100,255,0.2), (d)=>Ops.scanlines(d,0.7,2) ] },
{ id:"Cyber_Fog", p: [ (d)=>Ops.convolve(d,[1/9,1/9,1/9,1/9,1/9,1/9,1/9,1/9,1/9]), (d)=>Ops.tint(d,200,200,220,0.3), (d)=>Ops.noise(d,10) ] },
{ id:"Broken_Glass", p: [ (d)=>Ops.glitch(d,50,10), (d)=>Ops.sobel(d), (d)=>Ops.invert(d), (d)=>Ops.chromatic(d,4) ] }
],
"Math Twist": [
{ id:"Kaleidoscope", p: [ (d)=>Ops.kaleidoscope(d,8), (d)=>Ops.posterize(d,5) ] },
{ id:"Liquid_Pixel", p: [ (d)=>Ops.liquid(d), (d)=>Ops.chromatic(d,5) ] },
{ id:"Fractal_Split", p: [ (d)=>Ops.fractalSplit(d), (d)=>Ops.convolve(d,[0,-1,0,-1,5,-1,0,-1,0]) ] },
{ id:"Swirl_Effect", p: [ (d)=>Ops.distort(d,30), (d)=>Ops.liquid(d) ] },
{ id:"Mirror_Maze", p: [ (d)=>Ops.kaleidoscope(d,4), (d)=>Ops.glitch(d,20,5) ] }
],
"Optical": [
{ id:"Extreme_Sharpen", p: [ (d)=>Ops.convolve(d, [0,-2,0,-2,9,-2,0,-2,0]) ] },
{ id:"Emboss", p: [ (d)=>Ops.gray(d), (d)=>Ops.convolve(d, [-2,-1,0,-1,1,1,0,1,2]) ] },
{ id:"Laplacian_Edge", p: [ (d)=>Ops.convolve(d, [-1,-1,-1,-1,8,-1,-1,-1,-1]) ] },
{ id:"Light_Blur", p: [ (d)=>Ops.convolve(d, [1/9,1/9,1/9,1/9,1/9,1/9,1/9,1/9,1/9]) ] },
{ id:"Lomography", p: [ (d)=>Ops.vignette(d,2), (d)=>Ops.tint(d,255,150,0,0.2), (d)=>Ops.posterize(d,6) ] },
{ id:"Dark_Room", p: [ (d)=>Ops.vignette(d,3), (d)=>Ops.tint(d,255,0,0,0.1) ] },
{ id:"Overexposure", p: [ (d)=>Ops.tint(d,255,255,255,0.4), (d)=>Ops.convolve(d, [0,-1,0,-1,5,-1,0,-1,0]) ] },
{ id:"Cinematic_Teal_Orange", p: [ (d)=>Ops.colorFilter(d, [1.2,0,0, 0,1,0.2, 0,0,1.5]), (d)=>Ops.vignette(d,1) ] },
{ id:"Gothic_Haze", p: [ (d)=>Ops.gray(d), (d)=>Ops.tint(d,0,0,0,0.5), (d)=>Ops.noise(d,20) ] },
{ id:"Polaroid_Faded", p: [ (d)=>Ops.tint(d,250,240,200,0.2), (d)=>Ops.vignette(d,1.5) ] },
{ id:"Invert_Negative", p: [ (d)=>Ops.invert(d) ] },
{ id:"High_Contrast_BW", p: [ (d)=>Ops.gray(d), (d)=>Ops.thresh(d,128) ] }
]
};
const generateProceduralEffects = () => {
let proceduralCat = [];
let duotones = [
["Blood_Moon",[50,0,0],[255,100,100]], ["Ocean_Floor",[0,10,50],[0,200,255]], ["Toxic_Jungle",[0,50,10],[100,255,0]],
["Gold_Dust",[30,20,0],[255,200,50]], ["Ice_Age",[200,200,255],[255,255,255]], ["Ashes",[20,20,20],[150,150,150]],
["Neon_Pink",[50,0,50],[255,50,200]], ["Dark_Matter",[0,0,0],[100,0,255]], ["Sandstorm",[50,30,0],[255,200,150]]
];
let blends = [
{n:"_Classic", o:[]}, {n:"_Striped", o:[(d)=>Ops.scanlines(d,0.5,3)]}, {n:"_Broken", o:[(d)=>Ops.glitch(d,15,10)]},
{n:"_Pixel", o:[(d)=>Ops.pixelate(d,4)]}, {n:"_Edge", o:[(d)=>Ops.sobel(d)]}, {n:"_Dither", o:[(d)=>Ops.bayer(d)]}
];
duotones.forEach(dt => {
blends.forEach(bl => {
let ops = [ (d)=>Ops.duotone(d, dt[1], dt[2]) ];
ops.push(...bl.o);
proceduralCat.push({ id: dt[0]+bl.n, p: ops });
});
});
let swaps = [['g','b','r'], ['b','r','g'], ['r','r','b'], ['g','g','g']];
swaps.forEach((sw, i) => {
proceduralCat.push({ id: `Dimension_Gate_v${i+1}`, p: [ (d)=>Ops.channelSwap(d, sw[0], sw[1], sw[2]), (d)=>Ops.solarize(d), (d)=>Ops.chromatic(d,10) ] });
proceduralCat.push({ id: `Alien_World_v${i+1}`, p: [ (d)=>Ops.channelSwap(d, sw[0], sw[1], sw[2]), (d)=>Ops.posterize(d,3), (d)=>Ops.invert(d) ] });
proceduralCat.push({ id: `Synthetic_Dream_v${i+1}`, p: [ (d)=>Ops.channelSwap(d, sw[0], sw[1], sw[2]), (d)=>Ops.noise(d,50), (d)=>Ops.vignette(d,2) ] });
});
effectCategories["Procedural Engine"] = proceduralCat;
};
generateProceduralEffects();
const menu=document.getElementById("menu");
let activePipeline = [];
let totalEffects = 0;
Object.entries(effectCategories).forEach(([title, list])=>{
let t=document.createElement("div"); t.className="cat-title";
t.innerHTML = `${title}`;
menu.appendChild(t);
let g=document.createElement("div"); g.className="grid";
list.forEach(effect => {
totalEffects++;
let b=document.createElement("button"); b.className="btn";
b.textContent=effect.id.replace(/_/g,' ');
b.onclick=() => {
document.querySelectorAll(".btn").forEach(x=>x.classList.remove("active"));
b.classList.add("active");
activePipeline = effect.p;
applyCurrent();
if(window.innerWidth <= 768) toggleMenu();
};
g.appendChild(b);
});
menu.appendChild(g);
});
document.getElementById("stats").textContent = `PIPELINES LOADED: ${totalEffects}`;
document.getElementById("up").onchange=e=>{
if(!e.target.files[0]) return;
let r=new FileReader();
r.onload=f=>{
img=new Image();
img.onload=()=>{
let sc=Math.min(1200/img.width, 1200/img.height, 1);
cv.width=img.width*sc; cv.height=img.height*sc;
ctx.drawImage(img,0,0,cv.width,cv.height);
origData = ctx.getImageData(0,0,cv.width,cv.height);
activePipeline = [];
document.querySelectorAll(".btn").forEach(x=>x.classList.remove("active"));
// UI GÜNCELLEME
document.getElementById("upload-label").style.display = "none";
document.getElementById("action-btns").style.display = "flex";
cv.style.display = "block";
};
img.src=f.target.result;
};
r.readAsDataURL(e.target.files[0]);
e.target.value = "";
};
function applyCurrent(){
if(!origData || activePipeline.length === 0) return;
const loader = document.getElementById("loader");
loader.style.display = "block";
cv.style.filter = "blur(10px) brightness(0.5)";
setTimeout(() => {
let d = new ImageData(new Uint8ClampedArray(origData.data), origData.width, origData.height);
activePipeline.forEach(step => step(d));
ctx.putImageData(d,0,0);
loader.style.display = "none";
cv.style.filter = "none";
}, 50);
}
function downloadImg() {
if(!origData) return;
const link = document.createElement('a');
link.download = 'prisma_evo_x.png';
link.href = cv.toDataURL("image/png");
link.click();
}
</script>
</body>
</html>