2012-02-25 75 views
3

好吧,所以我意识到有这样的事情有成千上万的问题,但没有答案真的似乎覆盖我的需求。所以这是我的问题。为成千上万的图像添加动态水印?

我有一个房地产CRM系统,几家公司用来存储他们的财产细节和图像,然后我服务到各种不同的财产门户网站上,他们在这些门户网站上宣传上述财产。现在他们显然需要有照片进行水印处理,我的系统允许他们以两种方式进行水印处理,即在中间有一个透明的照片,或者在右下角有一个不透明的较小的照片。取决于此设置,这会反映在XML Feed中的图像URL中,该图像URL会生成并发送到各个网站。他们当然可以自由地改变那里的标志等等,而不会出现有图像的硬拷贝等问题。

现在,当使用右下角的水印时,没有问题,因为php的处理很少,但是当一些门户抓住所有的图像,我正在谈论数千+(并且每天和每个加入的公司都在增加),这自然会使VPS服务器超负荷运行,而且流动主机会让我停下来。这是我正在使用的第三方脚本,完美的作业只是使用了太多的资源。任何改进想法?我知道人们提到缓存,但每个图像都不同,可能只需要一次,那么它会受益多少?所有的帮助都是值得赞赏的,因为这是我在扩展系统时遇到的头痛问题。提前致谢!

<?php 
class watermark{ 

# given two images, return a blended watermarked image 
function create_watermark($main_img_obj, $watermark_img_obj, $alpha_level = 100) { 
    $alpha_level /= 100; # convert 0-100 (%) alpha to decimal 

    # calculate our images dimensions 
    $main_img_obj_w = imagesx($main_img_obj); 
    $main_img_obj_h = imagesy($main_img_obj); 
    $watermark_img_obj_w = imagesx($watermark_img_obj); 
    $watermark_img_obj_h = imagesy($watermark_img_obj); 

    # determine center position coordinates 
    $main_img_obj_min_x = floor(($main_img_obj_w/2) - ($watermark_img_obj_w/2)); 
    $main_img_obj_max_x = ceil(($main_img_obj_w/2) + ($watermark_img_obj_w/2)); 
    $main_img_obj_min_y = floor(($main_img_obj_h/2) - ($watermark_img_obj_h/2)); 
    $main_img_obj_max_y = ceil(($main_img_obj_h/2) + ($watermark_img_obj_h/2)); 


    # create new image to hold merged changes 
    $return_img = imagecreatetruecolor($main_img_obj_w, $main_img_obj_h); 

    # walk through main image 
    for($y = 0; $y < $main_img_obj_h; $y++) { 
     for($x = 0; $x < $main_img_obj_w; $x++) { 
      $return_color = NULL; 


      # determine the correct pixel location within our watermark 
      $watermark_x = $x - $main_img_obj_min_x; 
      $watermark_y = $y - $main_img_obj_min_y; 

      # fetch color information for both of our images 
      $main_rgb = imagecolorsforindex($main_img_obj, imagecolorat($main_img_obj, $x, $y)); 

      # if our watermark has a non-transparent value at this pixel intersection 
      # and we're still within the bounds of the watermark image 
      if ( $watermark_x >= 0 && $watermark_x < $watermark_img_obj_w && 
         $watermark_y >= 0 && $watermark_y < $watermark_img_obj_h) { 
       $watermark_rbg = imagecolorsforindex($watermark_img_obj, imagecolorat($watermark_img_obj, $watermark_x, $watermark_y)); 

       # using image alpha, and user specified alpha, calculate average 
       $watermark_alpha = round(((127 - $watermark_rbg['alpha'])/127), 2); 
       $watermark_alpha = $watermark_alpha * $alpha_level; 

       # calculate the color 'average' between the two - taking into account the specified alpha level 
       $avg_red  = $this->_get_ave_color($main_rgb['red'],  $watermark_rbg['red'],  $watermark_alpha); 
       $avg_green = $this->_get_ave_color($main_rgb['green'], $watermark_rbg['green'], $watermark_alpha); 
       $avg_blue  = $this->_get_ave_color($main_rgb['blue'], $watermark_rbg['blue'],  $watermark_alpha); 

       # calculate a color index value using the average RGB values we've determined 
       $return_color = $this->_get_image_color($return_img, $avg_red, $avg_green, $avg_blue); 

      # if we're not dealing with an average color here, then let's just copy over the main color 
      } else { 
       $return_color = imagecolorat($main_img_obj, $x, $y); 

      } # END if watermark 

      # draw the appropriate color onto the return image 
      imagesetpixel($return_img, $x, $y, $return_color); 

     } # END for each X pixel 
    } # END for each Y pixel 

    # return the resulting, watermarked image for display 
    return $return_img; 

} # END create_watermark() 

# average two colors given an alpha 
function _get_ave_color($color_a, $color_b, $alpha_level) { 
    return round((($color_a * (1 - $alpha_level)) + ($color_b * $alpha_level))); 
} # END _get_ave_color() 

# return closest pallette-color match for RGB values 
function _get_image_color($im, $r, $g, $b) { 
    $c=imagecolorexact($im, $r, $g, $b); 
    if ($c!=-1) return $c; 
    $c=imagecolorallocate($im, $r, $g, $b); 
    if ($c!=-1) return $c; 
    return imagecolorclosest($im, $r, $g, $b); 
} # EBD _get_image_color() 

} # END watermark API 
?> 

