[Code bijgewerkt met oplossing Firefox probleem]Ik zag een tijdje geleden al een een aantal vragen langskomen op het forum over het toepassen van watermerken bij het tonen van foto's via Photostation.
Omdat de vraag mij intrigeerde ben ik eens aan het pluizen geslagen:
in het bestand convert.php (lokatie: /usr/syno/synoman/phpsrc/photo/) wordt het oproepen van de afbeeldingen geregeld.
Op regel negentig van dit bestand wordt gescheiden op welk soort bestand getoond moet worden. Keuze bestaat uit:
0) Kleine thumbnail
1) Grote thumbnail
2) Origineel bestand
3) Video
Middels het select case principe wordt hierin onderscheid gemaakt.
Ik heb de procedures bij 1 en 2 zo aangepast dat daar waar de variabele $file wordt gevuld ($file = etc.) een aanroep wordt gedaan naar een nieuw toe te voegen functie WATERMARK.
Deze functie zorgt voor het invoegen van een watermerk rechtsonder in de afbeelding.
Hoe toe te passen:
1) Maak een reservekopie van het bestand /usr/syno/synoman/phpsrc/photo/convert.php
2) Pas convert.php als volgt aan:
na regel met 'case '1'' de regel met
$file = SYNOPHOTO_CONVERT_GetThumbPathFromFullPath($dir."/".$name, 1);
wijzigen in
$file = WATERMARK($dir,$name,1,1);
na regel met 'case '2'' de regel met
$file = $dir."/".$name;
wijzigen in
$file = WATERMARK($dir,$name,0,0);
op de regel voor de php eindtag '?>' de volgende regels invoegen
function WATERMARK($dir, $name, $thumb, $thumbsize)
{
$watermark = imagecreatefrompng('/var/services/web/copyright.png');
$watermark_width = imagesx($watermark);
$watermark_height = imagesy($watermark);
$image = imagecreatetruecolor($watermark_width, $watermark_height);
if ($thumb != 1) {
$image = imagecreatefromjpeg($dir."/".$name);
$size = getimagesize($dir."/".$name);
} else{
$image = imagecreatefromjpeg(SYNOPHOTO_CONVERT_GetThumbPathFromFullPath($dir."/".$name, $thumbsize));
$size = getimagesize(SYNOPHOTO_CONVERT_GetThumbPathFromFullPath($dir."/".$name, $thumbsize));
}
$dest_x = $size[0] - $watermark_width - 5;
$dest_y = $size[1] - $watermark_height - 5;
imagecopymerge($image, $watermark, $dest_x, $dest_y, 0, 0, $watermark_width, $watermark_height, 100);
imagejpeg($image,"/volume1/@tmp/tmp.jpg");
$file = "/volume1/@tmp/tmp.jpg";
imagedestroy($image);
imagedestroy($watermark);
return $file;
}
?>
Na de regel
@readfile($file);
invoegen:
unlink("/volume1/@tmp/tmp.jpg");
Het uiteindelijke bestand komt er dan bij mij als volgt uit te zien (ik heb de oude regels als commentaar (//) laten staan...
<?php
session_cache_limiter("must-revalidate");
if(!session_id()) {
session_start();
}
$SYNOPHOTO_ADMIN_PASS = "hlinak3";
SYNOPHOTO_CONVERT_AccessRightCheck();
$SYNOPHOTO_SERVICE_DIR = "/var/services/photo";
$SYNOPHOTO_EADIR = "@eaDir";
$SYNOPHOTO_THUMB_FILE_BIG = "SYNOPHOTO:THUMB_B.jpg";
$SYNOPHOTO_THUMB_FILE_SMALL = "SYNOPHOTO:THUMB_S.jpg";
$SYNOPHOTO_FLV_FILE = "SYNOPHOTO:FILM.flv";
$SYNOPHOTO_FLV_FILE_FAIL = "SYNOPHOTO:FILM.fail";
$SYNOPHOTO_ALLOW_PICT_NAMES_EXT = array(
"jpg",
"jpeg",
"jpe",
"bmp",
"gif",
"png"
);
$SYNOPHOTO_ALLOW_PICT_WITH_THUMB_EXT = array(
"jpg",
"jpeg",
"jpe",
"bmp"
);
$SYNOPHOTO_ALLOW_PICT_NAMES_MIME = array(
'jpg' => 'image/jpeg',
'jpeg' => 'image/jpeg',
'jpe' => 'image/jpeg',
'bmp' => 'image/bmp',
'gif' => 'image/gif',
'png' => 'image/png'
);
$SYNOPHOTO_VIDEO_MIME = array(
'avi' => 'video/x-msvideo',
'm4v' => 'video/x-m4v',
'mov' => 'video/quicktime',
'mp4' => 'video/mp4',
'mpe'=> 'video/mpeg',
'mpeg'=> 'video/mpeg',
'mpg'=> 'video/mpeg',
'qt' => 'video/quicktime',
'asf' => 'video/x-ms-asf',
'wmv' => 'video/x-ms-wmv'
);
if(isset($_GET['currdir']) && isset($_GET['currname'])) {
$dir = $SYNOPHOTO_SERVICE_DIR."/".$_GET['currdir'];
$name = $_GET['currname'];
$is_photo_file = SYNOPHOTO_CONVERT_IsPhotoFile($name);
if(isset($_GET['showorig'])) {
if($is_photo_file) {
if(!SYNOPHOTO_CONVERT_CheckAllowOrig($dir, $name)) {
exit;
}
$mime_type = SYNOPHOTO_CONVERT_GetPhotoMimeType($name);
$file = $dir."/".$name;
} else {
$mime_type = "video/x-flv";
$file = SYNOPHOTO_CONVERT_GetFlvPath($dir, $name);
$name = $name.".flv";
}
} else if(isset($_GET['showthumb'])) {
$file = SYNOPHOTO_CONVERT_GetThumbPathFromFullPath($SYNOPHOTO_SERVICE_DIR."/".$_GET['currdir']."/".$_GET['currname'], 0);
$mime_type = "image/jpeg";
} else {
$file = SYNOPHOTO_CONVERT_GetThumbPathFromFullPath($SYNOPHOTO_SERVICE_DIR."/".$_GET['currdir']."/".$_GET['currname'], 1);
$mime_type = "image/jpeg";
}
} elseif(isset($_GET['dir']) && isset($_GET['name'])) {
$dir = $SYNOPHOTO_SERVICE_DIR."/".@pack('H*', $_GET['dir']);
$name = @pack('H*', $_GET['name']);
$is_photo_file = SYNOPHOTO_CONVERT_IsPhotoFile($name);
// 0:small; 1:big; 2:org; 3:flv;
switch ($_GET['type']) {
case '0':
$file = SYNOPHOTO_CONVERT_GetThumbPathFromFullPath($dir."/".$name, 0);
$mime_type = "image/jpeg";
break;
case '1':
//$file = SYNOPHOTO_CONVERT_GetThumbPathFromFullPath($dir."/".$name, 1);
$file = WATERMARK($dir,$name,1,1);
$mime_type = "image/jpeg";
break;
case '2':
if(!SYNOPHOTO_CONVERT_CheckAllowOrig($dir, $name)) {
exit;
}
if($is_photo_file) {
$mime_type = SYNOPHOTO_CONVERT_GetPhotoMimeType($name);
} else {
$mime_type = SYNOPHOTO_CONVERT_GetVideoMimeType($name);
if(!$mime_type) {
$mime_type = "application/octet-stream";
}
}
//$file = $dir."/".$name;
$file = WATERMARK($dir,$name,0,0);
break;
case '3':
$mime_type = "video/x-flv";
$file = SYNOPHOTO_CONVERT_GetFlvPath($dir, $name);
$name = $name.".flv";
break;
default:
exit;
break;
}
}
$signature = SYNOPHOTO_CONVERT_CreateSig($file);
if($signature) {
SYNOPHOTO_CONVERT_CheckSigExit($signature);
@header("Last-Modified: " . $signature[0]);
}
@header("Cache-Control: max-age=".(3600*24*7));
@header("Content-Type: ".$mime_type);
@header("Content-Length: ".filesize($file));
if($is_photo_file) {
@header("Content-Disposition: inline; filename=".addslashes($name));
}
@readfile($file);
unlink("/volume1/@tmp/tmp.jpg");
function SYNOPHOTO_CONVERT_GetPhotoMimeType($path)
{
global $SYNOPHOTO_ALLOW_PICT_NAMES_MIME;
$path = strtolower($path);
$path_parts = pathinfo($path);
$extension = $path_parts['extension'];
return $SYNOPHOTO_ALLOW_PICT_NAMES_MIME[$extension];
}
function SYNOPHOTO_CONVERT_IsPhotoFile($path)
{
global $SYNOPHOTO_ALLOW_PICT_NAMES_EXT;
$path = strtolower($path);
$path_parts = pathinfo($path);
$extension = $path_parts['extension'];
if(in_array($extension, $SYNOPHOTO_ALLOW_PICT_NAMES_EXT)) {
return true;
} else {
return false;
}
}
function SYNOPHOTO_CONVERT_GetVideoMimeType($path)
{
global $SYNOPHOTO_VIDEO_MIME;
$path = strtolower($path);
$path_parts = pathinfo($path);
$extension = $path_parts['extension'];
if(array_key_exists($extension, $SYNOPHOTO_VIDEO_MIME)) {
return $SYNOPHOTO_VIDEO_MIME[$extension];
}
return '';
}
function SYNOPHOTO_CONVERT_IsPhotoFileWithThumb($path)
{
global $SYNOPHOTO_ALLOW_PICT_WITH_THUMB_EXT;
$path = strtolower($path);
$path_parts = pathinfo($path);
$extension = $path_parts['extension'];
if(in_array($extension, $SYNOPHOTO_ALLOW_PICT_WITH_THUMB_EXT)) {
return true;
} else {
return false;
}
}
function SYNOPHOTO_CONVERT_GetFlvPath($dir, $name)
{
global $SYNOPHOTO_EADIR, $SYNOPHOTO_FLV_FILE, $SYNOPHOTO_SERVICE_DIR;
return $dir."/".$SYNOPHOTO_EADIR."/".$name."/".$SYNOPHOTO_FLV_FILE;
}
function SYNOPHOTO_CONVERT_GetFlvFailPath($dir, $name)
{
global $SYNOPHOTO_EADIR, $SYNOPHOTO_FLV_FILE_FAIL, $SYNOPHOTO_SERVICE_DIR;
return $dir."/".$SYNOPHOTO_EADIR."/".$name."/".$SYNOPHOTO_FLV_FILE_FAIL;
}
function SYNOPHOTO_CONVERT_GetThumbPathFromFullPath($path, $is_big_thumb)
{
global $SYNOPHOTO_EADIR;
global $SYNOPHOTO_THUMB_FILE_BIG, $SYNOPHOTO_THUMB_FILE_SMALL;
$file_name = basename($path);
$dir = substr($path, 0, strlen($path) - strlen($file_name));
if($is_big_thumb) {
$thumb_file = $dir.$SYNOPHOTO_EADIR."/".$file_name."/".$SYNOPHOTO_THUMB_FILE_BIG;
} else {
$thumb_file = $dir.$SYNOPHOTO_EADIR."/".$file_name."/".$SYNOPHOTO_THUMB_FILE_SMALL;
}
return $thumb_file;
}
function SYNOPHOTO_CONVERT_CreateSig($thumbpath) {
$filest = @stat($thumbpath);
$etag = "";
if($filest != FALSE) {
$lastmod = gmdate('D, d M Y H:i:s', $filest[9]) . ' GMT';
return array($lastmod);
} else {
return FALSE;
}
}
function SYNOPHOTO_CONVERT_CheckSigExit($signature) {
$etag = $signature[0];
$lastmod = $signature[1];
if(isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
$ims = preg_replace('/;.*$/', '', $_SERVER['HTTP_IF_MODIFIED_SINCE'] );
if($ims == $lastmod) {
@header("HTTP/1.1 304 Not Modified");
exit;
}
}
}
function SYNOPHOTO_CONVERT_AccessRightCheck()
{
global $SYNOPHOTO_ADMIN_PASS;
if(isset($_SESSION['admin_syno_user']) && $_SESSION['admin_syno_user'] == $SYNOPHOTO_ADMIN_PASS) {
return;
}
if(isset($_GET['currdir']) && isset($_GET['currname'])) {
$_GET['dir'] = bin2hex($_GET['currdir']);
$_GET['name'] = bin2hex($_GET['currname']);
}
if(!isset($_GET['dir']) || $_GET['dir'] == "" || !isset($_GET['name']) || $_GET['name'] == "") {
header("Location: /photo/index.php");
exit;
}
$orig_dir = @pack('H*', $_GET['dir']);
$dir = $orig_dir;
if(strstr($orig_dir, "/")) {
$dir = substr($orig_dir, 0, strpos($orig_dir, "/"));
if(strpos($orig_dir, "/", strlen($dir) + 1)) {
$sub_dir = substr($orig_dir, 0, strpos($orig_dir, "/", strlen($dir) + 1));
} else {
$sub_dir = $orig_dir;
}
} else {
$sub_dir = "";
}
if(!isset($_SESSION['accessible_album'])) {
SYNOPHOTO_CONVERT_GetAccessibleAlbums();
}
if(!$_SESSION['accessible_album'][$dir] ||
($sub_dir != "" && !$_SESSION['accessible_subdir'][$sub_dir])) {
echo "<script>";
echo "parent.location = "/photo/login.php?url=".bin2hex($_SERVER['PHP_SELF']."?".$_SERVER['QUERY_STRING'])."";";
echo "</script>";
exit;
}
}
function SYNOPHOTO_CONVERT_GetAccessibleAlbums()
{
$_SESSION['accessible_album'] = null;
$_SESSION['accessible_subdir'] = null;
if (isset($_SESSION['admin_syno_user'])) {
$query = "Select * from photo_share order by sharename asc";
} elseif (isset($_SESSION['reg_syno_user'])) {
$query = "Select * from photo_share where shareid in (select shareid from photo_access_right where userid = ".$_SESSION['reg_syno_userid'].") or public = true order by sharename asc";
} else {
$query = "Select * from photo_share where public = true order by sharename asc";
}
$username = "admin";
$dbname = "photo";
$conn_string = "dbname=".$dbname." user=".$username;
if (!isset($GLOBALS['dbconn_photo']) || $GLOBALS['dbconn_photo'] == null) {
$GLOBALS['dbconn_photo'] = pg_connect($conn_string) or die("Failed to connect");
}
$db_result = pg_query($GLOBALS['dbconn_photo'], $query);
while($row = pg_fetch_row($db_result)) {
if($row[8] == 't') {
$_SESSION['accessible_subdir'][$row[1]] = 1;
} else {
$_SESSION['accessible_album'][$row[1]] = 1;
}
}
}
function SYNOPHOTO_CONVERT_CheckAllowOrig($dir, $name)
{
if(SYNOPHOTO_CONVERT_IsPhotoFile($name)) {
if(!SYNOPHOTO_CONVERT_IsPhotoFileWithThumb($name)) {
return TRUE;
}
} else {
$file = SYNOPHOTO_CONVERT_GetFlvFailPath($dir, $name);
// User can download video when this video can not be converted to flv.
if(@file_exists($file)) {
return TRUE;
}
$is_video = TRUE;
}
$username = "admin";
$dbname = "photo";
$conn_string = "dbname=".$dbname." user=".$username;
if (!isset($GLOBALS['dbconn_photo']) || $GLOBALS['dbconn_photo'] == null) {
$GLOBALS['dbconn_photo'] = pg_connect($conn_string) or die("Failed to connect");
}
$result = FALSE;
$config_name = "allow_orig";
if($is_video) {
$config_name = "allow_video_download";
}
$query = "Select config_value from photo_config where module_name = 'photo' and config_key = '".$config_name."'";
$db_result = pg_query($GLOBALS['dbconn_photo'], $query);
if($row = pg_fetch_row($db_result)) {
if($row[0] == 'on') {
$result = TRUE;
}
}
return $result;
}
function WATERMARK($dir, $name, $thumb, $thumbsize)
{
$watermark = imagecreatefrompng('/var/services/web/copyright.png');
$watermark_width = imagesx($watermark);
$watermark_height = imagesy($watermark);
$image = imagecreatetruecolor($watermark_width, $watermark_height);
if ($thumb != 1) {
$image = imagecreatefromjpeg($dir."/".$name);
$size = getimagesize($dir."/".$name);
} else{
$image = imagecreatefromjpeg(SYNOPHOTO_CONVERT_GetThumbPathFromFullPath($dir."/".$name, $thumbsize));
$size = getimagesize(SYNOPHOTO_CONVERT_GetThumbPathFromFullPath($dir."/".$name, $thumbsize));
}
$dest_x = $size[0] - $watermark_width - 5;
$dest_y = $size[1] - $watermark_height - 5;
imagecopymerge($image, $watermark, $dest_x, $dest_y, 0, 0, $watermark_width, $watermark_height, 100);
//$file = imagejpeg($image);
imagejpeg($image,"/volume1/@tmp/tmp.jpg");
$file = "/volume1/@tmp/tmp.jpg";
imagedestroy($image);
imagedestroy($watermark);
return $file;
}
?>
Wat er hier gebeurt is dat een ander plaatje, nl. /var/services/web/copyright.png in de rechteronderhoek van een nieuw tijdelijk plaatje (/volume1/@tmp/tmp.jpg) op basis van de originele (thumbnail)afbeelding wordt geplakt. Overigens is /var/services/web hetzelfde als /volume1/web
. Je kan natuurlijk een andere lokatie kiezen: pas dan het script overeenkomstig aan!
Het plaatje in kwestie is een simpel png bestandje: zwarte tekst op een transparante achtergrond.
De tijdelijke afbeelding wordt na verzending naar de bezoeker automatisch verwijderd.
!BELANGRIJK OM TE WETEN!
- Het watermerk wordt alleen toegevoegd aan de afbeeldingen die via Photostation naar een bezoeker worden verzonden. Dit betekent dus dat de originele bestanden en thumbnails ONGEWIJZIGD blijven!
- Het watermerk wordt niet toegevoegd aan de hele kleine thumbnails in de overzichten. Leek mij niet zinvol. Ook video's worden niet meegenomen.
- Getest op DSM 2.2-9042 onder IE7 en Firefox 3
- Wijzigingen op eigen risico. Maak backups!
- Code met dank aan Brock Ferguson (
http://articles.sitepoint.com/article/w ... images-php)
- Gooi de cache van je browser leeg, anders kan het zijn dat het net lijkt of er niets gewijzigd is.
- Herstelactie voor als het misgaat: plaats de in stap 1 gemaakte backup terug
Veel plezier er mee!
Wizjos