├── README.md ├── config.php ├── curl.class.php ├── imagick.class.php ├── nginx_test.img.conf ├── resize.php ├── upload.php └── watermark ├── .svn ├── all-wcprops ├── dir-prop-base ├── entries ├── prop-base │ ├── coke.png.svn-base │ ├── money.png.svn-base │ └── youxinpai.png.svn-base └── text-base │ ├── coke.png.svn-base │ ├── money.png.svn-base │ └── youxinpai.png.svn-base ├── coke.png ├── money.png └── youxinpai.png /README.md: -------------------------------------------------------------------------------- 1 | FastDFS_Imagick 2 | =============== 3 | 4 | 研究FastDFS有一段时间,因为现有业务图片存储每天以G级增量,考虑使用FastDFS架设图片服务,用PHP做图片切割处理然后上传,从而达到永久化效果 5 | -------------------------------------------------------------------------------- /config.php: -------------------------------------------------------------------------------- 1 | 5 | * @modify 2013-05-20 21:05:09 6 | * 7 | */ 8 | 9 | /** 10 | * 项目定义 11 | * array(app => key,...) 12 | * array(应用名称=>密钥,...) 13 | * 14 | */ 15 | $_CONFIG_APP_KEY = array( 16 | 'test' => 'youxinpai', 17 | ); 18 | 19 | //宽高最大值,为保证原始文件过大 20 | $_CONFIG_MAX_SIZE = 1600; 21 | //默认压缩质量 22 | $_CONFIG_COMPRESS_QUALITY = 85; 23 | 24 | //默认水印图片 25 | $_CONFIG_WATERMARK_IMG = 'watermark/youxinpai.png'; 26 | 27 | //默认水印边距 28 | $_CONFIG_WATERMARK_MARGIN = 20; 29 | /** 30 | * 图片路径对应尺寸 31 | * 两位字符图片后缀,支持_[0-9a-z]{2}路径 32 | * 后缀名 => array(...) 33 | * 'width'=>宽:生成图片的宽度 34 | * 'height'=>高:生成图片的高度 35 | * 'model'=>压缩模式:默认模式表示剪切压缩,为1表示尺寸不超过定义的宽和高,为2表示居中四周补白边, 36 | * 'quality'=>压缩质量,为0使用默认压缩质量 37 | * 'wmp'=>水印位置:(象限表示法)默认0不添加水印,1右上角,2右下角,3左下角,4左上角,5中心,6随机。 38 | * 'wmi'=>水印图片:水印图片文件路径,相对于当前文件路径或绝对路径。 39 | * 'wmm'=>水印边距,为0使用默认。 40 | */ 41 | $_CONFIG_IMG_SIZE = array( 42 | '01' => array( 43 | 'width' => 800, 44 | 'height' => 600, 45 | 'wmp' => 1, 46 | ), 47 | '02' => array( 48 | 'width' => 640, 49 | 'height' => 480, 50 | 'model' => 1, 51 | 'wmp' => 2, 52 | ), 53 | '03' => array( 54 | 'width' => 640, 55 | 'height' => 480, 56 | 'model' => 2, 57 | 'wmp' => 3, 58 | ), 59 | '04' => array( 60 | 'width' => 640, 61 | 'height' => 480, 62 | 'wmp' => 4, 63 | ), 64 | '05' => array( 65 | 'width' => 640, 66 | 'height' => 480, 67 | 'model' => 1, 68 | 'wmp' => 5, 69 | ), 70 | '06' => array( 71 | 'width' => 640, 72 | 'height' => 480, 73 | 'model' => 2, 74 | 'wmp' => 6, 75 | ), 76 | ); -------------------------------------------------------------------------------- /curl.class.php: -------------------------------------------------------------------------------- 1 | 3 10 | $client = new curl_class(array( 11 | 12 | CURLOPT_FRESH_CONNECT => 1, 13 | CURLOPT_TIMEOUT => 30, 14 | CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3' 15 | 16 | ), $max_redirect); 17 | 18 | $client->setResponseSequenceFlag(true); // Skipable: default => false 19 | $client->setMetaRedirectFlag(false); // Skipable: default => true 20 | $client->setCompression('gzip,deflate'); // Skipable: default => '' 21 | 22 | $url = 'http://example.com/index.php'; 23 | $client->get($url); 24 | 25 | $url = 'http://example.com/login.php'; 26 | $params = array('id' => 'user_id', 'pass' => 'user_pass'); 27 | $client->post($url, $params); 28 | 29 | $url = 'http://example.com/login_2.php'; 30 | $client->get($url); 31 | 32 | print_r($client->currentResponse()); 33 | echo $client->currentResponse('body'); 34 | 35 | $cookies = $client->getCurrentCookies(); 36 | print_r($cookies); 37 | 38 | echo $client->getCurrentCookies('session_key'); 39 | */ 40 | 41 | class curl_class { 42 | 43 | private $_parse_url; 44 | private $_options; 45 | private $_current_redirect; 46 | private $_max_redirect; 47 | private $_responses; 48 | private $_response_parts; 49 | private $_response_sequence_flag = false; 50 | private $_meta_redirect_flag = true; 51 | private $_compression = ''; 52 | private $_cookies = array(); 53 | private $_default_options = array(); 54 | private $_basic_info = array(); 55 | 56 | public function __construct($default_options=array(), $max_redirect=3) { 57 | 58 | if($default_options != array()) { 59 | 60 | $this->setDefaultOptions($default_options); 61 | 62 | } 63 | 64 | $this->setMaxRedirect($max_redirect); 65 | 66 | } 67 | 68 | public function setDefaultOptions($default_options) { 69 | 70 | $this->_default_options = $default_options; 71 | 72 | } 73 | 74 | public function setMaxRedirect($max_redirect) { 75 | 76 | $this->_max_redirect = intval($max_redirect); 77 | 78 | } 79 | 80 | public function setResponseSequenceFlag($bool) { 81 | 82 | $this->_response_sequence_flag = $bool; 83 | 84 | } 85 | 86 | public function setMetaRedirectFlag($bool) { 87 | 88 | $this->_meta_redirect_flag = $bool; 89 | 90 | } 91 | 92 | public function setCompression($str) { 93 | 94 | $this->_compression = $str; 95 | 96 | } 97 | 98 | public function get($url) { 99 | 100 | //$this->reset(); 101 | $this->refreshOption(); 102 | 103 | //add rhf 2013/5/24 如果是get请求重试三次 104 | for($i = 0; $i < 3; $i++) { 105 | $this->request($url); 106 | if($this->_response_parts[0]['code'] == 200) { 107 | return ; 108 | } 109 | } 110 | } 111 | 112 | public function post($url, $params) { 113 | 114 | $this->refreshOption(); 115 | $this->_options[CURLOPT_POST] = true; 116 | $this->_options[CURLOPT_POSTFIELDS] = $this->getPostData($params); 117 | $this->request($url); 118 | 119 | } 120 | 121 | private function getPostData($datas) { 122 | 123 | $returns = array(); 124 | 125 | foreach($datas as $key => $value) { 126 | 127 | $returns[] = $key .'='. urlencode($value); 128 | 129 | } 130 | 131 | return implode('&', $returns); 132 | 133 | } 134 | 135 | private function redirect($target_url, $referer_url) { 136 | 137 | $this->refreshOption(); 138 | $this->_options[CURLOPT_REFERER] = $referer_url; 139 | $this->request($target_url, true); 140 | 141 | } 142 | 143 | private function refreshOption() { 144 | 145 | $this->_options = $this->_default_options; 146 | $this->_options[CURLOPT_HEADER] = true; 147 | $this->_options[CURLOPT_RETURNTRANSFER] = true; 148 | $this->_options[CURLOPT_SSL_VERIFYPEER] = false; 149 | $this->_options[CURLOPT_SSL_VERIFYHOST] = false; 150 | $this->_options[CURLOPT_ENCODING] = $this->_compression; 151 | 152 | } 153 | 154 | private function request($request_url, $redirect_flag=false) { 155 | 156 | if($request_url == '') { 157 | 158 | return false; 159 | 160 | } else { 161 | 162 | $this->setUrlInfo($request_url); 163 | $url_info = $this->getUrlInfo(); 164 | $host = $url_info['host']; 165 | $basic_user = $url_info['user']; 166 | $basic_pass = $url_info['pass']; 167 | 168 | if($basic_user != '' && $basic_pass != '') { 169 | 170 | $basic_code = $basic_user .':'. $basic_pass; 171 | $this->setBasicCode($host, $basic_code); 172 | $request_url = str_replace('://'. $basic_code .'@', '://', $request_url); 173 | 174 | } else { 175 | 176 | $basic_code = $this->getBasicCode($host); 177 | 178 | } 179 | 180 | if($basic_code) { 181 | 182 | $this->_options[CURLOPT_USERPWD] = $basic_code; 183 | 184 | } 185 | 186 | $this->_options[CURLOPT_URL] = $request_url; 187 | 188 | } 189 | 190 | if(!$redirect_flag) { 191 | 192 | $this->_current_redirect = 1; 193 | $this->_response_parts = array(); 194 | 195 | } 196 | 197 | $ch = curl_init(); 198 | $this->setOptionsSavedCookie(); 199 | curl_setopt_array($ch, $this->_options); 200 | curl_exec($ch); 201 | $curl_info = curl_getinfo($ch); 202 | $curl_content = curl_multi_getcontent($ch); 203 | curl_close($ch); 204 | 205 | $url = $curl_info['url']; 206 | $code = $curl_info['http_code']; 207 | $headers = $this->getHeaders(substr($curl_content, 0, $curl_info['header_size'])); 208 | $body = substr($curl_content, $curl_info['header_size']); 209 | $this->_response_parts[] = array( 210 | 211 | 'url' => $url, 212 | 'code' => $code, 213 | 'headers' => $headers, 214 | 'body' => $body 215 | 216 | ); 217 | 218 | $header_location = $headers['location']; 219 | 220 | if($header_location == '' && $this->_meta_redirect_flag) { 221 | 222 | $header_location = $this->getMetaRedirectUrl($body); 223 | 224 | } 225 | 226 | if($header_location != '' && $this->_current_redirect <= $this->_max_redirect) { 227 | 228 | $this->_current_redirect++; 229 | $header_location = $this->getAbsolutePath($url, $header_location); 230 | $this->redirect($header_location, $url); 231 | 232 | } else { 233 | 234 | if($this->_response_sequence_flag) { 235 | 236 | $this->_responses[] = $this->_response_parts; 237 | 238 | } else { 239 | 240 | $this->_responses[0][0] = $this->_response_parts[count($this->_response_parts)-1]; 241 | 242 | } 243 | 244 | } 245 | 246 | } 247 | 248 | public function getAbsolutePath($base_url='', $relative_path='') { 249 | 250 | $base_urls = explode('/', $base_url); 251 | $base_urls_max_number = count($base_urls)-1; 252 | $base_urls[$base_urls_max_number] = ''; 253 | $base_url = implode('/', $base_urls); 254 | 255 | $parse = array(); 256 | $parse = parse_url($base_url); 257 | 258 | if(preg_match('|^http[s]?://|', $relative_path)) { 259 | 260 | return $relative_path; 261 | 262 | } else if(preg_match('|^/.*$|', $relative_path)) { 263 | 264 | return $parse['scheme'] .'://'. $parse['host']. $relative_path; 265 | 266 | } else { 267 | 268 | $a = $this->getRealArray(split('/', $parse['path'])); 269 | $b = $this->getRealArray(split('/', $relative_path)); 270 | 271 | foreach($b as $v){ 272 | 273 | if ($v == '.') {} 274 | else if($v == '..') { array_pop($a); } 275 | else if($v != '') { array_push($a, $v); } 276 | 277 | } 278 | 279 | $path = join('/', $a); 280 | return $parse['scheme'] .'://'. $parse['host'] .'/'. $path; 281 | 282 | } 283 | 284 | } 285 | 286 | private function getRealArray($data) { 287 | 288 | $return = array(); 289 | 290 | foreach($data as $key => $value) { 291 | 292 | if($value != '') { 293 | 294 | $return[] = $value; 295 | 296 | } 297 | 298 | } 299 | 300 | return $return; 301 | 302 | } 303 | 304 | private function getMetaRedirectUrl($body) { 305 | 306 | if(!preg_match('!]*http-equiv\\s*=\\s*("Refresh"|\'Refresh\'|Refresh)[^>]*)>!is', $body, $matches)) { 307 | 308 | return ''; 309 | 310 | } 311 | 312 | if(!preg_match('!content\\s*=\\s*("[^"]+"|\'[^\']+\'|\\S+)!is', $matches[1], $urlMatches)) { 313 | 314 | return ''; 315 | 316 | } 317 | 318 | $parts = explode(';', ('\'' == substr($urlMatches[1], 0, 1) || '"' == substr($urlMatches[1], 0, 1))? 319 | substr($urlMatches[1], 1, -1): $urlMatches[1]); 320 | 321 | if(!preg_match('/url\\s*=\\s*("[^"]+"|\'[^\']+\'|\\S+)/is', $parts[1], $urlMatches)) { 322 | 323 | return ''; 324 | 325 | } 326 | 327 | return trim($urlMatches[1]); 328 | 329 | } 330 | 331 | private function setUrlInfo($url) { 332 | 333 | $this->_parse_url = parse_url($url); 334 | 335 | } 336 | 337 | private function getUrlInfo($place='') { 338 | 339 | if($place != '') { 340 | 341 | return $this->_parse_url[$place]; 342 | 343 | } else { 344 | 345 | return $this->_parse_url; 346 | 347 | } 348 | 349 | } 350 | 351 | private function setBasicCode($host, $code) { 352 | 353 | $this->_basic_info['H:'. $host] = $code; 354 | 355 | } 356 | 357 | private function getBasicCode($host) { 358 | 359 | return $this->_basic_info['H:'. $host]; 360 | 361 | } 362 | 363 | private function getHeaders($header_content) { 364 | 365 | if($header_content == '') return ''; 366 | 367 | $headers = array(); 368 | 369 | preg_match_all('|(.+): (.+)|', $header_content, $matches); 370 | $matches_count = count($matches[0]); 371 | 372 | if($matches_count > 0) { 373 | 374 | for($loop2 = 0; $loop2 < $matches_count; $loop2++) { 375 | 376 | $header_name = strtolower($matches[1][$loop2]); 377 | $header_value = trim($matches[2][$loop2]); 378 | 379 | if($header_name == 'set-cookie') { 380 | 381 | $this->addCookie($header_value); 382 | 383 | } else { 384 | 385 | $headers[$header_name] = $header_value; 386 | 387 | } 388 | 389 | } 390 | 391 | $header_number++; 392 | 393 | } 394 | 395 | return $headers; 396 | 397 | } 398 | 399 | function addCookie($cookie_content) { 400 | 401 | $cookie_datas = explode(';', $cookie_content); 402 | $cookie_datas = array_map('trim', $cookie_datas); 403 | $cookie_datas_count = count($cookie_datas); 404 | 405 | $cookie_contents = array(); 406 | $pattern_1 = '!^(expires|path|domain|secure)=(.*)!i'; 407 | $pattern_2 = '!^([^=]+)=(.*)!'; 408 | 409 | for($loop = 0; $loop < $cookie_datas_count; $loop++) { 410 | 411 | $cookie_data = $cookie_datas[$loop]; 412 | 413 | if(preg_match($pattern_1, $cookie_data, $matches)) { 414 | 415 | $name = $matches[1]; 416 | $value = $matches[2]; 417 | $cookie_contents[$name] = $value; 418 | 419 | } else if(preg_match($pattern_2, $cookie_data, $matches)) { 420 | 421 | $name = $matches[1]; 422 | $value = $matches[2]; 423 | $cookie_contents['argument'] = array('name' => $name, 'value' => $value); 424 | 425 | } 426 | 427 | } 428 | 429 | $cookie_host = $this->getUrlInfo('host'); 430 | 431 | $expires = $cookie_contents['expires']; 432 | $domain = $cookie_contents['domain']; 433 | $path = $cookie_contents['path']; 434 | $secure = intval($cookie_contents['secure']); 435 | $argument_name = $cookie_contents['argument']['name']; 436 | $argument_value = $cookie_contents['argument']['value']; 437 | 438 | if($domain == '') $domain = $this->getUrlInfo('host'); 439 | if(substr($domain, 0, 1) == '.') $domain = substr($domain, 1); 440 | if($path == '') $path = '/'; 441 | 442 | $domain_var_name = '[D]:'. $domain; 443 | $path_var_name = '[P]:'. $path; 444 | $this->_cookies[$domain_var_name][$path_var_name][$argument_name] = array( 445 | 446 | 'value' => $argument_value, 447 | 'expires' => $expires, 448 | 'secure' => $secure 449 | 450 | ); 451 | 452 | } 453 | 454 | private function setOptionsSavedCookie() { 455 | 456 | $current_cookies = $this->getCurrentCookies(); 457 | 458 | if(count($current_cookies) > 0) { 459 | 460 | $cookie_option_values = array(); 461 | 462 | foreach($current_cookies as $cookie_name => $value) { 463 | 464 | $cookie_option_values[] = $cookie_name .'='. $value; 465 | 466 | } 467 | 468 | $this->_options[CURLOPT_COOKIE] = implode('; ', $cookie_option_values); 469 | 470 | } else { 471 | 472 | unset($this->_options[CURLOPT_COOKIE]); 473 | 474 | } 475 | 476 | } 477 | 478 | public function getCurrentCookies($key='') { 479 | 480 | $returns = array(); 481 | $access_protocol = $this->getUrlInfo('protocol'); 482 | $access_domain = $this->getUrlInfo('host'); 483 | $access_path = $this->getUrlInfo('path'); 484 | $cookie_option_values = array(); 485 | 486 | foreach($this->_cookies as $cookie_domain => $domain_infos) { 487 | 488 | $cookie_domain = substr($cookie_domain, 4); 489 | 490 | if($cookie_domain == substr($access_domain, 0-strlen($cookie_domain))) { 491 | 492 | foreach($domain_infos as $cookie_path => $cookie_infos) { 493 | 494 | $cookie_path = substr($cookie_path, 4); 495 | $access_domain_path = $access_domain . $access_path; 496 | $cookie_domain_path = $cookie_domain . $cookie_path; 497 | 498 | if(!substr($cookie_domain_path, -1) == '/') { 499 | 500 | $cookie_domain_path .= '/'; 501 | 502 | } 503 | 504 | if($cookie_path == '/' || $cookie_domain_path == substr($access_domain_path, 0, strlen($cookie_domain_path))) { 505 | 506 | foreach($cookie_infos as $cookie_name => $cookie_values) { 507 | 508 | $secure = $cookie_values['secure']; 509 | $value = $cookie_values['value']; 510 | 511 | if($secure == 0 || ($secure == 1 && $access_protocol == 'https')) { 512 | 513 | $returns[$cookie_name] = $value; 514 | 515 | } 516 | 517 | } 518 | 519 | } 520 | 521 | } 522 | 523 | } 524 | 525 | } 526 | 527 | if($key != '') { 528 | 529 | return $returns[$key]; 530 | 531 | } else { 532 | 533 | return $returns; 534 | 535 | } 536 | 537 | } 538 | 539 | public function response($response_number='') { 540 | 541 | if(!is_numeric($response_number)) { 542 | 543 | return $this->_responses; 544 | 545 | } else { 546 | 547 | return $this->_responses[$response_number]; 548 | 549 | } 550 | 551 | } 552 | 553 | public function currentResponse($place='', $number=0) { 554 | 555 | $current_response = $this->response(count($this->_responses) - 1); 556 | $max_number = count($current_response)-1; 557 | 558 | if($place == '') { 559 | 560 | return $current_response[$max_number]; 561 | 562 | } else { 563 | 564 | return $current_response[$max_number][$place]; 565 | 566 | } 567 | 568 | } 569 | 570 | public function reset() { 571 | 572 | $this->_cookies = array(); 573 | $this->_responses = array(); 574 | 575 | } 576 | 577 | } 578 | 579 | -------------------------------------------------------------------------------- /imagick.class.php: -------------------------------------------------------------------------------- 1 | 5 | * @modify 2013-05-20 21:05:09 6 | * 7 | */ 8 | 9 | class imagick_class 10 | { 11 | /** 12 | * 压缩图片,二进制方式 13 | * @param $buff 源图片二进制内容(必选) 14 | * @param $width 生成图片宽(必选) 15 | * @param $height 生成图片高(必选) 16 | * @param $config['model'] 压缩方式,默认剪切压缩,对应配置文件config.php压缩方式 17 | * @param $config['quality'] 压缩质量 18 | * @param $config['wmp'] 水印位置,为0不添加水印,对应配置文件config.php水印位置 19 | * @param $config['wmi'] 水印图片路径,只有当添加水印时有效,为空使用默认水印图片 20 | * @param $config['wmm'] 水印图片边距,默认20 21 | * @return array('buff'=>生成的图片二进制内容,'width'=>宽,'height'=>高) 22 | */ 23 | public function compress_buff($buff, $width, $height, $config=array()) 24 | { 25 | $imagick = new Imagick(); 26 | $imagick->readImageBlob($buff); 27 | $format = $imagick->getImageFormat(); 28 | //不同压缩模式分别处理 29 | if ($config['model'] == 1) //自适应 30 | { 31 | $imagick->resizeImage($width, $height, Imagick::FILTER_CATROM, 1, true); 32 | $width = $imagick->getImageWidth(); 33 | $height = $imagick->getImageHeight(); 34 | if (!$width || !$height) 35 | { 36 | return false; 37 | } 38 | 39 | } 40 | elseif ($config['model'] == 2) //四周补白 41 | { 42 | $w = $imagick->getImageWidth(); 43 | $h = $imagick->getImageHeight(); 44 | $background = new ImagickPixel('white'); 45 | if (!$w || !$h) 46 | { 47 | return false; 48 | } 49 | if ($w/$h > $width/$height) //上下补白 50 | { 51 | //以宽度进行缩放 52 | $imagick->resizeImage($width, 3600, Imagick::FILTER_CATROM, 1, true); 53 | $w = $width; 54 | $h = $imagick->getImageHeight(); 55 | //补白 56 | $canvas = new Imagick(); 57 | $canvas->newImage($width, $height, $background, $format); 58 | $canvas->compositeImage($imagick, Imagick::COMPOSITE_OVER, 0, floor(($height-$h)/2)); 59 | $imagick = $canvas; 60 | } 61 | else 62 | { 63 | //以高度进行缩放 64 | $imagick->resizeImage(3600, $height, Imagick::FILTER_CATROM, 1, true); 65 | $w = $imagick->getImageWidth(); 66 | $h = $height; 67 | //补白 68 | $canvas = new Imagick(); 69 | $canvas->newImage($width, $height, $background, $format); 70 | $canvas->compositeImage($imagick, Imagick::COMPOSITE_OVER, floor(($width-$w)/2), 0); 71 | $imagick = $canvas; 72 | } 73 | } 74 | else //缩放后裁边 75 | { 76 | $w = $imagick->getImageWidth(); 77 | $h = $imagick->getImageHeight(); 78 | if (!$w || !$h) 79 | { 80 | return false; 81 | } 82 | if ($w/$h > $width/$height) 83 | { 84 | //以高度进行缩放 85 | $imagick->resizeImage(3600, $height, Imagick::FILTER_CATROM, 1, true); 86 | $imagick->cropImage($width, $height, ceil(($height*$w/$h-$width)/2) , 0); 87 | } 88 | else 89 | { 90 | //以宽度进行缩放 91 | $imagick->resizeImage($width, 3600, Imagick::FILTER_CATROM, 1, true); 92 | $imagick->cropImage($width, $height, 0, ceil(($width*$h/$w-$height)/2)); 93 | } 94 | } 95 | 96 | //添加水印 todo... 97 | if ($config['wmp']) 98 | { 99 | $water = new Imagick($config['wmi']); 100 | $water_page = $water->getImagePage(); 101 | $w = $water_page['width']; 102 | $h = $water_page['height']; 103 | if ($config['wmp'] == 1) 104 | { 105 | $x = $width - $w - $config['wmm']; 106 | $y = $config['wmm']; 107 | } 108 | elseif ($config['wmp'] == 2) 109 | { 110 | $x = $width - $w - $config['wmm']; 111 | $y = $height - $h - $config['wmm']; 112 | 113 | } 114 | elseif ($config['wmp'] == 3) 115 | { 116 | $x = $config['wmm']; 117 | $y = $height - $h - $config['wmm']; 118 | } 119 | elseif ($config['wmp'] == 4) 120 | { 121 | $x = $y = $config['wmm']; 122 | } 123 | elseif ($config['wmp'] == 5) 124 | { 125 | $x = ceil(($width - $w)/2); 126 | $y = ceil(($height - $h)/2); 127 | } 128 | else 129 | { 130 | $x = rand(($config['wmm']), ($width - $w - $config['wmm'])); 131 | $y = rand(($config['wmm']), ($height - $h - $config['wmm'])); 132 | } 133 | $imagick->compositeImage($water, Imagick::COMPOSITE_OVER, $x, $y); 134 | } 135 | //设置压缩质量 136 | if ($config['quality']) 137 | { 138 | $imagick->setImageCompressionQuality($config['quality']); 139 | } 140 | 141 | //去除exif信息 142 | $imagick->stripImage(); 143 | $buff = $imagick->getImageBlob(); 144 | return array('buff'=>$buff, 'width'=>$width, 'height'=>$height, 'format'=>$format); 145 | } 146 | 147 | 148 | } 149 | -------------------------------------------------------------------------------- /nginx_test.img.conf: -------------------------------------------------------------------------------- 1 | server { 2 | # Replace this port with the right one for your requirements 3 | listen 80; #could also be 1.2.3.4:80 4 | 5 | # Multiple hostnames separated by spaces. Replace these as well. 6 | server_name test.img.com; 7 | 8 | root /home/www/test.img.com/; 9 | autoindex on; 10 | error_page 404 = resize.php; 11 | index index.php index.html; 12 | 13 | 14 | #error_page 404 errors/404.html; 15 | #access_log logs/test.img.com.access.log; 16 | 17 | index index.php index.html; 18 | 19 | # static file 404's aren't logged and expires header is set to maximum age 20 | access_log off; 21 | expires max; 22 | 23 | location /g1/M00 { 24 | alias /opt/fastdfs/data; 25 | ngx_fastdfs_module; 26 | } 27 | 28 | 29 | 30 | location ~ \.php$ { 31 | include fastcgi_params; 32 | #fastcgi_intercept_errors on; 33 | # By all means use a different server for the fcgi processes if you need to 34 | fastcgi_pass 127.0.0.1:9000; 35 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 36 | 37 | 38 | } 39 | 40 | 41 | 42 | } 43 | 44 | -------------------------------------------------------------------------------- /resize.php: -------------------------------------------------------------------------------- 1 | 5 | * @Modify 2013-05-20 21:12:21 6 | */ 7 | 8 | require('config.php'); 9 | require('imagick.class.php'); 10 | 11 | $url = $_SERVER['REQUEST_URI']; 12 | if (!preg_match('/^\/([0-9a-z_\-\/]{43})_([0-9a-z]{2})\.(jpg|png|gif|bmp)$/i', $url, $match)) 13 | { 14 | err404(); 15 | } 16 | //print_r($match);exit; 17 | //原图 18 | $remote_filename = $match[1].'.'.$match[3]; 19 | //echo $remote_filename; 20 | 21 | //尺寸编码 22 | $config = $_CONFIG_IMG_SIZE[$match[2]]; 23 | if (!$config) //请求尺寸不存在 24 | { 25 | err404(); 26 | } 27 | 28 | if (!$config['quality']) 29 | { 30 | $config['quality'] = $_CONFIG_COMPRESS_QUALITY; 31 | } 32 | if ($config['wmp']) //需要添加水印 33 | { 34 | if (!$config['wmi']) 35 | { 36 | $config['wmi'] = $_CONFIG_WATERMARK_IMG; 37 | } 38 | if (!$config['wmm']) 39 | { 40 | $config['wmm'] = $_CONFIG_WATERMARK_MARGIN; 41 | } 42 | } 43 | 44 | //下载原图 45 | $imgdata = fastdfs_storage_download_file_to_buff1($remote_filename); 46 | if (!$imgdata) 47 | { 48 | err404(); 49 | } 50 | //压缩处理 51 | $img = new imagick_class(); 52 | $ret = $img->compress_buff($imgdata, $config['width'], $config['height'], $config); 53 | $imgdata = $ret['buff']; 54 | 55 | //显示 56 | header('Content-Type: image/'.$ret['format']); 57 | header('Content-Length: '.strlen($imgdata)); 58 | echo $imgdata; 59 | 60 | //上传 61 | $prefix_name = '_'.$match[2]; 62 | $ext_name = $match[3]; 63 | fastdfs_storage_upload_slave_by_filebuff1($imgdata, $remote_filename, $prefix_name, $ext_name); 64 | 65 | 66 | 67 | /** 68 | * 返回404 69 | */ 70 | function err404() 71 | { 72 | header('HTTP/1.1 404 Not Found'); 73 | header("status: 404 Not Found"); 74 | exit; 75 | } 76 | -------------------------------------------------------------------------------- /upload.php: -------------------------------------------------------------------------------- 1 | 5 | * @Modify 2013-05-29 21:12:21 6 | * 7 | * 通过POST方式上传图片或图片URL,本程序返回存储后的图片路径和尺寸。 8 | * @param app 应用名,key 应用密钥 9 | * @param method,默认post文件流$_FILES['pic'],form表单 10 | * method=url以POST图片URL地址的方式$_POST['pic']='http://img.....jpg',自动去抓取并存储。 11 | * method=buff以POST图片文件buff方式上传$_POST['pic']=图片文件二进制数据 12 | * @return width图片宽度,height图片高度。 13 | */ 14 | 15 | require('config.php'); 16 | require('imagick.class.php'); 17 | 18 | //验证app key 19 | if ( !$_POST['app'] || !$_CONFIG_APP_KEY[$_POST['app']] || ($_CONFIG_APP_KEY[$_POST['app']] != $_POST['key']) ) 20 | { 21 | err_ret('app key error.'); 22 | } 23 | 24 | if ($_POST['method'] == 'url') //URL方式上传 25 | { 26 | // require('curl.class.php'); 27 | // $curl = new curl_class(); 28 | // $curl->get($_POST['pic']); 29 | // if ($buff = $curl->currentResponse('body')) 30 | if ($buff = file_get_contents($_POST['pic'])) 31 | { 32 | $imagick = new Imagick(); 33 | if ( $imagick->readImageBlob($buff) ) 34 | { 35 | resize_upload($imagick); 36 | } 37 | else 38 | { 39 | err_ret("url's content is not pic."); 40 | } 41 | 42 | } 43 | else 44 | { 45 | err_ret('file not exists.'); 46 | } 47 | 48 | } 49 | elseif ($_POST['method'] == 'buff') //POST buff方式上传 50 | { 51 | if ($buff = $_POST['pic']) 52 | { 53 | $imagick = new Imagick(); 54 | if ( $imagick->readImageBlob($buff) ) 55 | { 56 | resize_upload($imagick); 57 | } 58 | else 59 | { 60 | err_ret("post buff is not pic."); 61 | } 62 | 63 | } 64 | else 65 | { 66 | err_ret('file buff is empty.'); 67 | } 68 | } 69 | else 70 | { 71 | if ($_FILES['pic']['size']) 72 | { 73 | $imagick = new Imagick(); 74 | if ( $imagick->readImage($_FILES['pic']['tmp_name']) ) 75 | { 76 | unlink($_FILES['pic']['tmp_name']); 77 | resize_upload($imagick); 78 | 79 | } 80 | else 81 | { 82 | err_ret("post file is not pic."); 83 | } 84 | 85 | } 86 | else 87 | { 88 | err_ret('post file is empty.'); 89 | } 90 | } 91 | //处理图片 92 | function resize_upload($imagick) 93 | { 94 | global $_CONFIG_MAX_SIZE; 95 | $width = $imagick->getImageWidth(); 96 | $height = $imagick->getImageHeight(); 97 | if ($width > $height && $width > $_CONFIG_MAX_SIZE) 98 | { 99 | $width = $_CONFIG_MAX_SIZE; 100 | $imagick->resizeImage($_CONFIG_MAX_SIZE, $_CONFIG_MAX_SIZE, Imagick::FILTER_CATROM, 1, true); 101 | $height = $imagick->getImageHeight(); 102 | } 103 | elseif ($height > $width && $height > $_CONFIG_MAX_SIZE) 104 | { 105 | $height = $_CONFIG_MAX_SIZE; 106 | $imagick->resizeImage($_CONFIG_MAX_SIZE, $_CONFIG_MAX_SIZE, Imagick::FILTER_CATROM, 1, true); 107 | $width = $imagick->getImageWidth(); 108 | } 109 | $file_ext_name = strtolower($imagick->getImageFormat()); 110 | if (!$file_ext_name || $file_ext_name == 'jpeg') 111 | { 112 | $imagick->setImageFormat('jpeg'); 113 | $file_ext_name = 'jpg'; 114 | } 115 | $buff = $imagick->getImageBlob(); 116 | if ($ret = fastdfs_storage_upload_by_filebuff1($buff, $file_ext_name)) 117 | { 118 | $ret = '/'.$ret; 119 | ok_ret($ret, $width, $height); 120 | exit; 121 | } 122 | else 123 | { 124 | err_ret('upload fail.'); 125 | } 126 | 127 | } 128 | 129 | /** 130 | * 成功时返回 131 | * @param $pic 文件名 132 | * @param $width 宽 133 | * @param $height 高 134 | */ 135 | function ok_ret($pic, $width, $height) 136 | { 137 | if ($_POST['backurl']) 138 | { 139 | $url = $_POST['backurl'].'?code=1&pic='.$pic.'&width='.$width.'&height='.$height; 140 | header('location:'.$url); 141 | } 142 | else 143 | { 144 | $json = array('code'=>1, 'pic'=>$pic, 'width'=>$width, 'height'=>$height); 145 | echo json_encode($json); 146 | } 147 | exit; 148 | } 149 | //失败返回信息 150 | function err_ret( $msg ) 151 | { 152 | if ($_POST['backurl']) 153 | { 154 | $url = $_POST['backurl'].'?code=-1&msg='.$msg; 155 | header('location:'.$url); 156 | } 157 | else 158 | { 159 | $json = array('code'=>-1, 'msg'=>$msg); 160 | echo json_encode($json); 161 | } 162 | exit; 163 | } -------------------------------------------------------------------------------- /watermark/.svn/all-wcprops: -------------------------------------------------------------------------------- 1 | K 25 2 | svn:wc:ra_dav:version-url 3 | V 56 4 | /svn/web/!svn/ver/825/img3.youxinpai.com/trunk/watermark 5 | END 6 | coke.png 7 | K 25 8 | svn:wc:ra_dav:version-url 9 | V 65 10 | /svn/web/!svn/ver/806/img3.youxinpai.com/trunk/watermark/coke.png 11 | END 12 | youxinpai.png 13 | K 25 14 | svn:wc:ra_dav:version-url 15 | V 70 16 | /svn/web/!svn/ver/825/img3.youxinpai.com/trunk/watermark/youxinpai.png 17 | END 18 | money.png 19 | K 25 20 | svn:wc:ra_dav:version-url 21 | V 66 22 | /svn/web/!svn/ver/806/img3.youxinpai.com/trunk/watermark/money.png 23 | END 24 | -------------------------------------------------------------------------------- /watermark/.svn/dir-prop-base: -------------------------------------------------------------------------------- 1 | K 10 2 | svn:ignore 3 | V 17 4 | youxinpai-80.png 5 | 6 | END 7 | -------------------------------------------------------------------------------- /watermark/.svn/entries: -------------------------------------------------------------------------------- 1 | 10 2 | 3 | dir 4 | 1039 5 | https://192.168.200.44/svn/web/img3.youxinpai.com/trunk/watermark 6 | https://192.168.200.44/svn/web 7 | 8 | 9 | 10 | 2013-05-28T05:59:15.970841Z 11 | 825 12 | gongziming 13 | has-props 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 5417a120-331b-9a43-85fe-210f7fe4acd4 28 | 29 | coke.png 30 | file 31 | 32 | 33 | 34 | 35 | 2013-05-28T00:54:50.152841Z 36 | a1a69da11d6db1c21bbc0b2e950c741e 37 | 2013-05-28T00:58:46.202073Z 38 | 806 39 | gongziming 40 | has-props 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 18241 62 | 63 | youxinpai.png 64 | file 65 | 66 | 67 | 68 | 69 | 2013-05-28T05:55:23.963841Z 70 | d70ae196b1ff9750a62d32be24bd16d8 71 | 2013-05-28T05:59:15.970841Z 72 | 825 73 | gongziming 74 | has-props 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 9321 96 | 97 | money.png 98 | file 99 | 100 | 101 | 102 | 103 | 2013-05-28T00:54:50.153841Z 104 | 63b41ef7881221852918d45ad76d9142 105 | 2013-05-28T00:58:46.202073Z 106 | 806 107 | gongziming 108 | has-props 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 26542 130 | 131 | -------------------------------------------------------------------------------- /watermark/.svn/prop-base/coke.png.svn-base: -------------------------------------------------------------------------------- 1 | K 13 2 | svn:mime-type 3 | V 24 4 | application/octet-stream 5 | END 6 | -------------------------------------------------------------------------------- /watermark/.svn/prop-base/money.png.svn-base: -------------------------------------------------------------------------------- 1 | K 13 2 | svn:mime-type 3 | V 24 4 | application/octet-stream 5 | END 6 | -------------------------------------------------------------------------------- /watermark/.svn/prop-base/youxinpai.png.svn-base: -------------------------------------------------------------------------------- 1 | K 13 2 | svn:mime-type 3 | V 24 4 | application/octet-stream 5 | END 6 | -------------------------------------------------------------------------------- /watermark/.svn/text-base/coke.png.svn-base: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iwangq/FastDFS_Imagick/ac06466f2bed5817c23880a1e4b6c95eb8aae368/watermark/.svn/text-base/coke.png.svn-base -------------------------------------------------------------------------------- /watermark/.svn/text-base/money.png.svn-base: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iwangq/FastDFS_Imagick/ac06466f2bed5817c23880a1e4b6c95eb8aae368/watermark/.svn/text-base/money.png.svn-base -------------------------------------------------------------------------------- /watermark/.svn/text-base/youxinpai.png.svn-base: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iwangq/FastDFS_Imagick/ac06466f2bed5817c23880a1e4b6c95eb8aae368/watermark/.svn/text-base/youxinpai.png.svn-base -------------------------------------------------------------------------------- /watermark/coke.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iwangq/FastDFS_Imagick/ac06466f2bed5817c23880a1e4b6c95eb8aae368/watermark/coke.png -------------------------------------------------------------------------------- /watermark/money.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iwangq/FastDFS_Imagick/ac06466f2bed5817c23880a1e4b6c95eb8aae368/watermark/money.png -------------------------------------------------------------------------------- /watermark/youxinpai.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iwangq/FastDFS_Imagick/ac06466f2bed5817c23880a1e4b6c95eb8aae368/watermark/youxinpai.png --------------------------------------------------------------------------------