Last active
February 10, 2025 14:38
-
-
Save Sauerstoffdioxid/b70648ed4eda0c1c876fc7919c0dff98 to your computer and use it in GitHub Desktop.
UserScript for WebSDR Background Recording (+Custom Colormaps)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Since I wrote this mostly for myself, there's some slight issues to be aware of. | |
On PhantomSDR instances for the background recording to capture the waterfall, | |
you will have to wait for the custom color map to be inserted before you start | |
the audio. That's because the colormap script also injects a custom waterfall | |
rendering function that runs a bit more efficiently and produces slightly better | |
results than the original PhantomSDR waterfall renderer. | |
This is not an issue on KiwiSDR instances. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name PhantomSDR BG Recorder | |
// @namespace Violentmonkey Scripts | |
// @match *://*:*/* | |
// @match *://*sdr*.*/* | |
// @match *://*kiwi*.*/* | |
// @match *://*.swl.su/* | |
// @grant GM_registerMenuCommand | |
// @grant GM_addElement | |
// @version 1.2 | |
// ==/UserScript== | |
//SETTINGS | |
const individualChunkDuration = 10 * 6e4 //6e4 = 60 000 ms = 1min | |
const replayDuration = 30 //in minutes minutes | |
//audio quality | |
const audioBitRate = 128000 | |
//video quality | |
const videoBitsPerPixel = 1.3 //more means higher quality. 1 is about the minimum I'd consider. 0 disables video altogether. | |
//Info text | |
const infoTemplate = `${location.host} #[TIME] #[FREQ]#[MODE]` | |
const infoFontSize = 14 | |
function injectScript(f, p=[]) { | |
if (window.mozInnerScreenX) { | |
//Firefox | |
GM_addElement('script', { | |
src: URL.createObjectURL( | |
new Blob([`!${f}(${p});document.currentScript.remove()`],{type:'application/javascript'}) | |
) | |
}); | |
} else { | |
GM_addElement('script', { | |
textContent: `!${f}(${p});document.currentScript.remove()` | |
}); | |
} | |
} | |
window.addEventListener('bgRecorderReady', ()=> { | |
const recordingCanvas = document.createElement('canvas') | |
const recordingCtx = recordingCanvas.getContext('2d', {alpha: false}) | |
let recordingCanvasUpdated = false | |
//recordingCtx.globalCompositeOperation = 'multiply' | |
//TODO: Modulation mode | |
let waterfallElem, labelElem, frequencyInput, audioTrack, pathToWaterfallUpdateFunction, updateRecordingCanvas, demodulationMode, currentFreq | |
const infoTemplateRegex = new RegExp(/\#\[(\w+)\]/g) | |
const executeInfoTemplate = () => { | |
return infoTemplate.replaceAll(infoTemplateRegex, function(m, instruction){ | |
switch(instruction.toUpperCase()) { | |
case 'TIME': | |
return new Date().toISOString().replace(/\.\d+/, '') | |
case 'MODE': | |
return resolvePath(demodulationMode) | |
case 'FREQ': | |
return currentFreq | |
} | |
}) | |
} | |
const resolvePath = (path) => { | |
let obj = globalThis.unsafeWindow || window | |
path.forEach(x => {obj = obj[x]}) | |
return obj | |
} | |
if((globalThis.unsafeWindow||window).spectrumWaterfall) { | |
waterfallElem = spectrumWaterfall.canvasElem | |
labelElem = spectrumWaterfall.graduationCanvasElem | |
frequencyInput = document.querySelector('input[name=frequency]') | |
audioTrack = spectrumAudio.destinationNode._nativeAudioNode.stream.getAudioTracks()[0] | |
demodulationMode = ["spectrumAudio", "demodulation"] | |
pathToWaterfallUpdateFunction = ["spectrumWaterfall", "drawWaterfallLine"] | |
recordingCanvas.width = waterfallElem.width | |
recordingCanvas.height = waterfallElem.height + labelElem.height + 10 + infoFontSize*devicePixelRatio | |
recordingCtx.textBaseline = 'ideographic' | |
updateRecordingCanvas = function() { | |
//for recording | |
const updY = 0 //recordingCanvas.height - ctx.canvas.height | |
recordingCtx.globalCompositeOperation = 'source-over' | |
recordingCtx.globalAlpha = 1 | |
//recordingCtx.drawImage(recordingCanvas, 0, -1) | |
recordingCtx.drawImage(waterfallElem, 0, updY) | |
recordingCtx.fillStyle = '#111' | |
recordingCtx.fillRect(0, waterfallElem.height, recordingCanvas.width, 500) | |
recordingCtx.drawImage(labelElem, 0, waterfallElem.height + 8) | |
recordingCtx.globalCompositeOperation = 'multiply' | |
recordingCtx.fillStyle = '#aaa' | |
//recordingCtx.globalAlpha = 0.7 | |
const curAudio = spectrumAudio.getAudioRange().map(x=>spectrumWaterfall.idxToFreq(x)).map(x=>spectrumWaterfall.freqToCanvasX(x)) | |
recordingCtx.fillRect(0, updY, Math.min(curAudio[0], recordingCanvas.width), recordingCanvas.height) | |
recordingCtx.fillRect(Math.max(curAudio[2], 0), updY, recordingCanvas.width, recordingCanvas.height) | |
/*recordingCtx.globalCompositeOperation = 'soft-light' | |
recordingCtx.fillRect(curAudio[0], updY, curAudio[2]-curAudio[0], recordingCanvas.height)*/ | |
recordingCtx.globalCompositeOperation = 'source-over' | |
recordingCtx.fillRect(curAudio[0], waterfallElem.height + 2, curAudio[2]-curAudio[0], 2) | |
recordingCtx.fillText(executeInfoTemplate(), 2, recordingCanvas.height - 2) | |
recordingCanvasUpdated = true | |
} | |
} else if ((globalThis.unsafeWindow||window).kiwi) { | |
//TODO: figure out waterfall | |
waterfallElem = wf_cur_canvas | |
labelElem = scale_canvas | |
frequencyInput = document.querySelector('#id-freq-input') | |
pathToWaterfallUpdateFunction = ["waterfall_add"] | |
let audioStreamSink = audio_context.createMediaStreamDestination() | |
audio_convolver.connect(audioStreamSink) | |
audioTrack = audioStreamSink.stream.getAudioTracks()[0] | |
demodulationMode = ["cur_mode"] | |
recordingCanvas.width = waterfallElem.width | |
recordingCanvas.height = waterfallElem.height*1.5 + labelElem.height + 10 + infoFontSize*devicePixelRatio | |
recordingCtx.textBaseline = 'hanging' | |
updateRecordingCanvas = function() { | |
//for recording | |
const labelH = recordingCanvas.width * (labelElem.height/labelElem.width) | |
let y = labelH + infoFontSize*devicePixelRatio + 6 - wf_canvas_actual_line | |
let i = 0 | |
while (y < recordingCanvas.height && i < wf_canvases.length) { | |
recordingCtx.drawImage(wf_canvases[i], 0, y) | |
y += wf_canvases[i].height | |
i++ | |
} | |
recordingCtx.fillStyle = '#111' | |
recordingCtx.fillRect(0, 0, recordingCanvas.width, labelH + infoFontSize*devicePixelRatio + 6) | |
recordingCtx.fillStyle = '#aaa' | |
recordingCtx.fillText(executeInfoTemplate(), 2, 2) | |
recordingCtx.drawImage(labelElem, | |
0, infoFontSize*devicePixelRatio + 4, | |
recordingCanvas.width, labelH) | |
recordingCanvasUpdated = true | |
} | |
} else if (document.getElementById('wf1canvas0')) { | |
//classic WebSDR | |
waterfallElem = document.getElementById('wf1canvas0') | |
labelElem = document.querySelector('#clipscale0 > img') | |
frequencyInput = document.querySelector('input[name="frequency"]') | |
const o = document.ct.constructor.prototype.createConvolver | |
let convolver | |
document.ct.constructor.prototype.createConvolver = function() { | |
convolver = o.apply(this, arguments) | |
return convolver | |
} | |
soundapplet.restartaudio() | |
let audioStreamSink = convolver.context.createMediaStreamDestination(); | |
convolver.connect(audioStreamSink) | |
audioTrack = audioStreamSink.stream.getAudioTracks()[0] | |
demodulationMode = ["mode"] | |
pathToWaterfallUpdateFunction = ["waterfallapplet", "0", "d", "onmessage"] | |
recordingCanvas.width = waterfallElem.width | |
recordingCanvas.height = waterfallElem.height + labelElem.height + 20 + infoFontSize*devicePixelRatio | |
recordingCtx.textBaseline = 'ideographic' | |
updateRecordingCanvas = function() { | |
//for recording | |
const updY = 0 //recordingCanvas.height - ctx.canvas.height | |
recordingCtx.globalCompositeOperation = 'source-over' | |
recordingCtx.globalAlpha = 1 | |
recordingCtx.drawImage(waterfallElem, 0, updY) | |
recordingCtx.fillStyle = '#111' | |
recordingCtx.fillRect(0, waterfallElem.height, recordingCanvas.width, 500) | |
for (let x of scaleobjs[0].children) { | |
recordingCtx.drawImage(x, parseFloat(x.style.left), waterfallElem.height + 8) | |
} | |
recordingCtx.globalCompositeOperation = 'multiply' | |
recordingCtx.fillStyle = '#aaa' | |
//recordingCtx.globalAlpha = 0.7 | |
const left = parseFloat(passbandobj.style.left), width = parseFloat(passbandobj.style.width) | |
recordingCtx.fillRect(0, updY, Math.min(left, recordingCanvas.width), recordingCanvas.height) | |
recordingCtx.fillRect(Math.max(left+width, 0), updY, recordingCanvas.width, recordingCanvas.height) | |
recordingCtx.globalCompositeOperation = 'source-over' | |
recordingCtx.fillRect(left, waterfallElem.height + 2, width, 2) | |
recordingCtx.fillText(executeInfoTemplate(), 2, recordingCanvas.height - 2) | |
recordingCanvasUpdated = true | |
} | |
} else { | |
debugger | |
return | |
} | |
currentFreq = frequencyInput.value | |
function createDownload(url, filename) { | |
let a = document.createElement('a') | |
a.href = url | |
a.download = filename | |
a.click() | |
} | |
const NutLib = (()=>{ | |
"use strict"; | |
return function(){f.from=async function(e,t){var n,[,,a,r]=arguments,o="number"==typeof a?new f(e,void 0,a):new f(e,a,r);for(n of t)o.addTask(n);return o.finalize()};const t=f;function f(e,t={},n=navigator.hardwareConcurrency){let a=[],r=[],o=[],f=[],i=0,s=-1;var u,c,l=(e,t)=>`var ${e}=${"function"==typeof t?t.toString():JSON.stringify(t)};`;let d="";for([u,c]of Object.entries(t))d+=l(u,c);d=d+l("THREADFUNC",e)+"onmessage="+(async e=>{let t=await THREADFUNC(e.data.a),n=[];const a=e=>{if("object"==typeof e){["ArrayBuffer","ReadableStream","ImageBitmap","OffscreenCanvas","MediaSourceHandle"].includes(e[Symbol.toStringTag])&&n.push(e);for(var t of Object.values(e))a(t)}};a(t),postMessage({r:t,i:e.data.i},n)});const g=URL.createObjectURL(new Blob([d]));function y(e){o[e.data.i](e.data.r),h(e.srcElement)}function h(e){var t;++s<i&&("arg"in(t=r[s])&&"transfer"in t?e.postMessage({i:s,a:t.arg},t.transfer):e.postMessage({i:s,a:t}))}return{addTask:function(e){i=r.push(e),f.push(new Promise(e=>{o.push(e)})),a.length<n&&((e=new Worker(g)).onmessage=y,a.push(e),h(e))},finalize:async function(){var e,t=await Promise.all(f);for(e of a)e.terminate();return t}}}var e=function(){const A=n=>[(e,t)=>n.setUint16(e,t,!0),(e,t)=>n.setUint32(e,t,!0)];async function e(v){const H=v.crcLut;return async function(e){let t,n,a,{name:r,data:o}=v.file,f=new Uint8Array(o),i=function(e){let[t,n,a,r,o,f,i,s]=H,u=-1,c=0;for(var l,d,g=new Uint32Array(e.buffer,0,e.buffer.byteLength>>>2),y=4294967294&g.length;c<y;)l=g[c++]^u,d=g[c++],u=s[255&l]^i[l>>>8&255]^f[l>>>16&255]^o[l>>>24]^r[255&d]^a[d>>>8&255]^n[d>>>16&255]^t[d>>>24];let h=4*c;for(;h<e.length;)u=u>>>8^t[255&u^e[h++]];return~u}(f),s=e?(t=f,n=new CompressionStream("deflate-raw"),a=new Response(t).body.pipeThrough(n),await new Response(a).arrayBuffer()):f.buffer,u=new ArrayBuffer(30),c=new DataView(u),l=new ArrayBuffer(46),d=new DataView(l),g=new Date,y=g.getFullYear(),h=g.getMonth()+1,w=g.getDate(),p=g.getHours()<<11|g.getMinutes()<<5|g.getSeconds()>>>1,b=(y<1980?0:2107<y?127:y-1980)<<9|h<<5|w,[m,L]=A(c);return L(0,67324752),e?m(4,2580):m(4,2570),m(6,2048),e?m(8,8):m(8,0),m(10,p),m(12,b),L(14,i),L(18,s.byteLength),L(22,f.byteLength),m(26,r.byteLength),[m,L]=A(d),L(0,33639248),m(4,2623),e?m(6,2580):m(6,2570),m(8,2048),e?m(10,8):m(10,0),m(12,p),m(14,b),L(16,i),L(20,s.byteLength),L(24,f.byteLength),m(28,r.byteLength),{data:s,name:r,localHeader:u,centralHeader:l}}(v.compress)}const r=function(){var e=Array.from({length:8},()=>new Uint32Array(256)),[n,t,a,r,o,f,i,s]=e;for(let e=0;e<=255;e++){let t=e;for(let e=0;e<8;e++)t=t>>>1^3988292384*(1&t);n[e]=t}for(let e=0;e<=255;e++)t[e]=n[e]>>>8^n[255&n[e]],a[e]=t[e]>>>8^n[255&t[e]],r[e]=a[e]>>>8^n[255&a[e]],o[e]=r[e]>>>8^n[255&r[e]],f[e]=o[e]>>>8^n[255&o[e]],i[e]=f[e]>>>8^n[255&f[e]],s[e]=i[e]>>>8^n[255&i[e]];return e}(),o=new TextEncoder;function f(){const u=new t(e,{[A.name]:A});this.addFile=function(e,t=!1){let{name:n,data:a}=e;n=o.encode(n).buffer,(a="string"==typeof a?o.encode(a):a).buffer&&"object"==typeof a.buffer&&(a=a.buffer),u.addTask({arg:{file:{data:a,name:n},compress:t,crcLut:r},transfer:[a,n]})},this.finalize=async function(){var e,t,n=await u.finalize(),a=[];let r=0;for(e of n)e.offset=r,a.push(e.localHeader),a.push(e.name),a.push(e.data),r+=e.localHeader.byteLength+e.name.byteLength+e.data.byteLength;let o=0;for(t of n)new DataView(t.centralHeader).setUint32(42,t.offset,!0),a.push(t.centralHeader),a.push(t.name),o+=t.centralHeader.byteLength+t.name.byteLength;var f=new ArrayBuffer(22),i=new DataView(f),[i,s]=A(i);return s(0,101010256),i(8,n.length),i(10,n.length),s(12,o),s(16,r),a.push(f),new Blob(a,{type:"application/zip"})}}return f.from=async function(e,t=0){var n,a=new f;for(n of e)a.addFile(n);return a.finalize()},f}();return{Parallel:t,Zip:e}}(); | |
})() | |
//trackA.applyConstraints({noiseSuppresion:true}) | |
//spectrumWaterfall.wfheight = spectrumWaterfall.canvasWidth / (16/9), spectrumWaterfall.resizeCallback() | |
let tracks = [audioTrack] | |
if (videoBitsPerPixel) { | |
let videoTrack = recordingCanvas.captureStream(0) | |
tracks.push(videoTrack.getVideoTracks()[0]) | |
window.setInterval(()=>{ | |
if (recordingCanvasUpdated) { | |
videoTrack.requestFrame() | |
} | |
}, 1e3/24) | |
} | |
let stream = new MediaStream(tracks) | |
let recorder = (function(stream, replayDuration, individualChunkDuration){ | |
let audioChunks = [] | |
let firstRun = true | |
let currentRecorder = new MediaRecorder(stream, { | |
//mimeType: 'audio/ogg; codecs=opus', | |
audioBitsPerSecond: audioBitRate, | |
videoBitsPerSecond: recordingCanvas.width*recordingCanvas.height * videoBitsPerPixel, | |
}) | |
let timer = null | |
let chunkStartTime = 0 | |
let recordedTime = 0 | |
let dataAddedCallback = () => undefined | |
currentRecorder.ondataavailable = async (e) => { | |
let obj = audioChunks[1] | |
obj.data = e.data | |
let otherFreqs = currentFreq != obj.startFreq || resolvePath(demodulationMode) != obj.startMode | |
obj.name = `${ | |
obj.startTime.toISOString().replace(/\.\d+/, '').replaceAll(':', '-').replace('T', 'T_') | |
}_${ | |
obj.startFreq + obj.startMode + (otherFreqs ? '(+more)' : '') | |
}_${ | |
location.hostname | |
}.${/\/(\w+)/.exec(e.data.type)[1]}` | |
obj.duration = e.timeStamp - chunkStartTime | |
chunkStartTime = e.timeStamp | |
recordedTime += obj.duration | |
while(recordedTime > replayDuration*6e4) { | |
let toDelete = audioChunks.pop() | |
recordedTime -= toDelete.duration | |
} | |
dataAddedCallback() | |
} | |
currentRecorder.onstart = (e) => { | |
chunkStartTime = e.timeStamp | |
} | |
function concludeChunk() { | |
if (timer !== null) window.clearTimeout(timer); | |
if (firstRun) { | |
firstRun = false | |
} else { | |
currentRecorder.stop() | |
} | |
audioChunks.unshift({ | |
startTime: new Date(), | |
startFreq: currentFreq, | |
startMode: resolvePath(demodulationMode) || 'kHz' | |
}) | |
currentRecorder.start() | |
timer = window.setTimeout(concludeChunk, individualChunkDuration) | |
} | |
function saveChunks() { | |
dataAddedCallback = async () => { | |
let completedChunks = audioChunks.filter(x => x.data) | |
let buffers = await Promise.all(completedChunks.map(x=>x.data.arrayBuffer())) | |
let zip = await NutLib.Zip.from(completedChunks.map((x,i)=>({data:buffers[i], name:x.name}))) | |
let zipUrl = URL.createObjectURL(zip) | |
createDownload(zipUrl, `websdr_last${replayDuration}min_${+new Date()}.zip`) | |
URL.revokeObjectURL(zipUrl) | |
dataAddedCallback = ()=>undefined | |
} | |
concludeChunk() | |
} | |
let newFreqTimeout = -1 | |
window.addEventListener('SDRFrequencyChanged', (e) => { | |
window.clearTimeout(newFreqTimeout) | |
currentFreq = e.detail.newFrequency | |
if (currentFreq % 1 == 0) { | |
newFreqTimeout = window.setTimeout(concludeChunk, 3000) | |
} else { | |
newFreqTimeout = window.setTimeout(concludeChunk, 10000) | |
} | |
}) | |
concludeChunk() | |
return {saveChunks} | |
})(stream, replayDuration, individualChunkDuration) | |
GM_registerMenuCommand(`Download last ${replayDuration} minutes of audio`, ()=>recorder.saveChunks()) | |
recordingCtx.font = `550 ${infoFontSize}px helvetica, sans-serif` | |
let waterfallParentObj = resolvePath(pathToWaterfallUpdateFunction.slice(0, -1)) | |
const origWaterfallLineFunc = waterfallParentObj[pathToWaterfallUpdateFunction[pathToWaterfallUpdateFunction.length-1]] | |
waterfallParentObj[pathToWaterfallUpdateFunction[pathToWaterfallUpdateFunction.length-1]] = function(){ | |
origWaterfallLineFunc.apply(this, arguments) | |
updateRecordingCanvas() | |
} | |
}) | |
function injectBgRecorder() { | |
const notifyFreqChange = (f) => { | |
let e = new CustomEvent('SDRFrequencyChanged', { | |
detail: {newFrequency: f} | |
}) | |
window.dispatchEvent(e) | |
} | |
let timer = window.setInterval(()=>{ | |
if (document.querySelector('input[name=frequency]') && window.spectrumAudio?.audioCtx?.state == 'running') { | |
//PhantomSDR | |
let a = document.querySelector('input[name=frequency]') | |
let prop = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value') | |
Object.defineProperty(a, 'value', {set(x){ | |
prop.set.call(this, x); | |
notifyFreqChange(x) | |
},get:prop.get}) | |
a.addEventListener('change', ()=>notifyFreqChange(a.value)) | |
window.clearInterval(timer) | |
let e = new Event('bgRecorderReady') | |
window.dispatchEvent(e) | |
} else if (window?.audio_context?.state == 'running' && window.audio_convolver) { | |
//KiwiSDR | |
let a = document.querySelector('#id-freq-input') | |
let prop = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value') | |
Object.defineProperty(a, 'value', {set(x){ | |
prop.set.call(this, x); | |
notifyFreqChange(x) | |
},get:prop.get}) | |
a.addEventListener('change', ()=>notifyFreqChange(a.value)) | |
window.clearInterval(timer) | |
let e = new Event('bgRecorderReady') | |
window.dispatchEvent(e) | |
} else if (window?.soundapplet?.p?.context?.state == 'running') { | |
//classic WebSDR | |
let a = document.querySelector('input[name="frequency"]') | |
let prop = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value') | |
Object.defineProperty(a, 'value', {set(x){ | |
prop.set.call(this, x); | |
notifyFreqChange(x) | |
},get:prop.get}) | |
a.addEventListener('change', ()=>notifyFreqChange(a.value)) | |
window.clearInterval(timer) | |
let e = new Event('bgRecorderReady') | |
window.dispatchEvent(e) | |
} | |
}) | |
} | |
injectScript(injectBgRecorder) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name WebSDR Custom Colors | |
// @namespace Violentmonkey Scripts | |
// @match *://*:*/* | |
// @match *://*sdr*.*/* | |
// @match *://*kiwi*.*/* | |
// @match *://*.swl.su/* | |
// @grant GM_registerMenuCommand | |
// @grant GM_addElement | |
// @version 1.3 | |
// @author - | |
// ==/UserScript== | |
function colormapV51() { | |
let c = document.createElement('canvas') | |
c.width = 256 | |
c.height = 1 | |
let ctx = c.getContext('2d'), g, it | |
let svg = ` | |
<svg width="1024" height="256" xmlns="http://www.w3.org/2000/svg" style="outline: 1px solid black;"> | |
<foreignObject x="0" y="0" width="1024" height="256"> | |
<div xmlns="http://www.w3.org/1999/xhtml" | |
style="background-image: linear-gradient(90deg in lab, | |
#0000 0%, | |
#0000 50%, | |
#fff0 50%/*, | |
#fff5 90%, | |
#fff3 100%*/ | |
), linear-gradient(90deg in oklch, | |
oklch(30% 20% 225deg) 0%, | |
oklch(40% 35% 270deg) 25%, | |
lch(50% 40% 0deg) 50%, | |
oklch(90% 40% 50deg) 75%, | |
oklch(100% 10% 90deg) 100% | |
) | |
;width:100%;height:100%"></div> | |
</foreignObject> | |
</svg> | |
` | |
let i = new Image() | |
i.src = URL.createObjectURL(new Blob([svg], {type:'image/svg+xml'})) | |
return new Promise((resolve, reject) => { | |
i.onload = () => { | |
let linMix = (a, b, k) => (1-k)*a + k*b | |
const lfunc = (x, lowValDeEmph_a = 1, lowValDeEmph_b = 0) => (1 - ((1 - Math.cos(Math.PI*(x - 1)))*0.5)**(2**lowValDeEmph_a))**((1+lowValDeEmph_a**(-lowValDeEmph_b))**1) | |
for (let j = 0, x0 = 0; j < 256; j++, x0 = j/255) { | |
let x = x0**0.9 | |
ctx.drawImage(i, Math.min(x*255,255)*4, 0, 4, 256, j, 0, 1, 256) | |
} | |
let g = ctx.createLinearGradient(0,0,c.width,0) | |
let id = ctx.getImageData(0,0,c.width,1).data | |
let cutoff = c.width | |
for (let i = 0; i < cutoff; i++) { | |
let x0 = i / (cutoff-1) | |
let x = x0 | |
let rgb = `rgb(${id[i*4]} ${id[i*4+1]} ${id[i*4+2]})` | |
let lch = `lch(from ${rgb} l c h)` | |
let ok = `lch(from ${rgb} ${linMix(x, lfunc(x**1, 0.7), 0.4)*100}% calc(c * ${(1-x)**0.005 * x**0.7 * 1.5}) h)` | |
g.addColorStop(x, ok) | |
} | |
ctx.fillStyle = g | |
ctx.fillRect(0,0,cutoff,c.height) | |
let idata = ctx.getImageData(0,0,256,1) | |
let colormap = new Array(256).fill(0).map((x, i) => new Array(4).fill(0).map((y,j)=>idata.data[i*4+j])) | |
resolve(colormap) | |
} | |
}) | |
} | |
function colormapV52() { | |
let c = document.createElement('canvas') | |
c.width = 256 | |
c.height = 1 | |
let ctx = c.getContext('2d'), g, it | |
let svg = ` | |
<svg width="1024" height="256" xmlns="http://www.w3.org/2000/svg" style="outline: 1px solid black;"> | |
<foreignObject x="0" y="0" width="1024" height="256"> | |
<div xmlns="http://www.w3.org/1999/xhtml" | |
style="background-image: linear-gradient(90deg in oklch, | |
transparent 30%, | |
lch(60% 45% 25deg) 50%, | |
oklch(90% 40% 50deg) 75%, | |
oklch(100% 10% 90deg) 100% | |
), linear-gradient(90deg in oklch, | |
oklch(30% 20% 225deg) 0%, | |
oklch(40% 30% 290deg) 100% | |
) | |
;width:100%;height:100%"></div> | |
</foreignObject> | |
</svg> | |
` | |
let i = new Image() | |
i.src = URL.createObjectURL(new Blob([svg], {type:'image/svg+xml'})) | |
return new Promise((resolve, reject) => { | |
i.onload = () => { | |
let linMix = (a, b, k) => (1-k)*a + k*b | |
const lfunc = (x, lowValDeEmph_a = 1, lowValDeEmph_b = 0) => (1 - ((1 - Math.cos(Math.PI*(x - 1)))*0.5)**(2**lowValDeEmph_a))**((1+lowValDeEmph_a**(-lowValDeEmph_b))**1) | |
for (let j = 0, x0 = 0; j < 256; j++, x0 = j/255) { | |
let x = x0**0.9 | |
ctx.drawImage(i, Math.min(x*255,255)*4, 0, 4, 256, j, 0, 1, 256) | |
} | |
let g = ctx.createLinearGradient(0,0,c.width,0) | |
let id = ctx.getImageData(0,0,c.width,1).data | |
let cutoff = c.width | |
for (let i = 0; i < cutoff; i++) { | |
let x0 = i / (cutoff-1) | |
let x = x0 | |
let rgb = `rgb(${id[i*4]} ${id[i*4+1]} ${id[i*4+2]})` | |
let lch = `lch(from ${rgb} l c h)` | |
let ok = `lch(from ${rgb} ${linMix(x, lfunc(x**1, 0.7), 0.4)*100}% calc(c * ${(1-x)**0.005 * x**0.7 * 1.5}) h)` | |
g.addColorStop(x, ok) | |
} | |
ctx.fillStyle = g | |
ctx.fillRect(0,0,cutoff,c.height) | |
let idata = ctx.getImageData(0,0,256,1) | |
let colormap = new Array(256).fill(0).map((x, i) => new Array(4).fill(0).map((y,j)=>idata.data[i*4+j])) | |
resolve(colormap) | |
} | |
}) | |
} | |
function colormapV53() { | |
let c = document.createElement('canvas') | |
c.width = 256 | |
c.height = 1 | |
let ctx = c.getContext('2d'), g, it | |
let svg = ` | |
<svg width="1024" height="256" xmlns="http://www.w3.org/2000/svg" style="outline: 1px solid black;"> | |
<foreignObject x="0" y="0" width="1024" height="256"> | |
<div xmlns="http://www.w3.org/1999/xhtml" | |
style="background-image: linear-gradient(90deg in oklch, | |
transparent 30%, | |
lch(60% 45% 30deg / 0.9) 50%, | |
lch(65% 40% 38deg) 60%, | |
oklch(80% 40% 50deg) 75%, | |
oklch(100% 10% 90deg) 100% | |
), linear-gradient(90deg in oklch, | |
oklch(30% 20% 225deg) 0%, | |
oklch(40% 30% 290deg) 100% | |
) | |
;width:100%;height:100%"></div> | |
</foreignObject> | |
</svg> | |
` | |
let i = new Image() | |
i.src = URL.createObjectURL(new Blob([svg], {type:'image/svg+xml'})) | |
return new Promise((resolve, reject) => { | |
i.onload = () => { | |
let linMix = (a, b, k) => (1-k)*a + k*b | |
const lfunc = (x, lowValDeEmph_a = 1, lowValDeEmph_b = 0) => (1 - ((1 - Math.cos(Math.PI*(x - 1)))*0.5)**(2**lowValDeEmph_a))**((1+lowValDeEmph_a**(-lowValDeEmph_b))**1) | |
for (let j = 0, x0 = 0; j < 256; j++, x0 = j/255) { | |
let x = x0**0.8 | |
ctx.drawImage(i, Math.min(x*255,255)*4, 0, 4, 256, j, 0, 1, 256) | |
} | |
let g = ctx.createLinearGradient(0,0,c.width,0) | |
let id = ctx.getImageData(0,0,c.width,1).data | |
let cutoff = c.width | |
for (let i = 0; i < cutoff; i++) { | |
let x0 = i / (cutoff-1) | |
let x = x0 | |
let rgb = `rgb(${id[i*4]} ${id[i*4+1]} ${id[i*4+2]})` | |
let lch = `lch(from ${rgb} l c h)` | |
let ok = `lch(from ${rgb} ${linMix(x, lfunc(x**1, 0.7), 0.5)*100}% calc(c * ${(1-x)**0.005 * x**0.7 * 1.9}) h)` | |
console.log(ok) | |
g.addColorStop(x, ok) | |
} | |
ctx.fillStyle = g | |
ctx.fillRect(0,0,cutoff,c.height) | |
ctx.filter = 'blur(25px)' | |
ctx.drawImage(c, 0, 0) | |
ctx.filter = 'none' | |
g = ctx.createLinearGradient(0,0,c.width,0) | |
id = ctx.getImageData(0,c.height>>1,c.width,1).data | |
cutoff = c.width | |
for (let i = 0; i < cutoff; i++) { | |
let x0 = i / (cutoff-1) | |
let x = x0 | |
let rgb = `rgb(${id[i*4]} ${id[i*4+1]} ${id[i*4+2]})` | |
let lch = `lch(from ${rgb} l c h)` | |
let ok = `lch(from ${rgb} ${linMix(x**0.8, lfunc(x, 0.7), 0.6)*100}% calc(c * ${(1-x)**0.05 * x**0.1 * 1}) h)` | |
console.log(ok) | |
g.addColorStop(x, ok) | |
} | |
ctx.fillStyle = g | |
ctx.filter = 'blur(0px)' | |
ctx.fillRect(0,0,cutoff,c.height) | |
let idata = ctx.getImageData(0,0,256,1) | |
let colormap = new Array(256).fill(0).map((x, i) => new Array(4).fill(0).map((y,j)=>idata.data[i*4+j])) | |
resolve(colormap) | |
} | |
}) | |
} | |
function colormapV54() { | |
let c = document.createElement('canvas') | |
c.width = 256 | |
c.height = 1 | |
let ctx = c.getContext('2d'), g, it | |
let svg = ` | |
<svg width="1024" height="256" xmlns="http://www.w3.org/2000/svg" style="outline: 1px solid black;"> | |
<foreignObject x="0" y="0" width="1024" height="256"> | |
<div xmlns="http://www.w3.org/1999/xhtml" | |
style="background-image: linear-gradient(90deg in oklch, | |
transparent 35%, | |
lch(60% 45% 30deg / 0.5) 50%, | |
lch(65% 40% 38deg) 60%, | |
oklch(80% 40% 50deg) 75%, | |
oklch(100% 10% 90deg) 100% | |
), linear-gradient(90deg in oklch, | |
oklch(30% 20% 225deg) 0%, | |
oklch(40% 20% 240deg) 25%, | |
oklch(40% 20% 260deg) 40%, | |
oklch(40% 40% 30deg) 60% | |
) | |
;width:100%;height:100%"></div> | |
</foreignObject> | |
</svg> | |
` | |
let i = new Image() | |
i.src = URL.createObjectURL(new Blob([svg], {type:'image/svg+xml'})) | |
return new Promise((resolve, reject) => { | |
i.onload = () => { | |
let linMix = (a, b, k) => (1-k)*a + k*b | |
const lfunc = (x, lowValDeEmph_a = 1, lowValDeEmph_b = 0) => (1 - ((1 - Math.cos(Math.PI*(x - 1)))*0.5)**(2**lowValDeEmph_a))**((1+lowValDeEmph_a**(-lowValDeEmph_b))**1) | |
for (let j = 0, x0 = 0; j < 256; j++, x0 = j/255) { | |
let x = x0**0.85 | |
ctx.drawImage(i, Math.min(x*255,255)*4, 0, 4, 256, j, 0, 1, 256) | |
} | |
let g = ctx.createLinearGradient(0,0,c.width,0) | |
let id = ctx.getImageData(0,0,c.width,1).data | |
let cutoff = c.width | |
for (let i = 0; i < cutoff; i++) { | |
let x0 = i / (cutoff-1) | |
let x = x0 | |
let rgb = `rgb(${id[i*4]} ${id[i*4+1]} ${id[i*4+2]})` | |
let lch = `lch(from ${rgb} l c h)` | |
let ok = `lch(from ${rgb} ${linMix(x, lfunc(x**1, 0.7), 0.5)*100}% calc(c * ${(1-x)**0.005 * x**0.7 * 1.9}) h)` | |
console.log(ok) | |
g.addColorStop(x, ok) | |
} | |
ctx.fillStyle = g | |
ctx.fillRect(0,0,cutoff,c.height) | |
ctx.filter = 'blur(20px)' | |
ctx.drawImage(c, 0, 0) | |
ctx.filter = 'none' | |
g = ctx.createLinearGradient(0,0,c.width,0) | |
id = ctx.getImageData(0,c.height>>1,c.width,1).data | |
cutoff = c.width | |
for (let i = 0; i < cutoff; i++) { | |
let x0 = i / (cutoff-1) | |
let x = x0 | |
let rgb = `rgb(${id[i*4]} ${id[i*4+1]} ${id[i*4+2]})` | |
let lch = `lch(from ${rgb} l c h)` | |
let ok = `lch(from ${rgb} ${linMix(x**0.8, lfunc(x, 0.7), 0.6)*100}% calc(c * ${(1-x)**0.05 * x**0.1 * 1}) h)` | |
console.log(ok) | |
g.addColorStop(x, ok) | |
} | |
ctx.fillStyle = g | |
ctx.filter = 'blur(0px)' | |
ctx.fillRect(0,0,cutoff,c.height) | |
let idata = ctx.getImageData(0,0,256,1) | |
let colormap = new Array(256).fill(0).map((x, i) => new Array(4).fill(0).map((y,j)=>idata.data[i*4+j])) | |
resolve(colormap) | |
} | |
}) | |
} | |
function colormapV544() { | |
let c = document.createElement('canvas') | |
c.width = 256 | |
c.height = 1 | |
let ctx = c.getContext('2d'), g, it | |
let svg = ` | |
<svg width="1024" height="256" xmlns="http://www.w3.org/2000/svg" style="outline: 1px solid black;"> | |
<foreignObject x="0" y="0" width="1024" height="256"> | |
<div xmlns="http://www.w3.org/1999/xhtml" | |
style="background-image: linear-gradient(90deg in oklch, | |
transparent 25%, | |
lch(60% 45% 30deg / 0.5) 50%, | |
lch(65% 40% 38deg) 60%, | |
oklch(80% 40% 50deg) 75%, | |
oklch(100% 10% 90deg) 100% | |
), linear-gradient(90deg in oklch, | |
oklch(30% 20% 265deg) 0%, | |
oklch(40% 20% 230deg) 35%, | |
oklch(40% 40% 20deg) 60% | |
) | |
;width:100%;height:100%"></div> | |
</foreignObject> | |
</svg> | |
` | |
let i = new Image() | |
i.src = URL.createObjectURL(new Blob([svg], {type:'image/svg+xml'})) | |
return new Promise((resolve, reject) => { | |
i.onload = () => { | |
let linMix = (a, b, k) => (1-k)*a + k*b | |
const lfunc = (x, lowValDeEmph_a = 1, lowValDeEmph_b = 0) => (1 - ((1 - Math.cos(Math.PI*(x - 1)))*0.5)**(2**lowValDeEmph_a))**((1+lowValDeEmph_a**(-lowValDeEmph_b))**1) | |
for (let j = 0, x0 = 0; j < 256; j++, x0 = j/255) { | |
let x = x0//**0.85 | |
ctx.drawImage(i, Math.min(x*255,255)*4, 0, 4, 256, j, 0, 1, 256) | |
} | |
let g = ctx.createLinearGradient(0,0,c.width,0) | |
let id = ctx.getImageData(0,0,c.width,1).data | |
let cutoff = c.width | |
for (let i = 0; i < cutoff; i++) { | |
let x0 = i / (cutoff-1) | |
let x = x0 | |
let rgb = `rgb(${id[i*4]} ${id[i*4+1]} ${id[i*4+2]})` | |
let lch = `lch(from ${rgb} l c h)` | |
let ok = `lch(from ${rgb} ${linMix(x, lfunc(x**1, 0.7), 0.5)*100}% calc(c * ${(1-x)**0.005 * x**0.7 * 1.9}) h)` | |
console.log(ok) | |
g.addColorStop(x, ok) | |
} | |
ctx.fillStyle = g | |
ctx.fillRect(0,0,cutoff,c.height) | |
ctx.filter = 'blur(20px)' | |
ctx.drawImage(c, 0, 0) | |
ctx.filter = 'none' | |
g = ctx.createLinearGradient(0,0,c.width,0) | |
id = ctx.getImageData(0,c.height>>1,c.width,1).data | |
cutoff = c.width | |
for (let i = 0; i < cutoff; i++) { | |
let x0 = i / (cutoff-1) | |
let x = x0 | |
let rgb = `rgb(${id[i*4]} ${id[i*4+1]} ${id[i*4+2]})` | |
let lch = `lch(from ${rgb} l c h)` | |
let ok = `lch(from ${rgb} ${linMix(linMix(x**3, x**0.6, 0.7), lfunc(x**1, 0.2, 0.2), 0.6)*100}% calc(c * ${(1-x)**0.05 * x**0.1 * 1}) h)` | |
console.log(ok) | |
g.addColorStop(x, ok) | |
} | |
ctx.fillStyle = g | |
ctx.filter = 'blur(0px)' | |
ctx.fillRect(0,0,cutoff,c.height) | |
let idata = ctx.getImageData(0,0,256,1) | |
let colormap = new Array(256).fill(0).map((x, i) => new Array(4).fill(0).map((y,j)=>idata.data[i*4+j])) | |
resolve(colormap) | |
} | |
}) | |
} | |
function colormapV6() { | |
let c = document.createElement('canvas') | |
c.width = 256 | |
c.height = 1 | |
let ctx = c.getContext('2d'), g, it | |
let svg = ` | |
<svg width="1024" height="256" xmlns="http://www.w3.org/2000/svg" style="outline: 1px solid black;"> | |
<foreignObject x="0" y="0" width="1024" height="256"> | |
<div xmlns="http://www.w3.org/1999/xhtml" | |
style="background-image: /*linear-gradient(90deg in oklch, | |
transparent 25%, | |
lch(60% 45% 30deg / 0.5) 50%, | |
lch(65% 40% 38deg) 60%, | |
oklch(80% 40% 50deg) 75%, | |
oklch(100% 10% 90deg) 100% | |
), */ | |
linear-gradient(90deg in oklch, | |
rgb(0 0 0),rgb(0 1.3732 2.4379),rgb(0 2.5688 4.594),rgb(0 3.7865 6.8207),rgb(0 5.0223 9.1106),rgb(0 6.2714 11.401),rgb(0 7.5309 13.492),rgb(0 8.7991 15.415),rgb(0 10.075 17.206),rgb(0 11.311 18.89),rgb(0 12.471 20.484),rgb(0 13.568 22.002),rgb(0 14.611 23.455),rgb(0 15.607 24.851),rgb(0 16.561 26.197),rgb(0 17.478 27.499),rgb(0 18.362 28.761),rgb(0 19.216 29.988),rgb(0 20.042 31.183),rgb(0 20.844 32.349),rgb(0 21.623 33.489),rgb(0 22.381 34.606),rgb(0 23.119 35.701),rgb(0 23.84 36.777),rgb(0 24.544 37.835),rgb(0 25.233 38.877),rgb(0 25.908 39.906),rgb(0 26.569 40.921),rgb(0 27.218 41.926),rgb(0 27.855 42.921),rgb(0 28.482 43.908),rgb(0 29.098 44.887),rgb(0 29.705 45.861),rgb(0 30.303 46.831),rgb(0 30.893 47.797),rgb(0 31.476 48.762),rgb(0 32.051 49.725),rgb(0 32.619 50.689),rgb(0 33.181 51.655),rgb(0 33.737 52.624),rgb(0 34.288 53.597),rgb(0 34.834 54.576),rgb(0 35.375 55.561),rgb(0 35.912 56.555),rgb(0 36.444 57.558),rgb(0 36.973 58.573),rgb(0 37.499 59.6),rgb(0 38.021 60.641),rgb(0 38.54 61.697),rgb(0.5862 39.04 62.523),rgb(1.3808 39.534 63.283),rgb(2.2201 40.026 64.048),rgb(3.0954 40.517 64.822),rgb(4.0089 41.007 65.607),rgb(4.9633 41.496 66.403),rgb(5.961 41.985 67.211),rgb(7.0051 42.474 68.031),rgb(8.0986 42.962 68.864),rgb(9.245 43.45 69.711),rgb(10.445 43.938 70.571),rgb(11.638 44.426 71.447),rgb(12.813 44.915 72.338),rgb(13.976 45.404 73.244),rgb(15.133 45.893 74.167),rgb(16.287 46.383 75.106),rgb(17.441 46.873 76.062),rgb(18.6 47.363 77.036),rgb(19.766 47.854 78.028),rgb(20.941 48.345 79.038),rgb(22.129 48.835 80.066),rgb(23.332 49.326 81.113),rgb(24.551 49.817 82.178),rgb(25.82 50.296 83.289),rgb(27.169 50.741 84.504),rgb(28.541 51.17 85.799),rgb(29.921 51.591 87.153),rgb(31.318 52.002 88.563),rgb(32.739 52.402 90.028),rgb(34.194 52.79 91.543),rgb(35.689 53.163 93.105),rgb(37.23 53.52 94.711),rgb(38.824 53.861 96.357),rgb(40.476 54.183 98.038),rgb(42.19 54.484 99.749),rgb(43.971 54.765 101.49),rgb(45.821 55.023 103.24),rgb(47.745 55.257 105.01),rgb(49.744 55.466 106.79),rgb(51.819 55.649 108.57),rgb(53.973 55.805 110.34),rgb(56.205 55.934 112.1),rgb(58.515 56.036 113.84),rgb(60.903 56.109 115.54),rgb(63.368 56.156 117.21),rgb(65.908 56.175 118.83),rgb(68.521 56.167 120.4),rgb(71.205 56.135 121.9),rgb(73.958 56.078 123.33),rgb(76.775 56 124.68),rgb(79.654 55.901 125.93),rgb(82.59 55.785 127.09),rgb(85.58 55.655 128.14),rgb(88.619 55.513 129.07),rgb(91.703 55.364 129.88),rgb(94.826 55.211 130.56),rgb(97.984 55.059 131.11),rgb(101.17 54.913 131.51),rgb(104.38 54.776 131.77),rgb(107.61 54.655 131.88),rgb(110.86 54.554 131.84),rgb(114.11 54.48 131.65),rgb(117.37 54.436 131.3),rgb(120.62 54.43 130.79),rgb(123.86 54.466 130.14),rgb(127.09 54.55 129.33),rgb(130.3 54.687 128.38),rgb(133.49 54.883 127.28),rgb(136.65 55.141 126.05),rgb(139.77 55.468 124.68),rgb(142.85 55.867 123.19),rgb(145.89 56.343 121.59),rgb(148.89 56.898 119.88),rgb(151.83 57.537 118.06),rgb(154.71 58.263 116.16),rgb(157.53 59.077 114.18),rgb(160.29 59.982 112.14),rgb(162.97 60.98 110.03),rgb(165.59 62.072 107.88),rgb(168.13 63.258 105.7),rgb(170.4 64.536 104.49),rgb(172.43 65.874 104.27),rgb(174.47 67.229 104.04),rgb(176.51 68.601 103.8),rgb(178.55 69.989 103.56),rgb(180.59 71.395 103.31),rgb(182.63 72.817 103.05),rgb(184.67 74.256 102.78),rgb(186.71 75.711 102.51),rgb(188.74 77.183 102.23),rgb(190.77 78.67 101.94),rgb(192.8 80.174 101.64),rgb(194.82 81.694 101.34),rgb(196.84 83.229 101.02),rgb(198.85 84.78 100.71),rgb(200.85 86.347 100.38),rgb(202.85 87.929 100.05),rgb(204.83 89.525 99.712),rgb(206.81 91.137 99.368),rgb(208.78 92.763 99.019),rgb(210.73 94.404 98.663),rgb(212.68 96.059 98.303),rgb(214.61 97.728 97.937),rgb(216.52 99.411 97.567),rgb(218.43 101.11 97.193),rgb(220.32 102.82 96.815),rgb(222.19 104.54 96.433),rgb(224.04 106.27 96.049),rgb(225.88 108.02 95.662),rgb(227.7 109.78 95.273),rgb(229.49 111.55 94.883),rgb(231.27 113.33 94.492),rgb(233.03 115.13 94.101),rgb(234.77 116.93 93.71),rgb(236.48 118.74 93.321),rgb(238.17 120.57 92.933),rgb(239.83 122.4 92.548),rgb(241.47 124.25 92.167),rgb(243.09 126.1 91.789),rgb(244.67 127.96 91.417),rgb(246.23 129.83 91.051),rgb(247.77 131.7 90.692),rgb(249.27 133.59 90.341),rgb(250.74 135.48 89.999),rgb(252.19 137.37 89.667),rgb(253.6 139.27 89.346),rgb(254.69 141.34 89.452),rgb(255 143.82 90.675),rgb(255 146.43 92.372),rgb(255 149 94.109),rgb(255 151.53 95.882),rgb(255 154.02 97.689),rgb(255 156.47 99.528),rgb(255 158.89 101.4),rgb(255 161.27 103.29),rgb(255 163.61 105.21),rgb(255 165.92 107.16),rgb(255 168.2 109.13),rgb(255 170.44 111.11),rgb(255 172.65 113.12),rgb(255 174.83 115.14),rgb(255 176.98 117.17),rgb(255 179.1 119.22),rgb(255 181.19 121.28),rgb(255 183.25 123.35),rgb(255 185.28 125.43),rgb(255 187.28 127.51),rgb(255 189.24 129.6),rgb(255 191.18 131.7),rgb(255 193.1 133.8),rgb(255 194.98 135.91),rgb(255 196.83 138.01),rgb(255 198.66 140.12),rgb(255 200.46 142.23),rgb(255 202.23 144.34),rgb(255 203.97 146.44),rgb(255 205.68 148.55),rgb(255 207.37 150.65),rgb(255 209.03 152.75),rgb(255 210.66 154.84),rgb(255 212.26 156.93),rgb(255 213.84 159.01),rgb(255 215.39 161.09),rgb(255 216.91 163.16),rgb(255 218.4 165.22),rgb(255 219.87 167.28),rgb(255 221.31 169.33),rgb(255 222.72 171.37),rgb(255 224.1 173.41),rgb(255 225.46 175.44),rgb(255 226.79 177.47),rgb(255 228.1 179.48),rgb(255 229.37 181.5),rgb(255 230.63 183.5),rgb(255 231.85 185.51),rgb(255 233.04 187.51),rgb(255 234.21 189.51),rgb(255 235.36 191.51),rgb(255 236.47 193.52),rgb(255 237.56 195.53),rgb(255 238.62 197.55),rgb(255 239.66 199.58),rgb(255 240.66 201.63),rgb(255 241.64 203.71),rgb(255 242.59 205.82),rgb(255 243.51 207.97),rgb(255 244.4 210.17),rgb(255 245.26 212.44),rgb(255 246.09 214.79),rgb(255 246.89 217.24),rgb(255 247.65 219.81),rgb(255 248.37 222.53),rgb(255 249.06 225.43),rgb(255 249.7 228.54),rgb(255 250.31 231.87),rgb(255 250.87 235.43),rgb(255 251.4 239.17),rgb(255 251.91 242.95),rgb(255 252.42 246.56),rgb(255 252.97 249.64),rgb(255 253.59 251.96),rgb(255 254.29 253.35),rgb(255 254.94 254.84),rgb(255 255 255),rgb(255 255 255),rgb(255 255 255),rgb(255 255 255),rgb(255 255 255) | |
) | |
;width:100%;height:100%"></div> | |
</foreignObject> | |
</svg> | |
` | |
let i = new Image() | |
i.src = URL.createObjectURL(new Blob([svg], {type:'image/svg+xml'})) | |
return new Promise((resolve, reject) => { | |
i.onload = () => { | |
let linMix = (a, b, k) => (1-k)*a + k*b | |
const lfunc = (x, lowValDeEmph_a = 1, lowValDeEmph_b = 0) => (1 - ((1 - Math.cos(Math.PI*(x - 1)))*0.5)**(2**lowValDeEmph_a))**((1+lowValDeEmph_a**(-lowValDeEmph_b))**1) | |
for (let j = 0, x0 = 0; j < 256; j++, x0 = j/255) { | |
let x = x0//**0.85 | |
ctx.drawImage(i, Math.min(x*255,255)*4, 0, 4, 256, j, 0, 1, 256) | |
} | |
let idata = ctx.getImageData(0,0,256,1) | |
let colormap = new Array(256).fill(0).map((x, i) => new Array(4).fill(0).map((y,j)=>idata.data[i*4+j])) | |
resolve(colormap) | |
} | |
}) | |
} | |
function colormapV62() { | |
let c = document.createElement('canvas') | |
c.width = 256 | |
c.height = 1 | |
let ctx = c.getContext('2d'), g, it | |
let svg = ` | |
<svg width="1024" height="256" xmlns="http://www.w3.org/2000/svg" style="outline: 1px solid black;"> | |
<foreignObject x="0" y="0" width="1024" height="256"> | |
<div xmlns="http://www.w3.org/1999/xhtml" | |
style="background-image: /*linear-gradient(90deg in oklch, | |
transparent 25%, | |
lch(60% 45% 30deg / 0.5) 50%, | |
lch(65% 40% 38deg) 60%, | |
oklch(80% 40% 50deg) 75%, | |
oklch(100% 10% 90deg) 100% | |
), */ | |
linear-gradient(90deg in oklch, | |
rgb(6.0918 5.8396 4.3814),rgb(6.2748 6.0968 4.6113),rgb(6.4612 6.3613 4.849),rgb(6.628 6.624 5.0944),rgb(6.7971 6.8936 5.3477),rgb(6.9525 7.1598 5.6048),rgb(7.1096 7.4325 5.8696),rgb(7.2546 7.7015 6.1375),rgb(7.4007 7.9764 6.413),rgb(7.5355 8.2476 6.6912),rgb(7.6711 8.5243 6.9769),rgb(7.7961 8.7972 7.2651),rgb(7.9213 9.0753 7.5607),rgb(8.0366 9.3497 7.8543),rgb(8.1518 9.6288 8.1547),rgb(8.2575 9.9043 8.445),rgb(8.3629 10.184 8.7408),rgb(8.4592 10.458 9.0283),rgb(8.555 10.729 9.3209),rgb(8.642 10.993 9.6059),rgb(8.7283 11.257 9.8955),rgb(8.8064 11.515 10.18),rgb(8.8835 11.772 10.466),rgb(8.9528 12.023 10.748),rgb(9.021 12.273 11.031),rgb(9.0817 12.518 11.312),rgb(9.1412 12.763 11.593),rgb(9.1936 13.002 11.873),rgb(9.2446 13.241 12.152),rgb(9.289 13.476 12.431),rgb(9.3319 13.71 12.709),rgb(9.3685 13.94 12.987),rgb(9.4036 14.169 13.264),rgb(9.4327 14.395 13.541),rgb(9.4602 14.62 13.818),rgb(9.4821 14.842 14.095),rgb(9.5024 15.064 14.372),rgb(9.5175 15.282 14.648),rgb(9.5308 15.5 14.925),rgb(9.5393 15.716 15.202),rgb(9.546 15.931 15.48),rgb(9.5482 16.145 15.758),rgb(9.5487 16.357 16.036),rgb(9.545 16.568 16.315),rgb(9.5395 16.779 16.594),rgb(9.5301 16.988 16.875),rgb(9.519 17.197 17.155),rgb(9.5044 17.405 17.437),rgb(9.488 17.613 17.72),rgb(9.4684 17.82 18.004),rgb(9.447 18.026 18.288),rgb(9.4228 18.232 18.575),rgb(9.3968 18.438 18.862),rgb(9.3683 18.644 19.151),rgb(9.3381 18.85 19.441),rgb(9.3056 19.056 19.733),rgb(9.2715 19.261 20.026),rgb(9.2354 19.467 20.321),rgb(9.1977 19.673 20.618),rgb(9.1583 19.88 20.917),rgb(9.1174 20.087 21.217),rgb(9.0751 20.294 21.52),rgb(9.0314 20.502 21.825),rgb(8.9866 20.711 22.132),rgb(8.9404 20.92 22.441),rgb(8.8934 21.131 22.753),rgb(8.8452 21.342 23.067),rgb(8.7964 21.554 23.384),rgb(8.7465 21.767 23.703),rgb(8.6964 21.981 24.026),rgb(8.6452 22.196 24.351),rgb(8.5941 22.413 24.68),rgb(8.5421 22.63 25.01),rgb(8.4905 22.849 25.345),rgb(8.4381 23.07 25.682),rgb(8.3864 23.292 26.023),rgb(8.3341 23.515 26.366),rgb(8.2828 23.741 26.714),rgb(8.2311 23.967 27.065),rgb(8.1807 24.196 27.42),rgb(8.1301 24.426 27.778),rgb(8.0813 24.659 28.141),rgb(8.0324 24.893 28.507),rgb(7.9856 25.129 28.878),rgb(7.939 25.367 29.251),rgb(7.8949 25.607 29.631),rgb(7.8513 25.849 30.013),rgb(7.8106 26.094 30.401),rgb(7.7706 26.34 30.792),rgb(7.734 26.59 31.189),rgb(7.6985 26.84 31.589),rgb(7.6668 27.094 31.996),rgb(7.6365 27.35 32.406),rgb(7.6106 27.609 32.822),rgb(7.5866 27.869 33.242),rgb(7.5674 28.133 33.668),rgb(7.5506 28.399 34.098),rgb(7.5391 28.668 34.535),rgb(7.5306 28.938 34.976),rgb(7.5281 29.213 35.423),rgb(7.529 29.489 35.875),rgb(7.5366 29.768 36.334),rgb(7.5483 30.05 36.797),rgb(7.5675 30.335 37.268),rgb(7.5914 30.622 37.743),rgb(7.6235 30.913 38.225),rgb(7.6613 31.206 38.713),rgb(7.7081 31.502 39.207),rgb(7.7615 31.801 39.707),rgb(7.8247 32.103 40.214),rgb(7.8955 32.408 40.727),rgb(7.9772 32.716 41.247),rgb(8.0676 33.026 41.772),rgb(8.1699 33.34 42.306),rgb(8.2822 33.656 42.845),rgb(8.4076 33.976 43.392),rgb(8.5442 34.298 43.945),rgb(8.6953 34.624 44.505),rgb(8.8591 34.952 45.073),rgb(9.0388 35.284 45.647),rgb(9.2329 35.618 46.229),rgb(9.4444 35.955 46.818),rgb(9.6721 36.295 47.415),rgb(9.9188 36.638 48.019),rgb(10.184 36.984 48.63),rgb(10.466 37.333 49.249),rgb(10.763 37.685 49.875),rgb(11.075 38.04 50.51),rgb(11.404 38.397 51.152),rgb(11.749 38.757 51.801),rgb(12.111 39.121 52.459),rgb(12.49 39.486 53.125),rgb(12.886 39.855 53.798),rgb(13.299 40.226 54.479),rgb(13.73 40.6 55.169),rgb(14.178 40.977 55.866),rgb(14.643 41.356 56.572),rgb(15.126 41.738 57.286),rgb(15.627 42.122 58.008),rgb(16.145 42.509 58.737),rgb(16.682 42.898 59.476),rgb(17.235 43.289 60.222),rgb(17.809 43.683 60.977),rgb(18.422 44.094 61.768),rgb(19.084 44.527 62.605),rgb(19.808 44.99 63.512),rgb(20.61 45.494 64.51),rgb(21.423 45.995 65.52),rgb(22.252 46.492 66.546),rgb(23.092 46.986 67.584),rgb(23.951 47.476 68.636),rgb(24.822 47.963 69.7),rgb(25.714 48.445 70.778),rgb(26.62 48.922 71.866),rgb(27.549 49.395 72.968),rgb(28.492 49.863 74.08),rgb(29.461 50.325 75.204),rgb(30.444 50.782 76.337),rgb(31.455 51.233 77.483),rgb(32.481 51.678 78.636),rgb(33.536 52.116 79.8),rgb(34.607 52.549 80.972),rgb(35.708 52.974 82.153),rgb(36.824 53.393 83.34),rgb(37.973 53.803 84.536),rgb(39.138 54.208 85.737),rgb(40.335 54.603 86.945),rgb(41.548 54.992 88.157),rgb(42.796 55.37 89.374),rgb(44.059 55.743 90.595),rgb(45.357 56.105 91.819),rgb(46.669 56.461 93.045),rgb(48.018 56.806 94.272),rgb(49.38 57.144 95.5),rgb(50.78 57.47 96.728),rgb(52.193 57.79 97.955),rgb(53.643 58.099 99.179),rgb(55.105 58.4 100.4),rgb(56.606 58.689 101.62),rgb(58.117 58.972 102.83),rgb(59.667 59.243 104.04),rgb(61.227 59.506 105.24),rgb(62.825 59.758 106.43),rgb(64.433 60.003 107.62),rgb(66.079 60.236 108.79),rgb(67.733 60.462 109.96),rgb(69.424 60.677 111.11),rgb(71.124 60.885 112.25),rgb(72.859 61.082 113.37),rgb(74.602 61.272 114.48),rgb(76.38 61.452 115.57),rgb(78.165 61.625 116.65),rgb(79.983 61.789 117.71),rgb(81.808 61.947 118.75),rgb(83.665 62.096 119.76),rgb(85.527 62.238 120.77),rgb(87.42 62.374 121.73),rgb(89.318 62.503 122.69),rgb(91.245 62.627 123.61),rgb(93.177 62.744 124.52),rgb(95.135 62.858 125.38),rgb(97.097 62.965 126.24),rgb(99.084 63.071 127.05),rgb(101.07 63.17 127.85),rgb(103.09 63.27 128.59),rgb(105.1 63.363 129.33),rgb(107.14 63.459 130.02),rgb(109.18 63.549 130.69),rgb(111.23 63.644 131.31),rgb(113.29 63.734 131.91),rgb(115.36 63.83 132.46),rgb(117.44 63.921 133),rgb(119.53 64.023 133.48),rgb(121.61 64.118 133.94),rgb(123.71 64.227 134.35),rgb(125.81 64.33 134.74),rgb(127.92 64.449 135.07),rgb(130.03 64.562 135.39),rgb(132.14 64.695 135.64),rgb(134.25 64.821 135.89),rgb(136.36 64.97 136.07),rgb(138.47 65.113 136.23),rgb(140.59 65.282 136.34),rgb(142.7 65.444 136.43),rgb(144.8 65.635 136.46),rgb(146.91 65.82 136.47),rgb(149.01 66.036 136.43),rgb(151.11 66.247 136.37),rgb(153.2 66.491 136.25),rgb(155.29 66.73 136.13),rgb(157.36 67.006 135.94),rgb(159.43 67.276 135.74),rgb(161.49 67.585 135.49),rgb(163.55 67.889 135.23),rgb(165.59 68.234 134.91),rgb(167.63 68.574 134.59),rgb(169.64 68.958 134.22),rgb(171.66 69.337 133.83),rgb(173.65 69.762 133.41),rgb(175.64 70.181 132.97),rgb(177.61 70.649 132.5),rgb(179.57 71.112 132.02),rgb(181.51 71.624 131.51),rgb(183.44 72.131 131),rgb(185.34 72.69 130.46),rgb(187.24 73.244 129.91),rgb(189.11 73.851 129.36),rgb(190.98 74.452 128.8),rgb(192.81 75.108 128.25),rgb(194.64 75.759 127.69),rgb(196.43 76.465 127.17),rgb(198.22 77.166 126.64),rgb(199.97 77.923 126.21),rgb(201.72 78.676 125.76),rgb(203.43 79.484 125.55),rgb(205.14 80.289 125.34),rgb(206.8 81.149 127.92),rgb(208.46 82.007 130.49),rgb(209.18 82.406 129.98),rgb(209.9 82.801 129.45),rgb(210.61 83.211 128.92),rgb(211.32 83.62 128.38),rgb(212.02 84.043 127.85),rgb(212.72 84.464 127.31),rgb(213.42 84.9 126.77),rgb(214.11 85.335 126.23),rgb(214.8 85.784 125.68),rgb(215.49 86.231 125.14),rgb(216.16 86.693 124.59),rgb(216.84 87.153 124.05),rgb(217.51 87.626 123.5),rgb(218.18 88.099 122.95),rgb(218.84 88.585 122.4),rgb(219.5 89.07 121.85),rgb(220.15 89.568 121.3),rgb(220.8 90.065 120.75),rgb(221.45 90.575 120.2),rgb(222.09 91.084 119.65),rgb(222.72 91.606 119.1),rgb(223.36 92.127 118.54),rgb(223.98 92.66 118),rgb(224.61 93.193 117.44),rgb(225.22 93.737 116.9),rgb(225.84 94.281 116.35),rgb(226.44 94.837 115.8),rgb(227.05 95.393 115.25),rgb(227.64 95.959 114.71),rgb(228.24 96.526 114.17),rgb(228.83 97.104 113.63),rgb(229.41 97.681 113.08),rgb(229.99 98.27 112.55),rgb(230.56 98.858 112.01),rgb(231.13 99.457 111.48),rgb(231.69 100.06 110.94),rgb(232.25 100.67 110.42),rgb(232.8 101.27 109.89),rgb(233.35 101.89 109.36),rgb(233.89 102.51 108.84),rgb(234.43 103.14 108.32),rgb(234.96 103.77 107.81),rgb(235.48 104.41 107.3),rgb(236.01 105.05 106.79),rgb(236.52 105.7 106.28),rgb(237.03 106.35 105.78),rgb(237.53 107.01 105.28),rgb(238.03 107.67 104.79),rgb(238.52 108.33 104.3),rgb(239.01 109 103.82),rgb(239.49 109.68 103.34),rgb(239.97 110.36 102.86),rgb(240.44 111.04 102.39),rgb(240.9 111.73 101.92),rgb(241.36 112.42 101.47),rgb(241.81 113.11 101.01),rgb(242.26 113.82 100.56),rgb(242.7 114.52 100.12),rgb(243.13 115.23 99.684),rgb(243.56 115.94 99.25),rgb(243.99 116.66 98.828),rgb(244.4 117.38 98.407),rgb(244.81 118.11 97.999),rgb(245.22 118.83 97.591),rgb(245.62 119.57 97.197),rgb(246.01 120.3 96.804),rgb(246.4 121.04 96.424),rgb(246.78 121.79 96.046),rgb(247.15 122.54 95.682),rgb(247.52 123.29 95.321),rgb(247.88 124.04 94.973),rgb(248.24 124.8 94.628),rgb(248.58 125.56 94.297),rgb(248.93 126.32 93.97),rgb(249.26 127.09 93.658),rgb(249.6 127.86 93.349),rgb(249.92 128.64 93.055),rgb(250.24 129.41 92.766),rgb(250.55 130.19 92.492),rgb(250.85 130.98 92.224),rgb(251.15 131.76 91.97),rgb(251.44 132.55 91.723),rgb(251.73 133.35 91.491),rgb(252.01 134.14 91.265),rgb(252.28 134.94 91.056),rgb(252.55 135.74 90.853),rgb(252.81 136.54 90.667),rgb(253.06 137.34 90.489),rgb(253.31 138.15 90.327),rgb(253.55 138.96 90.173),rgb(253.78 139.77 90.036),rgb(254.01 140.59 89.908),rgb(254.23 141.41 89.797),rgb(254.45 142.22 89.695),rgb(254.65 143.05 89.611),rgb(254.86 143.87 89.536),rgb(254.95 144.75 89.624),rgb(254.99 145.66 89.812),rgb(255 146.57 90.043),rgb(255 147.49 90.302),rgb(255 148.41 90.573),rgb(255 149.33 90.852),rgb(255 150.24 91.143),rgb(255 151.14 91.442),rgb(255 152.05 91.752),rgb(255 152.95 92.071),rgb(255 153.85 92.401),rgb(255 154.75 92.739),rgb(255 155.64 93.087),rgb(255 156.53 93.443),rgb(255 157.42 93.81),rgb(255 158.3 94.184),rgb(255 159.18 94.568),rgb(255 160.06 94.96),rgb(255 160.94 95.361),rgb(255 161.81 95.769),rgb(255 162.68 96.187),rgb(255 163.55 96.612),rgb(255 164.41 97.046),rgb(255 165.28 97.487),rgb(255 166.14 97.936),rgb(255 166.99 98.392),rgb(255 167.85 98.856),rgb(255 168.7 99.327),rgb(255 169.55 99.805),rgb(255 170.4 100.29),rgb(255 171.24 100.78),rgb(255 172.08 101.28),rgb(255 172.92 101.79),rgb(255 173.76 102.3),rgb(255 174.6 102.82),rgb(255 175.43 103.34),rgb(255 176.26 103.87),rgb(255 177.09 104.41),rgb(255 177.91 104.95),rgb(255 178.74 105.5),rgb(255 179.56 106.06),rgb(255 180.37 106.62),rgb(255 181.19 107.18),rgb(255 182 107.75),rgb(255 182.81 108.33),rgb(255 183.62 108.91),rgb(255 184.43 109.49),rgb(255 185.23 110.08),rgb(255 186.04 110.67),rgb(255 186.84 111.27),rgb(255 187.63 111.88),rgb(255 188.43 112.48),rgb(255 189.22 113.09),rgb(255 190.01 113.71),rgb(255 190.8 114.33),rgb(255 191.59 114.95),rgb(255 192.37 115.58),rgb(255 193.15 116.21),rgb(255 193.93 116.84),rgb(255 194.71 117.48),rgb(255 195.48 118.11),rgb(255 196.25 118.76),rgb(255 197.02 119.4),rgb(255 197.79 120.05),rgb(255 198.56 120.7),rgb(255 199.32 121.35),rgb(255 200.08 122.01),rgb(255 200.84 122.66),rgb(255 201.6 123.32),rgb(255 202.35 123.98),rgb(254.97 203.11 124.73),rgb(254.87 203.89 125.66),rgb(254.76 204.66 126.62),rgb(254.63 205.44 127.65),rgb(254.49 206.21 128.68),rgb(254.36 206.99 129.73),rgb(254.22 207.75 130.78),rgb(254.09 208.52 131.85),rgb(253.96 209.28 132.92),rgb(253.82 210.04 134),rgb(253.69 210.79 135.09),rgb(253.56 211.54 136.19),rgb(253.42 212.29 137.29),rgb(253.29 213.03 138.4),rgb(253.16 213.77 139.52),rgb(253.03 214.51 140.64),rgb(252.9 215.24 141.77),rgb(252.78 215.97 142.91),rgb(252.65 216.7 144.05),rgb(252.53 217.42 145.2),rgb(252.41 218.14 146.36),rgb(252.29 218.85 147.52),rgb(252.17 219.56 148.68),rgb(252.06 220.26 149.85),rgb(251.94 220.97 151.02),rgb(251.84 221.66 152.2),rgb(251.73 222.36 153.38),rgb(251.63 223.05 154.57),rgb(251.52 223.73 155.76),rgb(251.43 224.41 156.95),rgb(251.33 225.09 158.14),rgb(251.25 225.76 159.34),rgb(251.16 226.43 160.54),rgb(251.08 227.09 161.74),rgb(251 227.76 162.95),rgb(250.93 228.41 164.15),rgb(250.86 229.06 165.36),rgb(250.79 229.71 166.57),rgb(250.73 230.35 167.78),rgb(250.68 230.99 168.99),rgb(250.63 231.63 170.2),rgb(250.58 232.26 171.41),rgb(250.54 232.88 172.62),rgb(250.51 233.5 173.83),rgb(250.48 234.12 175.04),rgb(250.45 234.73 176.25),rgb(250.43 235.34 177.46),rgb(250.42 235.95 178.67),rgb(250.41 236.55 179.87),rgb(250.41 237.14 181.08),rgb(250.42 237.74 182.28),rgb(250.43 238.32 183.48),rgb(250.44 238.91 184.68),rgb(250.47 239.48 185.88),rgb(250.5 240.06 187.07),rgb(250.54 240.63 188.26),rgb(250.58 241.19 189.45),rgb(250.63 241.75 190.64),rgb(250.68 242.31 191.82),rgb(250.74 242.87 193),rgb(250.81 243.42 194.17),rgb(250.89 243.96 195.34),rgb(250.97 244.5 196.51),rgb(251.06 245.04 197.67),rgb(251.15 245.57 198.83),rgb(251.26 246.1 199.98),rgb(251.36 246.63 201.13),rgb(251.48 247.15 202.27),rgb(251.6 247.67 203.41),rgb(251.74 248.18 204.54),rgb(251.87 248.69 205.67),rgb(252.02 249.19 206.79),rgb(252.16 249.7 207.91),rgb(252.32 250.19 209.02),rgb(252.48 250.69 210.13),rgb(252.66 251.18 211.22),rgb(252.83 251.67 212.32),rgb(253.02 252.15 213.4),rgb(253.21 252.63 214.48),rgb(253.41 253.11 215.55),rgb(253.61 253.58 216.62),rgb(253.82 254.05 217.68),rgb(254.04 254.51 218.78),rgb(254.4 254.76 221.93),rgb(254.76 254.99 225.23),rgb(254.84 254.52 239.07),rgb(255 253.93 252.52),rgb(255 254.46 253.76),rgb(255 255 255) | |
) | |
;width:100%;height:100%"></div> | |
</foreignObject> | |
</svg> | |
` | |
let i = new Image() | |
i.src = URL.createObjectURL(new Blob([svg], {type:'image/svg+xml'})) | |
return new Promise((resolve, reject) => { | |
i.onload = () => { | |
let linMix = (a, b, k) => (1-k)*a + k*b | |
const lfunc = (x, lowValDeEmph_a = 1, lowValDeEmph_b = 0) => (1 - ((1 - Math.cos(Math.PI*(x - 1)))*0.5)**(2**lowValDeEmph_a))**((1+lowValDeEmph_a**(-lowValDeEmph_b))**1) | |
for (let j = 0, x0 = 0; j < 256; j++, x0 = j/255) { | |
let x = x0//**0.85 | |
ctx.drawImage(i, Math.min(x*255,255)*4, 0, 4, 256, j, 0, 1, 256) | |
} | |
let idata = ctx.getImageData(0,0,256,1) | |
let colormap = new Array(256).fill(0).map((x, i) => new Array(4).fill(0).map((y,j)=>idata.data[i*4+j])) | |
resolve(colormap) | |
} | |
}) | |
} | |
function colormapV7() { | |
let c = document.createElement('canvas') | |
c.width = 256 | |
c.height = 1 | |
let ctx = c.getContext('2d'), g, it | |
let svg = ` | |
<svg width="1024" height="256" xmlns="http://www.w3.org/2000/svg" style="outline: 1px solid black;"> | |
<foreignObject x="0" y="0" width="1024" height="256"> | |
<div xmlns="http://www.w3.org/1999/xhtml" | |
style="background-image: /*linear-gradient(90deg in oklch, | |
transparent 25%, | |
lch(60% 45% 30deg / 0.5) 50%, | |
lch(65% 40% 38deg) 60%, | |
oklch(80% 40% 50deg) 75%, | |
oklch(100% 10% 90deg) 100% | |
), */ | |
linear-gradient(90deg in oklch, | |
#000000, #000008, #000009, #00000d, #00000f, #000010, #000011, #000112, #000113, #000114, #000115, #000115, #000116, #000216, #000217, #010217, #010218, #010218, #010219, #020319, #020319, #02031a, #02031a, #02031b, #03031b, #03031b, #03041c, #03041c, #04041c, #04041d, #04041d, #04041d, #04051e, #05051e, #05051e, #05051e, #05051f, #05051f, #05061f, #050620, #050620, #060620, #060620, #060721, #060721, #060721, #060721, #060722, #060822, #060822, #060822, #060823, #070823, #070923, #070923, #070924, #070924, #070924, #070a24, #070a24, #070a25, #070a25, #070a25, #070a25, #070b26, #080b26, #080b26, #080b26, #080b26, #080c27, #080c27, #080c27, #080c27, #080c28, #080c28, #080d28, #080d28, #080d28, #080d29, #080d29, #080e29, #080e29, #080e29, #080e2a, #080e2a, #090e2a, #090e2a, #090f2a, #090f2b, #090f2b, #090f2b, #090f2b, #090f2b, #09102c, #09102c, #09102c, #09102c, #09102c, #09102c, #09102d, #09112d, #09112d, #09112d, #09112d, #09112e, #09112e, #09112e, #09122e, #09122e, #09122e, #09122f, #09122f, #0a122f, #0a122f, #0a132f, #0a1330, #0a1330, #0a1330, #0a1330, #0a1330, #0a1330, #0a1331, #0a1431, #0a1431, #0a1431, #0a1431, #0a1431, #0a1432, #0b1432, #0b1432, #0b1432, #0b1532, #0b1532, #0b1533, #0b1533, #0b1533, #0b1533, #0b1533, #0c1533, #0c1534, #0c1634, #0c1634, #0c1634, #0c1634, #0c1634, #0c1635, #0d1635, #0d1635, #0d1635, #0d1635, #0d1735, #0d1736, #0d1736, #0e1736, #0e1736, #0e1736, #0e1736, #0e1737, #0e1737, #0e1737, #0f1837, #0f1837, #0f1837, #0f1838, #0f1838, #0f1838, #101838, #101838, #101838, #101838, #101939, #101939, #111939, #111939, #111939, #111939, #11193a, #12193a, #12193a, #12193a, #121a3a, #121a3a, #121a3a, #131a3b, #131a3b, #131a3b, #131a3b, #131a3b, #141a3b, #141a3c, #141b3c, #141b3c, #141b3c, #151b3c, #151b3c, #151b3c, #151b3d, #151b3d, #161b3d, #161c3d, #161c3d, #161c3d, #171c3d, #171c3e, #171c3e, #171c3e, #171c3e, #181c3e, #181c3e, #181d3e, #181d3f, #191d3f, #191d3f, #191d3f, #191d3f, #1a1d3f, #1a1d40, #1a1d40, #1a1d40, #1b1e40, #1b1e40, #1b1e40, #1b1e40, #1c1e41, #1c1e41, #1c1e41, #1c1e41, #1d1e41, #1d1f41, #1d1f41, #1d1f42, #1e1f42, #1e1f42, #1e1f42, #1e1f42, #1f1f42, #1f1f42, #1f2043, #1f2043, #202043, #202043, #202043, #212043, #212043, #212044, #212044, #222044, #222144, #222144, #232144, #232144, #232145, #232145, #242145, #242145, #242145, #252245, #252245, #252246, #262246, #262246, #262246, #262246, #272246, #272246, #272347, #282347, #282347, #282347, #292347, #292347, #292347, #2a2348, #2a2348, #2a2448, #2b2448, #2b2448, #2b2448, #2c2448, #2c2449, #2c2449, #2d2449, #2d2449, #2d2549, #2e2549, #2e2549, #2e254a, #2f254a, #2f254a, #30254a, #30254a, #30254a, #31264a, #31264a, #31264b, #32264b, #32264b, #32264b, #33264b, #33264b, #34264b, #34274c, #34274c, #35274c, #35274c, #35274c, #36274c, #36274c, #37274d, #37284d, #37284d, #38284d, #38284d, #39284d, #39284d, #39284e, #3a284e, #3a284e, #3b294e, #3b294e, #3b294e, #3c294e, #3c294f, #3d294f, #3d294f, #3d294f, #3e2a4f, #3e2a4f, #3f2a4f, #3f2a4f, #402a50, #402a50, #402a50, #412a50, #412a50, #422b50, #422b50, #432b51, #432b51, #442b51, #442b51, #442b51, #452b51, #452c51, #462c52, #462c52, #472c52, #472c52, #482c52, #482c52, #492c52, #492d52, #492d53, #4a2d53, #4a2d53, #4b2d53, #4b2d53, #4c2d53, #4c2d53, #4d2e54, #4d2e54, #4e2e54, #4e2e54, #4f2e54, #4f2e54, #502e54, #502e54, #512f55, #512f55, #522f55, #522f55, #532f55, #532f55, #542f55, #542f55, #553056, #553056, #563056, #563056, #573056, #573056, #583056, #583056, #593157, #593157, #5a3157, #5a3157, #5b3157, #5c3157, #5c3157, #5d3157, #5d3257, #5e3258, #5e3258, #5f3258, #5f3258, #603258, #603258, #613358, #613358, #623359, #633359, #633359, #643359, #643359, #653359, #653459, #663459, #663459, #673459, #68345a, #68345a, #69345a, #69355a, #6a355a, #6a355a, #6b355a, #6c355a, #6c355a, #6d355a, #6d365b, #6e365b, #6f365b, #6f365b, #70365b, #70365b, #71365b, #72375b, #72375b, #73375b, #73375b, #74375b, #75375b, #75375c, #76385c, #76385c, #77385c, #78385c, #78385c, #79385c, #79395c, #7a395c, #7b395c, #7b395c, #7c395c, #7c395c, #7d3a5c, #7e3a5d, #7e3a5d, #7f3a5d, #7f3a5d, #803a5d, #813b5d, #813b5d, #823b5d, #823b5d, #833b5d, #843c5d, #843c5d, #853c5d, #853c5d, #863c5d, #873d5e, #873d5e, #883d5e, #883d5e, #893d5e, #8a3e5e, #8a3e5e, #8b3e5e, #8b3e5e, #8c3e5e, #8c3f5e, #8d3f5e, #8e3f5e, #8e3f5e, #8f405e, #8f405e, #90405e, #91405f, #91405f, #92415f, #92415f, #93415f, #94415f, #94425f, #95425f, #95425f, #96425f, #97435f, #97435f, #98435f, #98435f, #99445f, #99445f, #9a445f, #9b445f, #9b455f, #9c455f, #9c455f, #9d455f, #9e465f, #9e465f, #9f4660, #9f4760, #a04760, #a04760, #a14760, #a24860, #a24860, #a34860, #a34960, #a44960, #a44960, #a54a60, #a64a60, #a64a60, #a74a60, #a74b60, #a84b60, #a84b60, #a94c60, #aa4c60, #aa4c60, #ab4d60, #ab4d60, #ac4d60, #ac4e60, #ad4e60, #ad4e60, #ae4f60, #af4f60, #af4f60, #b05060, #b05060, #b15060, #b15160, #b25160, #b25160, #b35260, #b45260, #b45260, #b55360, #b55360, #b65360, #b65460, #b75460, #b75560, #b85560, #b85560, #b95660, #b95660, #ba5660, #bb5760, #bb5760, #bc5860, #bc5860, #bd5860, #bd5960, #be5960, #be5a60, #bf5a60, #bf5a60, #c05b60, #c05b60, #c15c60, #c15c60, #c25c60, #c25d60, #c35d60, #c35e60, #c45e60, #c45e60, #c55f60, #c55f60, #c66060, #c66060, #c76060, #c76160, #c86160, #c86260, #c96260, #c96360, #ca6360, #ca6460, #cb6460, #cb6460, #cc6560, #cc6560, #cd6660, #cd6660, #ce6760, #ce6760, #ce6860, #cf6860, #cf6860, #d06960, #d06960, #d16a60, #d16a60, #d26b60, #d26b5f, #d36c5f, #d36c5f, #d46d5f, #d46d5f, #d46e5f, #d56e5f, #d56e5f, #d66f5f, #d66f5f, #d7705f, #d7705f, #d8715f, #d8715f, #d8725f, #d9725f, #d9735f, #da735f, #da745f, #db745f, #db755f, #db755f, #dc765f, #dc765f, #dd775f, #dd7760, #de7860, #de7960, #df7960, #df7a60, #df7a60, #e07b60, #e07b60, #e17c60, #e17c60, #e17d60, #e27d60, #e27e60, #e27e60, #e37f60, #e37f60, #e48060, #e48060, #e48160, #e58160, #e58260, #e58260, #e68360, #e68360, #e68460, #e78460, #e78560, #e78560, #e88660, #e88660, #e88760, #e98760, #e98860, #e98860, #ea8960, #ea8960, #ea8a60, #eb8a60, #eb8b60, #eb8b60, #eb8c60, #ec8c60, #ec8d60, #ec8d60, #ed8e60, #ed8e60, #ed8f60, #ed8f60, #ee9060, #ee9060, #ee9160, #ef9160, #ef9260, #ef9260, #ef9360, #f09360, #f09460, #f09460, #f09560, #f19560, #f19560, #f19660, #f19660, #f29760, #f29760, #f29860, #f29861, #f29961, #f39961, #f39a61, #f39a61, #f39b61, #f49b61, #f49c61, #f49c61, #f49d61, #f49d61, #f59e61, #f59e61, #f59f61, #f59f61, #f5a061, #f6a062, #f6a162, #f6a162, #f6a262, #f6a262, #f7a362, #f7a362, #f7a362, #f7a462, #f7a462, #f7a562, #f8a563, #f8a663, #f8a663, #f8a763, #f8a763, #f8a863, #f9a863, #f9a963, #f9a963, #f9aa64, #f9aa64, #f9aa64, #faab64, #faab64, #faac64, #faac64, #faad65, #faad65, #faae65, #faae65, #fbaf65, #fbaf65, #fbaf65, #fbb066, #fbb066, #fbb166, #fbb166, #fcb266, #fcb266, #fcb366, #fcb367, #fcb367, #fcb467, #fcb467, #fcb567, #fcb567, #fdb668, #fdb668, #fdb768, #fdb768, #fdb768, #fdb868, #fdb869, #fdb969, #fdb969, #fdba69, #fdba69, #feba6a, #febb6a, #febb6a, #febc6a, #febc6a, #febc6b, #febd6b, #febd6b, #febe6b, #febe6b, #febe6c, #febf6c, #ffbf6c, #ffc06c, #ffc06c, #ffc06d, #ffc16d, #ffc16d, #ffc26d, #ffc26e, #ffc26e, #ffc36e, #ffc36e, #ffc46e, #ffc46f, #ffc46f, #ffc56f, #ffc56f, #ffc670, #ffc670, #ffc670, #ffc770, #ffc770, #ffc771, #ffc871, #ffc871, #ffc971, #ffc972, #ffc972, #ffca72, #ffca72, #ffca73, #ffcb73, #ffcb73, #ffcc73, #ffcc74, #ffcc74, #ffcd74, #ffcd74, #ffcd75, #ffce75, #ffce75, #ffce75, #ffcf76, #ffcf76, #ffcf76, #ffd076, #ffd077, #ffd177, #ffd177, #ffd177, #ffd278, #ffd278, #ffd278, #ffd378, #ffd379, #ffd379, #ffd479, #ffd479, #ffd47a, #ffd57a, #ffd57a, #ffd57a, #ffd67b, #ffd67b, #ffd67b, #ffd67b, #ffd77c, #ffd77c, #ffd77c, #ffd87c, #ffd87d, #ffd87d, #ffd97d, #ffd97d, #ffd97e, #ffda7e, #ffda7e, #ffda7e, #ffdb7f, #ffdb7f, #ffdb7f, #ffdb7f, #ffdc80, #ffdc80, #ffdc80, #ffdd80, #ffdd81, #ffdd81, #ffdd81, #ffde81, #ffde82, #ffde82, #ffdf82, #ffdf83, #ffdf83, #ffe083, #ffe083, #ffe084, #ffe084, #ffe184, #ffe184, #ffe185, #ffe185, #ffe285, #ffe285, #ffe286, #ffe386, #ffe386, #ffe386, #ffe387, #ffe487, #ffe487, #ffe487, #ffe488, #ffe588, #ffe588, #ffe588, #ffe589, #ffe689, #ffe689, #ffe689, #ffe68a, #ffe78a, #ffe78a, #ffe78a, #ffe78b, #ffe88b, #ffe88b, #ffe88b, #ffe88c, #ffe98c, #ffe98c, #ffe98c, #ffe98d, #ffea8d, #ffea8d, #ffea8d, #ffea8e, #ffeb8e, #ffeb8e, #ffeb8e, #ffeb8f, #ffec8f, #ffec8f, #ffec8f, #ffec90, #ffed90, #ffed90, #ffed90, #ffed91, #ffed91, #ffee91, #ffee91, #ffee92, #ffee92, #ffef92, #ffef92, #ffef93, #ffef93, #fff093, #fff093, #fff094, #fff094, #fff094, #fff195, #fff195, #fff195, #fff195, #fff196, #fff296, #fff296, #fff296, #fff297, #fff397, #fff397, #fff398, #fff399, #fff399, #fff49a, #fff49b, #fff49c, #fff49c, #fff49d, #fff59e, #fff59f, #fff5a0, #fff5a0, #fff5a1, #fff6a2, #fff6a3, #fff6a4, #fff6a5, #fff6a6, #fff7a7, #fff7a7, #fff7a8, #fff7a9, #fff7aa, #fff8ab, #fff8ac, #fff8ad, #fff8ae, #fff8af, #fff8b0, #fff9b1, #fff9b2, #fff9b3, #fff9b4, #fff9b5, #fffab6, #fffab8, #fffab9, #fffaba, #fffabb, #fffabc, #fffbbd, #fffbbe, #fffbbf, #fffbc0, #fffbc2, #fffbc3, #fffcc4, #fffcc5, #fffcc6, #fffcc8, #fffcc9, #fffcca, #fffccc, #fffdcd, #fffdce, #fffdd0, #fffdd1, #fffdd2, #fffdd4, #fffdd5, #fffed7, #fffed8, #fffed9, #fffedb, #fffedc, #fffede, #fffedf, #fffee1, #ffffe3, #ffffe4, #ffffe6, #ffffe8 | |
) | |
;width:100%;height:100%"></div> | |
</foreignObject> | |
</svg> | |
` | |
let i = new Image() | |
i.src = URL.createObjectURL(new Blob([svg], {type:'image/svg+xml'})) | |
return new Promise((resolve, reject) => { | |
i.onload = () => { | |
let linMix = (a, b, k) => (1-k)*a + k*b | |
const lfunc = (x, lowValDeEmph_a = 1, lowValDeEmph_b = 0) => (1 - ((1 - Math.cos(Math.PI*(x - 1)))*0.5)**(2**lowValDeEmph_a))**((1+lowValDeEmph_a**(-lowValDeEmph_b))**1) | |
for (let j = 0, x0 = 0; j < 256; j++, x0 = j/255) { | |
let x = x0//**0.85 | |
ctx.drawImage(i, Math.min(x*255,255)*4, 0, 4, 256, j, 0, 1, 256) | |
} | |
let idata = ctx.getImageData(0,0,256,1) | |
let colormap = new Array(256).fill(0).map((x, i) => new Array(4).fill(0).map((y,j)=>idata.data[i*4+j])) | |
resolve(colormap) | |
} | |
}) | |
} | |
function colormapV72() { | |
let c = document.createElement('canvas') | |
c.width = 256 | |
c.height = 1 | |
let ctx = c.getContext('2d'), g, it | |
let svg = ` | |
<svg width="1024" height="256" xmlns="http://www.w3.org/2000/svg" style="outline: 1px solid black;"> | |
<foreignObject x="0" y="0" width="1024" height="256"> | |
<div xmlns="http://www.w3.org/1999/xhtml" | |
style="background-image: linear-gradient(90deg in oklch, | |
#000000, #010001, #010002, #010003, #010004, #010105, #010105, #010106, #010107, #010107, #010108, #010108, #010109, #01020a, #01020a, #01020b, #01020b, #01020c, #02020d, #02020d, #02020d, #02030e, #02030e, #02030f, #02030f, #020310, #020310, #020310, #020311, #030411, #030411, #030412, #030412, #030412, #030412, #030413, #030413, #040413, #040513, #040514, #040514, #040514, #040514, #040515, #040515, #040615, #040615, #050616, #050616, #050616, #050616, #050616, #050617, #050717, #050717, #050717, #050717, #060718, #060718, #060718, #060718, #060818, #060819, #060819, #060819, #060819, #070819, #070819, #07091a, #07091a, #07091a, #07091a, #07091a, #07091a, #07091b, #07091b, #080a1b, #080a1b, #080a1b, #080a1c, #080a1c, #080a1c, #080a1c, #080b1c, #080b1c, #080b1d, #090b1d, #090b1d, #090b1d, #090b1d, #090b1d, #090c1e, #090c1e, #090c1e, #090c1e, #090c1e, #0a0c1e, #0a0c1e, #0a0d1f, #0a0d1f, #0a0d1f, #0a0d1f, #0a0d1f, #0a0d1f, #0a0d20, #0a0d20, #0b0e20, #0b0e20, #0b0e20, #0b0e20, #0b0e21, #0b0e21, #0b0e21, #0b0e21, #0b0f21, #0b0f21, #0b0f22, #0c0f22, #0c0f22, #0c0f22, #0c0f22, #0c0f22, #0c0f23, #0c1023, #0c1023, #0c1023, #0c1023, #0c1023, #0c1024, #0d1024, #0d1024, #0d1124, #0d1124, #0d1124, #0d1124, #0d1125, #0d1125, #0d1125, #0d1125, #0d1125, #0d1225, #0e1226, #0e1226, #0e1226, #0e1226, #0e1226, #0e1226, #0e1227, #0e1327, #0e1327, #0e1327, #0e1327, #0e1327, #0e1328, #0f1328, #0f1328, #0f1328, #0f1428, #0f1428, #0f1429, #0f1429, #0f1429, #0f1429, #0f1429, #0f1429, #0f142a, #10152a, #10152a, #10152a, #10152a, #10152a, #10152b, #10152b, #10152b, #10152b, #10162b, #11162b, #11162c, #11162c, #11162c, #11162c, #11162c, #11162c, #11162d, #12162d, #12172d, #12172d, #12172d, #12172d, #12172e, #12172e, #12172e, #13172e, #13172e, #13172e, #13182f, #13182f, #13182f, #13182f, #14182f, #14182f, #141830, #141830, #141830, #141930, #151930, #151930, #151931, #151931, #151931, #151931, #161931, #161931, #161a32, #161a32, #161a32, #161a32, #171a32, #171a33, #171a33, #171a33, #171a33, #181b33, #181b33, #181b34, #181b34, #181b34, #181b34, #191b34, #191b34, #191c35, #191c35, #191c35, #1a1c35, #1a1c35, #1a1c36, #1a1c36, #1a1c36, #1b1d36, #1b1d36, #1b1d36, #1b1d37, #1c1d37, #1c1d37, #1c1d37, #1c1d37, #1c1e38, #1d1e38, #1d1e38, #1d1e38, #1d1e38, #1e1e38, #1e1e39, #1e1e39, #1e1f39, #1f1f39, #1f1f39, #1f1f3a, #1f1f3a, #201f3a, #201f3a, #201f3a, #20203b, #21203b, #21203b, #21203b, #21203b, #22203b, #22203c, #22203c, #22213c, #23213c, #23213c, #23213d, #24213d, #24213d, #24213d, #25223d, #25223e, #25223e, #25223e, #26223e, #26223e, #26223e, #27223f, #27233f, #27233f, #28233f, #28233f, #282340, #292340, #292340, #292340, #2a2440, #2a2441, #2b2441, #2b2441, #2b2441, #2c2441, #2c2441, #2c2542, #2d2542, #2d2542, #2e2542, #2e2542, #2e2543, #2f2543, #2f2543, #302543, #302643, #302643, #312644, #312644, #322644, #322644, #332644, #332645, #342745, #342745, #342745, #352745, #352745, #362746, #362746, #372746, #372746, #382846, #382846, #392847, #392847, #3a2847, #3a2847, #3b2847, #3b2847, #3c2848, #3c2848, #3d2948, #3d2948, #3e2948, #3f2948, #3f2949, #402949, #402949, #412949, #412949, #422949, #422949, #432a4a, #432a4a, #442a4a, #452a4a, #452a4a, #462a4a, #462a4a, #472a4a, #472a4b, #482a4b, #492a4b, #492a4b, #4a2b4b, #4a2b4b, #4b2b4b, #4c2b4b, #4c2b4c, #4d2b4c, #4d2b4c, #4e2b4c, #4f2b4c, #4f2b4c, #502b4c, #502b4c, #512b4c, #522c4c, #522c4d, #532c4d, #532c4d, #542c4d, #552c4d, #552c4d, #562c4d, #572c4d, #572c4d, #582c4d, #582c4d, #592c4d, #5a2c4d, #5a2d4e, #5b2d4e, #5c2d4e, #5c2d4e, #5d2d4e, #5d2d4e, #5e2d4e, #5f2d4e, #5f2d4e, #602d4e, #612d4e, #612d4e, #622e4e, #622e4e, #632e4e, #642e4e, #642e4e, #652e4e, #662e4e, #662e4f, #672e4f, #672e4f, #682e4f, #692f4f, #692f4f, #6a2f4f, #6a2f4f, #6b2f4f, #6c2f4f, #6c2f4f, #6d2f4f, #6e2f4f, #6e304f, #6f304f, #6f304f, #70304f, #71304f, #71304f, #72304f, #72304f, #73304f, #74314f, #74314f, #75314f, #76314f, #76314f, #77314f, #77314f, #78314f, #79324f, #79324f, #7a324f, #7a324f, #7b324e, #7c324e, #7c334e, #7d334e, #7d334e, #7e334e, #7f334e, #7f334e, #80344e, #80344e, #81344e, #81344e, #82344e, #83344e, #83354e, #84354e, #84354e, #85354e, #85354e, #86364e, #87364e, #87364e, #88364e, #88364e, #89374e, #89374e, #8a374e, #8a374e, #8b384e, #8b384e, #8c384e, #8d384e, #8d394e, #8e394e, #8e394e, #8f394e, #8f394e, #903a4e, #903a4e, #913a4e, #913a4e, #923b4e, #923b4e, #933b4e, #943b4e, #943c4e, #953c4e, #953c4e, #963d4e, #963d4e, #973d4e, #973d4e, #983e4e, #983e4e, #993e4e, #993e4e, #9a3f4e, #9a3f4e, #9b3f4e, #9b404e, #9c404e, #9c404e, #9d414e, #9d414e, #9e414e, #9e414e, #9f424e, #9f424e, #a0424e, #a0434e, #a1434e, #a1434e, #a2444e, #a2444e, #a3444e, #a3454e, #a4454e, #a4454e, #a5454e, #a5464e, #a6464e, #a6464e, #a7474e, #a7474e, #a8474e, #a8484e, #a9484e, #a9484e, #aa494e, #aa494e, #ab494e, #ab4a4e, #ac4a4e, #ac4a4e, #ad4b4e, #ad4b4e, #ae4c4e, #ae4c4e, #af4c4e, #af4d4e, #af4d4e, #b04d4e, #b04e4e, #b14e4e, #b14e4e, #b24f4e, #b24f4e, #b34f4e, #b3504e, #b4504e, #b4504e, #b5514e, #b5514e, #b6524e, #b6524e, #b6524e, #b7534e, #b7534e, #b8534e, #b8544e, #b9544e, #b9554e, #ba554e, #ba554e, #bb564e, #bb564e, #bb564e, #bc574e, #bc574e, #bd584e, #bd584e, #be584e, #be594e, #bf594e, #bf5a4f, #bf5a4f, #c05a4f, #c05b4f, #c15b4f, #c15b4f, #c25c4f, #c25c4f, #c35d4f, #c35d4f, #c35d4f, #c45e4f, #c45e4f, #c55f4f, #c55f4f, #c65f4f, #c6604f, #c6604f, #c7614f, #c7614f, #c8614f, #c8624f, #c9624f, #c9634f, #c9634f, #ca634f, #ca644f, #cb6450, #cb6550, #cc6550, #cc6550, #cc6650, #cd6650, #cd6750, #ce6750, #ce6850, #cf6850, #cf6850, #cf6950, #d06950, #d06a50, #d16a50, #d16b50, #d16b50, #d26b50, #d26c50, #d36c51, #d36d51, #d46d51, #d46e51, #d46e51, #d56e51, #d56f51, #d66f51, #d67051, #d77051, #d77151, #d77151, #d87151, #d87252, #d97252, #d97352, #d97352, #da7452, #da7452, #da7452, #db7552, #db7552, #dc7652, #dc7652, #dc7752, #dd7752, #dd7752, #de7852, #de7852, #de7953, #df7953, #df7a53, #df7a53, #e07a53, #e07b53, #e07b53, #e17c53, #e17c53, #e17d53, #e27d53, #e27d53, #e37e53, #e37e53, #e37f53, #e47f54, #e48054, #e48054, #e58054, #e58154, #e58154, #e68254, #e68254, #e68354, #e78354, #e78354, #e78454, #e88454, #e88554, #e88554, #e98555, #e98655, #e98655, #ea8755, #ea8755, #ea8855, #ea8855, #eb8855, #eb8955, #eb8955, #ec8a55, #ec8a55, #ec8a55, #ed8b55, #ed8b56, #ed8c56, #ee8c56, #ee8d56, #ee8d56, #ee8d56, #ef8e56, #ef8e56, #ef8f56, #f08f56, #f09056, #f09056, #f09056, #f19157, #f19157, #f19257, #f29257, #f29257, #f29357, #f29357, #f39457, #f39457, #f39457, #f39557, #f49558, #f49658, #f49658, #f49758, #f59758, #f59758, #f59858, #f59858, #f69958, #f69958, #f69958, #f69a59, #f79a59, #f79b59, #f79b59, #f79b59, #f89c59, #f89c59, #f89d59, #f89d59, #f99e59, #f99e5a, #f99e5a, #f99f5a, #fa9f5a, #faa05a, #faa05a, #faa05a, #faa15a, #fba15a, #fba25a, #fba25b, #fba25b, #fca35b, #fca35b, #fca45b, #fca45b, #fca45b, #fda55b, #fda55b, #fda65c, #fda65c, #fda65c, #fea75c, #fea75c, #fea85c, #fea85c, #fea85c, #ffa95d, #ffa95d, #ffaa5d, #ffaa5d, #ffaa5d, #ffab5d, #ffab5d, #ffac5d, #ffac5e, #ffac5e, #ffad5e, #ffad5e, #ffad5e, #ffae5e, #ffae5e, #ffaf5e, #ffaf5f, #ffaf5f, #ffb05f, #ffb05f, #ffb15f, #ffb15f, #ffb15f, #ffb260, #ffb260, #ffb360, #ffb360, #ffb360, #ffb460, #ffb460, #ffb461, #ffb561, #ffb561, #ffb661, #ffb661, #ffb661, #ffb761, #ffb762, #ffb762, #ffb862, #ffb862, #ffb962, #ffb962, #ffb963, #ffba63, #ffba63, #ffba63, #ffbb63, #ffbb63, #ffbc64, #ffbc64, #ffbc64, #ffbd64, #ffbd64, #ffbd64, #ffbe65, #ffbe65, #ffbf65, #ffbf66, #ffbf66, #ffc067, #ffc067, #ffc168, #ffc168, #ffc269, #ffc269, #ffc26a, #ffc36a, #ffc36a, #ffc36b, #ffc46b, #ffc46c, #ffc56c, #ffc56d, #ffc56d, #ffc66e, #ffc66e, #ffc76f, #ffc76f, #ffc76f, #ffc870, #ffc870, #ffc971, #ffc971, #ffc972, #ffca72, #ffca73, #ffca73, #ffcb74, #ffcb74, #ffcc74, #ffcc75, #ffcc75, #ffcd76, #ffcd76, #ffcd77, #ffce77, #ffce77, #ffcf78, #ffcf78, #ffcf79, #ffd079, #ffd07a, #ffd07a, #ffd17b, #ffd17b, #ffd17c, #ffd27c, #ffd27c, #ffd27d, #ffd37d, #ffd37e, #ffd47e, #ffd47f, #ffd47f, #ffd57f, #ffd580, #ffd580, #ffd681, #ffd681, #ffd682, #ffd782, #ffd782, #ffd783, #ffd883, #ffd884, #ffd884, #ffd985, #ffd985, #ffd986, #ffda86, #ffda86, #ffda87, #ffdb87, #ffdb88, #ffdb88, #ffdc89, #ffdc89, #ffdc8a, #ffdd8a, #ffdd8b, #ffdd8b, #ffde8c, #ffde8c, #ffde8c, #ffdf8d, #ffdf8d, #ffdf8e, #ffe08e, #ffe08f, #ffe08f, #ffe190, #ffe190, #ffe191, #ffe291, #ffe291, #ffe292, #ffe392, #ffe393, #ffe393, #ffe494, #ffe494, #ffe495, #ffe595, #ffe596, #ffe596, #ffe697, #ffe697, #ffe698, #ffe698, #ffe799, #ffe799, #ffe79a, #ffe89a, #ffe89b, #ffe89b, #ffe99c, #ffe99c, #ffe99d, #ffea9d, #ffea9e, #ffea9e, #ffea9f, #ffeba0, #ffeba0, #ffeba1, #ffeca1, #ffeca2, #ffeca2, #ffeda3, #ffeda4, #ffeda4, #ffeda5, #ffeea5, #ffeea6, #ffeea6, #ffefa7, #ffefa8, #ffefa8, #fff0a9, #fff0a9, #fff0aa, #fff0ab, #fff1ab, #fff1ac, #fff1ad, #fff2ad, #fff2ae, #fff2af, #fff2af, #fff3b0, #fff3b1, #fff3b2, #fff4b2, #fff4b3, #fff4b4, #fff4b4, #fff5b5, #fff5b6, #fff5b7, #fff6b8, #fff6b8, #fff6b9, #fff6ba, #fff7bb, #fff7bc, #fff7bc, #fff7be, #fff8be, #fff8bf, #fff8c0, #fff8c1, #fff9c2, #fff9c3, #fff9c4, #fffac5, #fffac6, #fffac7, #fffac8, #fffbc9, #fffbcb, #fffbcc, #fffbcd, #fffcce, #fffccf, #fffcd1, #fffcd2, #fffcd3, #fffdd5, #fffdd6, #fffdd7, #fffdd9, #fffedb, #fffedc, #fffede, #fffee0, #fffee1, #ffffe3, #ffffe5, #ffffe7 | |
) | |
;width:100%;height:100%"></div> | |
</foreignObject> | |
</svg> | |
` | |
let i = new Image() | |
i.src = URL.createObjectURL(new Blob([svg], {type:'image/svg+xml'})) | |
return new Promise((resolve, reject) => { | |
i.onload = () => { | |
let linMix = (a, b, k) => (1-k)*a + k*b | |
const lfunc = (x, lowValDeEmph_a = 1, lowValDeEmph_b = 0) => (1 - ((1 - Math.cos(Math.PI*(x - 1)))*0.5)**(2**lowValDeEmph_a))**((1+lowValDeEmph_a**(-lowValDeEmph_b))**1) | |
for (let j = 0, x0 = 0; j < 256; j++, x0 = j/255) { | |
let x = x0//**0.85 | |
ctx.drawImage(i, Math.min(x*255,255)*4, 0, 4, 256, j, 0, 1, 256) | |
} | |
let idata = ctx.getImageData(0,0,256,1) | |
let colormap = new Array(256).fill(0).map((x, i) => new Array(4).fill(0).map((y,j)=>idata.data[i*4+j])) | |
resolve(colormap) | |
} | |
}) | |
} | |
function colormapV73() { | |
let c = document.createElement('canvas') | |
c.width = 256 | |
c.height = 1 | |
let ctx = c.getContext('2d'), g, it | |
let svg = ` | |
<svg width="1024" height="256" xmlns="http://www.w3.org/2000/svg" style="outline: 1px solid black;"> | |
<foreignObject x="0" y="0" width="1024" height="256"> | |
<div xmlns="http://www.w3.org/1999/xhtml" | |
style="background-image: linear-gradient(90deg in oklch, | |
#000000, #000018, #000101, #000102, #000103, #000104, #000105, #000106, #000108, #000109, #00020a, #00020b, #00020c, #00020e, #00020f, #000210, #000211, #000212, #000213, #000214, #000215, #000315, #000316, #000317, #000318, #000319, #00031a, #00031a, #00031b, #00031c, #00031d, #00031d, #00031d, #00041d, #00041d, #00041d, #00041d, #00041d, #00041e, #00041e, #00051e, #00051e, #00051e, #00051e, #00051e, #00051e, #00051f, #00061f, #00061f, #00061f, #00061f, #00061f, #00061f, #00071f, #000720, #000720, #000720, #000720, #000720, #000820, #000820, #000820, #000821, #000821, #000821, #000821, #000921, #000921, #000921, #000921, #000922, #000922, #000a22, #000a22, #000a22, #000a22, #000a22, #000a22, #000b23, #000b23, #000b23, #000b23, #000b23, #000b23, #000b23, #000c23, #000c24, #000c24, #000c24, #000c24, #000c24, #000c24, #000d24, #000d24, #000d25, #000d25, #000d25, #000d25, #000d25, #000e25, #000e25, #000e26, #000e26, #000e26, #000e26, #000e26, #000f26, #010f26, #010f26, #010f27, #010f27, #010f27, #010f27, #010f27, #011027, #011027, #011028, #011028, #011028, #011028, #011028, #011128, #011128, #011129, #011129, #011129, #011129, #011129, #011129, #011229, #01122a, #01122a, #01122a, #01122a, #01122a, #01122a, #01122b, #01132b, #01132b, #01132b, #01132b, #01132b, #01132b, #01132c, #01132c, #01142c, #01142c, #01142c, #01142c, #01142c, #01142d, #01142d, #01142d, #01152d, #01152d, #01152d, #01152e, #01152e, #01152e, #01152e, #01152e, #01162e, #01162f, #01162f, #01162f, #01162f, #01162f, #01162f, #011630, #011630, #011730, #011730, #011730, #011730, #011731, #011731, #011731, #011731, #011831, #011831, #011832, #011832, #011832, #011832, #011832, #011832, #011833, #011933, #011933, #011933, #011933, #011933, #011934, #011934, #011934, #011a34, #011a34, #011a35, #011a35, #011a35, #011a35, #011a35, #021a35, #021b36, #021b36, #021b36, #021b36, #021b36, #021b37, #021b37, #021b37, #021c37, #021c37, #021c37, #021c38, #021c38, #021c38, #021c38, #021c38, #021d39, #031d39, #031d39, #031d39, #031d39, #031d3a, #031d3a, #031e3a, #031e3a, #031e3a, #031e3b, #031e3b, #031e3b, #031e3b, #041f3b, #041f3c, #041f3c, #041f3c, #041f3c, #041f3c, #041f3d, #04203d, #04203d, #05203d, #05203d, #05203e, #05203e, #05203e, #05213e, #05213e, #05213f, #06213f, #06213f, #06213f, #06223f, #062240, #062240, #062240, #072240, #072240, #072241, #072341, #072341, #082341, #082342, #082342, #082342, #082442, #082442, #092443, #092443, #092443, #092443, #0a2543, #0a2544, #0a2544, #0a2544, #0b2544, #0b2545, #0b2645, #0b2645, #0c2645, #0c2645, #0c2646, #0c2646, #0d2746, #0d2746, #0d2747, #0e2747, #0e2747, #0e2747, #0f2848, #0f2848, #0f2848, #102848, #102848, #102849, #112949, #112949, #112949, #12294a, #12294a, #13294a, #132a4a, #142a4b, #142a4b, #152a4b, #152a4b, #152a4c, #162a4c, #162b4c, #172b4c, #182b4c, #182b4d, #192b4d, #192b4d, #1a2c4d, #1a2c4e, #1b2c4e, #1c2c4e, #1c2c4e, #1d2c4f, #1d2c4f, #1e2c4f, #1f2d4f, #1f2d50, #202d50, #212d50, #212d50, #222d50, #232d51, #242d51, #242d51, #252e51, #262e52, #272e52, #272e52, #282e52, #292e52, #2a2e53, #2a2e53, #2b2e53, #2c2e53, #2d2e54, #2e2e54, #2e2e54, #2f2e54, #302f54, #312f55, #322f55, #332f55, #342f55, #342f55, #352f56, #362f56, #372f56, #382f56, #392f56, #3a2f56, #3b2f57, #3b2f57, #3c2f57, #3d2f57, #3e2f57, #3f2f57, #402f58, #412f58, #422f58, #432f58, #442f58, #442f58, #452f58, #462f58, #472f59, #482f59, #492f59, #4a2f59, #4b2f59, #4c2f59, #4d2e59, #4e2e59, #4f2e59, #4f2e59, #502e59, #512e5a, #522e5a, #532e5a, #542e5a, #552e5a, #562e5a, #572e5a, #582e5a, #592e5a, #5a2e5a, #5a2e5a, #5b2d5a, #5c2d5a, #5d2d5a, #5e2d5a, #5f2d5a, #602d5a, #612d5a, #622d5a, #622d5a, #632d5a, #642d5a, #652d5a, #662d5a, #672c5a, #682c5a, #692c5a, #692c5a, #6a2c5a, #6b2c5a, #6c2c5a, #6d2c5a, #6e2c5a, #6f2c59, #6f2c59, #702c59, #712c59, #722c59, #732b59, #742b59, #742b59, #752b59, #762b59, #772b59, #782b59, #782b58, #792b58, #7a2b58, #7b2b58, #7c2b58, #7c2b58, #7d2b58, #7e2b58, #7f2b58, #7f2b57, #802b57, #812b57, #822b57, #832b57, #832b57, #842b57, #852b56, #862b56, #862b56, #872b56, #882b56, #882b56, #892b56, #8a2b55, #8b2b55, #8b2b55, #8c2b55, #8d2b55, #8d2b55, #8e2b54, #8f2b54, #902b54, #902b54, #912c54, #922c54, #922c53, #932c53, #942c53, #942c53, #952c53, #962c53, #962c52, #972c52, #982d52, #982d52, #992d52, #9a2d51, #9a2d51, #9b2d51, #9c2d51, #9c2e51, #9d2e51, #9e2e50, #9e2e50, #9f2e50, #9f2e50, #a02f50, #a12f4f, #a12f4f, #a22f4f, #a22f4f, #a3304f, #a4304f, #a4304e, #a5304e, #a5314e, #a6314e, #a7314e, #a7314d, #a8314d, #a8324d, #a9324d, #aa324d, #aa324d, #ab334c, #ab334c, #ac334c, #ac344c, #ad344c, #ae344b, #ae344b, #af354b, #af354b, #b0354b, #b0364b, #b1364a, #b2364a, #b2374a, #b3374a, #b3374a, #b4374a, #b43849, #b53849, #b53849, #b63949, #b63949, #b73948, #b73a48, #b83a48, #b93a48, #b93b48, #ba3b48, #ba3c47, #bb3c47, #bb3c47, #bc3d47, #bc3d47, #bd3d47, #bd3e47, #be3e46, #be3e46, #bf3f46, #bf3f46, #c04046, #c04046, #c14045, #c14145, #c24145, #c24145, #c34245, #c34245, #c44345, #c44344, #c54344, #c54444, #c64444, #c64544, #c64544, #c74544, #c74643, #c84643, #c84743, #c94743, #c94843, #ca4843, #ca4843, #cb4942, #cb4942, #cc4a42, #cc4a42, #cd4a42, #cd4b42, #cd4b42, #ce4c42, #ce4c41, #cf4d41, #cf4d41, #d04d41, #d04e41, #d14e41, #d14f41, #d14f41, #d25041, #d25040, #d35040, #d35140, #d45140, #d45240, #d55240, #d55340, #d55340, #d65440, #d65440, #d7543f, #d7553f, #d7553f, #d8563f, #d8563f, #d9573f, #d9573f, #da583f, #da583f, #da593f, #db593f, #db593f, #dc5a3f, #dc5a3e, #dc5b3e, #dd5b3e, #dd5c3e, #de5c3e, #de5d3e, #df5d3e, #df5e3e, #df5e3e, #e05f3e, #e05f3e, #e1603e, #e1603e, #e1603e, #e2613e, #e2613e, #e3623e, #e3623e, #e3633e, #e4633e, #e4643e, #e5643e, #e5653e, #e5653e, #e6663e, #e6663e, #e7673e, #e7673e, #e7683e, #e8683e, #e8693d, #e8693d, #e96a3d, #e96a3d, #ea6b3d, #ea6b3d, #ea6c3d, #eb6c3d, #eb6c3d, #eb6d3d, #ec6d3d, #ec6e3d, #ec6e3d, #ed6f3d, #ed6f3d, #ed703d, #ee703d, #ee713d, #ee713d, #ef723d, #ef723d, #ef733d, #f0733e, #f0743e, #f0743e, #f1753e, #f1753e, #f1753e, #f2763e, #f2763e, #f2773e, #f3773e, #f3783e, #f3783e, #f4793e, #f4793e, #f47a3e, #f47a3e, #f57b3e, #f57b3e, #f57c3e, #f67c3e, #f67c3e, #f67d3e, #f67d3e, #f77e3e, #f77e3e, #f77f3f, #f87f3f, #f8803f, #f8803f, #f8813f, #f9813f, #f9823f, #f9823f, #fa823f, #fa833f, #fa833f, #fa843f, #fb843f, #fb8540, #fb8540, #fb8640, #fc8640, #fc8740, #fc8740, #fc8840, #fd8840, #fd8840, #fd8940, #fd8941, #fe8a41, #fe8a41, #fe8b41, #fe8b41, #fe8c41, #ff8c41, #ff8d41, #ff8d42, #ff8e42, #ff8e42, #ff8e42, #ff8f42, #ff8f42, #ff9042, #ff9043, #ff9143, #ff9143, #ff9243, #ff9243, #ff9343, #ff9344, #ff9344, #ff9444, #ff9444, #ff9544, #ff9544, #ff9645, #ff9645, #ff9745, #ff9745, #ff9745, #ff9845, #ff9846, #ff9946, #ff9946, #ff9a46, #ff9a46, #ff9b47, #ff9b47, #ff9b47, #ff9c47, #ff9c47, #ff9d48, #ff9d48, #ff9e48, #ff9e48, #ff9f49, #ff9f49, #ff9f49, #ffa049, #ffa04a, #ffa14a, #ffa14a, #ffa24b, #ffa24c, #ffa34c, #ffa34d, #ffa44d, #ffa44e, #ffa54e, #ffa54f, #ffa64f, #ffa650, #ffa751, #ffa751, #ffa852, #ffa852, #ffa953, #ffa953, #ffaa54, #ffaa54, #ffab55, #ffab56, #ffac56, #ffac57, #ffac57, #ffad58, #ffad58, #ffae59, #ffae59, #ffaf5a, #ffaf5a, #ffb05b, #ffb05c, #ffb15c, #ffb15d, #ffb25d, #ffb25e, #ffb25e, #ffb35f, #ffb35f, #ffb460, #ffb460, #ffb561, #ffb561, #ffb562, #ffb662, #ffb663, #ffb763, #ffb764, #ffb864, #ffb865, #ffb965, #ffb966, #ffb966, #ffba67, #ffba67, #ffbb68, #ffbb68, #ffbb69, #ffbc69, #ffbc6a, #ffbd6a, #ffbd6b, #ffbe6b, #ffbe6c, #ffbe6c, #ffbf6d, #ffbf6d, #ffc06e, #ffc06e, #ffc06f, #ffc16f, #ffc170, #ffc270, #ffc271, #ffc271, #ffc372, #ffc372, #ffc473, #ffc473, #ffc474, #ffc574, #ffc574, #ffc575, #ffc675, #ffc676, #ffc776, #ffc777, #ffc777, #ffc878, #ffc878, #ffc979, #ffc979, #ffc97a, #ffca7a, #ffca7b, #ffca7b, #ffcb7c, #ffcb7c, #ffcc7c, #ffcc7d, #ffcc7d, #ffcd7e, #ffcd7e, #ffcd7f, #ffce7f, #ffce80, #ffce80, #ffcf81, #ffcf81, #ffd082, #ffd082, #ffd082, #ffd183, #ffd183, #ffd184, #ffd284, #ffd285, #ffd285, #ffd386, #ffd386, #ffd386, #ffd487, #ffd487, #ffd588, #ffd588, #ffd589, #ffd689, #ffd68a, #ffd68a, #ffd78b, #ffd78b, #ffd78b, #ffd88c, #ffd88c, #ffd88d, #ffd98d, #ffd98e, #ffd98e, #ffda8f, #ffda8f, #ffda8f, #ffdb90, #ffdb90, #ffdb91, #ffdc91, #ffdc92, #ffdc92, #ffdd93, #ffdd93, #ffdd94, #ffde94, #ffde94, #ffde95, #ffdf95, #ffdf96, #ffdf96, #ffe097, #ffe097, #ffe098, #ffe198, #ffe199, #ffe199, #ffe29a, #ffe29a, #ffe29a, #ffe39b, #ffe39b, #ffe39c, #ffe39c, #ffe49d, #ffe49d, #ffe49e, #ffe59e, #ffe59f, #ffe59f, #ffe6a0, #ffe6a0, #ffe6a1, #ffe7a1, #ffe7a2, #ffe7a2, #ffe8a2, #ffe8a3, #ffe8a3, #ffe8a4, #ffe9a5, #ffe9a5, #ffe9a5, #ffeaa6, #ffeaa6, #ffeaa7, #ffeba7, #ffeba8, #ffeba9, #ffeca9, #ffecaa, #ffecaa, #ffecab, #ffedab, #ffedac, #ffedac, #ffeead, #ffeead, #ffeeae, #ffefae, #ffefaf, #ffefb0, #ffefb0, #fff0b1, #fff0b1, #fff0b2, #fff1b2, #fff1b3, #fff1b4, #fff1b4, #fff2b5, #fff2b6, #fff2b6, #fff3b7, #fff3b7, #fff3b8, #fff3b9, #fff4b9, #fff4ba, #fff4bb, #fff5bb, #fff5bc, #fff5bd, #fff5be, #fff6be, #fff6bf, #fff6c0, #fff7c0, #fff7c1, #fff7c2, #fff7c3, #fff8c4, #fff8c4, #fff8c5, #fff8c6, #fff9c7, #fff9c8, #fff9c9, #fffaca, #fffacb, #fffacc, #fffacd, #fffbce, #fffbcf, #fffbd0, #fffbd1, #fffcd2, #fffcd3, #fffcd4, #fffcd5, #fffdd7, #fffdd8, #fffdd9, #fffddb, #fffddc, #fffedd, #fffedf, #fffee0, #fffee2, #fffee4, #ffffe6, #ffffe8 | |
) | |
;width:100%;height:100%"></div> | |
</foreignObject> | |
</svg> | |
` | |
let i = new Image() | |
i.src = URL.createObjectURL(new Blob([svg], {type:'image/svg+xml'})) | |
return new Promise((resolve, reject) => { | |
i.onload = () => { | |
let linMix = (a, b, k) => (1-k)*a + k*b | |
const lfunc = (x, lowValDeEmph_a = 1, lowValDeEmph_b = 0) => (1 - ((1 - Math.cos(Math.PI*(x - 1)))*0.5)**(2**lowValDeEmph_a))**((1+lowValDeEmph_a**(-lowValDeEmph_b))**1) | |
for (let j = 0, x0 = 0; j < 256; j++, x0 = j/255) { | |
let x = x0//**0.85 | |
ctx.drawImage(i, Math.min(x*255,255)*4, 0, 4, 256, j, 0, 1, 256) | |
} | |
let idata = ctx.getImageData(0,0,256,1) | |
let colormap = new Array(256).fill(0).map((x, i) => new Array(4).fill(0).map((y,j)=>idata.data[i*4+j])) | |
resolve(colormap) | |
} | |
}) | |
} | |
function colormapV74() { | |
let c = document.createElement('canvas') | |
c.width = 256 | |
c.height = 1 | |
let ctx = c.getContext('2d'), g, it | |
let svg = ` | |
<svg width="1024" height="256" xmlns="http://www.w3.org/2000/svg" style="outline: 1px solid black;"> | |
<foreignObject x="0" y="0" width="1024" height="256"> | |
<div xmlns="http://www.w3.org/1999/xhtml" | |
style="background-image: linear-gradient(90deg in oklch, | |
#000000, #000018, #000018, #000018, #000000, #000001, #000101, #000101, #000102, #000103, #000103, #000104, #000104, #000105, #000106, #000106, #000107, #000108, #000209, #00020a, #00020a, #00020b, #00020c, #00020d, #00020e, #00020f, #00020f, #000210, #000211, #000212, #000213, #000213, #000214, #000315, #000315, #000316, #000316, #000317, #000317, #000318, #000318, #000319, #000319, #000319, #00041a, #00041a, #00041b, #00041b, #00041b, #00041c, #00041c, #00041c, #00041d, #00051d, #00051e, #00051e, #00051e, #00051f, #00051f, #00051f, #00061f, #00061f, #00061f, #00061f, #00061f, #000620, #000620, #000720, #000720, #000720, #000720, #000720, #000720, #000721, #000821, #000821, #000821, #000821, #000821, #000821, #000921, #000922, #000922, #000922, #000922, #000922, #000a22, #000a22, #000a22, #000a23, #000a23, #000a23, #000b23, #000b23, #000b23, #000b23, #000b23, #000b24, #000b24, #000c24, #000c24, #000c24, #000c24, #000c24, #000c25, #000d25, #000d25, #000d25, #000d25, #000d25, #000d25, #000d25, #000e26, #000e26, #000e26, #000e26, #000e26, #000e26, #000e26, #000f27, #000f27, #000f27, #000f27, #000f27, #000f27, #000f27, #000f28, #001028, #001028, #001028, #001028, #001028, #001028, #001028, #001029, #001129, #001129, #001129, #001129, #001129, #001129, #00112a, #00112a, #00122a, #00122a, #00122a, #00122a, #00122a, #00122b, #00122b, #00122b, #00132b, #00132b, #00132b, #00132b, #00132c, #00132c, #00132c, #00132c, #00142c, #00142c, #00142c, #00142d, #00142d, #00142d, #00142d, #00142d, #00142d, #00152d, #00152e, #00152e, #00152e, #00152e, #00152e, #00152e, #00152e, #00152f, #00162f, #00162f, #00162f, #00162f, #00162f, #00162f, #001630, #001630, #001630, #001730, #001730, #001730, #001730, #001731, #001731, #001731, #001731, #001731, #001831, #001831, #001832, #001832, #001832, #001832, #001832, #001832, #001833, #001833, #001933, #001933, #001933, #001933, #001933, #001934, #001934, #001934, #001934, #001934, #001a34, #001a34, #001a35, #001a35, #001a35, #001a35, #001a35, #001a35, #001a35, #001a36, #001b36, #001b36, #001b36, #001b36, #001b36, #001b36, #001b36, #001b37, #001b37, #001b37, #001c37, #001c37, #001c37, #011c37, #011c38, #011c38, #011c38, #011c38, #011c38, #011c38, #011d38, #011d39, #011d39, #011d39, #011d39, #011d39, #011d39, #011d39, #011d39, #011e3a, #021e3a, #021e3a, #021e3a, #021e3a, #021e3a, #021e3a, #021e3b, #021e3b, #021e3b, #021f3b, #021f3b, #021f3b, #031f3b, #031f3b, #031f3c, #031f3c, #031f3c, #031f3c, #03203c, #03203c, #03203c, #04203c, #04203d, #04203d, #04203d, #04203d, #04203d, #05203d, #05213d, #05213d, #05213e, #05213e, #05213e, #06213e, #06213e, #06213e, #06213e, #07213e, #07223f, #07223f, #08223f, #08223f, #08223f, #09223f, #09223f, #09223f, #0a223f, #0a2240, #0b2240, #0b2340, #0c2340, #0c2340, #0c2340, #0d2340, #0d2340, #0e2341, #0e2341, #0f2341, #102341, #102341, #112341, #112441, #122442, #122442, #132442, #142442, #142442, #152442, #162442, #162442, #172443, #182443, #182443, #192443, #1a2443, #1a2443, #1b2544, #1c2544, #1c2544, #1d2544, #1e2544, #1f2544, #1f2545, #202545, #212545, #222545, #232545, #232545, #242546, #252546, #262546, #272546, #272546, #282546, #292547, #2a2547, #2b2647, #2c2647, #2c2647, #2d2648, #2e2648, #2f2648, #302648, #312648, #322649, #332649, #342649, #352649, #352649, #36264a, #37264a, #38264a, #39264a, #3a264a, #3b264b, #3c264b, #3d264b, #3e264b, #3f264b, #40264c, #41264c, #42264c, #43264c, #44264c, #45264d, #46264d, #47264d, #48264d, #49264d, #4a264e, #4a264e, #4b264e, #4c264e, #4d264e, #4e264e, #4f264f, #50264f, #51264f, #52264f, #53264f, #542650, #552650, #562650, #572650, #582650, #592650, #5a2651, #5b2651, #5c2751, #5d2751, #5e2751, #5f2751, #602751, #612752, #622752, #632752, #642752, #652752, #662752, #672752, #682752, #692753, #6a2753, #6b2753, #6c2753, #6d2753, #6e2753, #6f2753, #702753, #712753, #722754, #732754, #742854, #752854, #752854, #762854, #772854, #782854, #792854, #7a2854, #7b2854, #7c2854, #7d2854, #7e2954, #7f2954, #802954, #812955, #812955, #822955, #832955, #842955, #852a55, #862a55, #872a55, #882a55, #882a55, #892a55, #8a2b55, #8b2b55, #8c2b55, #8d2b55, #8e2b55, #8e2b55, #8f2c55, #902c55, #912c55, #922c55, #932c55, #932d55, #942d55, #952d54, #962d54, #972d54, #972e54, #982e54, #992e54, #9a2e54, #9a2f54, #9b2f54, #9c2f54, #9d2f54, #9d3054, #9e3054, #9f3054, #a03054, #a03154, #a13154, #a23153, #a33153, #a33253, #a43253, #a53253, #a63353, #a63353, #a73353, #a83353, #a83453, #a93453, #aa3452, #aa3552, #ab3552, #ac3552, #ac3652, #ad3652, #ae3652, #ae3752, #af3752, #b03751, #b03751, #b13851, #b13851, #b23851, #b33951, #b33951, #b43950, #b43a50, #b53a50, #b63a50, #b63b50, #b73b50, #b73b4f, #b83c4f, #b83c4f, #b93c4f, #ba3d4f, #ba3d4f, #bb3d4f, #bb3e4e, #bc3e4e, #bc3e4e, #bd3f4e, #bd3f4e, #be3f4e, #bf404d, #bf404d, #c0404d, #c0414d, #c1414d, #c1424d, #c2424d, #c2424c, #c3434c, #c3434c, #c4434c, #c4444c, #c5444c, #c5454c, #c6454b, #c6454b, #c7464b, #c7464b, #c8464b, #c8474b, #c9474a, #c9484a, #ca484a, #ca484a, #cb494a, #cb494a, #cc4a4a, #cc4a49, #cd4a49, #cd4b49, #ce4b49, #ce4c49, #ce4c49, #cf4c49, #cf4d48, #d04d48, #d04e48, #d14e48, #d14e48, #d24f48, #d24f47, #d25047, #d35047, #d35047, #d45147, #d45147, #d55247, #d55246, #d55246, #d65346, #d65346, #d75446, #d75446, #d75446, #d85545, #d85545, #d95645, #d95645, #d95645, #da5745, #da5745, #db5844, #db5844, #db5844, #dc5944, #dc5944, #dc5a44, #dd5a44, #dd5a44, #de5b43, #de5b43, #de5c43, #df5c43, #df5c43, #df5d43, #e05d43, #e05e42, #e05e42, #e15f42, #e15f42, #e15f42, #e26042, #e26042, #e26142, #e36141, #e36141, #e36241, #e46241, #e46341, #e46341, #e56341, #e56441, #e56441, #e66540, #e66540, #e66540, #e76640, #e76640, #e76740, #e86740, #e86840, #e86840, #e86840, #e9693f, #e9693f, #e96a3f, #ea6a3f, #ea6a3f, #ea6b3f, #eb6b3f, #eb6c3f, #eb6c3f, #eb6c3f, #ec6d3e, #ec6d3e, #ec6e3e, #ec6e3e, #ed6f3e, #ed6f3e, #ed6f3e, #ee703e, #ee703e, #ee713e, #ee713e, #ef713e, #ef723e, #ef723e, #ef733d, #f0733d, #f0733d, #f0743d, #f0743d, #f1753d, #f1753d, #f1753d, #f1763d, #f2763d, #f2773d, #f2773d, #f2783d, #f3783d, #f3783d, #f3793d, #f3793d, #f37a3d, #f47a3d, #f47a3d, #f47b3d, #f47b3d, #f57c3d, #f57c3d, #f57c3d, #f57d3c, #f57d3c, #f67e3c, #f67e3c, #f67e3c, #f67f3c, #f67f3c, #f7803c, #f7803c, #f7803c, #f7813c, #f7813d, #f8823d, #f8823d, #f8833d, #f8833d, #f8833d, #f9843d, #f9843d, #f9853d, #f9853d, #f9853d, #fa863d, #fa863d, #fa873d, #fa873d, #fa873d, #fa883d, #fb883d, #fb893d, #fb893d, #fb893d, #fb8a3d, #fb8a3d, #fc8b3d, #fc8b3e, #fc8b3e, #fc8c3e, #fc8c3e, #fc8d3e, #fd8d3e, #fd8e3e, #fd8e3e, #fd8e3e, #fd8f3e, #fd8f3e, #fe903f, #fe903f, #fe903f, #fe913f, #fe913f, #fe923f, #fe923f, #ff923f, #ff9340, #ff9340, #ff9440, #ff9440, #ff9440, #ff9540, #ff9540, #ff9640, #ff9641, #ff9641, #ff9741, #ff9741, #ff9841, #ff9841, #ff9842, #ff9942, #ff9942, #ff9a42, #ff9a42, #ff9b43, #ff9b43, #ff9b43, #ff9c43, #ff9c43, #ff9d43, #ff9d44, #ff9d44, #ff9e44, #ff9e44, #ff9f45, #ff9f45, #ff9f45, #ffa045, #ffa045, #ffa146, #ffa146, #ffa146, #ffa246, #ffa247, #ffa347, #ffa347, #ffa347, #ffa448, #ffa448, #ffa548, #ffa548, #ffa549, #ffa649, #ffa649, #ffa749, #ffa74a, #ffa74a, #ffa84a, #ffa84b, #ffa94b, #ffa94b, #ffa94b, #ffaa4c, #ffaa4c, #ffab4c, #ffab4d, #ffab4d, #ffac4d, #ffac4e, #ffad4e, #ffad4e, #ffae4f, #ffae4f, #ffae4f, #ffaf4f, #ffaf50, #ffb050, #ffb050, #ffb051, #ffb151, #ffb152, #ffb252, #ffb252, #ffb253, #ffb353, #ffb353, #ffb454, #ffb454, #ffb454, #ffb555, #ffb555, #ffb655, #ffb656, #ffb656, #ffb757, #ffb757, #ffb857, #ffb858, #ffb858, #ffb959, #ffb959, #ffba59, #ffba5a, #ffba5a, #ffbb5b, #ffbb5b, #ffbb5b, #ffbc5c, #ffbc5c, #ffbd5d, #ffbd5d, #ffbd5d, #ffbe5e, #ffbe5e, #ffbf5f, #ffbf5f, #ffbf60, #ffc060, #ffc060, #ffc161, #ffc161, #ffc162, #ffc262, #ffc263, #ffc363, #ffc364, #ffc364, #ffc464, #ffc465, #ffc565, #ffc566, #ffc566, #ffc667, #ffc667, #ffc768, #ffc768, #ffc769, #ffc869, #ffc86a, #ffc86a, #ffc96b, #ffc96b, #ffca6c, #ffca6c, #ffca6d, #ffcb6d, #ffcb6e, #ffcc6e, #ffcc6f, #ffcc6f, #ffcd70, #ffcd70, #ffce71, #ffce71, #ffce72, #ffcf72, #ffcf73, #ffcf73, #ffd074, #ffd074, #ffd175, #ffd175, #ffd176, #ffd276, #ffd277, #ffd377, #ffd378, #ffd378, #ffd479, #ffd47a, #ffd47a, #ffd57b, #ffd57b, #ffd67c, #ffd67c, #ffd67d, #ffd77d, #ffd77e, #ffd77e, #ffd87f, #ffd880, #ffd980, #ffd981, #ffd981, #ffda82, #ffda82, #ffda83, #ffdb84, #ffdb84, #ffdc85, #ffdc85, #ffdc86, #ffdd87, #ffdd87, #ffdd88, #ffde88, #ffde89, #ffdf89, #ffdf8a, #ffdf8b, #ffe08b, #ffe08c, #ffe08c, #ffe18d, #ffe18e, #ffe28e, #ffe28f, #ffe28f, #ffe390, #ffe391, #ffe391, #ffe492, #ffe493, #ffe493, #ffe594, #ffe594, #ffe695, #ffe696, #ffe696, #ffe797, #ffe798, #ffe798, #ffe899, #ffe89a, #ffe89a, #ffe99b, #ffe99b, #ffe99c, #ffea9d, #ffea9d, #ffeb9e, #ffeb9f, #ffeb9f, #ffeca0, #ffeca1, #ffeca1, #ffeda2, #ffeda3, #ffeda3, #ffeea4, #ffeea5, #ffeea5, #ffefa6, #ffefa7, #ffefa8, #fff0a9, #fff0a9, #fff0aa, #fff1ab, #fff1ac, #fff1ad, #fff2ae, #fff2ae, #fff3af, #fff3b0, #fff3b1, #fff4b2, #fff4b3, #fff4b4, #fff5b5, #fff5b6, #fff5b7, #fff6b8, #fff6b9, #fff6ba, #fff7bb, #fff7bc, #fff7bd, #fff7be, #fff8bf, #fff8c0, #fff8c2, #fff9c3, #fff9c4, #fff9c5, #fffac7, #fffac8, #fffac9, #fffbcb, #fffbcc, #fffbcd, #fffbcf, #fffcd0, #fffcd2, #fffcd3, #fffdd5, #fffdd7, #fffdd9, #fffdda, #fffedc, #fffede, #fffee0, #fffee2, #ffffe5, #ffffe7 | |
) | |
;width:100%;height:100%"></div> | |
</foreignObject> | |
</svg> | |
` | |
let i = new Image() | |
i.src = URL.createObjectURL(new Blob([svg], {type:'image/svg+xml'})) | |
return new Promise((resolve, reject) => { | |
i.onload = () => { | |
let linMix = (a, b, k) => (1-k)*a + k*b | |
const lfunc = (x, lowValDeEmph_a = 1, lowValDeEmph_b = 0) => (1 - ((1 - Math.cos(Math.PI*(x - 1)))*0.5)**(2**lowValDeEmph_a))**((1+lowValDeEmph_a**(-lowValDeEmph_b))**1) | |
for (let j = 0, x0 = 0; j < 256; j++, x0 = j/255) { | |
let x = x0//**0.85 | |
ctx.drawImage(i, Math.min(x*255,255)*4, 0, 4, 256, j, 0, 1, 256) | |
} | |
let idata = ctx.getImageData(0,0,256,1) | |
let colormap = new Array(256).fill(0).map((x, i) => new Array(4).fill(0).map((y,j)=>idata.data[i*4+j])) | |
resolve(colormap) | |
} | |
}) | |
} | |
async function injectScript(colormapGen) { | |
let colormap = await colormapGen() | |
let f | |
if ((globalThis.unsafeWindow||window).wf?.custom_colormaps) { | |
f = function(colormap) { | |
window.wf.custom_colormaps[3] = Uint8Array.from(colormap.map(x => x.slice(0,3)).flat()) | |
w3_call('wf_cmap_cb', 'wf.cmap', '9', false, 'undefined') | |
} | |
} else if ((globalThis.unsafeWindow||window).spectrumWaterfall?.colormap) { | |
f = function(colormap) { | |
window.spectrumWaterfall.colormap = colormap.map(x => Uint8ClampedArray.from(x)) | |
} | |
} | |
if (window.mozInnerScreenX) { | |
//Firefox | |
GM_addElement('script', { | |
src: URL.createObjectURL( | |
new Blob([`!${f}(${JSON.stringify(colormap)});document.currentScript.remove()`],{type:'application/javascript'}) | |
) | |
}); | |
} else { | |
GM_addElement('script', { | |
textContent: `!${f}(${JSON.stringify(colormap)});document.currentScript.remove()` | |
}); | |
} | |
} | |
GM_registerMenuCommand('Apply Custom Color Map 5.1', ()=>injectScript(colormapV51)) | |
//GM_registerMenuCommand('Apply Custom Color Map 5.2', ()=>injectScript(colormapV52)) | |
GM_registerMenuCommand('Apply Custom Color Map 5.3', ()=>injectScript(colormapV53)) | |
GM_registerMenuCommand('Apply Custom Color Map 5.4', ()=>injectScript(colormapV54)) | |
//GM_registerMenuCommand('Apply Custom Color Map 5.4.4', ()=>injectScript(colormapV544)) | |
//GM_registerMenuCommand('Apply Custom Color Map 6.1', ()=>injectScript(colormapV6)) | |
GM_registerMenuCommand('Apply Custom Color Map 6.2', ()=>injectScript(colormapV62)) | |
GM_registerMenuCommand('Apply Custom Color Map 7', ()=>injectScript(colormapV7)) | |
GM_registerMenuCommand('Apply Custom Color Map 7.2', ()=>injectScript(colormapV72)) | |
GM_registerMenuCommand('Apply Custom Color Map 7.3', ()=>injectScript(colormapV73)) | |
GM_registerMenuCommand('Apply Custom Color Map 7.4', ()=>injectScript(colormapV74)) | |
//window.setTimeout(injectScript, 2000, inject4, sliders.map(x=>x.value)) | |
// AUDIORECORDING | |
/*let m = new MediaRecorder(spectrumAudio.destinationNode._nativeAudioNode.stream) | |
let chunks = [] | |
m.ondataavailable = (e) => { | |
chunks.push(e.data); | |
//console.log(e) | |
} | |
m.start(2000)*/ | |
window.addEventListener('SDRReadyForColormapInjection', ()=> { | |
let w = globalThis.unsafeWindow || window | |
if (w.spectrumWaterfall) { | |
let buffer = new Uint8ClampedArray() | |
const max = (a, b) => a < b ? b : a | |
const wf_w = spectrumWaterfall.canvasElem.width | |
//const colorarr = new Uint8Array(wf_w*4); | |
let autoAdjust = false | |
spectrumWaterfall.drawWaterfallLine = function(arr, pxL, pxR, line, ctx){ | |
//pxL = 0, pxR = 1000 | |
//pxL = Math.floor(pxL); | |
//pxR = Math.ceil(pxR); | |
line = Math.floor(line); | |
const width = pxR - pxL; | |
const arr_l_unclipped = Math.floor(-pxL * arr.length / width) | |
const arr_l = Math.max(0, arr_l_unclipped) | |
const arr_r = Math.min(arr.length, Math.ceil((wf_w-pxL) * arr.length / width)) | |
const arr_w = arr_r - arr_l | |
const colLength = Math.round(Math.min(pxR, wf_w) - Math.max(pxL, 0)) | |
if (buffer.length < colLength * 4) { | |
buffer = new Uint8ClampedArray(colLength * 4) | |
} | |
const colorarr = buffer.subarray(0, colLength * 4) | |
if (colLength > arr_w) { | |
const scale = colLength/arr_w | |
let z = 0, j = 0 | |
for (let i = 0; i < arr_w; i++) { | |
const w = Math.round(scale*i+ 1e-8) | |
const x = spectrumWaterfall.colormap[arr[arr_l+i]] | |
do { | |
colorarr[j++] = x[0]; | |
colorarr[j++] = x[1]; | |
colorarr[j++] = x[2]; | |
colorarr[j++] = x[3]; | |
} while (z++ < w) | |
} | |
} else { | |
const scale = arr_w/colLength | |
let z = arr_l, j = 0 | |
for (let i = 0; i < colLength; i++) { | |
const w = Math.round(scale*i)+arr_l | |
let y = 0 | |
do { | |
y = max(y, arr[z]) | |
} while (z++ < w); | |
const x = spectrumWaterfall.colormap[y] | |
colorarr[j++] = x[0]; | |
colorarr[j++] = x[1]; | |
colorarr[j++] = x[2]; | |
colorarr[j++] = x[3]; | |
} | |
} | |
const idata = new ImageData(colorarr, colLength) | |
ctx.putImageData(idata, Math.round(Math.max(pxL, 0)), ctx.canvas.height - 1 - line) | |
}; | |
const calculateOffsetsOrig = spectrumWaterfall.calculateOffsets | |
//spectrumWaterfall.accumulateAdjustmentData = ()=>{} | |
spectrumWaterfall.calculateOffsets = function(arr, x, y) { | |
if (autoAdjust) { | |
console.debug(arr) | |
autoAdjust = false | |
const avg = arr.reduce((a,x) => a+x) / arr.length | |
const std = (arr.reduce((a,x) => a+(x - avg)**2) / arr.length)**0.5 | |
let low = arr.filter(x => x < avg) | |
const lowAvg = low.reduce((a,x) => a+x, 0) / low.length | |
const lowStd = (low.reduce((a,x) => a+(x - lowAvg)**2, 0) / low.length)**0.5 | |
let high = arr.filter(x => x > avg+std) | |
const highAvg = high.reduce((a,x) => a+x, 0) / high.length | |
const highStd = (high.reduce((a,x) => a+(x - highAvg)**2, 0) / high.length)**0.5 | |
const lowOffset = lowAvg-lowStd-0.5*std | |
const highOffset = Math.max(avg + lowOffset - highAvg+2*highStd, 70)//+std*Math.max(0, avg-0.5*(highAvg+lowAvg))**0.1 | |
spectrumWaterfall.setMinOffset(lowOffset) | |
spectrumWaterfall.setMaxOffset(highOffset) | |
console.log({lowOffset, highOffset, avg, lowAvg, highAvg, std, lowStd, highStd}) | |
} | |
return calculateOffsetsOrig.apply(this, arguments) | |
} | |
GM_registerMenuCommand('Auto Adjust', () => {autoAdjust = true}) | |
} | |
injectScript(colormapV74) | |
}) | |
let tryInject = true | |
let timer = window.setInterval(()=>{ | |
let w = globalThis.unsafeWindow || window | |
if (tryInject) { | |
console.log('trying to inject'); | |
if (w.spectrumWaterfall) { | |
//phantomSDR | |
let then | |
if ((then = w.spectrumWaterfall?.promise?.then)) { | |
then.call(w.spectrumWaterfall.promise, x => { | |
w.clearInterval(timer) | |
let e = new Event('SDRReadyForColormapInjection') | |
w.dispatchEvent(e) | |
}) | |
tryInject = false | |
} | |
} else if (w.wf?.custom_colormaps) { | |
//kiwiSDR | |
w.clearInterval(timer) | |
let e = new Event('SDRReadyForColormapInjection') | |
w.dispatchEvent(e) | |
} | |
} else { | |
w.clearInterval(timer) | |
} | |
}, 500) | |
window.setTimeout(()=>{tryInject = false}, 15e3) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment