XSP

Xerox Shop Pro

Scan · OCR · Resume · Passport · Compress · AI · Billing · Image Perfect

All tools DD Seva home WhatsApp

Scan to PDF

Upload photos or use the phone camera. Rotate, reorder, then download one PDF.
01 · Scan
Click to upload or drag & drop pages
JPG / PNG · several files at once

Image to Text (OCR)

Extract editable English or Hindi text from a document photo. Runs in your browser.
02 · OCR
Upload a document photo
Clearer photo = better text
0 words

Resume Builder

Photo + details to a print-ready PDF. Live preview, three themes.
Photo
Upload profile photo
Work Experience
Education
Classic Blue Modern Dark Minimal Gray

Passport Photos

Crop to exact size, then pack copies on 4×6 photo paper.
04 · Photo
Upload photo

Photo / Signature Compressor

Hit exact KB limits for online forms. If quality is not enough, the image is also scaled down.
05 · Compress
Upload photo / signature

AI Typing Assistant

Letters, applications and translations — ready to print.
Job ApplicationLeave LetterAffidavitNOCPolice ComplaintBusiness LetterHindi TranslationEnglish TranslationEmail Draft
Namaste. Click a template or type what you need below.

Bill / Receipt Maker

Your rates, optional GST, auto bill number. Shop details stay saved in this browser.
#DescriptionQtyRateAmount
Suggestions: B/W CopyColor CopyLaminationPassport PhotoPrintoutScanSpiral BindingPhoto Print 4x6

Image Perfect

Crop ID cards, combine front + back, print 4×6 sheets, enhance scans.
Card
Upload ID card photo

AI Image Generator

Text to image, or apply a photo effect. Download PNG or send to Doc Maker.
Takes 5–15 seconds

Doc Maker — Image + Text to One PDF

