
    g@jV:                     (   d Z ddlZddlZddlZddlZddlZddlZddlZddl	m
Z
mZ dZej                            ed          Zej                            ed          Z ed           ddlmZ dd	lmZ  ej        ej                                        rd
nd          Z eeee          Z ee          Z ede            dZd ZddZdadad Z d Z!d Z" G d de          Z#e$dk    r  e
de#          %                                 dS dS )u3   عدسة النقوش SAM 2 — نسخة مطورة    N)
HTTPServerBaseHTTPRequestHandlerz/var/www/html/sam2zsam2_hiera_large.ptzsam2_hiera_l.yamlu    ⏳ جاري تحميل SAM 2...)
build_sam2)SAM2ImagePredictorcudacpu)deviceu   ✅ SAM 2 جاهز على u&  <!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-title" content="SAM 2">
    <link rel="icon" type="image/png" href="/favicon.png">
    <link rel="apple-touch-icon" href="/favicon.png">
    <title>عدسة النقوش SAM 2</title>
    <style>
        *{box-sizing:border-box;margin:0;padding:0}
        body{font-family:'Segoe UI',sans-serif;background:#1e1e24;color:#f5f5f5;padding:15px;display:flex;flex-direction:column;align-items:center}
        .card{background:#2b2b36;padding:15px;border-radius:10px;width:100%;max-width:800px;display:flex;flex-direction:column;gap:10px}
        .row{display:flex;justify-content:center;gap:10px;flex-wrap:wrap}
        button{background:#ffcc00;color:#1e1e24;border:none;padding:10px 18px;border-radius:5px;cursor:pointer;font-weight:bold;font-size:14px}
        button:hover{background:#e6b800}
        #result{display:none;width:100%;max-width:800px;margin-top:10px;position:relative}
        #result img{width:100%;border-radius:8px;border:2px solid #444;display:block;touch-action:none}
        #overlayCanvas{pointer-events:none}
        #loading{display:none;color:#ffcc00;text-align:center;padding:10px}
        #magnifier{display:none;position:fixed;z-index:99999;width:50px;height:50px;border-radius:50%;border:2px solid #ffcc00;box-shadow:0 0 10px rgba(255,204,0,0.6);pointer-events:none;overflow:hidden;background:#fff}
        #magnifier img{position:absolute;top:0;left:0;max-width:none;max-height:none;border:none}
        .no-callout{-webkit-touch-callout:none!important;-webkit-user-select:none!important;user-select:none!important}
        #waitToast{display:none;position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);z-index:99998;background:#2b2b36;color:#ffcc00;padding:20px 30px;border-radius:12px;border:1px solid #ffcc00;font-weight:bold;font-size:16px;box-shadow:0 4px 20px rgba(0,0,0,0.5);text-align:center}
    </style>
</head>
<body>
    <div id="magnifier"><img id="magImg"></div>
    <div id="waitToast">⏳ يرجى الانتظار...</div>
    <div class="card">
        <div class="row"><input type="file" id="imageInput" accept="image/*" style="flex:1"></div>
        <div class="row">
            <button onclick="initSAM2()">🧠 SAM 2</button>
            <button onclick="clearOverlay()">🗑️ مسح</button>
            <button onclick="downloadResult()">💾 تحميل</button>
        </div>
    </div>
    <div id="loading">⚙️ جاري المعالجة...</div>
    <div id="result">
        <div style="position:relative;width:100%">
            <img id="mainImg" class="no-callout" oncontextmenu="return false;" draggable="false" style="width:100%;display:block;border-radius:8px;border:2px solid #444;touch-action:none">
            <canvas id="overlayCanvas" style="position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;border-radius:8px"></canvas>
        </div>
        <div class="row" style="margin-top:8px">
            <button onclick="undoLast()">↩️ تراجع</button>
            <button id="toggleBtn" onclick="toggleView()">📸 الأصل</button>
            <button onclick="downloadResult()">💾 تحميل</button>
        </div>
    </div>
    <script>
    let magActive=false,magTimer=null,lastTX=0,lastTY=0,startTX=0,startTY=0,isScrolling=false,stepCount=0;
    function show(w){document.getElementById(w).style.display='block'}
    function hide(w){document.getElementById(w).style.display='none'}

    async function initSAM2(){
      const file=document.getElementById('imageInput').files[0];
      if(!file)return alert('اختر صورة أولاً');
      show('loading');document.getElementById('loading').textContent='🧠 جاري تحليل الصورة...';
      hide('result');stepCount=0;
      const fd=new FormData();fd.append('image',file);
      try{
        const r=await fetch('/init',{method:'POST',body:fd});const d=await r.json();
        if(d.error){alert(d.error);hide('loading');return}
        document.getElementById('mainImg').src='data:image/jpeg;base64,'+d.original;
        document.getElementById('mainImg').onload=function(){
          const ov=document.getElementById('overlayCanvas');
          ov.width=this.naturalWidth;ov.height=this.naturalHeight;
          ov.getContext('2d').clearRect(0,0,ov.width,ov.height);
          ov.style.display='block';
          document.getElementById('toggleBtn').textContent='📸 الأصل';
        };
        show('result');
        const img=document.getElementById('mainImg');
        img.addEventListener('touchstart',magStart,{passive:false});
        img.addEventListener('touchmove',magMove,{passive:false});
        img.addEventListener('touchend',magEnd);
        img.addEventListener('touchcancel',magCancel);
        img.addEventListener('mousedown',function(e){
          const r=img.getBoundingClientRect();
          submitClick(((e.clientX-r.left)/r.width)*100,((e.clientY-r.top)/r.height)*100);
        });
      }catch(e){alert('خطأ: '+e.message)}
      hide('loading')
    }

    function magStart(e){
      if(e.touches.length>1)return;
      startTX=e.touches[0].clientX;startTY=e.touches[0].clientY;
      lastTX=startTX;lastTY=startTY;isScrolling=false;
      if(magTimer)clearTimeout(magTimer);
      magTimer=setTimeout(function(){
        magTimer=null;
        if(!isScrolling){magActive=true;document.getElementById('magnifier').style.display='block';updateMag(lastTX,lastTY)}
      },350)
    }
    function magMove(e){
      if(e.touches.length>1){if(magTimer){clearTimeout(magTimer);magTimer=null}if(magActive){magActive=false;document.getElementById('magnifier').style.display='none'}return}
      lastTX=e.touches[0].clientX;lastTY=e.touches[0].clientY;
      if(magActive){if(e.cancelable)e.preventDefault();updateMag(lastTX,lastTY)}
      else if(magTimer&&(Math.abs(lastTX-startTX)>10||Math.abs(lastTY-startTY)>10)){isScrolling=true;clearTimeout(magTimer);magTimer=null}
    }
    function magEnd(e){
      if(magTimer){clearTimeout(magTimer);magTimer=null;return}
      if(!magActive)return;
      document.getElementById('magnifier').style.display='none';magActive=false;
      if(isScrolling)return;
      const img=document.getElementById('mainImg'),r=img.getBoundingClientRect(),t=e.changedTouches[0];
      const x=((t.clientX-r.left)/r.width)*100,y=((t.clientY-r.top)/r.height)*100;
      if(x<0||x>100||y<0||y>100)return;
      submitClick(x,y)
    }
    function magCancel(e){if(magTimer)clearTimeout(magTimer);magActive=false;isScrolling=false;document.getElementById('magnifier').style.display='none'}
    function updateMag(mx,my){
      const img=document.getElementById('mainImg'),r=img.getBoundingClientRect(),mag=document.getElementById('magnifier'),magImg=document.getElementById('magImg');
      let magX=mx-25,magY=my-130;
      if(magX<5)magX=5;if(magX>window.innerWidth-55)magX=window.innerWidth-55;
      if(magY<5)magY=my+50;
      mag.style.left=magX+'px';mag.style.top=magY+'px';
      magImg.src=img.src;magImg.style.width=(r.width*2.5)+'px';magImg.style.height=(r.height*2.5)+'px';
      magImg.style.left=(-(mx-r.left)*2.5+25)+'px';magImg.style.top=(-(my-r.top)*2.5+25)+'px'
    }

    async function submitClick(x,y){
      stepCount++;show('waitToast');
      const fd=new FormData();fd.append('image',document.getElementById('imageInput').files[0]);
      fd.append('x',x.toFixed(2));fd.append('y',y.toFixed(2));fd.append('step',stepCount);
      try{
        const r=await fetch('/click',{method:'POST',body:fd});const d=await r.json();
        if(d.error){alert(d.error);hide('waitToast');return}
        const ov=document.getElementById('overlayCanvas');ov.style.display='block';
        document.getElementById('toggleBtn').textContent='📸 الأصل';
        const img=new Image();img.onload=function(){ov.getContext('2d').drawImage(img,0,0)};
        img.src='data:image/png;base64,'+d.overlay;
      }catch(e){alert('خطأ: '+e.message)}
      hide('waitToast')
    }

    function toggleView(){
      const ov=document.getElementById('overlayCanvas'),btn=document.getElementById('toggleBtn');
      if(ov.style.display==='none'){ov.style.display='block';btn.textContent='📸 الأصل'}
      else{ov.style.display='none';btn.textContent='✏️ التعديل'}
    }
    function clearOverlay(){
      document.getElementById('overlayCanvas').getContext('2d').clearRect(0,0,
        document.getElementById('overlayCanvas').width,document.getElementById('overlayCanvas').height);
      stepCount=0;
    }
    async function undoLast(){
      if(stepCount<=0)return;stepCount--;show('waitToast');
      const fd=new FormData();fd.append('step',stepCount);
      try{
        const r=await fetch('/undo',{method:'POST',body:fd});const d=await r.json();
        if(d.error){alert(d.error);hide('waitToast');return}
        const ov=document.getElementById('overlayCanvas'),ctx=ov.getContext('2d');ctx.clearRect(0,0,ov.width,ov.height);
        if(d.overlay){const img=new Image();img.onload=function(){ctx.drawImage(img,0,0)};img.src='data:image/png;base64,'+d.overlay}
      }catch(e){alert('خطأ: '+e.message)}
      hide('waitToast')
    }
    function downloadResult(){
      const img=document.getElementById('mainImg');if(!img.src)return;
      const ov=document.getElementById('overlayCanvas'),c=document.createElement('canvas');
      c.width=ov.width;c.height=ov.height;const cx=c.getContext('2d');
      cx.drawImage(img,0,0,c.width,c.height);cx.drawImage(ov,0,0);
      const a=document.createElement('a');a.download='sam2_result.png';a.href=c.toDataURL('image/png');a.click()
    }
    </script>
</body>
</html>c                    | D ]}d| d                                 |v rj|                    d          }|dk    rO||dz   d          }|                    d          r
|d d         }|                    d          r
|d d         }|c S d S )	Nzname=""s   

   s   
   --)encodefindendswith)partskeypidatas        	server.pyparse_multipartr      s      C???!!##q(({##ABww1w==));$ss)4==''9SbS	4     c                     t          | |          }||S |                                                                S #  |cY S xY w)N)r   decodestrip)r   r   defaultvs       r   
