File source

<?php
/**
 * Helper functions for encoding screen images to bitmaps
 * compatible with the device
 */


/* Global variable :( */
// @TODO wrap this in Class
$lastBuf false;

/** Clears buffer **/
function clearBuf(){
  global 
$lastBuf;
  
$lastBuf false;
}

/** Sends GD image $img to Port $port
 * Sends only different sections if last
 * buffer is available
 **/
function sendImg($imgPort $port){
  global 
$lastBuf;
  
$buf imgToBuffer($img);
  if(!
$lastBuf){
    
$port->write("D");
    
$port->write(bufferToString($buf));  
  }else{
    
$d divide($buf$lastBuf);
    foreach(
$d as $part){
      
$len 1+($part[1] - $part[0]);
      
$b = Array(ord("C"), $part[0] & 0xff, ($part[0]>>8) & 0xff$len 0xff, ($len >> 8) & 0xff);
      for(
$i $part[0]; $i <= $part[1]; $i++){
        
$b[] = $buf[$i];
      }
      
$port->write(bufferToString($b));
      
$port->flush();
    }
  }
  
$lastBuf $buf;
}

/** Finds eqals sections in $buf1 and $buf2,
  beginning with first index $start up
  to index $end.
  Beginning and end indices of equal sections
  are returned in $start and $end variables
  by refference
*/
function findSame($buf1,$buf2,&$start,&$end){
  
$len $end+1;
    
// find start
  
for($i $start$i $len$i++){
    if(
$buf1[$i] !== $buf2[$i]){
      
$start $i;
      break;
    }
  }
  
// find end
  
for($i $start$i $len$i++){
    if(
$buf1[$i] == $buf2[$i]){
      
$end $i;
      break;
    }
  }

}

/** Finds different regions in $buf and $old arrays
 and returns array of Array(start, end) where
 start and end are indices of beginning and end of
 different sections.
 Sections are joined if overhead of sending
 two separate sections is greater than sending them
 together (ie. are close together)
*/
function divide($buf$old){
  
$out = Array();
  
$costHead 20// cost for sending one section
  
$maxlen 1000// max. length of section

  
$len count($buf);
  
$start 0;
  
$end $len-1;
  
findSame($buf$old$start$end);
  if(
$end == 0) return $out;
  
$start2 $end+1;
  
$end2 $len-1;
  while(
$start2 $len){  
    if(
$end-$start $maxlen){
      
$out[] = Array($start$start+$maxlen);
      
$start += $maxlen+1;
    }
    
$start2 $end+1;
    
$end2 $len-1;
    
findSame($buf,$old,$start2$end2);

    
$costApart 2*$costHead + ($end-$start) + ($end2-$start2);
    
$costTogether $costHead + ($end2 $start);
    if(
$costApart $costTogether){
      
$out[] = Array($start$end);
      
$start $start2+1;
      
$end $end2;
    }else{
      
$end $end2;
    }
  }
  
$out[] = Array($start$end);
  return 
$out;
}

/** returns string representation of GD image $img **/
function imgToString($img){
  return 
bufferToString(imgToBuffer($img));
}

/** returns string representation of byte Array $buff **/
function bufferToString($buff){
  
$o "";
  foreach(
$buff as $n){
    
$o .= chr($n);
  }
  return 
$o;
}

/** Converts GD image $im to byte Array.
  * Rotates that image by 90 deg
  */
function imgToBuffer($im){
  
$buff = Array();
  
$buflen=0;

  
// first word of buffer = width
  
$w imagesx($im);
  
$buff[] = $w 0xff;
  
$buff[] = ($w 0xff00) >> 8;
  
// second word of buffer = height
  
$h imagesy($im);
  
$buff[] = $h 0xff;
  
$buff[] = ($h 0xff00) >> 8;
  
  
//each byte codes 8 pixels
  //scan by rows, then cols <= 90 deg rotation
  
for($x $w-1$x>=0$x--){
    
$buf 0;
    for(
$y 0$y $h$y++){
      
$c imagecolorat($im,$x,$y);
      
$rgb imagecolorsforindex($im$c);
      
$val 0;
      if( 
$rgb["red"] > 128){
        
$val 0;
      }else{
        
$val 1;
      }
      
// each bit = pixel
      // shift them im
      
$buf $buf << 1;
      
$buf |= $val;
      
$buflen++;
      
//if we have 8, push it to the buffer
      
if($buflen >= 8){
        
$buff[] = $buf;
        
$buf 0;
        
$buflen 0;
      }
    }
    
// if size is not multiple of 8
    
if($buflen 0){
        
$buff[] = $buf;
        
$buflen 0;      
    }
  }

  return 
$buff;
}

/* same as imagettftext, but $x and $y are relative to center of string */
function imagettfcenter($img$size$angle$x$y$color$font$text){
  
$box imagettfbbox($size$angle$font$text);
  
$x-= max(abs($box[0]-$box[2]), abs($box[4]-$box[6]))/2;
  
$y+= max(abs($box[1]-$box[3]), abs($box[5]-$box[7]))/2;
  
imagettftext($img$size$angle$x$y$color$font$text);
}

/* returns new empty screen GD image */
function screen(){
 
$i imagecreatetruecolor(160,160);
 
$w imagecolorallocate($i255,255,255);
 
imagefill($i00$w);
 return 
$i;
}

/* copy $img to $screen, on $x $y (top, left) */
function paste($screen$img$x,$y){
  
imagecopy($screen$img$x,$y,0,0imagesx($img), imagesy($img));
}

/* copy $img to $screen, on $x $y (center coordinates) */
function pasteCenter($screen$img$x$y){
  
$x-=imagesx($img)/2;
  
$y-=imagesy($img)/2;
  
imagecopy($screen$img$x,$y,0,0,imagesx($img), imagesy($img)); 
}