Combine photos, scans and typed pages into one file.
+ Image Page (click or drop)
'); w.document.close();setTimeout(()=>w.print(),350);} function stopCam(e){e.preventDefault();e.stopPropagation();} function pickFiles(input,files,handler){if(!files||!files.length)return;handler(files);} let scanImgs=[]; const sd=$('scanDrop');sd.addEventListener('click',e=>{if(e.target.closest('#scanCamBtn'))return;$('scanFiles').click();}); sd.addEventListener('dragover',e=>{e.preventDefault();});sd.addEventListener('drop',e=>{e.preventDefault();handleScanFiles(e.dataTransfer.files);}); $('scanFiles').addEventListener('change',e=>handleScanFiles(e.target.files)); $('scanCamBtn').addEventListener('click',e=>{stopCam(e);$('scanCam').click();}); $('scanCam').addEventListener('change',e=>handleScanFiles(e.target.files)); function handleScanFiles(files){[...files].forEach(f=>{if(!f.type||f.type.startsWith('image/'))readFile(f,u=>{scanImgs.push({src:u,rot:0});renderScan();});});if(files.length)setStatus('scanStatus',scanImgs.length+' page(s) ready','ok');} function renderScan(){const t=$('scanThumbs');t.innerHTML='';scanImgs.forEach((im,i)=>{const d=document.createElement('div');d.className='thumb';d.innerHTML='
Page '+(i+1)+(im.rot?' ('+im.rot+'°)':'')+'
';t.appendChild(d);});} window.scanRot=i=>{scanImgs[i].rot=(scanImgs[i].rot+90)%360;renderScan();}; window.scanUp=i=>{if(i>0){[scanImgs[i-1],scanImgs[i]]=[scanImgs[i],scanImgs[i-1]];renderScan();}}; window.scanDn=i=>{if(i{scanImgs.splice(i,1);renderScan();}; $('scanClearBtn').addEventListener('click',()=>{scanImgs=[];renderScan();setStatus('scanStatus','Cleared');}); function rotateCanvas(img,rot){rot=((rot%360)+360)%360;const cv=document.createElement('canvas');const swap=rot===90||rot===270;cv.width=swap?img.height:img.width;cv.height=swap?img.width:img.height;const ctx=cv.getContext('2d');ctx.translate(cv.width/2,cv.height/2);ctx.rotate(rot*Math.PI/180);ctx.drawImage(img,-img.width/2,-img.height/2);return cv;} function scanBuild(cb){if(!scanImgs.length){setStatus('scanStatus','Upload at least one page','err');return;}if(!JS()){setStatus('scanStatus','PDF library still loading — wait a second','err');return;} const doc=new(JS())({unit:'mm',format:$('scanPage').value});let first=true; (function next(i){if(i>=scanImgs.length){cb(doc);return;} loadImage(scanImgs[i].src,img=>{if(!first)doc.addPage($('scanPage').value);first=false; const W=doc.internal.pageSize.getWidth(),H=doc.internal.pageSize.getHeight(),m=+$('scanMargin').value; const cv=rotateCanvas(img,scanImgs[i].rot);const u=cv.toDataURL('image/jpeg',0.92); const iw=cv.width,ih=cv.height;const pw=W-m*2,ph=H-m*2; let r=$('scanFit').value==='cover'?Math.max(pw/iw,ph/ih):Math.min(pw/iw,ph/ih); const dw=iw*r,dh=ih*r;doc.addImage(u,'JPEG',(W-dw)/2,(H-dh)/2,dw,dh);next(i+1);},()=>setStatus('scanStatus','Could not read page '+(i+1),'err'));})(0);} $('scanPdfBtn').addEventListener('click',()=>{setStatus('scanStatus','Building PDF...');scanBuild(d=>{d.save('documents.pdf');setStatus('scanStatus','PDF downloaded','ok');});}); $('scanPrintBtn').addEventListener('click',()=>{setStatus('scanStatus','Building PDF...');scanBuild(d=>{window.open(d.output('bloburl'));setStatus('scanStatus','PDF opened — press Ctrl+P','ok');});}); const od=$('ocrDrop');od.addEventListener('click',e=>{if(e.target.closest('#ocrCamBtn'))return;$('ocrFile').click();}); od.addEventListener('dragover',e=>e.preventDefault());od.addEventListener('drop',e=>{e.preventDefault();if(e.dataTransfer.files[0])ocrLoad(e.dataTransfer.files[0]);}); let ocrSrc=null; function ocrLoad(f){readFile(f,u=>{ocrSrc=u;$('ocrImg').src=u;$('ocrImg').style.display='block';$('ocrRun').disabled=false;setStatus('ocrStatus','Image loaded — click Extract','ok');});} $('ocrFile').addEventListener('change',e=>{if(e.target.files[0])ocrLoad(e.target.files[0]);}); $('ocrCamBtn').addEventListener('click',e=>{stopCam(e);$('ocrCam').click();}); $('ocrCam').addEventListener('change',e=>{if(e.target.files[0])ocrLoad(e.target.files[0]);}); $('ocrRun').addEventListener('click',async()=>{ if(!ocrSrc)return;if(!window.Tesseract){setStatus('ocrStatus','OCR library still loading','err');return;} setStatus('ocrStatus','Running OCR (first run downloads language data)…'); try{const res=await Tesseract.recognize(ocrSrc,$('ocrLang').value,{logger:m=>{if(m.status==='recognizing text')setStatus('ocrStatus','Recognizing… '+Math.round(m.progress*100)+'%');}}); $('ocrText').value=res.data.text||'';setStatus('ocrStatus',($('ocrText').value.trim()?'Text extracted — edit freely':'No text found — try a clearer photo'),$('ocrText').value.trim()?'ok':'err');ocrCountUpd(); }catch(err){setStatus('ocrStatus','OCR failed: '+err.message,'err');}}); function ocrCountUpd(){const t=$('ocrText').value;const w=t.trim()?t.trim().split(/\s+/).length:0;$('ocrCount').textContent=w+' words, '+t.length+' chars';} $('ocrText').addEventListener('input',ocrCountUpd); $('ocrCopy').addEventListener('click',()=>{navigator.clipboard.writeText($('ocrText').value).then(()=>setStatus('ocrStatus','Copied','ok'));}); $('ocrTxt').addEventListener('click',()=>{download(URL.createObjectURL(new Blob([$('ocrText').value],{type:'text/plain'})),'ocr-text.txt');}); $('ocrPdf').addEventListener('click',()=>{if(!$('ocrText').value.trim()){setStatus('ocrStatus','Nothing to print','err');return;}printText('OCR Text',$('ocrText').value);}); $('ocrToDoc').addEventListener('click',()=>{if(!$('ocrText').value.trim()){setStatus('ocrStatus','Nothing to send','err');return;}dmAddPage('text','OCR Text',$('ocrText').value);activateTab('docmaker');setStatus('dmStatus','OCR text added as page','ok');}); let rsTheme='blue',rsPhoto=null; $('rsPhotoDrop').addEventListener('click',()=>$('rsPhoto').click()); $('rsPhoto').addEventListener('change',e=>{const f=e.target.files[0];if(f)readFile(f,u=>{rsPhoto=u;renderResume();});}); ['rsName','rsTitle','rsPhone','rsEmail','rsAddr','rsSummary','rsSkills'].forEach(id=>$(id).addEventListener('input',renderResume)); $('rsAddExp').addEventListener('click',()=>addEntry('rsExpList',[{r:'Role',c:'Company',d:'Dates'},'Description'],renderResume)); $('rsAddEdu').addEventListener('click',()=>addEntry('rsEduList',[{r:'Degree',c:'Institute',d:'Year'},''],renderResume)); function addEntry(listId,fields,cb){const d=document.createElement('div');d.className='entry'; const f1=document.createElement('input');f1.type='text';f1.placeholder=fields[0].r; const f2=document.createElement('input');f2.type='text';f2.placeholder=fields[0].c; const f3=document.createElement('input');f3.type='text';f3.placeholder=fields[0].d; const f4=document.createElement('textarea');f4.placeholder=fields[1]||'Description (optional)'; [f1,f2,f3,f4].forEach(x=>{x.addEventListener('input',cb);x.style.cssText='width:100%;padding:7px 10px;border:1px solid #d3dcd0;border-radius:8px;font-size:13px;font-family:inherit;margin-bottom:6px';}); const del=document.createElement('button');del.textContent='Remove';del.className='mini danger';del.onclick=()=>{d.remove();cb();}; const row=document.createElement('div');row.style.cssText='display:grid;grid-template-columns:1fr 1fr;gap:8px';row.append(f1,f2); d.append(row,f3,f4,del);$(listId).appendChild(d);} function themeColors(){return rsTheme==='dark'?{h:'#111827',a:'#374151',line:'#111827'}:rsTheme==='gray'?{h:'#333',a:'#555',line:'#999'}:{h:'#0E7C8A',a:'#19A3B8',line:'#19A3B8'};} function renderResume(){const c=themeColors();const p=$('rpPreview'); const name=$('rsName').value||'Your Name';const title=$('rsTitle').value||'Job Title'; p.innerHTML='
'+(rsPhoto?'':'')+'
'+esc(name)+'
'+esc(title)+'
'+[esc($('rsPhone').value),esc($('rsEmail').value),esc($('rsAddr').value)].filter(Boolean).join(' | ')+'

Professional Summary

'+(esc($('rsSummary').value)||'...')+'

Work Experience

'+collectEntries('rsExpList')+'

Education

'+collectEntries('rsEduList')+'

Skills

'+(esc($('rsSkills').value)||'...')+'

';} function collectEntries(listId){const out=[];$(listId).querySelectorAll('.entry').forEach(e=>{const ins=e.querySelectorAll('input,textarea');const r=ins[0]?ins[0].value:'',c2=ins[1]?ins[1].value:'',d=ins[2]?ins[2].value:'',desc=ins[3]?ins[3].value:'';if(r||c2||desc)out.push('
'+esc(r)+(c2?' — '+esc(c2):'')+''+esc(d)+''+(desc?'

'+esc(desc)+'

':'')+'
');});return out.length?out.join(''):'

...