parse_textr!      sC    s##Ay.

  ""	"7NNNs	   %; Ac                    t          j        | t           j                  }t          j        |t          j                  }|dS |j        d d         \  }}|dk    r,d|z  }t          j        |dt          ||z            f          }t          j	        d|t          j
        dg          \  }}t          j        |                                          }t                              t          j        |t          j                             t          j        |j        d         |j        d         dft           j        	          adad
|id fS )N)Nu#   خطأ في قراءة الصورة      z.jpgU   r      r   dtypeoriginal)np
frombufferuint8cv2imdecodeIMREAD_COLORshaperesizeintimencodeIMWRITE_JPEG_QUALITYbase64	b64encoder   	predictor	set_imagecvtColorCOLOR_BGR2RGBzerosoverlayoverlay_step)		img_bytesarrimghwratio_oborigs	            r   process_initrG      s   
-	28
,
,C
,sC,
-
-C
{FF9RaR=DAq3wwASZc3qw<<-@AAsLs'?&DEEEArB&&((DS#*;<<===h	!cilA6bhGGGGLt##r   c           
         t          j        | t           j                  }t          j        |t          j                  }|dS |j        d d         \  }}|dk    r,d|z  }t          j        |dt          ||z            f          }t          
                    t          j        t          |dz  |j        d         z            t          |dz  |j        d         z            gg          t          j        dg          d          \  }	}
}|	d         }|d	z                      t           j                  }t          j        |t          j        t          j                  \  }}t          j        t"          |d
dd           t$          dz  at          j        dt$           dt"                     t          j        dt"                    \  }}dt+          j        |                                          id fS )N)Nu   خطأr#   r$   d   r&   r   F)point_coordspoint_labelsmultimask_output   r   )rM   rM   rM   rM   /tmp/sam2_hist_.pngr<   )r*   r+   r,   r-   r.   r/   r0   r1   r2   r7   predictarrayastypefindContoursRETR_EXTERNALCHAIN_APPROX_SIMPLEdrawContoursr<   r=   imwriter3   r5   r6   r   )r>   cxcystepr?   r@   rA   rB   rC   masksscoreslogitsmaskmu8contoursrD   rbs                    r   process_clickrb      s   
-	28
,
,C
,sC,
-
-C
{>>9RaR=DAq3wwASZc3qw<<-@AAs &--XBsF39Q<$7 8 8#bfSYq\>Q:R:RSTUUXqc]] .  E66
 8DDH,,RX66S"3(93;RSSKHaWh,@!DDDALK4,444g>>>L))EArv'++22445t;;r   c                     t           dk    rdS t           dz  a t           dk    rgt          j        dt          j                  at          j        dt                    \  } }dt          j        |          	                                id fS t          j
        dt            dt
          j                  at          j        dt                    \  } }dt          j        |          	                                id fS )	Nr   )Nu   لا يوجدr&   )r&   r&   r   r'   rO   r<   rN   )r=   r*   r;   r,   r<   r-   r3   r5   r6   r   imreadIMREAD_UNCHANGED)rD   ra   s     r   process_undorf      s    q!6!6ALq(7"(333VW--26+B//668894??j=<===s?STTGL))EArv'++22445t;;r   c                        e Zd Zd Zd Zd ZdS )Handlerc                     |                      d           |                     dd           |                                  | j                            t
                              d                     d S )N   Content-Typeztext/html; charset=utf-8utf-8)send_responsesend_headerend_headerswfilewrite	HTML_PAGEr   )selfs    r   do_GETzHandler.do_GET  si    3)CDDD
))'2233333r   c                 B   | j                             dd          }|                    d          s|                     ddi          S t	          | j                             dd                    }| j                            |                              d|                    d	          d
                                         z             }| j	        }|dk    rXt          |d          }|s|                     ddi          S t          |          \  }}|                     |rd|in|           d S |dk    rt          |d          }t          t          |dd                    }t          t          |dd                    }	t	          t          |dd                    }
