Aşağıdaki fonksiyon, ham piksel verisini `RawBase64` ile alır, JavaScript'te ayrılabilir (iki geçişli) bir Gaussian bulanıklık uygular ve sonucu PNG'ye dönüştürüp `SetPixelData` ile geri yazar. `SetPixelData` ham veri yerine PNG base64 beklediği için küçük, sıkıştırmasız bir PNG kodlayıcı da eklenmiştir. `OnStart` içine şu satırı ekleyin: ```javascript AddGaussianBlurImage(lay, "/Sys/Img/Hello.png", 0.2, 5) // Gaussian (JS) ``` Fonksiyonlar: ```javascript // ---- Gaussian Blur (RawBase64) ---- const RAW_ORDER = "RGBA"; // Renkler hatalı görünürse "ARGB" yapın function AddGaussianBlurImage(lay, path, width, radius) { const src = app.CreateImage(path, width, -1); const w = src.GetAbsWidth(), h = src.GetAbsHeight(); const r = radius || 5; // Ham piksel verisini al const bin = atob(src.GetPixelData("RawBase64", 0, 0, w, h)); const px = new Uint8ClampedArray(w * h * 4); for (let i = 0; i < px.length; i++) px[i] = bin.charCodeAt(i); if (RAW_ORDER === "ARGB") _argbToRgba(px); _gaussianBlur(px, w, h, r); // PNG'ye dönüştür ve geri yaz const png = _encodePng(px, w, h); const prefix = src.GetPixelData("pngBase64", 0, 0, 1, 1).indexOf("data:") === 0; const img = app.CreateImage(null, w, h, "px"); img.SetPixelData(prefix ? "data:image/png;base64," + png : png, w, h, "px"); lay.AddChild(img); return img; } function _argbToRgba(px) { for (let i = 0; i < px.length; i += 4) { const a = px[i]; px[i] = px[i + 1]; px[i + 1] = px[i + 2]; px[i + 2] = px[i + 3]; px[i + 3] = a; } } function _gaussianBlur(px, w, h, r) { // Çekirdeği oluştur const sigma = r / 2, size = r * 2 + 1, k = new Float32Array(size); let sum = 0; for (let i = -r; i <= r; i++) { k[i + r] = Math.exp(-(i * i) / (2 * sigma * sigma)); sum += k[i + r]; } for (let i = 0; i < size; i++) k[i] /= sum; const tmp = new Float32Array(px.length); // Yatay geçiş for (let y = 0; y < h; y++) for (let x = 0; x < w; x++) for (let c = 0; c < 4; c++) { let v = 0; for (let i = -r; i <= r; i++) { const xx = Math.min(w - 1, Math.max(0, x + i)); v += px[(y * w + xx) * 4 + c] * k[i + r]; } tmp[(y * w + x) * 4 + c] = v; } // Dikey geçiş for (let y = 0; y < h; y++) for (let x = 0; x < w; x++) for (let c = 0; c < 4; c++) { let v = 0; for (let i = -r; i <= r; i++) { const yy = Math.min(h - 1, Math.max(0, y + i)); v += tmp[(yy * w + x) * 4 + c] * k[i + r]; } px[(y * w + x) * 4 + c] = v; } } function _encodePng(px, w, h) { // Satırlara filtre baytı ekle const rowLen = w * 4 + 1, raw = new Uint8Array(rowLen * h); for (let y = 0; y < h; y++) raw.set(px.subarray(y * w * 4, (y + 1) * w * 4), y * rowLen + 1); // Sıkıştırmasız zlib akışı const blocks = Math.max(1, Math.ceil(raw.length / 65535)); const z = new Uint8Array(2 + raw.length + blocks * 5 + 4); let p = 0; z[p++] = 0x78; z[p++] = 0x01; for (let i = 0; i < blocks; i++) { const start = i * 65535, len = Math.min(65535, raw.length - start); z[p++] = i === blocks - 1 ? 1 : 0; z[p++] = len & 255; z[p++] = len >> 8; z[p++] = ~len & 255; z[p++] = (~len >> 8) & 255; z.set(raw.subarray(start, start + len), p); p += len; } let a = 1, b = 0; for (let i = 0; i < raw.length; i++) { a = (a + raw[i]) % 65521; b = (b + a) % 65521; } _u32(z, p, ((b << 16) | a) >>> 0); // PNG parçaları const ihdr = new Uint8Array(13); _u32(ihdr, 0, w); _u32(ihdr, 4, h); ihdr[8] = 8; ihdr[9] = 6; // 8 bit, RGBA const parts = [ new Uint8Array([137, 80, 78, 71, 13, 10, 26, 10]), _pngChunk("IHDR", ihdr), _pngChunk("IDAT", z), _pngChunk("IEND", new Uint8Array(0)) ]; let s = ""; parts.forEach(part => { for (let i = 0; i < part.length; i += 8192) s += String.fromCharCode.apply(null, part.subarray(i, i + 8192)); }); return btoa(s); } function _pngChunk(type, data) { const out = new Uint8Array(12 + data.length); _u32(out, 0, data.length); for (let i = 0; i < 4; i++) out[4 + i] = type.charCodeAt(i); out.set(data, 8); _u32(out, 8 + data.length, _crc32(out.subarray(4, 8 + data.length))); return out; } function _u32(arr, o, v) { arr[o] = v >>> 24; arr[o + 1] = (v >>> 16) & 255; arr[o + 2] = (v >>> 8) & 255; arr[o + 3] = v & 255; } let _crcTable = null; function _crc32(buf) { if (!_crcTable) { _crcTable = new Uint32Array(256); for (let n = 0; n < 256; n++) { let c = n; for (let k = 0; k < 8; k++) c = c & 1 ? 0xEDB88320 ^ (c >>> 1) : c >>> 1; _crcTable[n] = c >>> 0; } } let c = 0xFFFFFFFF; for (let i = 0; i < buf.length; i++) c = _crcTable[(c ^ buf[i]) & 255] ^ (c >>> 8); return (c ^ 0xFFFFFFFF) >>> 0; } ``` Birkaç önemli not: - `RawBase64` verisinin bayt sırası (RGBA veya ARGB) belgelenmemiştir. Renkler kaymış görünürse `RAW_ORDER` değerini `"ARGB"` yapmanız yeterlidir. - Bu yöntem ana iş parçacığında çalıştığı için büyük resimlerde ve yüksek yarıçaplarda arayüzü birkaç saniye dondurabilir. Küçük resimler (ör. ekran genişliğinin %20'si) için uygundur. - Üç yöntemi yan yana karşılaştırdığınızda kalite açısından Gaussian ve WebView sürümlerinin benzer, hız açısından ise WebView sürümünün belirgin şekilde üstün olmasını bekleyebilirsiniz.