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($img, Port $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($i, 255,255,255);
imagefill($i, 0, 0, $w);
return $i;
}
/* copy $img to $screen, on $x $y (top, left) */
function paste($screen, $img, $x,$y){
imagecopy($screen, $img, $x,$y,0,0, imagesx($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));
}