Verified Commit b7edbc73 authored by Luc Didry's avatar Luc Didry
Browse files

Fix #112 — Add watermarking feature

- tiling, unique or no watermark available in UI
- watermark enforcing available in configuration
parent a416a8ad
Pipeline #219949 passed with stages
in 17 minutes and 48 seconds
Revision history for Lutim
0.1?.? ????-??-??
0.12.0 ????-??-??
- Add watermarking feature (#112)
0.11.6 2019-11-16
- Remove the "Support the author" dropdown
......
......@@ -32,6 +32,29 @@ sub startup {
default => $default_config
});
if ($config->{watermark_path}) {
die sprintf('%s does not exist or is not readable.', $config->{watermark_path}) unless -r $config->{watermark_path};
my $valid = {
center => 1,
north => 1,
northeast => 1,
east => 1,
southeast => 1,
south => 1,
southwest => 1,
west => 1,
northwest => 1
};
die sprintf('%s is not a valid value for watermark_placement.', $config->{watermark_placement}) unless $valid->{lc($config->{watermark_placement})};
$valid = {
'tiling' => 1,
'single' => 1,
'none' => 1
};
die sprintf('%s is not a valid value for watermark_default.', $config->{watermark_default}) unless $valid->{lc($config->{watermark_default})};
die sprintf('%s is not a valid value for watermark_enforce.', $config->{watermark_enforce}) unless $valid->{lc($config->{watermark_enforce})};
}
if (scalar(@{$config->{memcached_servers}})) {
$self->plugin(CHI => {
lutim_images_cache => {
......@@ -90,7 +113,7 @@ sub startup {
if ($config->{minion}->{enabled}) {
$self->config->{minion}->{dbtype} = 'sqlite' unless defined $config->{minion}->{dbtype};
if ($config->{minion}->{dbtype} eq 'sqlite') {
$self->config('minion')->{db_path} = 'minion.db' unless defined $config->{minion}->{db_path};
$config->{minion}->{db_path} = 'minion.db' unless defined $config->{minion}->{db_path};
$self->plugin('Minion' => { SQLite => 'sqlite:'.$config->{minion}->{db_path} });
} elsif ($config->{minion}->{dbtype} eq 'postgresql') {
$self->plugin('PgURLHelper');
......@@ -147,14 +170,14 @@ sub startup {
});
# Authentication (if configured)
if (defined($self->config('ldap')) || defined($self->config('htpasswd'))) {
if (defined($self->config('ldap'))) {
if (defined($config->{ldap}) || defined($config->{htpasswd})) {
if (defined($config->{ldap})) {
require Net::LDAP;
}
if (defined($self->config('htpasswd'))) {
if (defined($config->{htpasswd})) {
require Apache::Htpasswd;
}
die 'Unable to read '.$self->config('htpasswd') if (defined($self->config('htpasswd')) && !-r $self->config('htpasswd'));
die sprintf('Unable to read %s', $config->{htpasswd}) if (defined($config->{htpasswd}) && !-r $config->{htpasswd});
$self->plugin('Authentication' =>
{
autoload_user => 1,
......@@ -243,7 +266,7 @@ sub startup {
}
}
);
$self->app->sessions->default_expiration($self->config('session_duration'));
$self->app->sessions->default_expiration($config->{session_duration});
}
$self->defaults(layout => 'default');
......@@ -256,7 +279,7 @@ sub startup {
$r->add_condition(authorized => sub {
my ($r, $c, $captures) = @_;
return 1 unless (defined($self->config('ldap')) || defined($self->config('htpasswd')));
return 1 unless (defined($config->{ldap}) || defined($config->{htpasswd}));
return $c->is_user_authenticated;
});
......@@ -275,7 +298,7 @@ sub startup {
to('Authent#index');
if (defined $self->config('ldap') || defined $self->config('htpasswd')) {
if (defined $config->{ldap} || defined $config->{htpasswd}) {
# Login page
$r->get('/login')
->to('Authent#index')
......
......@@ -285,6 +285,7 @@ sub add {
my $upload = $c->param('file');
my $file_url = $c->param('lutim-file-url');
my $keep_exif = $c->param('keep-exif');
my $wm = $c->param('watermark');
if(!defined($c->stash('stop_upload'))) {
if (defined($file_url) && $file_url) {
......@@ -406,14 +407,56 @@ sub add {
# Automatic rotation from EXIF tag
$im->AutoOrient();
# Update the uploaded file with it's auto-rotated clone
# Get dimensions
$width = $im->Get('width');
$height = $im->Get('height');
# Optionally add watermark
if ($c->config('watermark_path') && (
($wm && $wm ne 'none') ||
$c->config('watermark_enforce') ne 'none'
)) {
my $watermarkim = Image::Magick->new;
$watermarkim->ReadImage($c->config('watermark_path'));
$watermarkim->Evaluate(
operator => 'Multiply',
value => 0.25,
channel => 'Alpha'
);
if ($height <= 80) {
$watermarkim->Resize(geometry => 'x10');
} else {
$watermarkim->Resize(geometry => 'x80');
}
# Add one watermark or repeat it all over the image?
my $tilingw = 1 if ($c->config('watermark_enforce') eq 'tiling' || $wm eq 'tiling');
my $singlew = 1 if ($c->config('watermark_enforce') eq 'single' || $wm eq 'single');
if ($tilingw) {
$im->Composite(
image => $watermarkim,
compose => 'Dissolve',
tile => 'True',
gravity => 'Center'
);
} elsif ($singlew) {
$im->Composite(
image => $watermarkim,
compose => 'Dissolve',
tile => 'False',
x => '20',
y => '20',
gravity => $c->config('watermark_placement')
);
}
}
# Update the uploaded file with it's auto-rotated/watermarked clone
my $asset = Mojo::Asset::Memory->new->add_chunk($im->ImageToBlob());
$upload->asset($asset);
# Create the thumbnail
$width = $im->Get('width');
$height = $im->Get('height');
$im->Resize(geometry=>'x85');
$im->Resize(geometry => 'x85');
$thumb = 'data:'.$mediatype.';base64,';
if ($mediatype eq 'image/gif') {
......
......@@ -4,25 +4,29 @@ require Exporter;
@ISA = qw(Exporter);
@EXPORT_OK = qw($default_config);
our $default_config = {
provisioning => 100,
provis_step => 5,
length => 8,
always_encrypt => 0,
anti_flood_delay => 5,
max_file_size => 10*1024*1024,
https => 0,
proposed_delays => '0,1,7,30,365',
default_delay => 0,
max_delay => 0,
token_length => 24,
crypto_key_length => 8,
thumbnail_size => 100,
theme => 'default',
dbtype => 'sqlite',
db_path => 'lutim.db',
max_files_in_zip => 15,
prefix => '/',
minion => {
provisioning => 100,
provis_step => 5,
length => 8,
always_encrypt => 0,
anti_flood_delay => 5,
max_file_size => 10*1024*1024,
https => 0,
proposed_delays => '0,1,7,30,365',
default_delay => 0,
max_delay => 0,
token_length => 24,
crypto_key_length => 8,
thumbnail_size => 100,
watermark_path => '',
watermark_placement => 'SouthEast',
watermark_default => 'none',
watermark_enforce => 'none',
theme => 'default',
dbtype => 'sqlite',
db_path => 'lutim.db',
max_files_in_zip => 15,
prefix => '/',
minion => {
enabled => 0,
dbtype => 'sqlite',
db_path => 'minion.db'
......
......@@ -47,6 +47,7 @@ sub register {
$app->helper(max_delay => \&_max_delay);
$app->helper(default_delay => \&_default_delay);
$app->helper(is_selected => \&_is_selected);
$app->helper(is_wm_selected => \&_is_wm_selected);
$app->helper(crypt => \&_crypt);
$app->helper(decrypt => \&_decrypt);
$app->helper(delete_image => \&_delete_image);
......@@ -250,6 +251,13 @@ sub _is_selected {
return ($num == $c->default_delay) ? 'selected="selected"' : '';
}
sub _is_wm_selected {
my $c = shift;
my $wm = shift;
return ($wm eq $c->config('watermark_default')) ? 'selected="selected"' : '';
}
sub _crypt {
my $c = shift;
my $upload = shift;
......
......@@ -102,6 +102,29 @@
# optional, default is 0
#always_encrypt => 0,
# you can allow to use a watermark on the uploaded images (or enforce its use)
# define a path to the watermark image (provide an image with alpha channel)
# you can define the path relative to lutim directory or set an absolute path
# to disable the usage of a watermark, leave it blank or commented
# optional, no default
#watermark_path => '',
# the watermark can be a tiling one or a single one
# when using a small one, you can choose where to place it
# valid values are 'Center', 'North', 'NorthEast', 'East', 'SouthEast', 'South', 'SouthWest', 'West' and 'NorthWest' (case insensitive)
# optional, default is 'SouthEast'
#watermark_placement => 'SouthEast',
# choose which watermark (tiling, single or none) should be used by default
# valid values are 'tiling', 'single' or 'none' (case insensitive)
# optional, default is 'none'
#watermark_default => 'none',
# choose which watermark (tiling, single or none) should be enforced (users will always have a watermark and won’t be able to disable it)
# valid values are 'tiling', 'single' or 'none' (case insensitive)
# optional, default is 'none'
#watermark_enforce => 'none',
# length of the image's delete token
# optional, default is 24
#token_length => 24,
......
......@@ -28,15 +28,15 @@ msgstr ""
msgid "%1 sent images on this instance from beginning."
msgstr ""
#: themes/default/templates/index.html.ep:202
#: themes/default/templates/index.html.ep:228
msgid "-or-"
msgstr ""
#: lib/Lutim.pm:319 lib/Lutim/Command/cron/stats.pm:158 lib/Lutim/Command/cron/stats.pm:172 lib/Lutim/Command/cron/stats.pm:189 themes/default/templates/index.html.ep:5 themes/default/templates/myfiles.html.ep:5 themes/default/templates/partial/raw.js.ep:25 themes/default/templates/partial/raw.js.ep:8 themes/default/templates/raw.html.ep:10
#: lib/Lutim.pm:342 lib/Lutim/Command/cron/stats.pm:158 lib/Lutim/Command/cron/stats.pm:172 lib/Lutim/Command/cron/stats.pm:189 themes/default/templates/index.html.ep:5 themes/default/templates/myfiles.html.ep:5 themes/default/templates/partial/raw.js.ep:25 themes/default/templates/partial/raw.js.ep:8 themes/default/templates/raw.html.ep:10
msgid "1 year"
msgstr ""
#: lib/Lutim.pm:318 lib/Lutim/Command/cron/stats.pm:155 lib/Lutim/Command/cron/stats.pm:169 lib/Lutim/Command/cron/stats.pm:186 themes/default/templates/index.html.ep:4 themes/default/templates/myfiles.html.ep:33 themes/default/templates/myfiles.html.ep:4 themes/default/templates/partial/for_my_delay.html.ep:13 themes/default/templates/partial/lutim.js.ep:149 themes/default/templates/partial/raw.js.ep:22 themes/default/templates/partial/raw.js.ep:5 themes/default/templates/raw.html.ep:7
#: lib/Lutim.pm:341 lib/Lutim/Command/cron/stats.pm:155 lib/Lutim/Command/cron/stats.pm:169 lib/Lutim/Command/cron/stats.pm:186 themes/default/templates/index.html.ep:4 themes/default/templates/myfiles.html.ep:33 themes/default/templates/myfiles.html.ep:4 themes/default/templates/partial/for_my_delay.html.ep:13 themes/default/templates/partial/lutim.js.ep:149 themes/default/templates/partial/raw.js.ep:22 themes/default/templates/partial/raw.js.ep:5 themes/default/templates/raw.html.ep:7
msgid "24 hours"
msgstr ""
......@@ -52,7 +52,7 @@ msgstr ""
msgid "Active images"
msgstr ""
#: lib/Lutim/Controller/Image.pm:328
#: lib/Lutim/Controller/Image.pm:329
msgid "An error occured while downloading the image."
msgstr ""
......@@ -64,7 +64,7 @@ msgstr ""
msgid "Back to homepage"
msgstr ""
#: themes/default/templates/index.html.ep:205 themes/default/templates/index.html.ep:206
#: themes/default/templates/index.html.ep:231 themes/default/templates/index.html.ep:232
msgid "Click to open the file browser"
msgstr ""
......@@ -104,7 +104,7 @@ msgstr ""
msgid "Delay repartition chart for enabled images"
msgstr ""
#: themes/default/templates/index.html.ep:127 themes/default/templates/index.html.ep:159 themes/default/templates/index.html.ep:190 themes/default/templates/myfiles.html.ep:118 themes/default/templates/myfiles.html.ep:45 themes/default/templates/partial/lutim.js.ep:161
#: themes/default/templates/index.html.ep:127 themes/default/templates/index.html.ep:159 themes/default/templates/index.html.ep:203 themes/default/templates/myfiles.html.ep:118 themes/default/templates/myfiles.html.ep:45 themes/default/templates/partial/lutim.js.ep:161
msgid "Delete at first view?"
msgstr ""
......@@ -132,7 +132,7 @@ msgstr ""
msgid "Download zip link"
msgstr ""
#: themes/default/templates/index.html.ep:201
#: themes/default/templates/index.html.ep:227
msgid "Drag & drop images here"
msgstr ""
......@@ -140,7 +140,7 @@ msgstr ""
msgid "Drag and drop an image in the appropriate area or use the traditional way to send files and Lutim will provide you four URLs. One to view the image, an other to directly download it, one you can use on social networks and a last to delete the image when you want."
msgstr ""
#: themes/default/templates/index.html.ep:162 themes/default/templates/index.html.ep:193
#: themes/default/templates/index.html.ep:162 themes/default/templates/index.html.ep:206
msgid "Encrypt the image (Lutim does not keep the key)."
msgstr ""
......@@ -200,7 +200,7 @@ msgstr ""
msgid "If the files are deleted if you ask it while posting it, their SHA512 footprint are retained."
msgstr ""
#: themes/default/templates/index.html.ep:175 themes/default/templates/index.html.ep:215
#: themes/default/templates/index.html.ep:188 themes/default/templates/index.html.ep:241
msgid "Image URL"
msgstr ""
......@@ -212,7 +212,7 @@ msgstr ""
msgid "Image deleted"
msgstr ""
#: lib/Lutim/Controller/Image.pm:756
#: lib/Lutim/Controller/Image.pm:799
msgid "Image not found."
msgstr ""
......@@ -244,7 +244,7 @@ msgstr ""
msgid "Juste like you pronounce the French word <a href=\"https://fr.wikipedia.org/wiki/Lutin\">lutin</a> (/ly.tɛ̃/)."
msgstr ""
#: themes/default/templates/index.html.ep:165 themes/default/templates/index.html.ep:196
#: themes/default/templates/index.html.ep:165 themes/default/templates/index.html.ep:209
msgid "Keep EXIF tags"
msgstr ""
......@@ -252,7 +252,7 @@ msgstr ""
msgid "Language"
msgstr ""
#: themes/default/templates/index.html.ep:130 themes/default/templates/index.html.ep:178 themes/default/templates/index.html.ep:218 themes/default/templates/partial/lutim.js.ep:165
#: themes/default/templates/index.html.ep:130 themes/default/templates/index.html.ep:191 themes/default/templates/index.html.ep:244 themes/default/templates/partial/lutim.js.ep:165
msgid "Let's go!"
msgstr ""
......@@ -304,7 +304,11 @@ msgstr ""
msgid "No limit"
msgstr ""
#: themes/default/templates/index.html.ep:177 themes/default/templates/index.html.ep:210
#: themes/default/templates/index.html.ep:177 themes/default/templates/index.html.ep:221
msgid "No watermark"
msgstr ""
#: themes/default/templates/index.html.ep:190 themes/default/templates/index.html.ep:236
msgid "Only images are allowed"
msgstr ""
......@@ -349,7 +353,7 @@ msgstr ""
msgid "Save changes"
msgstr ""
#: themes/default/templates/index.html.ep:170
#: themes/default/templates/index.html.ep:183
msgid "Send an image"
msgstr ""
......@@ -357,12 +361,16 @@ msgstr ""
msgid "Signin"
msgstr ""
#: themes/default/templates/index.html.ep:174 themes/default/templates/index.html.ep:218
msgid "Single watermark"
msgstr ""
#: themes/default/templates/index.html.ep:145 themes/default/templates/partial/gallery.js.ep:211 themes/default/templates/partial/lutim.js.ep:176
msgid "Something bad happened"
msgstr ""
#. ($c->config('contact')
#: lib/Lutim/Controller/Image.pm:763
#: lib/Lutim/Controller/Image.pm:806
msgid "Something went wrong when creating the zip file. Try again later or contact the administrator (%1)."
msgstr ""
......@@ -374,7 +382,7 @@ msgstr ""
msgid "The Lutim software is a <a href=\"http://en.wikipedia.org/wiki/Free_software\">free software</a>, which allows you to download and install it on you own server. Have a look at the <a href=\"https://www.gnu.org/licenses/agpl-3.0.html\">AGPL</a> to see what you can do."
msgstr ""
#: lib/Lutim/Controller/Image.pm:347
#: lib/Lutim/Controller/Image.pm:348
msgid "The URL is not valid."
msgstr ""
......@@ -391,14 +399,14 @@ msgid "The delete token is invalid."
msgstr ""
#. ($upload->filename)
#: lib/Lutim/Controller/Image.pm:488
#: lib/Lutim/Controller/Image.pm:531
msgid "The file %1 is not an image."
msgstr ""
#. ($tx->res->max_message_size)
#. ($c->req->max_message_size)
#. (config('max_file_size')
#: lib/Lutim/Controller/Image.pm:311 lib/Lutim/Controller/Image.pm:380 themes/default/templates/partial/lutim.js.ep:249
#: lib/Lutim/Controller/Image.pm:312 lib/Lutim/Controller/Image.pm:381 themes/default/templates/partial/lutim.js.ep:249
msgid "The file exceed the size limit (%1)"
msgstr ""
......@@ -433,10 +441,14 @@ msgid "There is XXXX image(s) in the gallery"
msgstr ""
#. ($c->config->{contact})
#: lib/Lutim/Controller/Image.pm:485
#: lib/Lutim/Controller/Image.pm:528
msgid "There is no more available URL. Retry or contact the administrator. %1"
msgstr ""
#: themes/default/templates/index.html.ep:171 themes/default/templates/index.html.ep:215
msgid "Tiling watermark"
msgstr ""
#: themes/default/templates/gallery.html.ep:30
msgid "Toggle fullscreen"
msgstr ""
......@@ -462,7 +474,7 @@ msgstr ""
msgid "Unable to find the image %1."
msgstr ""
#: lib/Lutim/Controller/Image.pm:574 lib/Lutim/Controller/Image.pm:619 lib/Lutim/Controller/Image.pm:660 lib/Lutim/Controller/Image.pm:703 lib/Lutim/Controller/Image.pm:715 lib/Lutim/Controller/Image.pm:726 lib/Lutim/Controller/Image.pm:753 lib/Lutim/Plugin/Helpers.pm:88
#: lib/Lutim/Controller/Image.pm:617 lib/Lutim/Controller/Image.pm:662 lib/Lutim/Controller/Image.pm:703 lib/Lutim/Controller/Image.pm:746 lib/Lutim/Controller/Image.pm:758 lib/Lutim/Controller/Image.pm:769 lib/Lutim/Controller/Image.pm:796 lib/Lutim/Plugin/Helpers.pm:89
msgid "Unable to find the image: it has been deleted."
msgstr ""
......@@ -474,7 +486,7 @@ msgstr ""
msgid "Unlike many image sharing services, you don't give us rights on uploaded images."
msgstr ""
#: themes/default/templates/index.html.ep:174 themes/default/templates/index.html.ep:213
#: themes/default/templates/index.html.ep:187 themes/default/templates/index.html.ep:239
msgid "Upload an image with its URL"
msgstr ""
......@@ -487,7 +499,7 @@ msgid "Uploaded files by days"
msgstr ""
#. ($c->app->config('contact')
#: lib/Lutim/Plugin/Helpers.pm:221
#: lib/Lutim/Plugin/Helpers.pm:222
msgid "Uploading is currently disabled, please try later or contact the administrator (%1)."
msgstr ""
......@@ -547,7 +559,7 @@ msgstr ""
msgid "core developer"
msgstr ""
#: lib/Lutim.pm:317 lib/Lutim/Command/cron/stats.pm:154 lib/Lutim/Command/cron/stats.pm:168 lib/Lutim/Command/cron/stats.pm:185 themes/default/templates/index.html.ep:3 themes/default/templates/myfiles.html.ep:3 themes/default/templates/partial/raw.js.ep:21 themes/default/templates/partial/raw.js.ep:4 themes/default/templates/raw.html.ep:6
#: lib/Lutim.pm:340 lib/Lutim/Command/cron/stats.pm:154 lib/Lutim/Command/cron/stats.pm:168 lib/Lutim/Command/cron/stats.pm:185 themes/default/templates/index.html.ep:3 themes/default/templates/myfiles.html.ep:3 themes/default/templates/partial/raw.js.ep:21 themes/default/templates/partial/raw.js.ep:4 themes/default/templates/raw.html.ep:6
msgid "no time limit"
msgstr ""
......
......@@ -203,6 +203,7 @@
fd.append('crypt', ($("#crypt").prop('checked')) ? 1 : 0);
fd.append('keep-exif', ($("#keep-exif").prop('checked')) ? 1 : 0);
fd.append('delete-day', ($("#delete-day").val()));
fd.append('watermark', ($("#watermark").val()));
widget.settings.onBeforeUpload.call(widget.element, widget.queuePos);
......
......@@ -11,6 +11,7 @@
f.append('format', 'json');
f.append('first-view', ($("#first-view").prop('checked')) ? 1 : 0);
f.append('delete-day', ($("#delete-day").val()));
f.append('watermark', ($("#watermark").val()));
f.append('crypt', ($("#crypt").prop('checked')) ? 1 : 0);
f.append('keep-exif', ($("#keep-exif").prop('checked')) ? 1 : 0);
h.settings.onBeforeUpload.call(h.element,h.queuePos);h.queueRunning=true;c.ajax({url:h.settings.url,type:h.settings.method,dataType:h.settings.dataType,data:f,cache:false,contentType:false,processData:false,forceSync:false,xhr:function(){var i=c.ajaxSettings.xhr();if(i.upload){i.upload.addEventListener("progress",function(m){var l=0;var j=m.loaded||m.position;var k=m.total||e.totalSize;if(m.lengthComputable){l=Math.ceil(j/k*100)}h.settings.onUploadProgress.call(h.element,h.queuePos,l)},false)}return i},success:function(j,i,k){h.settings.onUploadSuccess.call(h.element,h.queuePos,j)},error:function(k,i,j){h.settings.onUploadError.call(h.element,h.queuePos,j)},complete:function(i,j){h.processQueue()}})};c.fn.dmUploader=function(f){return this.each(function(){if(!c.data(this,b)){c.data(this,b,new a(this,f))}})};c(document).on("dragenter",function(f){f.stopPropagation();f.preventDefault()});c(document).on("dragover",function(f){f.stopPropagation();f.preventDefault()});c(document).on("drop",function(f){f.stopPropagation();f.preventDefault()})})(jQuery);
......@@ -165,6 +165,19 @@
<input type="checkbox" name="keep-exif"> <%= l('Keep EXIF tags') %>
</label>
</div>
% if ($c->config('watermark_path') && $c->config('watermark_enforce') eq 'none') {
<select name="watermark" class="form-control">
<option value="tiling" <%== is_wm_selected('tiling') %>>
<%= l('Tiling watermark') %>
</option>
<option value="single" <%== is_wm_selected('single') %>>
<%= l('Single watermark') %>
</option>
<option value="none" <%== is_wm_selected('none') %>>
<%= l('No watermark') %>
</option>
</select>
% }
</div>
<div class="form-group">
<label for="lutim-file"><%= l('Send an image') %></label>
......@@ -196,6 +209,19 @@
<input type="checkbox" id="keep-exif"> <%= l('Keep EXIF tags') %>
</label>
</div>
% if ($c->config('watermark_path') && $c->config('watermark_enforce') eq 'none') {
<select id="watermark" class="form-control">
<option value="tiling" <%== is_wm_selected('tiling') %>>
<%= l('Tiling watermark') %>
</option>
<option value="single" <%== is_wm_selected('single') %>>
<%= l('Single watermark') %>
</option>
<option value="none" <%== is_wm_selected('none') %>>
<%= l('No watermark') %>
</option>
</select>
% }
</div>
<div id="drag-and-drop-zone" class="uploader">
<div><%= l('Drag & drop images here') %></div>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment