<?php
/*
Embroidery Reader - an application to view .pes embroidery designs

Copyright (C) 2009 Nathan Crawford
Converted from C# to php 2009 Robert Heel

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.

A copy of the full GPL 2 license can be found in the docs directory.
You can contact me at http://www.njcrawford.com/contact.php.
*/

class color {
    public 
$r;
    public 
$g;
    public 
$b;

    function 
__construct($r=0,$g=0,$b=0){
        
$this->r=$r;
        
$this->g=$g;
        
$this->b=$b;
    }
}

class 
point {
    public 
$x;
    public 
$y;

    function 
__construct($x=0,$y=0){
        
$this->x=$x;
        
$this->y=$y;
    }
}

class 
stitchBlock {
    public 
$color// color
    
public $colorIndex// int32
    
public $stitchesTotal// int32
    
public $stitches// array

    
function __construct(){
        
$this->color=new color();
    }
}

class 
PesFile {
    var 
$imageWidth;
    var 
$imageHeight;
    var 
$pesHeader// int64
    
var $blocks// stitchBlock
    
var $colorTable;
    var 
$startStitches 0// int64
    
var $lastError ""// string
    
var $pesNum ""// string
    
var $min// point

    //means we couldn't figure out some or all
    //of the colors, best guess will be used
    
private $colorWarning false// bool
    
private $formatWarning false// bool
    
private $classWarning false// bool

    
function PesFile($filename) {
        
$this->OpenFile($filename);
    }

    function 
OpenFile($filename) {
        
$file=fopen($filename,'r');
        if(
$file) {
            
// 4 bytes
            
$startFileSig fread($file,4);
            if (
$startFileSig!="#PES") {
                
//this is not a file that we can read
                
$this->lastError "Missing #PES at beginning of file";
                
fclose($file);
                return;
            }

            
// 4 bytes
            
fread($file,4);

            
// pecstart
            
$pecstart $this->readInt32($file,4);

            
// Design dimensions
            
$this->imageWidth=$this->readInt16($file);
            
$this->imageHeight=$this->readInt16($file);

            
// Color table
            
fseek($file,$pecstart+48);
            
$numColors $this->readInt8($file)+1;
            for (
$x 0$x $numColors$x++) {
                
$colorList[] = $this->readInt8($file);
            }

            
// Stitch data
            
fseek($file,$pecstart 532);
            
$thisPartIsDone false;
            
$prevX 0;
            
$prevY 0;
            
$maxX 0;
            
$minX 0;
            
$maxY 0;
            
$minY 0;
            
$colorNum = -1;
            
$colorIndex 0;
            
$tempStitches = array();
            while (!
$thisPartIsDone && !feof($file)) {
                
$val1 $this->readInt8($file);
                
$val2 $this->readInt8($file);
                if (
$val1 == 255 && $val2 == 0) {
                    
//end of stitches
                    
$thisPartIsDone true;

                    
//add the last block
                    
$curBlock = new stitchBlock();
                    
$curBlock->stitches $tempStitches;
                    
$curBlock->stitchesTotal count($tempStitches);
                    
$colorNum++;
                    
$colorIndex $colorList[$colorNum];
                    
$curBlock->colorIndex $colorIndex;
                    
$curBlock->color $this->getColorFromIndex($colorIndex);
                    
$this->blocks[]=$curBlock;
                } elseif (
$val1 == 254 && $val2 == 176) {
                    
//color switch, start a new block
                    
$curBlock = new stitchBlock();
                    
$curBlock->stitches $tempStitches;
                    
$curBlock->stitchesTotal count($tempStitches);
                    
$colorNum++;
                    
$colorIndex $colorList[$colorNum];
                    
$curBlock->colorIndex $colorIndex;
                    
$curBlock->color $this->getColorFromIndex($colorIndex);
                    
$this->blocks[]=$curBlock;

                    
$tempStitches = array();

                    
//read useless(?) byte
                    
fread($file,1);
                } else {
                    
$deltaX 0;
                    
$deltaY 0;
                    if ((
$val1 128) == 128) {//$80
                        //this is a jump stitch
                        
$deltaX = (($val1 15) * 256) + $val2;
                        if ((
$deltaX 2048) == 2048) {//$0800
                            
$deltaX $deltaX 4096;
                        }
                        
//read next byte for Y value
                        
$val2 $this->readInt8($file);
                    } else {
                        
//normal stitch
                        
$deltaX $val1;
                        if (
$deltaX 63) {
                            
$deltaX $deltaX 128;
                        }
                    }

                    if ((
$val2 128) == 128) {//$80
                        //this is a jump stitch
                        
$val3 $this->readInt8($file);
                        
$deltaY = (($val2 15) * 256) + $val3;
                        if ((
$deltaY 2048) == 2048) {
                            
$deltaY $deltaY 4096;
                        }
                    } else {
                        
//normal stitch
                        
$deltaY $val2;
                        if (
$deltaY 63) {
                            
$deltaY $deltaY 128;
                        }
                    }

                    
$prevX $prevX $deltaX;
                    
$prevY $prevY $deltaY;
                    
$tempStitches[]=new point($prevX$prevY);

                    if (
$prevX $maxX) {
                        
$maxX $prevX;
                    }    elseif (
$prevX $minX)    {
                        
$minX $prevX;
                    }

                    if (
$prevY $maxY) {
                        
$maxY $prevY;
                    }    elseif (
$prevY $minY) {
                        
$minY $prevY;
                    }
                }
            }
            
$this->imageWidth $maxX $minX;
            
$this->imageHeight $maxY $minY;
            
$this->min->$minX;
            
$this->min->$minY;
        }
    }

    function 
readInt8($file){
        return(
ord(fread($file,1)));
    }

    function 
readInt16($file){
        return(
array_shift(unpack('v',fread($file,2))));
    }

    function 
readInt32($file){
        return(
array_shift(unpack('V',fread($file,4))));
    }

    function 
getColorFromIndex($index){
        switch (
$index){
            case 
1:
                
$color=new color(1431124);
            break;
            case 
2:
                
$color=new color(1085163);
            break;
            case 
3:
                
$color=new color(48135119);
            break;
            case 
4:
                
$color=new color(75107175);
            break;
            case 
5:
                
$color=new color(2372331);
            break;
            case 
6:
                
$color=new color(209920);
            break;
            case 
7:
                
$color=new color(14554151);
            break;
            case 
8:
                
$color=new color(228154203);
            break;
            case 
9:
                
$color=new color(14595172);
            break;
            case 
10:
                
$color=new color(157214125);
            break;
            case 
11:
                
$color=new color(2321690);
            break;
            case 
12:
                
$color=new color(25418653);
            break;
            case 
13:
                
$color=new color(2552550);
            break;
            case 
14:
                
$color=new color(11218831);
            break;
            case 
15:
                
$color=new color(1921480);
            break;
            case 
16:
                
$color=new color(168168168);
            break;
            case 
17:
                
$color=new color(1231110);
            break;
            case 
18:
                
$color=new color(255255179);
            break;
            case 
19:
                
$color=new color(798586);
            break;
            case 
20:
                
$color=new color(000);
            break;
            case 
21:
                
$color=new color(1161145);
            break;
            case 
22:
                
$color=new color(1191118);
            break;
            case 
23:
                
$color=new color(414951);
            break;
            case 
24:
                
$color=new color(42191);
            break;
            case 
25:
                
$color=new color(24674138);
            break;
            case 
26:
                
$color=new color(17811836);
            break;
            case 
27:
                
$color=new color(252187196);
            break;
            case 
28:
                
$color=new color(2545515);
            break;
            case 
29:
                
$color=new color(240240240);
            break;
            case 
30:
                
$color=new color(10628138);
            break;
            case 
31:
                
$color=new color(168221196);
            break;
            case 
32:
                
$color=new color(37132187);
            break;
            case 
33:
                
$color=new color(25417967);
            break;
            case 
34:
                
$color=new color(255240141);
            break;
            case 
35:
                
$color=new color(20816696);
            break;
            case 
36:
                
$color=new color(209840);
            break;
            case 
37:
                
$color=new color(10218673);
            break;
            case 
38:
                
$color=new color(197470);
            break;
            case 
39:
                
$color=new color(135135135);
            break;
            case 
40:
                
$color=new color(216202198);
            break;
            case 
41:
                
$color=new color(67867);
            break;
            case 
42:
                
$color=new color(254227197);
            break;
            case 
43:
                
$color=new color(249147188);
            break;
            case 
44:
                
$color=new color(05634);
            break;
            case 
45:
                
$color=new color(178175212);
            break;
            case 
46:
                
$color=new color(104106176);
            break;
            case 
47:
                
$color=new color(239227185);
            break;
            case 
48:
                
$color=new color(24756102);
            break;
            case 
49:
                
$color=new color(18176100);
            break;
            case 
50:
                
$color=new color(194326);
            break;
            case 
51:
                
$color=new color(199185);
            break;
            case 
52:
                
$color=new color(25415850);
            break;
            case 
53:
                
$color=new color(168222235);
            break;
            case 
54:
                
$color=new color(010326);
            break;
            case 
55:
                
$color=new color(7841144);
            break;
            case 
56:
                
$color=new color(4712632);
            break;
            case 
57:
                
$color=new color(253217222);
            break;
            case 
58:
                
$color=new color(25521717);
            break;
            case 
59:
                
$color=new color(991166);
            break;
            case 
60:
                
$color=new color(240249112);
            break;
            case 
61:
                
$color=new color(22724391);
            break;
            case 
62:
                
$color=new color(255200100);
            break;
            case 
63:
                
$color=new color(255200150);
            break;
            case 
64:
                
$color=new color(255200200);
            break;
            default:
                
$color=new color(000);
                
$this->colorWarning true;
            break;
        }
        return 
$color;
    }
}
?>