Hi community,
For a project of mine I'm in need of watermarked images in the image gallery. After searching and following some related threads there dosn't seem to be any public solid contributed solution out there yet that targets this issue. Nevertheless this feature is searched and desired by some other people and is often needed on professional photographer sites. Although my skills are limeted I thought I'll take a try, get involved, contribute something back to the community, learn, extend my skills and build my first drupal modul.
I noticed that it likely won't be a feature included in image.module because it's invented to be basic and feature less. So the right way to go seems to be a new module named image_watermark.module as a contribution to the image.module. Due to my low skills I've got some basic problems which a moderate developer should laugh about and may help me with ease. So here's what I've managed on my own by now. The following codeblocks are all placed in a file called image_watermark.module.
First I became friend with the form api and build the first basic administrative settings:
- checkbox: to enable/disable the module
- checkbox: to apply watermarks to thumbnails if desired (may be seperated in all from image.module generated sizes)
- textfield: to set the location of the watermark image
- selectbox: to choose where the watermark should be placed on the image (only center center works for now)
// $Id: image_watermark.module,v 0.1 2006/07/07 22:51:51 ak Exp $
/**
* Implementation of hook_help().
*/
function image_watermark_help($section) {
switch ($section) {
case 'admin/modules#description':
return t('Adds watermarks to images. (requires image.module)');
}
}
/*
* Implementation of hook_settings().
*/
function image_watermark_settings() {
if (!image_get_toolkit()) {
drupal_set_message('image_watermark: You must enable an image toolkit for this module to work!', 'error');
} else {
$form['image_watermark'] = array(
'#type' => 'fieldset',
'#title' => t('Watermark settings')
);
$form['image_watermark']['image_watermark_enable'] = array(
'#type' => 'checkbox',
'#title' => t('Watermark images'),
'#default_value' => variable_get('image_watermark_enable', 0),
'#description' => t('If checked, this will create preview images with watermarks.')
);
// TODO
$form['image_watermark']['image_watermark_thumbs'] = array(
'#type' => 'checkbox',
'#title' => t('Watermark thumbs (TODO)'),
'#default_value' => variable_get('image_watermark_thumbs', 0),
'#description' => t('If checked, this will watermark thumbnail images as well.')
);
$form['image_watermark']['image_watermark_path'] = array(
'#type' => 'textfield',
'#title' => t('Watermark path'),
'#default_value' => variable_get('image_watermark_path', drupal_get_path('module', 'image_watermark').'/watermark.png'),
'#size' => 60,
'#description' => t('Path to the watermark image. This path is relative to the drupal base directory.')
);
$form['image_watermark']['image_watermark_position'] = array(
'#type' => 'select',
'#title' => t('Watermark position'),
'#default_value' => variable_get('image_watermark_position', 'center center'),
'#options' => array('center center', 'center left', 'center right', 'top center', 'top left', 'top right', 'bottom center', 'bottom left', 'bottom right'),
'#description' => t('Watermark position on the image.')
);
}
return $form;
}
First question:
- #1 Can I validate the existance of the watermark file directly in the hook_settings function and how?
Next I implemented the hook_nodeapi. I orientated myselfe by some code of the image_exact.module on using this. Give me a hint if there may be an other or better solution doing this.
- #2 Are all the published images updated automatically with the watermark by using this or is this just triggered for new uploaded images and what are the right hooks for both approaches? (both may seem desireable to me, could be implemented as either/or option)
/*
* Implementation of hook_nodeapi(&$node, $op, $teaser = NULL, $page = NULL)
*/
function image_watermark_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
if ($node->type == 'image' && $op == 'validate' && variable_get('image_watermark_enable', 1)) {
$source = file_create_path($node->images['_original']);
$destination = file_create_path($node->images['preview']);
$watermarkfile = variable_get('image_watermark_path', drupal_get_path('module', 'image_watermark').'/watermark.png');
if (file_exists($watermarkfile)) {
// TODO: How to save the returned image?
//$newimage = image_watermark_add($destination, $watermarkfile);
image_watermark_add($destination, $watermarkfile);
} else {
// TODO: Can this be validatet in the settings itselve?
drupal_set_message('image_watermark: Watermark file does not exist.', 'error');
}
}
}
Next I found and took some code out of the filerequest.module to create the new merged image out of the uploaded image and the watermark image. This code works great as is and is cool because it supports all file extentions and even 24 bit .png's correctly. But still here my main but simple problem occurs.
/*
Source of this routine:
http://www.php.net/manual/en/function.imagecopymerge.php
// TODO: Check this section below, mostly based on filerequest.module script.
*/
// if set upsample pallet images, produces better results
define("UPSAMPLE_PALLET", true);
// if set to true downsample the watermarked image to the original format,
// otherwise it will be converted to a jpg
define("DOWNSAMPLE_TO_ORIGIN", true);
function image_watermark_add($sourcefile, $watermarkfile) {
// $sourcefile = Filename of the picture to be watermarked.
// $watermarkfile = Filename of the 24-bit PNG watermark file.
//Get the resource ids of the pictures
$watermarkfile_id = imagecreatefrompng($watermarkfile);
imageAlphaBlending($watermarkfile_id, false);
imageSaveAlpha($watermarkfile_id, true);
$fileType = getimagesize($sourcefile);
switch($fileType[2]) {
case 1:
$sourcefile_id = imagecreatefromgif($sourcefile);
break;
case 2:
$sourcefile_id = imagecreatefromjpeg($sourcefile);
break;
case 3:
$sourcefile_id = imagecreatefrompng($sourcefile);
break;
}
// Get the sizes of both pix
$sourcefile_width = imageSX($sourcefile_id);
$sourcefile_height = imageSY($sourcefile_id);
$watermarkfile_width = imageSX($watermarkfile_id);
$watermarkfile_height = imageSY($watermarkfile_id);
// Center the watermark for now
$dest_x = ( $sourcefile_width / 2 ) - ( $watermarkfile_width / 2 );
$dest_y = ( $sourcefile_height / 2 ) - ( $watermarkfile_height / 2 );
$upsampled = 0;
// if a gif, we have to upsample it to a truecolor image
if(UPSAMPLE_PALLET && !imageistruecolor($sourcefile_id)) {
// create an empty truecolor container
$tempimage = imagecreatetruecolor($sourcefile_width, $sourcefile_height);
$upsampled = imagecolorstotal($sourcefile_id);
// copy the 8-bit gif into the truecolor image
imagecopy($tempimage, $sourcefile_id, 0, 0, 0, 0, $sourcefile_width, $sourcefile_height);
imagedestroy($sourcefile_id);
// copy the source_id int
$sourcefile_id = $tempimage;
}
imagecopy($sourcefile_id, $watermarkfile_id, $dest_x, $dest_y, 0, 0, $watermarkfile_width, $watermarkfile_height);
if ($upsampled) {
if (DOWNSAMPLE_TO_ORIGIN && function_exists('imagetruecolortopalette')) {
__fr_imagetruecolortopalette_ex($sourcefile_id, true, 256);
} else {
$fileType[2] = 2; // force to JPEG to reduce size
}
}
//Create a jpeg out of the modified picture
switch($fileType[2]) {
// remember we don't need gif any more, so we use only png or jpeg.
// See the upsaple code immediately above to see how we handle gifs
case 3:
header("Content-type: image/png");
imagepng($sourcefile_id);
break;
case 1:
if (imagetypes() & IMG_GIF) {
header("Content-type: image/gif");
imagegif($sourcefile_id);
break;
}
default:
header("Content-type: image/jpg");
imagejpeg($sourcefile_id);
}
// TODO: How to manage this?
//image_resize($sourcefile_id, $sourcefile, $sourcefile_width, $sourcefile_height);
imagedestroy($sourcefile_id);
imagedestroy($watermarkfile_id);
}
// litle helper function
// only applies to images other than jpg
// must be renamed latter
function __fr_imagetruecolortopalette_ex( $image, $dither, $ncolors )
{
if (function_exists('imagecolormatch')) {
$width = imagesx( $image );
$height = imagesy( $image );
$colors_handle = ImageCreateTrueColor( $width, $height );
ImageCopyMerge( $colors_handle, $image, 0, 0, 0, 0, $width, $height, 100 );
}
ImageTrueColorToPalette( $image, $dither, $ncolors );
if (function_exists('imagecolormatch')) {
ImageColorMatch( $colors_handle, $image );
ImageDestroy( $colors_handle );
}
}
So far, so good. If you now submit an image node you get an image with your 24 bit transparent watermark.png centered on the uploaded source image. But, thats all you see, just the image, nothing else. As you may noticed at the bottom of the image_watermark_add function there are headers set that result in just seeing the image and not your view/edit page any more.
So here's my third and most importend question:
- #3 How can I save and or overwrite the preview image generated by image.module with my newly generated, watermarked image.
Last but not least a wishlist and posible Roadmap for this module could be:
- asign watermarks per taxonomie (for selected galleries only)
- asign watermarks per node (as fieldset on node/xx/edit page)
- asign watermarks per user (upload watermark on user account page)
- apply different watermarks to different image sizes
- position watermarks individualy with drag&drop js
- .. tune in with some ideas ...
And please help me solve my problem.
Greetings Steven
Comments
sound promising
I can't offer any programming help, but i'm happy to betatest if there is a module i can download and install.
Also, i'd like to throw 100US$ in for the bounty.
--
Creativine: Brands coming alive as Drupal themes
Writing a module
I am writing a module for a client that does watermarking.
They do not need the taxonomy and fancy stuff, but I have it working well for applying a watermark.
--
Drupal development and customization: 2bits.com
Personal: Baheyeldin.com
--
Drupal performance tuning and optimization, hosting, development, and consulting: 2bits.com, Inc. and Twitter at: @2bits
Personal blog: Ba
Hi Khalid, thanks for tuning
Hi Khalid,
thanks for tuning in as an advanced developer that you surely are due to your profile page. At the bare bones, what my current client project requires is to just watermark images, same as you. I don't need the fancy features mentioned in the roadmap above for my client project as well, but I do think an "apply to taxonomie" could come in handy for some people. As several people in the community, besides me where searching for watermarking and it appears that nobody has published a solide solution yet I thought I'll give it a try.
By now alternatively one could use gallery2. It has a nice watermarking support out of the box and other highly attractive features like the whole filestorage system in single gallery folders. But after investigating that clumsy framework and following some threads at drupal.org I came to the result that extending our own image.module is the most desireable way to go for me, rather then implementing or even using third party solutions I'd rather stick to drupal and try to extend it in small steps. As first step I targeted the watermark functionality as I need it in my current project and I think it is a moderate approach that I hope to handel well, with a little help from the community. On the other hand it has plenty room to be extended and for me, offers the ability to learn how to work with the drupal api.
Would you like to share or contribute the work you got done so far? Could you paste some snippeds that will point me in the right direction to get on going? How about colaborating and making a fancy watermark for the community? (I must mention that I am coming in as a designer that has quite deap skills and understanding of programming in general but is quite new in doing this stuff in php or drupal) How is your module implemented by now?
I'd be glad for some feedback.
Is it possible to pass this
Is it possible to pass this on?
The only thing I would need other than simple watermarking would be a checkbox for specified roles and auto-watermarking for others...
This would allow admin users etc to upload images without the watermark (a logo image for instance) or images that can't have a watermark. It would also make sure all regular users had watermarks on their images.
It is ready
It is tested, working and pending delivery to the client who comissioned it.
I intend to release this to the community, as it is much needed.
Regarding the roles and other functionality, it is not there simply because the current client did not want it there. It can be added of course provided someone pays for the time it takes. Or it can be added by someone in the community if they feel like it.
--
Drupal development and customization: 2bits.com
Personal: Baheyeldin.com
--
Drupal performance tuning and optimization, hosting, development, and consulting: 2bits.com, Inc. and Twitter at: @2bits
Personal blog: Ba
It is ready
Please help me collect the bounty: http://drupal.org/node/76069
--
Creativine: Brands coming alive as Drupal themes
Module released
Image watermark module is now released.
--
Drupal development and customization: 2bits.com
Personal: Baheyeldin.com
--
Drupal performance tuning and optimization, hosting, development, and consulting: 2bits.com, Inc. and Twitter at: @2bits
Personal blog: Ba