';} document.querySelectorAll('.themes .tb').forEach(t=>t.addEventListener('click',()=>{document.querySelectorAll('.themes .tb').forEach(x=>x.classList.remove('sel'));t.classList.add('sel');rsTheme=t.dataset.theme;renderResume();})); $('rsPdf').addEventListener('click',()=>{if(!JS())return;const c=themeColors();const d=new(JS())();let y=15; if(rsPhoto){try{d.addImage(rsPhoto,'JPEG',15,15,32,40);}catch(e){}} d.setTextColor(c.h);d.setFontSize(22);d.text($('rsName').value||'Your Name',55,y+10); d.setFontSize(12);d.setTextColor(c.a);d.text($('rsTitle').value||'',55,y+18); d.setFontSize(9);d.setTextColor(80);y=wrapText(d,[$('rsPhone').value,$('rsEmail').value,$('rsAddr').value].filter(Boolean).join(' | '),55,y+26,130,4.5); y=Math.max(y+8,60);const sec=(title,body)=>{if(y>270){d.addPage();y=15;}d.setFontSize(12);d.setTextColor(c.h);d.text(title,15,y);d.setDrawColor(c.line);d.line(15,y+1.5,195,y+1.5);y+=8;d.setFontSize(10);d.setTextColor(50);y=wrapText(d,body||' ',15,y,180,5)+5;}; sec('PROFESSIONAL SUMMARY',$('rsSummary').value||''); const exps=[];$('rsExpList').querySelectorAll('.entry').forEach(e=>{const i=e.querySelectorAll('input,textarea');if(i[0].value)exps.push(i[0].value+(i[1].value?' - '+i[1].value:'')+(i[2].value?' ('+i[2].value+')':'')+'\n'+(i[3].value||''));}); sec('WORK EXPERIENCE',exps.join('\n')||''); const edus=[];$('rsEduList').querySelectorAll('.entry').forEach(e=>{const i=e.querySelectorAll('input,textarea');if(i[0].value)edus.push(i[0].value+(i[1].value?' - '+i[1].value:'')+(i[2].value?' ('+i[2].value+')':''));}); sec('EDUCATION',edus.join('\n')||'');sec('SKILLS',$('rsSkills').value||''); d.save(($('rsName').value||'resume').replace(/\s+/g,'_')+'_resume.pdf');}); $('rsPrint').addEventListener('click',()=>{const w=window.open('','_blank');w.document.write('Resume'+$('rpPreview').innerHTML+' ');w.document.close();setTimeout(()=>w.print(),300);}); let ppSrc=null; $('ppDrop').addEventListener('click',e=>{if(e.target.closest('#ppCamBtn'))return;$('ppFile').click();}); $('ppCamBtn').addEventListener('click',e=>{stopCam(e);$('ppCam').click();}); function ppLoad(f){readFile(f,u=>{ppSrc=u;loadImage(u,im=>{$('ppImg').src=u;$('ppCropWrap').style.display='inline-block';requestAnimationFrame(()=>requestAnimationFrame(()=>{initCrop('ppImg','ppCrop',im);setStatus('ppStatus','Drag or resize the box, then download','ok');}));});});} $('ppFile').addEventListener('change',e=>{if(e.target.files[0])ppLoad(e.target.files[0]);}); $('ppCam').addEventListener('change',e=>{if(e.target.files[0])ppLoad(e.target.files[0]);}); $('ppSize').addEventListener('change',()=>{$('ppCustomWrap').style.display=$('ppSize').value==='custom'?'inline':'none';}); function initCrop(imgId,boxId,img){const img2=$(imgId),box=$(boxId);const dispW=img2.clientWidth||300; const ratio=(img&&img.height&&img.width)?(img.height/img.width):1.3; box.style.width=Math.max(40,dispW*0.55)+'px';box.style.height=Math.max(50,dispW*0.55*ratio)+'px'; box.style.left='8px';box.style.top='8px';dragify(box,img2);} function dragify(box,img2){let sx,sy,bx,by,ow,oh,mode=null; box.addEventListener('pointerdown',e=>{sx=e.clientX;sy=e.clientY;bx=box.offsetLeft;by=box.offsetTop;ow=box.offsetWidth;oh=box.offsetHeight;mode=e.target.className.includes('hnd')?e.target.className.replace('hnd ','').trim():'move';box.setPointerCapture(e.pointerId);e.preventDefault();}); box.addEventListener('pointermove',e=>{if(sx==null)return;const dx=e.clientX-sx,dy=e.clientY-sy; if(mode==='move'){box.style.left=Math.max(0,Math.min(bx+dx,img2.clientWidth-ow))+'px';box.style.top=Math.max(0,Math.min(by+dy,img2.clientHeight-oh))+'px';} else{let w=ow,h=oh;if(mode.includes('l'))w=Math.max(40,ow-dx);if(mode.includes('r'))w=Math.max(40,ow+dx);if(mode.includes('t'))h=Math.max(50,oh-dy);if(mode.includes('b'))h=Math.max(50,oh+dy); if(mode==='tl'){box.style.width=w+'px';box.style.height=h+'px';box.style.left=(bx+(ow-w))+'px';box.style.top=(by+(oh-h))+'px';} else if(mode==='tr'){box.style.width=w+'px';box.style.height=h+'px';box.style.top=(by+(oh-h))+'px';} else if(mode==='bl'){box.style.width=w+'px';box.style.height=h+'px';box.style.left=(bx+(ow-w))+'px';} else{box.style.width=w+'px';box.style.height=h+'px';}}}); box.addEventListener('pointerup',()=>{sx=null;mode=null;});} function ppDims(){if($('ppSize').value==='custom')return[+$('ppW').value||35,+$('ppH').value||45];const parts=$('ppSize').value.split('x');return[+parts[0],+parts[1]];} function ppBuild(cb){if(!ppSrc){setStatus('ppStatus','Upload a photo first','err');return;}loadImage(ppSrc,src=>{const disp=$('ppImg');const box=$('ppCrop');const sx=src.width/Math.max(1,disp.clientWidth),sy=src.height/Math.max(1,disp.clientHeight); const cx=box.offsetLeft*sx,cy=box.offsetTop*sy,cw=box.offsetWidth*sx,ch=box.offsetHeight*sy; const cv=document.createElement('canvas');cv.width=Math.max(1,Math.round(cw));cv.height=Math.max(1,Math.round(ch));cv.getContext('2d').drawImage(src,cx,cy,cw,ch,0,0,cv.width,cv.height);cb(cv);});} $('ppSingle').addEventListener('click',()=>{ppBuild(cv=>{const w=ppDims()[0],h=ppDims()[1];const d=new(JS())({unit:'mm',format:[w,h]});d.addImage(cv.toDataURL('image/jpeg',0.95),'JPEG',0,0,w,h);d.save('passport_photo.pdf');setStatus('ppStatus','Single photo PDF saved','ok');});}); $('ppSheet').addEventListener('click',()=>{ppBuild(cv=>{const w=ppDims()[0],h=ppDims()[1];const W=101.6,H=152.4;const d=new(JS())({unit:'mm',format:[W,H]});const gap=1;let x=gap,y=gap,n=0;const u=cv.toDataURL('image/jpeg',0.92); while(true){if(x+w>W-1){x=gap;y+=h+gap;}if(y+h>H-1)break;d.addImage(u,'JPEG',x,y,w,h);x+=w+gap;n++;if(n>=40)break;} d.save('passport_sheet_4x6.pdf');setStatus('ppStatus','Sheet PDF saved — '+n+' copies','ok');});}); $('ppPng').addEventListener('click',()=>{ppBuild(cv=>{download(cv.toDataURL('image/png'),'passport_photo.png');setStatus('ppStatus','PNG saved','ok');});}); let cpData=null,cpOut=null; $('cpDrop').addEventListener('click',()=>$('cpFile').click()); $('cpFile').addEventListener('change',e=>{const f=e.target.files[0];if(f)readFile(f,u=>{cpData=u;$('cpBefore').src=u;$('cpBefore').style.display='block';$('cpRun').disabled=false;setStatus('cpStatus','Loaded: '+fmtKB(dataLen(u)),'ok');});}); $('cpTarget').addEventListener('change',()=>{$('cpCustomWrap').style.display=$('cpTarget').value==='custom'?'inline':'none';}); $('cpRun').addEventListener('click',()=>{if(!cpData)return;const kb=$('cpTarget').value==='custom'?+$('cpCustomKB').value:+$('cpTarget').value;if(!kb){setStatus('cpStatus','Enter target KB','err');return;} if(dataLen(cpData)<=kb*1024){cpOut=cpData;$('cpAfter').src=cpData;$('cpAfter').style.display='block';$('cpDownload').style.display='inline-flex';setStatus('cpStatus','Already under '+kb+' KB','ok');return;} setStatus('cpStatus','Compressing…'); loadImage(cpData,im=>{let w=im.width,h=im.height;function pass(){const cv=document.createElement('canvas');cv.width=Math.max(8,w);cv.height=Math.max(8,h);const ctx=cv.getContext('2d');ctx.fillStyle='#fff';ctx.fillRect(0,0,cv.width,cv.height);ctx.drawImage(im,0,0,cv.width,cv.height); let lo=0.05,hi=0.92,best=null;for(let i=0;i<14;i++){const q=(lo+hi)/2;const u=cv.toDataURL('image/jpeg',q);const bytes=dataLen(u);if(bytes<=kb*1024){best={u,bytes,q};lo=q;}else hi=q;} if(best){cpOut=best.u;$('cpAfter').src=best.u;$('cpAfter').style.display='block';$('cpDownload').style.display='inline-flex';setStatus('cpStatus','Original '+fmtKB(dataLen(cpData))+' → '+fmtKB(best.bytes)+' (target '+kb+'KB)','ok');return;} if(w<64||h<64){setStatus('cpStatus','Cannot reach '+kb+' KB even after shrinking. Try a simpler image.','err');return;} w=Math.round(w*0.8);h=Math.round(h*0.8);setStatus('cpStatus','Still large — shrinking to '+w+'×'+h+'…');setTimeout(pass,10);}pass();});}); $('cpDownload').addEventListener('click',()=>{if(cpOut)download(cpOut,'compressed.jpg');}); const TPL={job:'Type a professional job application letter. Details:\nPost: [post name]\nCompany: [company]\nMy name: [name]\nQualification: [degree]\nExperience: [years] years\nAddress: [address]', leave:'Type a leave application. Details:\nFrom: [your name], [class/job]\nTo: [principal/manager name]\nReason: [fever/personal work]\nDates: [from date] to [to date]', affidavit:'Type a general affidavit format (Indian style) for: [purpose]. Deponent: [name], [address]. Include standard declarations and verification paragraph.', noc:'Type a No Objection Certificate. From: [organization]. To: [employee name]. Purpose: [purpose]. Date: [date]. Authorized signatory block.', police:'Type a police complaint (FIR application) to SHO. Incident: [what happened]. Date/time: [when]. Place: [where]. My name: [name], [address]. Lost items: [items]', business:'Type a formal business letter. From: [company]. To: [recipient company]. Subject: [subject]. Points: [details]. Professional closing.', hindi:'Translate this to Hindi (Devanagari):\n[paste text here]', english:'Translate this Hindi text to English:\n[Hindi text here]', email:'Draft a professional email. To: [recipient]. Purpose: [purpose]. Tone: [formal/friendly]. Key points: [points]'}; document.querySelectorAll('.tpl[data-tpl]').forEach(t=>t.addEventListener('click',()=>{$('aiInput').value=TPL[t.dataset.tpl];$('aiInput').focus();})); function aiLogAdd(role,text){const log=$('aiLog');const d=document.createElement('div');d.className='msg '+(role==='user'?'user':'bot');d.textContent=text;log.appendChild(d);log.scrollTop=log.scrollHeight;return d;} let aiLast=null,aiLastPrompt=null,aiModelIdx=0,aiBusy=false; async function aiSendMsg(p,rotate){if(!p||aiBusy)return;aiBusy=true;aiLogAdd('user',p);$('aiInput').value='';if(!rotate)aiLastPrompt=p;setStatus('aiStatus','AI is typing…');const busyEl=aiLogAdd('bot','Working…'); try{const r=await fetch('ai-proxy.php',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({prompt:p,modelIndex:rotate?(aiModelIdx+1):aiModelIdx})}); const j=await r.json().catch(()=>({})); if(j.ok&&j.text){aiLast=j.text;if(typeof j.modelIndex==='number')aiModelIdx=j.modelIndex;busyEl.textContent=j.text;setStatus('aiStatus','Done — Copy, Print or Doc Maker','ok');} else{busyEl.textContent=j.error||('Could not type (HTTP '+r.status+')');setStatus('aiStatus',j.error||'AI unavailable','err');} }catch(err){busyEl.textContent='Network error. Check internet and try again.';setStatus('aiStatus','Network error','err');} aiBusy=false;} $('aiSend').addEventListener('click',()=>{const p=$('aiInput').value.trim();if(!p){setStatus('aiStatus','Type what you need','err');return;}aiSendMsg(p,false);}); $('aiInput').addEventListener('keydown',e=>{if(e.key==='Enter'){$('aiSend').click();}}); $('aiRetry').addEventListener('click',()=>{if(!aiLastPrompt){setStatus('aiStatus','Nothing to retry','err');return;}aiSendMsg(aiLastPrompt,true);}); $('aiCopy').addEventListener('click',()=>{if(aiLast)navigator.clipboard.writeText(aiLast).then(()=>setStatus('aiStatus','Copied','ok'));}); $('aiPdf').addEventListener('click',()=>{if(!aiLast){setStatus('aiStatus','Nothing typed yet','err');return;}printText('Typed document',aiLast);}); $('aiToDoc').addEventListener('click',()=>{if(!aiLast){setStatus('aiStatus','Nothing typed yet','err');return;}dmAddPage('text','AI Document',aiLast);activateTab('docmaker');setStatus('dmStatus','AI document added as page','ok');}); const BILL_KEY='xsp_bill',RATES_KEY='xsp_rates'; function billLoad(){try{const s=JSON.parse(localStorage.getItem(BILL_KEY)||'{}');['bShop','bPhone','bGst','bAddr'].forEach(k=>{if(s[k])$(k).value=s[k];});}catch(e){}renderBill();} function billRow(desc,qty,rate){return 'Rs 0';} window.billCalc=()=>{let sub=0;document.querySelectorAll('#billBody tr').forEach((tr,i)=>{tr.cells[0].textContent=String(i+1);const ins=tr.querySelectorAll('input');const q=+ins[1].value||0,r=+ins[2].value||0;const a=q*r;sub+=a;tr.querySelector('.amt').textContent='Rs '+a.toLocaleString('en-IN');}); const gst=$('billGstOn').checked?sub*0.18:0; $('billTotals').innerHTML='
SubtotalRs '+sub.toLocaleString('en-IN')+'
'+(gst?'
GST 18%Rs '+Math.round(gst).toLocaleString('en-IN')+'
':'')+'
Grand TotalRs '+Math.round(sub+gst).toLocaleString('en-IN')+'
';}; $('billGstOn').addEventListener('change',billCalc); function renderBill(){const b=$('billBody');if(!b.children.length){let rows;try{const rates=JSON.parse(localStorage.getItem(RATES_KEY)||'{}');const keys=Object.keys(rates);rows=keys.length?keys.slice(0,4).map(k=>billRow(k,1,rates[k])).join(''):(billRow('',1,'')+billRow('',1,''));}catch(e){rows=billRow('',1,'')+billRow('',1,'');}b.innerHTML=rows;}billCalc();} $('billAdd').addEventListener('click',()=>{$('billBody').insertAdjacentHTML('beforeend',billRow('',1,''));billCalc();}); document.querySelectorAll('.tpl[data-bill]').forEach(t=>t.addEventListener('click',()=>{$('billBody').insertAdjacentHTML('beforeend',billRow(t.dataset.bill,1,''));billCalc();})); $('billSave').addEventListener('click',()=>{localStorage.setItem(BILL_KEY,JSON.stringify({bShop:$('bShop').value,bPhone:$('bPhone').value,bGst:$('bGst').value,bAddr:$('bAddr').value})); const rates={};document.querySelectorAll('#billBody tr').forEach(tr=>{const ins=tr.querySelectorAll('input');if(ins[0].value&&ins[2].value)rates[ins[0].value]=ins[2].value;}); localStorage.setItem(RATES_KEY,JSON.stringify(rates));setStatus('billStatus','Shop details + rates saved on this computer','ok');}); function billNo(){const d=new Date();return 'XS-'+d.getFullYear()+String(d.getMonth()+1).padStart(2,'0')+String(d.getDate()).padStart(2,'0')+'-'+String(Math.floor(Math.random()*900)+100);} $('billPdf').addEventListener('click',()=>{const doc2=new(JS())();doc2.setFontSize(16);doc2.setTextColor(14,60,74); doc2.text($('bShop').value||'Xerox Shop',105,20,{align:'center'}); doc2.setFontSize(9);doc2.setTextColor(80);doc2.text(($('bAddr').value||'')+' | '+($('bPhone').value||''),105,26,{align:'center'}); if($('bGst').value)doc2.text('GSTIN: '+$('bGst').value,105,31,{align:'center'}); doc2.setDrawColor(25,163,184);doc2.setLineWidth(0.8);doc2.line(15,34,195,34); doc2.setFontSize(11);doc2.text('INVOICE / RECEIPT',105,42,{align:'center'}); const bn=billNo();doc2.setFontSize(9);doc2.text('Bill No: '+bn,15,50);doc2.text('Date: '+today(),195,50,{align:'right'}); let y2=60;doc2.setFontSize(10);doc2.setFillColor(231,246,248);doc2.rect(15,y2-5,180,8,'F'); doc2.text('#',18,y2);doc2.text('Description',30,y2);doc2.text('Qty',125,y2);doc2.text('Rate',145,y2);doc2.text('Amount',172,y2);y2+=10; let i=1,sub=0;document.querySelectorAll('#billBody tr').forEach(tr=>{const ins=tr.querySelectorAll('input');const q=+ins[1].value||0,r=+ins[2].value||0,a=q*r;sub+=a;if(ins[0].value||a){doc2.text(String(i++),18,y2);doc2.text(ins[0].value||'-',30,y2);doc2.text(String(q),125,y2);doc2.text(String(r),145,y2);doc2.text(String(a),172,y2);y2+=7;}}); const gst=$('billGstOn').checked?sub*0.18:0;y2+=4;doc2.line(130,y2,195,y2);y2+=6;doc2.text('Subtotal:',140,y2);doc2.text('Rs '+sub,195,y2,{align:'right'});y2+=6; if(gst){doc2.text('GST 18%:',140,y2);doc2.text('Rs '+Math.round(gst),195,y2,{align:'right'});y2+=6;} doc2.setFontSize(12);doc2.setFont(undefined,'bold');doc2.text('Grand Total:',140,y2);doc2.text('Rs '+Math.round(sub+gst),195,y2,{align:'right'}); y2+=14;doc2.setFontSize(8);doc2.setTextColor(120);doc2.text('Computer generated receipt — thank you, visit again!',105,y2+6,{align:'center'}); doc2.save(bn+'.pdf');setStatus('billStatus','Bill PDF saved ('+bn+')','ok');}); $('billPrint').addEventListener('click',()=>{const w=window.open('','_blank');let rows='';let sub=0,i=1; document.querySelectorAll('#billBody tr').forEach(tr=>{const ins=tr.querySelectorAll('input');const q=+ins[1].value||0,r=+ins[2].value||0,a=q*r;sub+=a;if(ins[0].value||a)rows+=''+(i++)+''+esc(ins[0].value||'-')+''+q+'Rs '+r+'Rs '+a.toLocaleString('en-IN')+'';}); const gst=$('billGstOn').checked?sub*0.18:0; w.document.write('Bill