<?php 

# include our watermerking class 
include 'api.watermark.php'; 
$watermark   = new watermark(); 

# create image objects using our user-specified images 
# NOTE: we're just going to assume we're dealing with a JPG and a PNG here - for example purposes 



$imgtype = exif_imagetype ($_GET['main']); 

if($imgtype === 3){ 
$main_img_obj    = imagecreatefrompng($_GET['main']); 
}else if($imgtype === 2){ 
$main_img_obj    = imagecreatefromjpeg( $_GET['main']); 
}else if($imgtype === 1){ 
$main_img_obj    = imagecreatefromgif( $_GET['main']); 
}else if($imgtype === 6){ 
$main_img_obj    = imagecreatefrombmp( $_GET['main']); 
} 



$watermark_img_obj = imagecreatefrompng( $_GET['watermark']); 

# create our watermarked image - set 66% alpha transparency for our watermark 
$return_img_obj   = $watermark->create_watermark($main_img_obj, $watermark_img_obj, 30); 

# display our watermarked image - first telling the browser that it's a JPEG, 
# and that it should be displayed inline 
if(($imgtype === 3)or($imgtype === 2)){ 
header('Content-Type: image/png','Content-Type: image/jpeg'); 
}else if(($imgtype === 1)or($imgtype === 6)){ 
header('Content-Type: image/gif','Content-Type: image/bmp'); 
} 

header('Content-Disposition: inline; filename=' . $_GET['src']); 
imagejpeg($return_img_obj, '', 50); 

?> 
+0

这些图像有多大? (尺寸我的意思是?)。另外,我建议在上传过程中将所有图像转换为通用格式(IE jpeg或gif),无论哪一种都以最佳质量与处理时间相隔离。 – BenOfTheNorth 2012-02-25 19:16:47

+0

我将它们全部调整大小,上传至最大宽度为800像素 - 处理上传时间不是一个问题,实际上只是对于水印的最佳选择。我可以从现在开始将图像转换为jpg我想不过已经有很多已经在系统中我会说95%是JPG但 – Ash 2012-02-25 20:16:58

+0

我之所以说这个文件类型的原因是因为如果它们都是一种类型,那么可以跳过阅读exif作为一个开始。 – BenOfTheNorth 2012-02-25 20:18:49

回答

0

我认为你没有缓存每次你可能重复使用的水印图像。

除此之外,我不认为PHP是用于这类工作的工具。我会寻找一个可以在PHP中使用的外部库来执行此操作。 PHP很好,只是不适合这种工作。您可以查看PHP和其他语言(以及其他地方)之间的大量内存/ CPU密集型任务的相对性能;

http://benchmarksgame.alioth.debian.org/u32/compare.php?lang=gcc&lang2=php

0

您应该使用GD imagecopymerge而不是迭代上的像素。并缓存结果(如果使用基于.htaccess的重定向来避免调用PHP缓存的图像,则奖励点数)。