* */ namespace SparkLib\Image; class Compressor { const URL = 'http://www.punypng.com/api/optimize'; const DOWNLOAD_URL = 'http://www.punypng.com/processor/download_image'; const MAX_FILESIZE = 5242880; // PunyPNG limit, 5MB. private $_ch; public function __construct() { // PunyPNG API key must be defined if(!defined('PUNYPNG_KEY')) throw new \Exception('PunyPNG API key undefined'); // ensure curl library is available if(!function_exists('curl_version')) throw new \Exception('cURL library support is required'); // initialize curl $this->_ch = curl_init(self::URL); } public function __destruct() { curl_close($this->_ch); } /* * upload and compress the given file * * @param $file - full path to uncompressed image * @param $lossy - defaults to false, lossless and lossy formats * will still be availbe, this is only for logging purposes. * @return mixed, false on failure */ public function compress($file, $lossy = false) { if(!file_exists($file)) throw new \Exception('File not found: ' . $file); if(!is_file($file)) throw new \Exception('Invalid file: ' . $file); if(filesize($file) > self::MAX_FILESIZE) throw new \Exception($file . ' exceeds maximum file size of ' . self::MAX_FILESIZE . ' bytes'); $result = $this->upload($file); if(!$result->status) return false; if(!isset($result->optimized_url)) throw new \Exception('PunyPNG API did not return a download URL'); if($lossy && !isset($result->indexed_url)) throw new \Exception('PunyPNG API did not return a lossy download URL'); // Log successful result $ics = new \ImageCompressionSaurus(); $ics->original_size = $result->original_size; if($lossy) $ics->optimized_size = ($result->original_size - $result->indexed_savings_bytes); else $ics->optimized_size = $result->optimized_size; $ics->ctime = \SparkLib\DB::Now(); $ics->insert(); return $result; } /* * download the optimized image * * @param $file mixed - this can either be the url * or the return value from compress() * @param $save_path - full save path for the downloaded image * @param $lossy boolean - if passing the result of compress(), specify * whether you'd like the lossy or lossless image. Defaults to false. */ public function download($file, $save_path, $lossy = false) { if(!is_string($file)) { if($lossy) { if(!isset($file->indexed_url)) throw new \Exception('missing indexed download url'); $file = $file->indexed_url; } else { if(!isset($file->optimized_url)) throw new \Exception('missing optimized download url'); $file = $file->optimized_url; } } curl_setopt($this->_ch, CURLOPT_URL, $file); curl_setopt($this->_ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($this->_ch, CURLOPT_FILE, fopen($save_path, 'w')); return curl_exec($this->_ch); } /* * upload the given file to PunyPNG for compression * * @return mixed - PunyPNG API Response and status code */ private function upload($file) { $postdata = [ 'key' => PUNYPNG_KEY, 'img' => new \CURLFile($file) ]; curl_setopt($this->_ch, CURLOPT_URL, self::URL); curl_setopt($this->_ch, CURLOPT_POST, true); curl_setopt($this->_ch, CURLOPT_POSTFIELDS, $postdata); curl_setopt($this->_ch, CURLOPT_RETURNTRANSFER, true); $result = json_decode(curl_exec($this->_ch)); $result->status = (curl_getinfo($this->_ch, CURLINFO_HTTP_CODE) === 200); return $result; } }