{"version":3,"file":"AutoDitherImage_1.0EAt2a3S.mjs","names":["useRef"],"sources":["https:/framerusercontent.com/modules/dvj4bBRZLLvRChtsJptR/XaVQrbF7dtE1qO0zvulh/AutoDitherImage_1.js"],"sourcesContent":["// AutoDitherImage component for Framer. Dither effect: Bayer 4x4, Grayscale, pixelation, brightness, quantization, resolution adjustable. Effect is pixel-accurate; output is rendered on canvas. Placeholder if no image.\nimport{jsx as _jsx,jsxs as _jsxs}from\"react/jsx-runtime\";import{useRef,useEffect}from\"react\";import{addPropertyControls,ControlType}from\"framer\";const placeholder=\"data:image/svg+xml,%3Csvg width='64' height='64' xmlns='http://www.w3.org/2000/svg'%3E%3Crect fill='%23eee' width='64' height='64'/%3E%3Cpath fill='%23999' d='M21 32a5 5 0 110-10 5 5 0 010 10zm22 13V22l-7 10-7-10-7 10V22m-4 23a4 4 0 01-4-4V27a4 4 0 014-4h40a4 4 0 014 4v18a4 4 0 01-4 4H15z'/%3E%3C/svg%3E\";function clamp(x,min,max){return Math.max(min,Math.min(max,x));}function bayerThreshold(x,y,levels=16){// Bayer 4x4 threshold (Matrix values 0-15):\nconst bayer4=[[0,8,2,10],[12,4,14,6],[3,11,1,9],[15,7,13,5]];return bayer4[y%4][x%4]/(levels-1)// 0.0-1.0\n;}function ditherImage(img,ctx,outW,outH,pixelSize,quant,grayscale,brightness){// Draw the image to match the dither resolution\nctx.clearRect(0,0,outW,outH);ctx.drawImage(img,0,0,img.width,img.height,0,0,outW,outH);let srcData=ctx.getImageData(0,0,outW,outH);let{data}=srcData;// quantize helper\nconst Q=clamp(Math.floor(quant),1,16);for(let y=0;y<outH;y++){for(let x=0;x<outW;x++){let idx=(y*outW+x)*4;let r=data[idx],g=data[idx+1],b=data[idx+2],a=data[idx+3];// brightness boost (range ~[-100,100])\nlet v=grayscale?.299*r+.587*g+.114*b:r// just red channel if not grayscale\n;v=clamp(v+brightness,0,255);if(!grayscale){// Quantize color mode (not grayscale, but user disables it): just use all 3 channels quantized\nconst qMap=[r,g,b].map(c=>{return Math.round(clamp(c+brightness,0,255)/255*(Q-1)+bayerThreshold(x,y,16))/(Q-1)*255;});data[idx]=qMap[0];data[idx+1]=qMap[1];data[idx+2]=qMap[2];continue;}// Grayscale: apply bayer dither\n// remap v -> (Q) gray steps, bayer thresholding\nlet step=Math.round(v/255*(Q-1)+bayerThreshold(x,y,16));step=clamp(step,0,Q-1);let gray=Math.round(step*255/(Q-1));data[idx]=data[idx+1]=data[idx+2]=gray;}}ctx.putImageData(srcData,0,0);// pixelate if required (draw to display canvas)\n}/**\n * AutoDitherImage component\n * @framerSupportedLayoutWidth any-prefer-fixed\n * @framerSupportedLayoutHeight any-prefer-fixed\n */export default function AutoDitherImage(props){const{image={src:\"\",alt:\"\"},pixelation=1,brightness=0,quantization=6,resolution=500,grayscale=true,layout=\"cover\",style={}}=props;const hasImage=!!image?.src;// Main and processing canvases\nconst canvasRef=useRef(null);const procRef=useRef(null);// Effect: update when any prop/image changes\nuseEffect(()=>{const canvas=canvasRef.current;const ctx=canvas&&canvas.getContext(\"2d\");if(!canvas||!ctx)return;// Clamp pixelation\nconst px=Math.max(1,Math.floor(pixelation));const Q=clamp(quantization,1,16);const R=clamp(resolution,16,2048);// load image and draw\nconst imgEl=new window.Image;imgEl.crossOrigin=\"anonymous\";imgEl.src=hasImage?image.src:\"\";imgEl.onload=function(){// scale to match R and preserve aspect ratio\nlet imgW=imgEl.naturalWidth,imgH=imgEl.naturalHeight;let scale=1;if(Math.max(imgW,imgH)>R){scale=R/Math.max(imgW,imgH);}let procW=Math.round(imgW*scale);let procH=Math.round(imgH*scale);// Draw dithered at 1px per pixel at procW x procH\n// Processing canvas (offscreen)\nlet procCv=procRef.current;procCv.width=procW;procCv.height=procH;let procCtx=procCv.getContext(\"2d\");procCtx.imageSmoothingEnabled=false;ditherImage(imgEl,procCtx,procW,procH,px,Q,grayscale,brightness);// Output canvas: scale to display dimensions, preserve aspect and crop/fit as required\n// (Use CSS object-fit for fast pixel scaling)\ncanvas.width=procW*px;canvas.height=procH*px;ctx.imageSmoothingEnabled=false;ctx.clearRect(0,0,canvas.width,canvas.height);ctx.drawImage(procCv,0,0,procW,procH,0,0,procW*px,procH*px);};imgEl.onerror=function(){ctx.clearRect(0,0,canvas.width,canvas.height);};if(!hasImage){ctx.clearRect(0,0,canvas.width,canvas.height);}},[image,pixelation,brightness,quantization,resolution,grayscale]);// CSS size: fills frame, respects Framer's style\nreturn /*#__PURE__*/_jsxs(\"div\",{style:{...style,width:\"100%\",height:\"100%\",display:\"flex\",alignItems:\"center\",justifyContent:\"center\",overflow:\"hidden\",background:!hasImage?\"#f5f5f5\":undefined,position:\"relative\"},children:[/*#__PURE__*/_jsx(\"canvas\",{ref:canvasRef,style:{width:\"100%\",height:\"100%\",objectFit:layout,display:hasImage?undefined:\"none\"},\"aria-label\":\"Dithered image\"}),/*#__PURE__*/_jsx(\"canvas\",{ref:procRef,style:{display:\"none\"}}),!hasImage&&/*#__PURE__*/_jsx(\"img\",{src:placeholder,alt:\"No image selected\",style:{width:80,height:80,opacity:.7},draggable:false})]});}addPropertyControls(AutoDitherImage,{image:{type:ControlType.ResponsiveImage,title:\"Image\"},pixelation:{type:ControlType.Number,title:\"Pixelation\",defaultValue:1,min:1,max:24,step:1},brightness:{type:ControlType.Number,title:\"Brightness\",defaultValue:0,min:-128,max:128,step:1},quantization:{type:ControlType.Number,title:\"Quantization\",defaultValue:6,min:2,max:16,step:1},resolution:{type:ControlType.Number,title:\"Resolution\",defaultValue:500,min:16,max:2048,step:1},grayscale:{type:ControlType.Boolean,title:\"Grayscale\",defaultValue:true,enabledTitle:\"On\",disabledTitle:\"Off\"},layout:{type:ControlType.Enum,title:\"Object Fit\",defaultValue:\"cover\",options:[\"cover\",\"contain\"],optionTitles:[\"Cover\",\"Contain\"],displaySegmentedControl:true}});\nexport const __FramerMetadata__ = {\"exports\":{\"default\":{\"type\":\"reactComponent\",\"name\":\"AutoDitherImage\",\"slots\":[],\"annotations\":{\"framerContractVersion\":\"1\",\"framerSupportedLayoutHeight\":\"any-prefer-fixed\",\"framerSupportedLayoutWidth\":\"any-prefer-fixed\"}},\"__FramerMetadata__\":{\"type\":\"variable\"}}}\n//# sourceMappingURL=./AutoDitherImage_1.map"],"mappings":"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"}