Оквадрачивание всех картинок внутри директории
Date January 20th, 2012 Author Vitaly Agapov
Взгляни на его форму: квадрат, воплощение коварства!
Возникла необходимость сделать все изображения в одной директории квадратными, причём таким образом, чтобы не нарушить центровку изображений. В моём случае это была директория с файлами изображений Drupal, поэтому задача разбивается на две части. Первая часть – универсальная – как автоматически отредактировать все изображения. Вторая часть – для Drupal – как обновить данные о новых изображениях в базе данных.
Пользоваться будем нашим любимым Perl и его модулем для работы с библиотекой ImageMagick.
Часть 1. Оквадрачиваем
Для достижения цели я набросал такой вот скрипт quad.pl:
01.
#!/usr/bin/perl
02.
use
Image::Magick;
03.
use
POSIX;
04.
05.
my
$path
=
"/var/www/drupal/sites/default/files"
;
06.
07.
# Пробежимся по всем файлам и для каждого вызовем функцию quad_image()
08.
my
@files
= <
$path
/*.jpg>;
09.
foreach
$file
(
@files
) {
10.
quad_image(
$file
,
$file
);
11.
}
12.
exit
(0);
13.
14.
sub
quad_image {
15.
my
(
$in_img
,
$out_img
) =
@_
;
16.
if
( !(-f
"$in_img"
) ) {
17.
die
(
"Image file not found"
);
18.
}
19.
my
$q
;
20.
# Создадим новый объект Image::Magick
21.
$q
= Image::Magick->new;
22.
$q
->
Read
(
"$in_img"
);
23.
# Узнаем ширину и высоту изображения
24.
my
(
$x_size
,
$y_size
) =
$q
->Get(
'width'
,
'height'
);
25.
26.
# Если один из параметро нулевой, то файл - битый
27.
if
(
$x_size
== 0 ||
$y_size
== 0){
28.
return
(
"Unable to get filesize: $in_img."
);
29.
}
30.
31.
my
$width
;
32.
if
(
$x_size
>
$y_size
) {
33.
$width
=
$x_size
;
34.
my
$yoffset
= floor( (
$x_size
-
$y_size
)*0.5 );
35.
# Растягиваем высоту до значения ширины
36.
$q
->Extent(geometry=>
$x_size
.
"x"
.
$y_size
.
"+0-"
.
$yoffset
, width=>
$width
, height=>
$width
);
37.
}
38.
elsif
(
$y_size
>
$x_size
) {
39.
$width
=
$y_size
;
40.
my
$xoffset
= floor( (
$y_size
-
$x_size
)*0.5 );
41.
# Растягиваем ширину до значения высоты
42.
$q
->Extent(geometry=>
$x_size
.
"x"
.
$y_size
.
"-"
.
$xoffset
.
"+0"
, width=>
$width
, height=>
$width
);
43.
}
44.
45.
if
(
$width
) {
46.
# Небольшой необязательный кусок. Здесь мы добавляем надпись на преобразованное изображение
47.
# Вычисляем размер букв
48.
my
$pointsize
= floor(
$width
*0.04 );
49.
# Вычисляем координаты надписи
50.
my
$x
= floor(
$width
*0.06 );
51.
my
$y
=
$width
-
$x
;
52.
my
$text
=
'my watermark'
;
53.
# Вставляем надпись
54.
$q
->Annotate(x=>
$x
, y=>
$y
, pointsize=>
$pointsize
, fill=>
'grey'
, text=>
$text
);
55.
56.
# Дальше устанавливаем качество JPEG-файла
57.
$q
->Set(quality=>75);
58.
# И записываем файл
59.
$q
->
Write
(
"$out_img"
);
60.
}
61.
}
С комментариями внутри скрипта должно вроде бы бть всё ясно.
Часть 2. Подгоняем Drupal
Вторую часть можно не читать тем, кому просто был интересен механизм преобразования изображений. У меня же была задача сделать квадратными все изображения товаров и каталогов Ubercart. Если просто оквадратить вышеприведённым скриптом все изображения и удалить все стили изображений из поддиректории styles, то пропорции всех выводимых изображений на странице исказятся. Это всё оттого, что ширина и высота изображений хранятся в базе данных и используются для установки атрибутов при выводе изображений на страницу.
Поэтому, когда я обнаружил такой вот эффект, пришлось срочно писать ещё один скрипт, исправляющий всё это безобразие. Скрипт просматривает все изображения в директории, сравнивает их размер со значением поля filesize таблицы file_managed и если находит несоответствие, то исправляет это значение на новое и заодно правит значения width и height во всех полях таблиц, ссылающихся на fid этого файла.
Вот и сам скрипт repair_drupal.pl.
01.
#!/usr/bin/perl
02.
use
Image::Magick;
03.
use
POSIX;
04.
use
DBI();
05.
06.
my
$path
=
"/var/www/drupal/sites/default/files"
;
07.
glob
$db
=
"mydb"
;
08.
glob
$dbuser
=
"myuser"
;
09.
glob
$dbpwd
=
"pypwd"
;
10.
$dbh
= DBI->
connect
(
"DBI:mysql:database=$db;host=localhost"
,
$dbuser
,
$dbpwd
,{
'RaiseError'
=> 1});
11.
12.
$dbh
->
do
(
"SET NAMES utf8"
);
13.
$dbh
->
do
(
"SET CHARACTER SET utf8"
);
14.
15.
my
@files
= <
$path
/*.jpg>;
16.
foreach
$file
(
@files
) {
17.
repair_drupal(
$file
);
18.
}
19.
exit
(0);
20.
21.
sub
repair_drupal {
22.
my
$in_img
=
$_
[0];
23.
if
( !(-f
"$in_img"
) ) {
24.
die
(
"Image file not found"
);
25.
}
26.
# Откусываем название файла от пути
27.
$in_img
=~ /([^\/]+)$/;
28.
my
$filename
=
$1
;
29.
# Получаем размер файла в байтах
30.
my
$filesize
= -s
$in_img
;
31.
my
$q
;
32.
$q
= Image::Magick->new;
33.
$q
->
Read
(
"$in_img"
);
34.
35.
my
(
$x_size
,
$y_size
) =
$q
->Get(
'width'
,
'height'
);
36.
if
(
$x_size
== 0 ||
$y_size
== 0){
37.
return
(
"Unable to get filesize: $in_img."
);
38.
}
39.
# Получаем размер этого файла, который указан в базе данных
40.
my
$sql
=
"SELECT fid,filesize FROM file_managed WHERE filename = '"
.
$filename
.
"'"
;
41.
print
$sql
.
"\n"
;
42.
my
$sth
=
$dbh
->prepare(
$sql
);
43.
$sth
->execute();
44.
if
(
$ref
=
$sth
->fetchrow_hashref() ) {
45.
# Если размеры не совпадают, то проворачиваем все нужные действия
46.
if
(
$ref
->{filesize} !=
$filesize
) {
47.
print
"Filesizes differ! ("
.
$ref
->{filesize}.
"->"
.
$filesize
.
")\n"
;
48.
$sql
=
"UPDATE file_managed SET filesize="
.
$filesize
;
49.
print
$sql
.
"\n"
;
50.
$dbh
->
do
(
$sql
);
51.
# Если речь не про Ubercart, то
52.
# Вместо uc_product и uc_catalog будут другие таблицы
53.
$sql
=
"UPDATE field_data_uc_product_image SET uc_product_image_width = "
.
$x_size
.
",uc_product_image_height="
.
$y_size
.
" WHERE uc_product_image_fid="
.
$ref
->{fid};
54.
print
$sql
.
"\n"
;
55.
$dbh
->
do
(
$sql
);
56.
$sql
=
"UPDATE field_revision_uc_product_image SET uc_product_image_width = "
.
$x_size
.
",uc_product_image_height="
.
$y_size
.
" WHERE uc_product_image_fid="
.
$ref
->{fid};
57.
print
$sql
.
"\n"
;
58.
$dbh
->
do
(
$sql
);
59.
$sql
=
"UPDATE field_data_uc_catalog_image SET uc_catalog_image_width = "
.
$x_size
.
",uc_catalog_image_height="
.
$y_size
.
" WHERE uc_catalog_image_fid="
.
$ref
->{fid};
60.
print
$sql
.
"\n"
;
61.
$dbh
->
do
(
$sql
);
62.
$sql
=
"UPDATE field_revision_uc_catalog_image SET uc_catalog_image_width = "
.
$x_size
.
",uc_catalog_image_height="
.
$y_size
.
" WHERE uc_catalog_image_fid="
.
$ref
->{fid};
63.
print
$sql
.
"\n"
;
64.
$dbh
->
do
(
$sql
);
65.
}
66.
else
{
67.
print
"Filesizes OK\n"
;
68.
}
69.
}
70.
else
{
71.
print
"\n!!!!! No such file! \n"
;
72.
}
73.
}
Итак, чтобы сделать квадратными все изображения в Drupal, надо сделать следующее:
- Преобразовать все картинки в sites/default/files скриптом из первой части.
- Удалить все миниатюры и прочие стили изображений из sites/default/files/styles.
- Поправить информацию о параметрах изображений в базе данных скриптом из второй части.
- Очистить кэш.
Ссылки
Документация по модулю Image::Magic
http://www.imagemagick.org/script/perl-magick.php
Tags: Drupal, Perl
Category:
Drupal, Perl |
No comments »