PP Reader

This script reads save files from Pocket Physics, a very cool Nintendo DS Homebrew game.

- It reads the built in thumbnail
- It can create a large preview by reading all elements itself.

You'll need this image:


Download Download script as zip

Tag Tags: GD Pocket Physics PHP

Source

  • ppreader.class.php
  • image.class.php
  1. <?php
  2. /**
  3.  * Lucky's Framework
  4.  * A highly extendable MVC PHP framework
  5.  *
  6.  * Created by Lucas van Dijk (http://www.return1.net)
  7.  * Copyright 2007 by Lucas van Dijk
  8.  *
  9.  * $Id$
  10.  *
  11.  * ---------------------------------------------------------------------
  12.  *
  13.  * This program is free software: you can redistribute it and/or modify
  14.  * it under the terms of the GNU General Public License as published by
  15.  * the Free Software Foundation, either version 3 of the License, or
  16.  * (at your option) any later version.
  17.  *
  18.  * This program is distributed in the hope that it will be useful,
  19.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21.  * GNU General Public License for more details.
  22.  *
  23.  * You should have received a copy of the GNU General Public License
  24.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  25.  */
  26.  
  27. include_once 'image.class.php';
  28.  
  29. class PPReader
  30. {
  31.     protected $filename;
  32.     protected $xml;
  33.    
  34.     protected $thumb;
  35.     protected $screenshot;
  36.    
  37.     public function __construct($filename)
  38.     {
  39.         if(!file_exists($filename))
  40.         {
  41.             throw new InvalidArgumentException('File does not exists');
  42.         }
  43.        
  44.         $this -> filename = $filename;
  45.        
  46.         $contents = file_get_contents($filename);
  47.         // remove html entities
  48.         $contents = preg_replace('#&(.*?);#i', '', $contents);
  49.        
  50.         $this -> xml = simplexml_load_string($contents);
  51.         if(!$this -> validate())
  52.         {
  53.             throw new Exception('Invalid Pocket Physics file! You need at least Pocket Physics 0.6');
  54.         }
  55.        
  56.         $this -> author = $this -> xml -> author;
  57.         $this -> version = preg_replace('#[^0-9.]+#i', '', $this -> xml -> creator);
  58.     }
  59.    
  60.     public function __get($name)
  61.     {
  62.         if(isset($this -> $name))
  63.         {
  64.             return $this -> $name;
  65.         }
  66.     }
  67.    
  68.     public function validate()
  69.     {
  70.         return $this -> xml -> creator && $this -> xml -> world && $this -> xml -> image;
  71.     }
  72.    
  73.     public function generate_thumb()
  74.     {      
  75.         $image_data = $this -> xml -> image;
  76.         $image_data = base64_decode($image_data);
  77.        
  78.         $this -> thumb = new Image(64, 48);
  79.        
  80.         for($i = 0, $j = strlen($image_data) / 2; $i < $j; $i++)
  81.         {
  82.             $n1 = ord($image_data[2 * $i]);
  83.             $n2 = ord($image_data[2 * $i + 1]);
  84.            
  85.             $rgb15col = $n1 + 256 * $n2;
  86.             $r = floor($rgb15col % 32) * 8;
  87.            
  88.             $rgb15col = floor($rgb15col / 32);
  89.             $g = floor($rgb15col % 32) * 8;
  90.            
  91.             $rgb15col = floor($rgb15col / 32);
  92.             $b = floor($rgb15col % 32) * 8;
  93.        
  94.             $col = $this -> thumb -> colorallocate($r, $g, $b);
  95.             $x = $i % 64;
  96.             $y = floor($i / 64);
  97.            
  98.             $this -> thumb -> setpixel($x, $y, $col);
  99.         }
  100.     }
  101.    
  102.     public function get_thumb()
  103.     {
  104.         return $this -> thumb;
  105.     }
  106.    
  107.     public function generate_screenshot()
  108.     {
  109.         // Edit the path
  110.         $this -> screenshot = new Image('back.png');
  111.        
  112.         $red = $this -> screenshot -> allocate_color('FF0000');
  113.         $blue = $this -> screenshot -> allocate_color('0000FF');
  114.        
  115.         $this -> screenshot -> setthickness(1);
  116.        
  117.         // Draw the elements
  118.         // Start with lines and rectangles
  119.         foreach($this -> xml -> world -> polygon as $polygon)
  120.         {
  121.             switch((string) $polygon['type'])
  122.             {
  123.                 case "solid":
  124.                     $color = $red;
  125.                 break;
  126.                 case "dynamic":
  127.                     $color = $blue;
  128.                 break;
  129.             }
  130.            
  131.             $base_x = (int) $polygon['x'] / 3;
  132.             $base_y = (int) $polygon['y'] / 3;
  133.            
  134.             for($i = 0, $j = count($polygon -> vertex); $i < ($j - 1); $i++)
  135.             {
  136.                 $this -> screenshot -> linethick($base_x + ((int) $polygon -> vertex[$i]['x'] / 3), $base_y + ((int) $polygon -> vertex[$i]['y'] / 3), $base_x + ((int) $polygon -> vertex[$i + 1]['x'] / 3), $base_y + ((int) $polygon -> vertex[$i + 1]['y'] / 3), $color, 1);
  137.             }
  138.            
  139.             if((int) $polygon['closed'] == 1)
  140.             {
  141.                 $this -> screenshot -> linethick($base_x + ((int) $polygon -> vertex[$i]['x'] / 3), $base_y + ((int) $polygon -> vertex[$i]['y'] / 3), $base_x + ((int) $polygon -> vertex[0]['x'] / 3), $base_y + ((int) $polygon -> vertex[0]['y'] / 3), $color, 1);
  142.             }
  143.         }
  144.        
  145.         // And now all circles
  146.         foreach($this -> xml -> world -> circle as $circle)
  147.         {
  148.             switch((string) $circle['type'])
  149.             {
  150.                 case "solid":
  151.                     $color = $red;
  152.                 break;
  153.                 case "dynamic":
  154.                     $color = $blue;
  155.                 break;
  156.             }
  157.            
  158.             $this -> screenshot -> ellipse((int) $circle['x'] / 3, (int) $circle['y'] / 3, (int) $circle['radius'] / 2, (int) $circle['radius'] / 2, $color);
  159.         }
  160.     }
  161.    
  162.     public function get_screenshot()
  163.     {
  164.         return $this -> screenshot;
  165.     }
  166. }
  167.  
  1. <?php
  2. /**
  3.  * Lucky's Framework
  4.  * A highly extendable MVC PHP framework
  5.  *
  6.  * Created by Lucas van Dijk (http://www.return1.net)
  7.  * Copyright 2007 by Lucas van Dijk
  8.  *
  9.  * $Id$
  10.  *
  11.  * ---------------------------------------------------------------------
  12.  *
  13.  * This program is free software: you can redistribute it and/or modify
  14.  * it under the terms of the GNU General Public License as published by
  15.  * the Free Software Foundation, either version 3 of the License, or
  16.  * (at your option) any later version.
  17.  *
  18.  * This program is distributed in the hope that it will be useful,
  19.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21.  * GNU General Public License for more details.
  22.  *
  23.  * You should have received a copy of the GNU General Public License
  24.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  25.  */
  26.  
  27. /**
  28.  * Represents an image.
  29.  *
  30.  * @package Images
  31.  * @author Lucas van Dijk
  32.  */
  33. class Image
  34. {
  35.    
  36.     /**
  37.      * Holds the image GD resource
  38.      *
  39.      * @var resource
  40.      */
  41.     protected $image_resource;
  42.    
  43.     /**
  44.      * Holds the width of the image
  45.      *
  46.      * @var int
  47.      */
  48.     protected $width;
  49.    
  50.     /**
  51.      * Holds the height of the image
  52.      *
  53.      * @var int
  54.      */
  55.     protected $height;
  56.    
  57.     /**
  58.      * Constructor, creates the image resource
  59.      * @param mixed $param1 The filename to open, or the width of the image
  60.      * @param int $param2 The height of the image, when creating a new image (not from a file)
  61.      */
  62.     public function __construct($param1, $param2 = null)
  63.     {
  64.         if(empty($param2))
  65.         {
  66.             // Just one parameter given,
  67.             // Param1 should be a filename
  68.             $this -> image_resource = $this -> create_image($param1);
  69.         }
  70.         else
  71.         {
  72.             // Param 2 is given
  73.             // So we create a new image with the width and height
  74.             $this -> image_resource = imagecreatetruecolor(intval($param1), intval($param2));
  75.         }
  76.  
  77.         if(!$this -> image_resource)
  78.         {
  79.             throw new Exception('Could not create image', 100);
  80.         }
  81.  
  82.         $this -> update_size();
  83.     }
  84.    
  85.     public function __call($name, $args)
  86.     {
  87.         if(!is_array($args))
  88.         {
  89.             $args = array();
  90.         }
  91.        
  92.         if(function_exists('image'.$name))
  93.         {
  94.             array_unshift($args, $this -> image_resource);
  95.             return call_user_func_array('image'.$name, $args);
  96.         }
  97.     }
  98.  
  99.     /**
  100.      * Creates an GD image resource based on image type
  101.      * @param string $file The file to open
  102.      * @return resource
  103.      */
  104.     protected function create_image($file)
  105.     {
  106.         list(, , $image_type) = getimagesize($file);
  107.         $img = false;
  108.  
  109.         switch($image_type)
  110.         {
  111.             case 3:
  112.                 $img = imagecreatefrompng($file);
  113.             break;
  114.             case 2:
  115.                 $img = imagecreatefromjpeg($file);
  116.             break;
  117.             case 1:
  118.                 $img = imagecreatefromgif($file);
  119.             break;
  120.             case 6:
  121.                 $img = imagecreatefromwbmp($file);
  122.             break;
  123.             default:
  124.                 throw new Exception('File is not a valid Image', 101);
  125.         }
  126.  
  127.         return $img;
  128.     }
  129.    
  130.     /**
  131.      * Allocates a color, based on a hex color
  132.      * @param string $color The hex color to allocate
  133.      * @param int The background color
  134.      */
  135.     public function allocate_color($color)
  136.     {
  137.         if(substr($color, 0, 1) == "#")
  138.         {
  139.             $color = substr($color, 1);
  140.         }
  141.        
  142.         $parts = str_split($color, 2);
  143.        
  144.         return eval('return imagecolorallocate($this -> image_resource, 0x'.$parts[0].', 0x'.$parts[1].', 0x'.$parts[2].');');
  145.     }
  146.    
  147.     /**
  148.      * Generates a random hex color
  149.      * @param bool $return_array return an array with three elememts containing each a part of the color, default false
  150.      * @return string|array The random hex color
  151.      */
  152.     protected function random_hex_color($return_array = false)
  153.     {
  154.         $chars = array_merge(range('A', 'F'), range('0', '9 '));
  155.  
  156.         $max_chars = count($chars) - 1;
  157.         srand( (double) microtime()*1000000);
  158.  
  159.         $rand_color = '#';
  160.         for($i = 0; $i < 6; $i++)
  161.         {
  162.             $rand_color = ( empty($rand_color)) ? $chars[rand(0, $max_chars)] : $rand_color . $chars[rand(0, $max_chars)];
  163.         }
  164.  
  165.         if($return_array)
  166.         {
  167.             $rand_color_array = array();
  168.             $rand_color_array[0] = substr($rand_color, 1, 2);
  169.             $rand_color_array[1] = substr($rand_color, 3, 2);
  170.             $rand_color_array[2] = substr($rand_color, 5, 2);
  171.  
  172.             return $rand_color_array;
  173.         }
  174.  
  175.         return $rand_color;
  176.     }
  177.    
  178.     /**
  179.      * Generates a random RGB Color
  180.      * @return array with key 0 as red, key 1 as green, and key 2 as blue
  181.      */
  182.     protected function random_rgb_color()
  183.     {
  184.         $color = array();
  185.         for ($c = 0; $c < 3; $c++)
  186.         {
  187.             $color[] = rand(1, 255);
  188.         }
  189.  
  190.         return $color;
  191.     }
  192.    
  193.     /**
  194.      * Updates the width and height of the image
  195.      */
  196.     protected function update_size()
  197.     {
  198.         $this -> width = imagesx($this -> image_resource);
  199.         $this -> height = imagesy($this -> image_resource);
  200.     }
  201.    
  202.     /**
  203.      * Returns the image resource
  204.      * @return resource
  205.      */
  206.     public function get_resource()
  207.     {
  208.         return $this -> image_resource;
  209.     }
  210.    
  211.     /**
  212.      * Copies an Image object into the current image
  213.      * @param Image $image the image object to copy
  214.      * @param int $x The X position
  215.      * @param int $y The Y psoition
  216.      */
  217.     public function copy(Image $image, $x, $y)
  218.     {
  219.         imagecopy($this -> image_resource, $image -> get_resource(), $x, $y, 0, 0, $image -> get_width() - 1, $image -> get_height() - 1);
  220.     }
  221.    
  222.     /**
  223.      * Resizes the image
  224.      * @param int $max_width max width of the image
  225.      * @param int $max_height max height of the image
  226.      * @param bool $keep_aspect_ratio True if you wnat to keep the aspect ratio
  227.      */
  228.     public function resize($max_width, $max_height, $keep_aspect_ratio = true)
  229.     {      
  230.         if($keep_aspect_ratio)
  231.         {
  232.             // Find resize scale
  233.             $resize_scale = min(min($max_width / $this -> width, $max_height / $this -> height), 1.0);
  234.    
  235.             $new_width = $resize_scale * $this -> width;
  236.             $new_height = $resize_scale * $this -> height;
  237.         }
  238.         else
  239.         {
  240.             $new_width = $max_width;
  241.             $new_height = $max_height;
  242.         }
  243.  
  244.         $new_img = imagecreatetruecolor($new_width, $new_height);
  245.  
  246.         // Resize it
  247.         imagecopyresampled($new_img, $this -> image_resource, 0, 0, 0, 0, $new_width, $new_height, $this -> width, $this -> height);
  248.        
  249.         $this -> image_resource = $new_img;
  250.         $this -> update_size();
  251.     }
  252.    
  253.     public function linethick($x1, $y1, $x2, $y2, $color, $thick = 1)
  254.     {
  255.         if ($thick == 1)
  256.         {
  257.             return imageline($this -> image_resource, $x1, $y1, $x2, $y2, $color);
  258.         }
  259.        
  260.         $t = $thick / 2 - 0.5;
  261.         if ($x1 == $x2 || $y1 == $y2)
  262.         {
  263.             return imagefilledrectangle($this -> image_resource, round(min($x1, $x2) - $t), round(min($y1, $y2) - $t), round(max($x1, $x2) + $t), round(max($y1, $y2) + $t), $color);
  264.         }
  265.        
  266.         $k = ($y2 - $y1) / ($x2 - $x1); //y = kx + q
  267.         $a = $t / sqrt(1 + pow($k, 2));
  268.         $points = array(
  269.             round($x1 - (1+$k)*$a), round($y1 + (1-$k)*$a),
  270.             round($x1 - (1-$k)*$a), round($y1 - (1+$k)*$a),
  271.             round($x2 + (1+$k)*$a), round($y2 - (1-$k)*$a),
  272.             round($x2 + (1-$k)*$a), round($y2 + (1+$k)*$a),
  273.         );
  274.        
  275.         imagefilledpolygon($this -> image_resource, $points, 4, $color);
  276.         return imagepolygon($this -> image_resource, $points, 4, $color);
  277.     }
  278.    
  279.    
  280.     /**
  281.      * Outputs the image to the screen
  282.      *
  283.      * This method outputs the current image to the screen.
  284.      * Note: This function does <b>not</b> send the right Content-Type
  285.      * for the image, you'll have to do that by yourself
  286.      * @param string $type The image type to output
  287.      * @param int $quality The quality of the image (only needed for JPEG images)
  288.      */
  289.     public function show_image($type = "png", $quality = 70)
  290.     {
  291.         switch($type)
  292.         {
  293.             case "png":
  294.                 imagepng($this -> image_resource);
  295.             break;
  296.             case "jpg":
  297.             case "jpeg":
  298.                 imagejpeg($this -> image_resource, null, $quality);
  299.             break;
  300.             case "gif":
  301.                 imagegif($this -> image_resource);
  302.             break;
  303.             default:
  304.                 imagepng($this -> image_resource);
  305.         }
  306.     }
  307.  
  308.     /**
  309.      * Saves the image to a specific path
  310.      * @param string $file The path where to save to
  311.      * @param string $type The image type
  312.      * @param int $quality The quality of the image (only needed for JPEG images)
  313.      */
  314.     public function save_to_file($file, $type = "png", $quality = 70)
  315.     {
  316.         switch($type)
  317.         {
  318.             case "png":
  319.                 imagepng($this -> image_resource, $file);
  320.             break;
  321.             case "jpg":
  322.             case "jpeg":
  323.                 imagejpeg($this -> image_resource, $file, $quality);
  324.             break;
  325.             case "gif":
  326.                 imagegif($this -> image_resource, $file);
  327.             break;
  328.             default:
  329.                 imagepng($this -> image_resource, $file);
  330.         }
  331.     }
  332.    
  333.     /**
  334.      * Returns the width of the image
  335.      *
  336.      * @return int
  337.      */
  338.     public function get_width()
  339.     {
  340.         return $this -> width;
  341.     }
  342.    
  343.     /**
  344.      * Returns the height of the image
  345.      *
  346.      * @return int
  347.      */
  348.     public function get_height()
  349.     {
  350.         return $this -> height;
  351.     }
  352.    
  353.     /**
  354.      * Outputs the image
  355.      */
  356.     public function __toString()
  357.     {
  358.         ob_start();
  359.         imagepng($this -> image_resource);
  360.         $contents = ob_get_contents();
  361.         ob_end_clean();
  362.        
  363.         return $contents;
  364.     }
  365. }
  366.