2012-02-25 3 views
3

ОК, поэтому я понимаю, что есть тысячи вопросов, относящихся к такого рода вещам, однако ответы на них действительно не покрывают моих потребностей. Итак, вот моя проблема.Обслуживание тысяч изображений, помеченных водяным знаком на лету?

У меня есть CRM-система недвижимости, которую несколько компаний используют для хранения своих данных о недвижимости и изображений, которые я затем обслуживаю на различных порталах свойств, на которых они рекламируют указанные свойства. Теперь они, очевидно, требуют, чтобы фотографии были водяными знаками, моя система позволяет им делать это двумя способами, имея прозрачную в центре или непрозрачную меньшую в нижнем правом углу. В зависимости от того, какой параметр находится на этом, это отражается в URL-адресах изображения в фиде XML, который генерируется и отправляется на различные сайты. Разумеется, они могут свободно менять логотип и т. Д. Свободно, без проблем с печатными копиями изображений и т. Д.

Теперь, когда используется нижний правый водяной знак, нет проблем, поскольку обработка php намного меньше, но для прозрачности, когда некоторые порталы захватить все изображения, и я говорю тысячи + (и увеличиваясь днем ​​и каждой присоединяющейся компанией), он, естественно, перегружает сервер VPS, а inmotionhosting отключает меня. Это третий сторонний скрипт, который я использую, и эта работа отлично использует слишком много ресурсов. Любые идеи для улучшения? Я знаю, что люди упоминают кеширование, но каждый образ отличается и, возможно, только один раз запрашивается, так что это принесет пользу? Вся ваша помощь приветствуется, поскольку у меня есть одна головная боль, когда дело доходит до масштабирования системы. Заранее спасибо!

<?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

+0

Я изменяю их размер при загрузке до максимальной ширины 800 пикселей - время обработки при загрузке не является проблемой действительно, что бы ни было лучше для водяных знаков. Я могу начать конвертировать изображения в jpg, теперь я думаю, что многое уже в системе, я бы сказал, что 95% - это jpg, хотя – Ash

+0

Причина, по которой я говорю о типе файла, состоит в том, что если они все одного типа, вы можете пропустить чтение exif для начала. – BenOfTheNorth

ответ

0

Я думаю, что вы не кешируете изображение с водяными знаками, которое вы, вероятно, повторно используете каждый раз.

Кроме того, я не думаю, что PHP - это инструмент, который можно использовать для такого рода работ. Я бы искал внешнюю библиотеку, которую вы можете использовать в PHP для этого. PHP в порядке, просто не для такого рода работы. Вы можете проверить относительную производительность для большого количества задач с памятью/процессором между PHP и другими языками здесь (среди других мест);

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

0

Вы должны использовать GD imagecopymerge вместо итерацию по пикселям. И кешируйте результаты (бонусные баллы, если вы используете перенаправление .htaccess, чтобы избежать вызова PHP для кешированных изображений).