|s|                     ddi          S t          |||	|
          \  }}|                     |rd|in|           d S |dk    r.t                      \  }}|                     |rd|in|           d S d S )Nrk   r   zmultipart/form-dataerroru   نوع غير مدعومzContent-Lengthr   r   =r&   z/initimageu   لا توجد صورةz/clickx50yrZ   0z/undo)headersget
startswith_jsonr2   rfilereadsplitr   pathr   rG   floatr!   rb   rf   )rs   ctclr   r   ibrerX   rY   sts              r   do_POSTzHandler.do_POST  s   \nb11}}233lDJJPjGk<l<l5l!!"2A6677
##))%"((3--2B2I2I2K2K*KLLI<< 00BLdjj'2J)KLLL##DAqJJq/||a00000(]] 00Bz%d3344Bz%d3344BZvs3344BLdjj'2J)KLLL RR00DAqJJq/||a00000'\\>>DAqJJq/||a00000 \r   c                    |                      d           |                     dd           |                                  | j                            t          j        |                              d                     d S )Nrj   rk   zapplication/json; charset=utf-8rl   )rm   rn   ro   rp   rq   jsondumpsr   )rs   ds     r   r   zHandler._json"  sq    3)JKKK
A--g6677777r   N)__name__
__module____qualname__rt   r   r    r   r   rh   rh     sA        4 4 4
1 1 1,8 8 8 8 8r   rh   __main__)z0.0.0.0i  )r   )&__doc__r-   numpyr*   r5   r   pickleostorchhttp.serverr   r   SAM2_DIRr   join
MODEL_PATHCFG_PATHprintsam2.build_samr   sam2.sam2_image_predictorr   r	   r   is_available
sam2_modelr7   rr   r   r!   r<   r=   rG   rb   rf   rh   r   serve_foreverr   r   r   <module>r      s   9 9 



     & & & & & & & & & & & & & & & & & & & & : : : : : : : :W\\($9::
7<<"566 ( ) ) ) % % % % % % 8 8 8 8 8 8	
 7 7 9 9Dffu	E	EZ*V<<<
z**	 +6++ , , ,h	T	 	 	    $ $ $< < <0
< 
< 
< 8  8  8  8  8$  8  8  8D zJ '**88::::: r   