-
Notifications
You must be signed in to change notification settings - Fork 0
/
Easy Compare.user.min.js
42 lines (42 loc) · 24.8 KB
/
Easy Compare.user.min.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// ==UserScript==
// @name Easy Compare
// @description Compare images
// @version 0.9.5
// @author Secant (TYT@NexusHD)
// @license GPL-3.0-or-later
// @supportURL zzwu@zju.edu.cn
// @contributionURL https://i.loli.net/2020/02/28/JPGgHc3UMwXedhv.jpg
// @contributionAmount 10
// @include *
// @require https://cdn.staticfile.org/jquery/3.4.1/jquery.min.js
// @require https://greasyfork.org/scripts/401377-pixelmatch/code/pixelmatch.js
// @resource PixelMatchCore https://greasyfork.org/scripts/401377-pixelmatch/code/pixelmatch.js
// @namespace https://greasyfork.org/users/152136
// @icon data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23008000'%3E%3Cpath id='ld' d='M20 6H10c-2.21 0-4 1.79-4 4v28c0 2.21 1.79 4 4 4h10v4h4V2h-4v4zm0 30H10l10-12v12zM38 6H28v4h10v26L28 24v18h10c2.21 0 4-1.79 4-4V10c0-2.21-1.79-4-4-4z'/%3E%3C/svg%3E
// @grant GM_xmlhttpRequest
// @grant GM_download
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_getResourceText
// @grant unsafewindow
// @connect hdbits.org
// @connect awesome-hd.me
// @connect ptpimg.me
// @connect imgbox.com
// @connect malzo.com
// @connect imagebam.com
// @connect pixhost.to
// @connect loli.net
// @connect funkyimg.com
// @connect ilikeshots.club
// @connect z4a.net
// @connect picgd.com
// @connect tu.totheglory.im
// @connect tpimg.ccache.org
// @connect pterclub.com
// @connect catbox.moe
// @connect sm.ms
// @connect broadcasthe.net
// @connect *
// ==/UserScript==
!async function($,Mousetrap,pixelmatch,URL){"use strict";if(Mousetrap){let target=Mousetrap.prototype||Mousetrap;const _originalStopCallback=target.stopCallback;target.stopCallback=function(e,element,combo){var self=this;return!!this.paused||_originalStopCallback.call(this,e,element,combo)},target.pause=function(){var self=this;this.paused=!0},target.unpause=function(){var self=this;this.paused=!1};try{Mousetrap.init()}catch(_){}}let timeout,scale=10;const t2oLib=[[/\.thumb\.jpe?g$/,""],[/\.md\.png$/,".png"],[/\.th\.png$/,".png"],[/_thumb\.png$/,".png"],[/img\.awesome\-hd\.me\/t(\/\d+)?\//,"img.awesome-hd.me/images/"],[/thumbs((?:\d+)?\.imgbox\.com\/.+_)t\.png$/,"images$1o.png"],[/t((?:\d+)?\.pixhost\.to\/)thumbs\//,"img$1images/"],[/t(\.hdbits\.org\/.+)\.jpg$/,"i$1.png"],[/^.*?imagecache\.php\?url=(https?)%3A%2F%2Fthumbs(\d+)?\.imgbox\.com%2F(\w+)%2F(\w+)%2F(\w+)_t\.png/,"$1://images$2.imgbox.com/$3/$4/$5_o.png"]],skipRedirLib=[[/^https?:\/\/anonym\.to\/\?(.*)$/,(_,p1)=>decodeURIComponent(p1)],[/^https?:\/\/www\.dereferer\.org\/\?(.*)$/,(_,p1)=>decodeURIComponent(p1)],[/^(?:https?:\/\/pterclub\.com)?\/link\.php\?sign=.+?&target=(.*)$/,(_,p1)=>decodeURIComponent(p1.replace(/\+/g," ")).replace(/ /g,"%20")],[/^.*?imagecache\.php\?url=(.*)$/,(_,p1)=>decodeURIComponent(p1.replace(/\+/g," ")).replace(/ /g,"%20")]],guessSelectorLib=["#image-viewer-container>img",".image-container img","div.img.big>img","img.mainimage","img.main-image","img#img"],filterImage={solar:img=>rgbImage(img,solarWorker||rgbSolarCurve),s2lar:img=>rgbImage(img,s2larWorker||rgbS2larCurve)};function solarCurve(x,t=5,k=5.5){const m=k*Math.PI-128/t,A=-1/4194304*m,B=3/32768*m,C=1/t;return Math.round(127.9999*Math.sin(A*x**3+B*x**2+C*x-Math.PI/2)+127.5)||0}let rgbSolarCurve=GM_getValue("solarCurve"),rgbS2larCurve=GM_getValue("s2larCurve"),diffWorker,solarWorker,s2larWorker,loadBufferPromise;async function loadBuffer(worker,[R,G,B]){return new Promise(resolve=>{worker.onmessage=e=>{resolve(e.data.result)},worker.postMessage({R:R.buffer,G:G.buffer,B:B.buffer},[R.buffer,G.buffer,B.buffer])})}function diffWork(f){f.apply(self);const u=Uint8ClampedArray;self.onmessage=({data:{key:key,img1:img1,img2:img2,width:width,height:height,init:init}})=>{img1=new u(img1),img2=new u(img2);const diff=new u(img1);try{self.pixelmatch(img1,img2,diff,width,height,init),self.postMessage({diff:diff.buffer,width:width,height:height,key:key},[diff.buffer])}catch(err){console.warn(err),self.postMessage({diff:null,key:key})}}}function rgbWork(f){const u=Uint8ClampedArray;self.onmessage=({data:{key:key,R:R,G:G,B:B,img:img,width:width,height:height}})=>{if(R&&G&&B)self.RGB=[new u(R),new u(G),new u(B)],self.postMessage({result:!0});else{img=new u(img);const filter=new u(img);try{f.apply(self,[img,filter,width,height,self.RGB]),self.postMessage({filter:filter.buffer,width:width,height:height,key:key},[filter.buffer])}catch(err){console.warn(err),self.postMessage({filter:null,key:key})}}}}function stringifyWork(workFun,arg){return`(${workFun.toString()})(${arg})`}rgbSolarCurve?(rgbSolarCurve=JSON.parse(rgbSolarCurve),rgbS2larCurve=JSON.parse(rgbS2larCurve)):(rgbSolarCurve=[Array.from({length:256},(_,x)=>solarCurve(x)),Array.from({length:256},(_,x)=>solarCurve(x-5)),Array.from({length:256},(_,x)=>solarCurve(x+5))],GM_setValue("solarCurve",JSON.stringify(rgbSolarCurve)),rgbS2larCurve=[Array.from({length:256},(_,x)=>rgbSolarCurve[0][[rgbSolarCurve[0][x]]]),Array.from({length:256},(_,x)=>rgbSolarCurve[1][[rgbSolarCurve[1][x]]]),Array.from({length:256},(_,x)=>rgbSolarCurve[2][[rgbSolarCurve[2][x]]])],GM_setValue("s2larCurve",JSON.stringify(rgbS2larCurve))),rgbSolarCurve=rgbSolarCurve.map(e=>new Uint8Array(e)),rgbS2larCurve=rgbS2larCurve.map(e=>new Uint8Array(e));try{const diffWorkerBlob=new Blob([stringifyWork(diffWork,new Function(GM_getResourceText("PixelMatchCore")))],{type:"application/javascript"});diffWorker=new Worker(URL.createObjectURL(diffWorkerBlob)),diffWorker.keyPool={},URL.revokeObjectURL(diffWorkerBlob);const rgbWorkerBlob=new Blob([stringifyWork(rgbWork,rgbRemap)],{type:"application/javascript"}),rgbWorkerURL=URL.createObjectURL(rgbWorkerBlob);solarWorker=new Worker(rgbWorkerURL),solarWorker.keyPool={};const transSo=loadBuffer(solarWorker,rgbSolarCurve);s2larWorker=new Worker(rgbWorkerURL),s2larWorker.keyPool={};const transS2=loadBuffer(s2larWorker,rgbS2larCurve);URL.revokeObjectURL(rgbWorkerURL),loadBufferPromise=Promise.all([transSo,transS2])}catch(e){try{const diffWorkerDataURI=`data:application/javascript,${encodeURIComponent(stringifyWork(diffWork,new Function(GM_getResourceText("PixelMatchCore"))))}`;diffWorker=new Worker(diffWorkerDataURI),diffWorker.keyPool={};const rgbWorkerDataURI=`data:application/javascript,${encodeURIComponent(stringifyWork(rgbWork,rgbRemap))}`;solarWorker=new Worker(rgbWorkerDataURI),solarWorker.keyPool={};const transSo=loadBuffer(solarWorker,rgbSolarCurve);s2larWorker=new Worker(rgbWorkerDataURI),s2larWorker.keyPool={};const transS2=loadBuffer(s2larWorker,rgbS2larCurve);loadBufferPromise=Promise.all([transSo,transS2])}catch(e){diffWorker=null,solarWorker=null}}function $$(htmlString){return $(htmlString,document.implementation.createHTMLDocument("virtual"))}function makeCanvas(outlineColor="red"){const $figure=$("<figure/>").css({width:"fit-content",position:"fixed",top:"50%",left:"50%",margin:"0","vertical-align":"middle"}),$canvas=$("<canvas/>").css({display:"none",transform:"translate(-50%, -50%)",opacity:"1",outline:"3px solid "+outlineColor,"outline-offset":"2px"});return $figure.append($canvas),$canvas[0]}function drawText(canvas,text,font="16px sans serif",fillStyle="rgba(255,255,255,255)"){const context=canvas.getContext("2d");context.font=font,canvas.width=context.measureText(text).width,canvas.height=20,context.font=font,context.fillStyle=fillStyle,context.fillText(text,0,15)}function drawImage(canvas,imageData){canvas.width=imageData.width,canvas.height=imageData.height,canvas.getContext("2d").putImageData(imageData,0,0)}function guessOriginalImage(url){return new Promise(resolve=>{GM_xmlhttpRequest({url:url,method:"GET",timeout:6e3,onload:x=>{if(200===x.status)try{const $e=$$(x.responseText),src=$e.find(guessSelectorLib.join(","))[0].src;let realSrc=src;for(let pairs of t2oLib)if(realSrc=realSrc.replace(pairs[0],pairs[1]),realSrc!==src)break;resolve(realSrc)}catch(e){console.warn(e),resolve(null)}else console.warn(x),resolve(null)},ontimeout:e=>{console.warn(e),resolve(null)}})})}function rgbRemap(raw,filter,width,height,rgb){const[R,G,B]=rgb;for(let row=0;row<height;++row)for(let col=0;col<width;++col){let ind=4*col+row*width*4;filter[ind]=R[raw[ind]],filter[ind+1]=G[raw[ind+1]],filter[ind+2]=B[raw[ind+2]],filter[ind+3]=raw[ind+3]}}async function GM_getImageData(src,fn){return new Promise(resolve=>{GM_xmlhttpRequest({url:src,method:"GET",overrideMimeType:"text/plain; charset=x-user-defined",onprogress:e=>{"function"==typeof fn&&(-1!==e.total?fn(e.loaded/e.total):fn(-e.loaded))},onload:e=>{if(200===e.status){const imageResponseText=e.responseText,l=imageResponseText.length,bytes=new Uint8Array(l);for(let i=0;i<l;i++)bytes[i]=255&imageResponseText.charCodeAt(i);const type=(e.responseHeaders.match(/content\-type: *(.+)$/m)||["","image/png"])[1];let ext;switch(type){case"image/apng":ext=".apng";break;case"image/bmp":ext=".bmp";break;case"image/gif":ext=".gif";break;case"image/x-icon":ext=".ico";break;case"image/jpeg":ext=".jpg";break;case"image/png":ext=".png";break;case"image/svg+xml":ext=".svg";break;case"image/tiff":ext=".tiff";break;case"image/webp":ext=".webp";break;default:if("image"===type.slice(0,5)){let temp=type.match(/\/(.*)/);ext=temp?"."+temp:""}else ext=(src.match(/\.[^\.]+$/)||[""])[0]}createImageBitmap(new Blob([bytes],{type:type})).then(e=>{const[width,height]=[e.width,e.height],canvas=document.createElement("canvas");canvas.width=width,canvas.height=height;const context=canvas.getContext("2d");context.drawImage(e,0,0),e.close(),resolve({imageData:new ImageData(context.getImageData(0,0,width,height).data,width,height),extension:ext})})}else console.warn(e),resolve(null)},onerror:e=>{console.warn(e),resolve(null)}})})}async function diffImage(img1,img2,init={alpha:.5,threshold:.007},worker=diffWorker){if(img1&&img2&&img1.width===img2.width&&img1.height===img2.height){if(worker){const[raw1,raw2,width,height]=[img1.data.buffer,img2.data.buffer,img1.width,img1.height],key=""+Date.now();return worker.onmessage=e=>{const returnKey=e.data.key,resolve=worker.keyPool[returnKey];resolve&&resolve(new ImageData(new Uint8ClampedArray(e.data.diff),e.data.width,e.data.height))},worker.postMessage({img1:raw1,img2:raw2,width:width,height:height,init:init,key:key},[raw1,raw2]),new Promise(res=>{worker.keyPool[key]=res})}{const[data1,data2,width,height]=[img1.data,img2.data,img1.width,img1.height],res=new Uint8ClampedArray(data1);return pixelmatch(data1,data2,res,width,height,init),new ImageData(res,width,height)}}return null}async function rgbImage(img,argument){if(img){if(argument instanceof Worker){const worker=argument,[raw,width,height]=[img.data.buffer,img.width,img.height],key=""+Date.now();return worker.onmessage=e=>{const returnKey=e.data.key,resolve=worker.keyPool[returnKey];resolve&&resolve(new ImageData(new Uint8ClampedArray(e.data.filter),e.data.width,e.data.height))},await loadBufferPromise,worker.postMessage({img:raw,width:width,height:height,key:key},[raw]),new Promise(res=>{worker.keyPool[key]=res})}{const rgb=argument,[data,width,height]=[img.data,img.width,img.height],res=new Uint8ClampedArray(data);return rgbRemap(data,res,width,height,rgb),new ImageData(res,width,height)}}return null}function getOriginalImage(target,$overlay){if(target.easyCompare&&target.easyCompare.originalImage){const originalImage=target.easyCompare.originalImage;return originalImage.ready&&(originalImage.style.width=`${10*scale}%`),originalImage}{const originalCanvas=makeCanvas(),updateProgress=p=>{let text;null!==p&&p>=0?drawText(originalCanvas,`Loading ${(100*p).toFixed(1)}%`):p<0&&drawText(originalCanvas,"Loading...")},resolveOriginal=(src,onprogress,resolve)=>{GM_getImageData(src,onprogress).then(({imageData:originalImageData,extension:extension})=>{resolve(originalImageData),originalCanvas.src=src,originalCanvas.ext=extension,drawImage(originalCanvas,originalImageData),originalCanvas.style.width=`${10*scale}%`,originalCanvas.ready=!0})};return drawText(originalCanvas,"Loading..."),originalCanvas.ready=!1,originalCanvas.targetImage=target,$overlay.append(originalCanvas.parentElement),target.easyCompare||(target.easyCompare={}),target.easyCompare.originalImage=originalCanvas,target.easyCompare.originalImagePromise=onprogress=>new Promise(async resolve=>{let realSrc=target.src,href,hrefOriginal;for(let pairs of t2oLib)if(realSrc=realSrc.replace(pairs[0],pairs[1]),realSrc!==target.src)return void resolveOriginal(realSrc,onprogress,resolve);if(hrefOriginal=target.parentElement.href,href=hrefOriginal){for(let pairs of skipRedirLib)if(href=href.replace(pairs[0],pairs[1]),href!==hrefOriginal)break;href.match(/\.png$|\.jpe?g$|\.webp|\.gif|\.bmp|\.svg$/)?resolveOriginal(href,onprogress,resolve):guessOriginalImage(href).then(src=>{resolveOriginal(src||realSrc,onprogress,resolve)})}else resolveOriginal(realSrc,onprogress,resolve)}),target.easyCompare.originalImagePromise(updateProgress),originalCanvas}}function getDiffedImage(target,base,$overlay){if(target.src===base.src)return getOriginalImage(target);if(target.easyCompare&&target.easyCompare[base.src]){target.easyCompare[base.src].targetImage=target,target.easyCompare[base.src].baseImage=base;const diffedCanvas=target.easyCompare[base.src];return diffedCanvas.ready&&(diffedCanvas.style.width=`${10*scale}%`),diffedCanvas}{const diffedCanvas=makeCanvas();drawText(diffedCanvas,"Loading..."),diffedCanvas.ready=!1,diffedCanvas.targetImage=target,diffedCanvas.baseImage=base,diffedCanvas.threshold=-1,diffedCanvas.step=.001,$overlay.append(diffedCanvas.parentElement),target.easyCompare||(target.easyCompare={}),target.easyCompare[base.src]=diffedCanvas,base.easyCompare||(base.easyCompare={}),base.easyCompare[target.src]=diffedCanvas;let progress=[0,0];const updateProgress=(p,ind)=>{null!==p&&p>=0&&null!==ind?(progress[ind]=p,drawText(diffedCanvas,`Loading ${(50*(progress[0]+progress[1])).toFixed(1)}%`)):drawText(diffedCanvas,p<0?"Loading...":"Diffing...")};return getOriginalImage(target,$overlay),getOriginalImage(base,$overlay),Promise.all([target.easyCompare.originalImagePromise(p=>updateProgress(p,0)),base.easyCompare.originalImagePromise(p=>updateProgress(p,1))]).then(imageData=>(updateProgress(null,null),diffImage(...imageData,{alpha:.5,threshold:.007}))).then(diffedImageData=>{null===diffedImageData?drawText(diffedCanvas,"Sizes Not Match"):(drawImage(diffedCanvas,diffedImageData),diffedCanvas.ext=".png",diffedCanvas.threshold=.007,diffedCanvas.style.width=`${10*scale}%`,diffedCanvas.ready=!0)}).catch(err=>{console.warn(err),drawText(diffedCanvas,"Something Went Wrong")}),diffedCanvas}}function getFilteredImage(target,ftType,$overlay){if(target.easyCompare&&target.easyCompare[ftType]){const filteredCanvas=target.easyCompare[ftType];return filteredCanvas.ready&&(filteredCanvas.style.width=`${10*scale}%`),filteredCanvas}{const filteredCanvas=makeCanvas();drawText(filteredCanvas,"Loading..."),filteredCanvas.ready=!1,filteredCanvas.targetImage=target,$overlay.append(filteredCanvas.parentElement),target.easyCompare||(target.easyCompare={}),target.easyCompare[ftType]=filteredCanvas;const updateProgress=p=>{drawText(filteredCanvas,null!==p&&p>=0?`Loading ${(100*p).toFixed(1)}%`:p<0?"Loading...":"Filtering...")};return getOriginalImage(target,$overlay),target.easyCompare.originalImagePromise(updateProgress).then(imageData=>(updateProgress(null),filterImage[ftType](imageData))).then(filterdImageData=>{drawImage(filteredCanvas,filterdImageData),filteredCanvas.ext=".png",filteredCanvas.style.width=`${10*scale}%`,filteredCanvas.ready=!0}),filteredCanvas}}function getActive($overlay){return $overlay.find("canvas:visible")}function activateCompare($target){$target.attr({fill:"#008000"}).css({cursor:"pointer",opacity:"1"})[0].state=!0}function leaveImage($overlay,target){const original=getActive($overlay).hide()[0];(original&&(target=original.targetImage)||target)&&target.easyCompare&&void 0!==target.easyCompare.boxShadow&&$(target).css("box-shadow",target.easyCompare.boxShadow)}function enterCompare($overlay,$images,$message){Mousetrap&&Mousetrap.pause(),$overlay.show()[0].state=!0;let colors=["red","blue"],step=1,baseImage,ftType="none",fadingTime=300;function setBaseImage(){try{baseImage=getActive($overlay)[0].targetImage}catch(err){baseImage=void 0,err instanceof TypeError||console.warn(err)}}function downloadImage(name="easycompare"){try{const target=getActive($overlay)[0],url=target.src||target.toDataURL("image/png").replace(/^data:image\/[^;]/,"data:application/octet-stream"),ext=target.ext||"";GM_download({url:url,name:name+ext})}catch(err){err instanceof TypeError||console.warn(err)}}function toggleFilter(filter){ftType=ftType===filter?"none":filter;try{const target=getActive($overlay).hide()[0];let $displayImage;$displayImage=$("none"===ftType?getOriginalImage(target.targetImage,$overlay):getFilteredImage(target.targetImage,ftType,$overlay)),$displayImage.css("outline-color",target.style["outline-color"]).show()}catch(err){err instanceof TypeError||console.warn(err)}}function adjustView(up){try{up&&scale<10?scale+=1:up&&scale<30?scale+=2:!up&&scale>10?scale-=2:!up&&scale>1&&(scale-=1);const target=getActive($overlay)[0];target.ready&&(target.style["image-rendering"]=scale>10?"pixelated":"auto",target.style.width=`${10*scale}%`),$message.text(`Zoom: ${parseInt(10*scale)}%`).css("opacity","1"),setTimeout(()=>{$message.css("opacity","0")},300)}catch(err){err instanceof TypeError||console.warn(err)}}function setView(scl){try{if(scale!==scl){scale=scl;const target=getActive($overlay)[0];target.ready&&(target.style.width=`${10*scale}%`,target.style["image-rendering"]="auto"),$message.text(`Zoom: ${parseInt(10*scale)}%`).css("opacity","1"),setTimeout(()=>{$message.css("opacity","0")},300)}}catch(err){err instanceof TypeError||console.warn(err)}}function adjustThreshold(up){try{const target=getActive($overlay)[0];let threshold=target.threshold;if(void 0!==threshold&&threshold>=0){const thresholdPrev=threshold;$message.text(`Threshold: ${thresholdPrev.toFixed(4)}`).css("opacity","1"),up?(threshold+=target.step,threshold>1&&(threshold=1)):(threshold-=target.step,threshold<0&&(threshold=0)),target.threshold=-1;const[baseCanvas,targetCanvas]=[target.baseImage.easyCompare.originalImage,target.targetImage.easyCompare.originalImage];diffImage(baseCanvas.getContext("2d").getImageData(0,0,baseCanvas.width,baseCanvas.height),targetCanvas.getContext("2d").getImageData(0,0,targetCanvas.width,targetCanvas.height),{alpha:.5,threshold:threshold}).then(imageData=>{target.getContext("2d").putImageData(imageData,0,0),$message.text(`Threshold: ${threshold.toFixed(4)}`).css("opacity","1"),setTimeout(()=>{target.threshold=threshold,$message.css("opacity","0")},300)})}}catch(err){err instanceof TypeError||console.warn(err)}}function adjustStep(left){try{const target=getActive($overlay)[0];let step=target.step;step&&(target.step=left&&step<=.1?10*step:left?1:!left&&step>=.001?step/10:1e-4,$message.text(`Step: ${target.step.toFixed(4)}`).css("opacity","1"),setTimeout(()=>$message.css("opacity","0"),300))}catch(err){err instanceof TypeError||console.warn(err)}}function clearCache(){try{leaveImage($overlay,getActive($overlay)[0].targetImage)}catch(err){err instanceof TypeError||console.warn(err)}$overlay.find("canvas").toArray().forEach(e=>{const target=e.targetImage;delete target.easyCompare,e.parentElement.remove()})}function switchImage(left,shiftKey){try{const targetImage=getActive($overlay)[0].targetImage,index=$images.index(targetImage);leaveImage($overlay,targetImage);const nextElem=$images[left?index-step:index+step]||$images[index];$(nextElem).trigger("mouseenter",[shiftKey])}catch(err){err instanceof TypeError||console.warn(err)}}$images.on("mouseenter.compare",(e,triggeredShiftKey)=>{const target=e.currentTarget;let displayedImage;if(clearTimeout(timeout),leaveImage($overlay),target.easyCompare||(target.easyCompare={},target.easyCompare.boxShadow=target.style["box-shadow"]),$(target).css({"box-shadow":"0px 0px 8px "+colors[0]}),(e.shiftKey||triggeredShiftKey)&&baseImage)displayedImage=$(getDiffedImage(target,baseImage,$overlay)).css("outline-color",colors[0]).show();else switch(ftType){case"none":displayedImage=$(getOriginalImage(target,$overlay)).css("outline-color",colors[0]).show();break;default:displayedImage=$(getFilteredImage(target,ftType,$overlay)).css("outline-color",colors[0]).show()}colors.push(colors.shift())}).on("mouseleave.compare",e=>{const target=e.currentTarget;timeout=setTimeout(()=>{leaveImage($overlay,target)},200)}),$(document).on("scroll.compare",e=>{const temp=getActive($overlay)[0];if(temp){const $prev=$(temp.targetImage);$prev.is(":hover")||(leaveImage($overlay,$prev[0]),$images.find("img:hover").trigger("mousenter"))}}).on("keydown.compare",e=>{switch(e.preventDefault(),e.stopImmediatePropagation(),e.key){case"Escape":exitCompare($overlay,$images);break;case"Shift":setBaseImage();break;case"+":case"=":e.ctrlKey&&adjustView(!0);break;case"-":case"_":e.ctrlKey&&adjustView(!1);break;case"O":case"o":e.ctrlKey&&setView(10);break;case"P":case"p":e.ctrlKey&&setView(30);break;case"S":case"s":e.ctrlKey?downloadImage():toggleFilter("solar");break;case"A":case"a":toggleFilter("s2lar");break;case"I":case"i":e.ctrlKey?setView(1):adjustThreshold(!0);break;case"ArrowUp":adjustThreshold(!0);break;case"K":case"k":case"ArrowDown":adjustThreshold(!1);break;case"J":case"j":case"ArrowLeft":adjustStep(!0);break;case"L":case"l":case"ArrowRight":e.ctrlKey?clearCache():adjustStep(!1);break;case"Q":case"q":$overlay.css("opacity",.5);break;case"1":case"2":case"3":case"4":case"5":case"6":case"7":case"8":case"9":step=parseInt(e.key);break;case"0":step=10;break;case"W":case"w":switchImage(!0,e.shiftKey);break;case"E":case"e":switchImage(!1,e.shiftKey)}return!1}).on("keyup.compare",e=>{switch(e.preventDefault(),e.stopImmediatePropagation(),e.key){case"Q":case"q":$overlay.css("opacity","")}return!1})}function exitCompare($overlay,$images){Mousetrap&&Mousetrap.unpause(),leaveImage($overlay),$overlay.hide()[0].state=!1,$images.off("mouseenter.compare").off("mouseleave.compare"),$(document).off("scroll.compare").off("keydown.compare")}const $message=$("<div>").css({top:"50%",left:"50%","z-index":2147483647,position:"fixed",transform:"translate(-50%, -50%)",opacity:"0","vertical-align":"middle","pointer-events":"none",transition:"all 0.1s","font-size":"500%",color:"yellow","font-weight":"bold"}),$overlay=$("<div/>").css({id:"easy-compare-overlay",position:"fixed",top:0,right:0,bottom:0,left:0,"z-index":2147483646,"background-color":"rgba(0, 0, 0, 0.75)","pointer-events":"none",display:"none"}).append($message),$compareButton=$('<svg xmlns="http://www.w3.org/2000/svg">\n<path id="ld" d="M20 6H10c-2.21 0-4 1.79-4 4v28c0 2.21 1.79 4 4 4h10v4h4V2h-4v4zm0 30H10l10-12v12zM38 6H28v4h10v26L28 24v18h10c2.21 0 4-1.79 4-4V10c0-2.21-1.79-4-4-4z"/>\n</svg>').attr({width:"30",height:"30",viewBox:"0 0 48 48",stroke:"white","stroke-width":"5px",fill:"gray"}).css({position:"fixed",top:"0px",right:"0px",padding:"15px","box-sizing":"content-box","z-index":2147483647,"paint-order":"stroke",opacity:0,transition:"all 0.2s",cursor:"auto"}).on("mouseenter",e=>{const $target=$(e.currentTarget);if($target[0].manualFlag){$target.attr({fill:"gray"}).css({opacity:.2,"pointer-events":"none"}),$target[0].manualFlag=!1;const clientWidth=document.documentElement.clientWidth;$(document).on("mousemove.compare",({clientX:clientX,clientY:clientY})=>{clientX<clientWidth-61||clientY>61?($target[0].insideFlag=0,clearTimeout(timeout),$target.attr({fill:"gray"}).css({cursor:"auto",opacity:0,"pointer-events":"auto"})[0].state=!1,$(document).off("mousemove.compare"),$target[0].manualFlag=!0):clientX>=clientWidth-45&&clientX<=clientWidth-15&&clientY>=15&&clientY<=45?$target[0].insideFlag||($target[0].insideFlag=1,timeout=setTimeout(()=>{activateCompare($target),$target.css({"pointer-events":"auto"})},$overlay[0].state?0:1e3)):(clientX<clientWidth-45||clientX>clientWidth-15||clientY<15||clientY>45)&&($target[0].insideFlag=0,clearTimeout(timeout),$target.attr({fill:"gray"}).css({cursor:"auto",opacity:.2,"pointer-events":"none"})[0].state=!1)})}}).click(e=>{if(e.currentTarget.state)switch($overlay[0].state){case!1:enterCompare($overlay,$(':not("#easy-compare-overlay") img:visible'),$message);break;case!0:exitCompare($overlay,$(':not("#easy-compare-overlay") img:visible'))}else{let x=e.clientX,y=e.clientY;const lowerElement=document.elementsFromPoint(x,y).find(e=>!["svg","path"].includes(e.tagName));lowerElement.click()}}).mousedown(e=>{e.currentTarget.state&&$(e.currentTarget).attr({fill:"#006000"})}).mouseup(e=>{e.currentTarget.state&&$(e.currentTarget).attr({fill:"#008000"})});$compareButton[0].manualFlag=!0,$compareButton[0].insideFlag=!1,$overlay[0].state=!1,$compareButton[0].state=!1,$("body").append($compareButton).append($overlay)}(window.$.noConflict(!0),unsafeWindow.Mousetrap,window.pixelmatch,unsafeWindow.URL.createObjectURL?unsafeWindow.URL:unsafeWindow.webkitURL);