'+esc($('bShop').value||'Xerox Shop')+'

'+esc($('bAddr').value||'')+' | '+esc($('bPhone').value||'')+'


Bill No: '+billNo()+'   Date: '+today()+'

'+rows+'
#DescriptionQtyRateAmount

Subtotal: Rs '+sub.toLocaleString('en-IN')+'

'+(gst?'

GST 18%: Rs '+Math.round(gst).toLocaleString('en-IN')+'

':'')+'

Grand Total: Rs '+Math.round(sub+gst).toLocaleString('en-IN')+'

');w.document.close();setTimeout(()=>w.print(),300);}); document.querySelectorAll('.ipTool').forEach(b=>b.addEventListener('click',()=>{document.querySelectorAll('.ipTool').forEach(x=>{x.classList.remove('sel');x.style.background='';x.style.color='';});b.classList.add('sel');b.style.background='var(--stub)';b.style.color='#fff'; const map={card:'ipCard',fb:'ipFb',sheet:'ipSheet',enhance:'ipEnh'};Object.values(map).forEach(id=>$(id).style.display='none');$(map[b.dataset.tool]).style.display='block';})); let ipCardSrc=null; $('ipCardDrop').addEventListener('click',()=>$('ipCardFile').click()); $('ipCardFile').addEventListener('change',e=>{const f=e.target.files[0];if(f)readFile(f,u=>{ipCardSrc=u;loadImage(u,im=>{$('ipCardImg').src=u;$('ipCardWrap').style.display='inline-block';requestAnimationFrame(()=>initCrop('ipCardImg','ipCardCrop',im));$('ipCardGo').disabled=false;setStatus('ipCardStatus','Adjust crop box, then Crop & PDF','ok');});});}); $('ipCardSize').addEventListener('change',()=>{$('ipCardCustom').style.display=$('ipCardSize').value==='custom'?'inline':'none';}); function ipCardDims(){const v=$('ipCardSize').value;if(v==='custom')return[+$('ipcW').value||86,+$('ipcH').value||54];return {a4card:[86,54],pan:[85,55],dl:[86,54],voter:[85,55]}[v];} $('ipCardGo').addEventListener('click',()=>{const disp=$('ipCardImg');const box=$('ipCardCrop');loadImage(ipCardSrc,src=>{const sx=src.width/Math.max(1,disp.clientWidth),sy=src.height/Math.max(1,disp.clientHeight); const cx=box.offsetLeft*sx,cy=box.offsetTop*sy,cw=box.offsetWidth*sx,ch=box.offsetHeight*sy; const cv=document.createElement('canvas');cv.width=Math.round(cw);cv.height=Math.round(ch);cv.getContext('2d').drawImage(src,cx,cy,cw,ch,0,0,cv.width,cv.height); const dims=ipCardDims();const d=new(JS())({unit:'mm',format:[dims[0],dims[1]]});d.addImage(cv.toDataURL('image/jpeg',0.95),'JPEG',0,0,dims[0],dims[1]);d.save('id_card.pdf');setStatus('ipCardStatus','Card PDF saved','ok');});}); let fbF=null,fbB=null; const ffd=$('ipFbFDrop'),fbd=$('ipFbBDrop');ffd.addEventListener('click',()=>$('ipFbF').click());fbd.addEventListener('click',()=>$('ipFbB').click()); $('ipFbF').addEventListener('change',e=>{const f=e.target.files[0];if(f)readFile(f,u=>{fbF=u;ffd.innerHTML='
1
Front loaded
';fbReady();});}); $('ipFbB').addEventListener('change',e=>{const f=e.target.files[0];if(f)readFile(f,u=>{fbB=u;fbd.innerHTML='
2
Back loaded
';fbReady();});}); function fbReady(){$('ipFbGo').disabled=!(fbF&&fbB);} $('ipFbGo').addEventListener('click',()=>{loadImage(fbF,f=>loadImage(fbB,b=>{const cv=document.createElement('canvas'); if($('ipFbLayout').value==='side'){cv.width=f.width+b.width+20;cv.height=Math.max(f.height,b.height);}else{cv.width=Math.max(f.width,b.width);cv.height=f.height+b.height+20;} const ctx=cv.getContext('2d');ctx.fillStyle='#fff';ctx.fillRect(0,0,cv.width,cv.height); if($('ipFbLayout').value==='side'){ctx.drawImage(f,0,0);ctx.drawImage(b,f.width+20,0);}else{ctx.drawImage(f,0,0);ctx.drawImage(b,0,f.height+20);} const u=cv.toDataURL('image/jpeg',0.92);const d=new(JS())();const pw=190,ph=272;const r=Math.min(pw/cv.width,ph/cv.height); d.addImage(u,'JPEG',(210-pw)/2,15,cv.width*r,cv.height*r);d.save('front_back.pdf');setStatus('ipFbStatus','Combined PDF saved','ok');}));}); let ipSheetSrc=null; $('ipSheetDrop').addEventListener('click',()=>$('ipSheetFile').click()); $('ipSheetFile').addEventListener('change',e=>{const f=e.target.files[0];if(f)readFile(f,u=>{ipSheetSrc=u;$('ipSheetGo').disabled=false;setStatus('ipSheetStatus','Photo loaded','ok');});}); $('ipSheetGo').addEventListener('click',()=>{loadImage(ipSheetSrc,im=>{const n=Math.min(40,+$('ipSheetN').value||8);const w=+$('ipSheetW').value||35,h=+$('ipSheetH').value||45; const W=101.6,H=152.4;const d=new(JS())({unit:'mm',format:[W,H]});const gap=1;let x=gap,y=gap,cnt=0;const u=ipSheetSrc.indexOf('image/png')>=0?im.src:ipSheetSrc; while(cntW-2){x=gap;y+=h+gap;}if(y+h>H-2)break;d.addImage(u,'JPEG',x,y,w,h);x+=w+gap;cnt++;} d.save('photo_sheet_4x6.pdf');setStatus('ipSheetStatus','Sheet saved — '+cnt+' copies','ok');});}); let enhSrc=null; $('ipEnhDrop').addEventListener('click',()=>$('ipEnhFile').click()); $('ipEnhFile').addEventListener('change',e=>{const f=e.target.files[0];if(f)readFile(f,u=>{enhSrc=u;$('enhPreview').src=u;$('enhPreview').style.display='block';$('ipEnhGo').disabled=false;setStatus('enhStatus','Loaded — adjust sliders then Apply','ok');applyEnh(false);});}); ['enhB','enhC','enhS'].forEach(id=>$(id).addEventListener('input',()=>{if(enhSrc)applyEnh(false);})); function applyEnh(dl2){loadImage(enhSrc,im=>{const cv=document.createElement('canvas');cv.width=im.width;cv.height=im.height;const ctx=cv.getContext('2d'); ctx.filter='brightness('+$('enhB').value+'%) contrast('+$('enhC').value+'%)';ctx.drawImage(im,0,0); const s=+$('enhS').value/100;if(s>0){const out=ctx.getImageData(0,0,cv.width,cv.height);const d2=out.data;const k=s*1.2;for(let i=0;iapplyEnh(true)); let genLastUrl=null;const genHist=[]; document.querySelectorAll('.genMode').forEach(b=>b.addEventListener('click',()=>{document.querySelectorAll('.genMode').forEach(x=>{x.classList.remove('sel');x.style.background='';x.style.color='';});b.classList.add('sel');b.style.background='var(--stub)';b.style.color='#fff'; $('genT2i').style.display=b.dataset.mode==='t2i'?'block':'none';$('genI2i').style.display=b.dataset.mode==='i2i'?'block':'none';})); const SURPRISE=['Lord Ganesha digital art for Ganesh Chaturthi festival poster','A beautiful Indian village sunset with bullock cart','Majestic tiger in jungle, photorealistic','Diwali festival lights and diyas celebration','Mysore Palace at night with lights','Kerala houseboat on backwaters','Colorful Holi festival celebration','Mountain landscape of Himalayas with snow','Modern office workspace for banner','Happy independence day poster with flag']; $('genSurprise').addEventListener('click',()=>{$('genPrompt').value=SURPRISE[Math.floor(Math.random()*SURPRISE.length)];}); $('genGo').addEventListener('click',()=>{ const p=$('genPrompt').value.trim();if(!p){setStatus('genStatus','Describe the image first','err');return;} const style=$('genStyle').value;const wh=$('genSize').value.split('x');const full=style?(p+', '+style):p; const url='https://image.pollinations.ai/prompt/'+encodeURIComponent(full)+'?width='+wh[0]+'&height='+wh[1]+'&nologo=true&seed='+Date.now(); setStatus('genStatus','Generating (5–15s)…'); const im=new Image();im.crossOrigin='anonymous'; im.onload=()=>{genLastUrl=url;$('genImg').src=url;$('genImg').style.display='block';['genDl','genToDoc','genPdf'].forEach(id=>$(id).style.display='inline-flex');genHist.unshift(url);if(genHist.length>6)genHist.pop();renderGenHist();setStatus('genStatus','Image generated','ok');}; im.onerror=()=>setStatus('genStatus','Generation failed — check internet and try again','err'); im.src=url;}); function renderGenHist(){const g=$('genHistory');g.innerHTML='';$('genHistoryWrap').style.display=genHist.length?'block':'none'; genHist.forEach(u=>{const im=document.createElement('img');im.src=u;im.onclick=()=>{genLastUrl=u;$('genImg').src=u;$('genImg').style.display='block';['genDl','genToDoc','genPdf'].forEach(id=>$(id).style.display='inline-flex');};g.appendChild(im);});} function canvasFrom(url,cb){loadImage(url,im=>{const cv=document.createElement('canvas');cv.width=im.naturalWidth||im.width;cv.height=im.naturalHeight||im.height;cv.getContext('2d').drawImage(im,0,0);cb(cv);},()=>setStatus('genStatus','Could not export image (blocked by source). Right-click the picture to save.','err'));} $('genDl').addEventListener('click',()=>{if(!genLastUrl)return;canvasFrom(genLastUrl,cv=>{download(cv.toDataURL('image/png'),'ai_image.png');setStatus('genStatus','PNG downloaded','ok');});}); $('genPdf').addEventListener('click',()=>{if(!genLastUrl)return;canvasFrom(genLastUrl,cv=>{const u=cv.toDataURL('image/jpeg',0.95);const d=new(JS())();const r=Math.min(190/cv.width,270/cv.height);d.addImage(u,'JPEG',(210-cv.width*r)/2,15,cv.width*r,cv.height*r);d.save('ai_image.pdf');setStatus('genStatus','PDF saved','ok');});}); $('genToDoc').addEventListener('click',()=>{if(!genLastUrl)return;canvasFrom(genLastUrl,cv=>{dmAddPage('image','AI Generated Image',cv.toDataURL('image/jpeg',0.92));activateTab('docmaker');setStatus('dmStatus','Image added as page','ok');});}); let i2iSrc=null; $('i2iDrop').addEventListener('click',()=>$('i2iFile').click()); $('i2iFile').addEventListener('change',e=>{const f=e.target.files[0];if(f)readFile(f,u=>{i2iSrc=u;$('i2iSrc').src=u;$('i2iSrc').style.display='block';$('i2iGo').disabled=false;setStatus('i2iStatus','Photo loaded — choose effect','ok');});}); $('i2iGo').addEventListener('click',()=>{if(!i2iSrc)return;setStatus('i2iStatus','Transforming…'); loadImage(i2iSrc,im=>{const cv=document.createElement('canvas');cv.width=im.width;cv.height=im.height;const ctx=cv.getContext('2d');ctx.drawImage(im,0,0);const dta=ctx.getImageData(0,0,cv.width,cv.height);const d2=dta.data;const str=+$('i2iStr').value/100;const fx=$('i2iFx').value; for(let i=0;i=0)?i-4:i;r=r+(r-(d2[j]+d2[k])/2)*0.5;g=g+(g-(d2[j+1]+d2[k+1])/2)*0.5;b=b+(b-(d2[j+2]+d2[k+2])/2)*0.5;} d2[i]=r+(d2[i]-r)*(1-str);d2[i+1]=g+(d2[i+1]-g)*(1-str);d2[i+2]=b+(d2[i+2]-b)*(1-str);} ctx.putImageData(dta,0,0);const u=cv.toDataURL('image/jpeg',0.95);$('i2iOut').src=u;$('i2iOut').style.display='block';['i2iDl','i2iToDoc'].forEach(id=>$(id).style.display='inline-flex');setStatus('i2iStatus','Transformed','ok');});}); $('i2iDl').addEventListener('click',()=>{const u=$('i2iOut').src;if(u)download(u,'transformed.jpg');}); $('i2iToDoc').addEventListener('click',()=>{const u=$('i2iOut').src;if(!u)return;dmAddPage('image','Transformed Image',u);activateTab('docmaker');setStatus('dmStatus','Image added as page','ok');}); let dmPages=[]; $('dmAddText').addEventListener('click',()=>{dmAddPage('text','New Text Page','');}); const dmd=$('dmImgDrop');dmd.addEventListener('click',()=>$('dmImgFile').click()); dmd.addEventListener('dragover',e=>e.preventDefault());dmd.addEventListener('drop',e=>{e.preventDefault();handleDmFiles(e.dataTransfer.files);}); $('dmImgFile').addEventListener('change',e=>handleDmFiles(e.target.files)); function handleDmFiles(files){[...files].forEach(f=>readFile(f,u=>dmAddPage('image',f.name,u)));} function dmAddPage(type,title,content){dmPages.push({type,title:title||'Untitled',content});renderDm();} function renderDm(){const l=$('dmList');l.innerHTML='';dmPages.forEach((p,i)=>{const d=document.createElement('div');d.className='docpage';d.innerHTML='
'+(p.type==='image'?'IMG':'TXT')+'
'+esc(p.title)+'
'+(p.type==='image'?'Image page':'Text page')+'
';l.appendChild(d);});} window.dmEdit=i=>{const p=dmPages[i];const t=prompt('Page title:',p.title);if(t===null)return;p.title=t;if(p.type==='text'){const c=prompt('Page text:',p.content);if(c!==null)p.content=c;}renderDm();}; window.dmUp=i=>{if(i>0){[dmPages[i-1],dmPages[i]]=[dmPages[i],dmPages[i-1]];renderDm();}}; window.dmDn=i=>{if(i{dmPages.splice(i,1);renderDm();}; $('dmClear').addEventListener('click',()=>{dmPages=[];renderDm();}); $('dmPdf').addEventListener('click',()=>{if(!dmPages.length){setStatus('dmStatus','No pages added','err');return;}setStatus('dmStatus','Building PDF…');const doc=new(JS())();let first=true;let i=0; (function next(){if(i>=dmPages.length){doc.save('document.pdf');setStatus('dmStatus','PDF downloaded — '+dmPages.length+' pages','ok');return;} const p=dmPages[i];if(!first)doc.addPage();first=false; if(p.type==='text'){doc.setFontSize(14);doc.setFont(undefined,'bold');doc.text(p.title||'Page',15,20);doc.setFontSize(11);doc.setFont(undefined,'normal');wrapText(doc,p.content||'',15,30,180,6);i++;next();} else{loadImage(p.content,im=>{const W=180,H=262;const r=Math.min(W/im.width,H/im.height);try{doc.addImage(p.content,'JPEG',(210-im.width*r)/2,20,im.width*r,im.height*r);}catch(e){}i++;next();},()=>{i++;next();});}})();}); renderResume();billLoad(); document.querySelector('.ipTool[data-tool="card"]').click(); document.querySelector('.genMode[data-mode="t2i"]').click(); routeHash();