| Server IP : 217.154.3.148 / Your IP : 216.73.216.90 Web Server : Apache System : Linux blissful-wright.217-154-3-148.plesk.page 6.8.0-124-generic #124-Ubuntu SMP PREEMPT_DYNAMIC Tue May 26 13:00:45 UTC 2026 x86_64 User : gracious-boyd_hfhh1h8vo9n ( 10000) PHP Version : 8.3.31 Disable Function : opcache_get_status MySQL : OFF | cURL : ON | WGET : OFF | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : /var/www/vhosts/gracious-boyd.217-154-3-148.plesk.page/nextjs/lib/render/ |
Upload File : |
import { boxBlur } from '@/utils/maskOps'
import { lumaFromRgba } from '@/lib/render/light_map'
export type MapU8 = { data: Uint8Array; width: number; height: number }
/**
* Builds a specular/highlight map from the original image via a high-pass:
* spec = clamp(L - blur(L, rSmall), 0..255)
*/
export function buildSpecularMap(opts: {
rgba: Uint8ClampedArray
width: number
height: number
tilesMask?: Uint8Array | null
blurRadiusPx?: number
postBlurPx?: number
strength?: number // 0..1
}): MapU8 {
const width = Math.max(1, Math.round(opts.width))
const height = Math.max(1, Math.round(opts.height))
const tilesMask = opts.tilesMask ?? null
const blurRadiusPx = Math.max(0, Math.round(opts.blurRadiusPx ?? 6))
const postBlurPx = Math.max(0, Math.round(opts.postBlurPx ?? 3))
const strength = Math.max(0, Math.min(1, opts.strength ?? 0.25))
const gray = lumaFromRgba(opts.rgba, width, height)
const low = blurRadiusPx ? boxBlur(gray, width, height, blurRadiusPx) : null
const spec = new Uint8Array(width * height)
for (let i = 0; i < spec.length; i++) {
if (tilesMask && !tilesMask[i]) {
spec[i] = 0
continue
}
const base = gray[i]
const blurred = low ? low[i] : base
const hp = base - (Number.isFinite(blurred) ? blurred : base)
const v = Math.max(0, Math.min(255, Math.round(hp * strength)))
spec[i] = v
}
if (!postBlurPx) return { data: spec, width, height }
const post = boxBlur(spec, width, height, postBlurPx)
const out = new Uint8Array(width * height)
for (let i = 0; i < out.length; i++) {
const v = post[i]
out[i] = Math.max(0, Math.min(255, Math.round(Number.isFinite(v) ? v : 0)))
}
return { data: out, width, height }
}