Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Общие вопросы > Управление качеством изображения


Автор: shootnix 9.3.2006, 09:05
Вот такая трабла у меня: ресайзю картинку на севере (jpeg) с исходного 800х600 до нужного 100х75.
Всё бы ничего, вот только качество просто никакущее! Ну плохо всё видать.

Есть ли у GD спецомные фишки насчёт качества изображения. А то я так думаю, что это просто вследствие максимального сжатия происходит... Есть ли способ программно управлять этим процессом?

Автор: sharq 9.3.2006, 10:49
shootnix,

Цитата

GD allows you to create color drawings using a large number of graphics primitives, and emit the drawings as PNG files.


Если тебе реально важно качество картинки (тем более jpeg), используй ImageMagick, не много медленее работает, но зато качественно!

smile

Автор: shootnix 9.3.2006, 11:49
Да уж... нет у меня на хосте этого самого... ImageMagik.

Автор: nitr 9.3.2006, 19:13
Установи или юзай
Код

use lib qw(./packages);

создав папку packages и внеси туды распакованный модуль со SEARCH.CPAN.ORG

Автор: sharq 9.3.2006, 19:23
nitr, ничего не получится так, нужно еще дистрибутив ImageMagick поставить на сервер.
ImagickMagick - это утилита, "фотошоп" для командной строки.
А из perl просто можно вызвать его функции (для этого и не нужен модуль).

smile

Автор: nitr 9.3.2006, 19:30
Обычно библиотеки в *nix стоят, так как пхп развит ;) а он юзает данные либы!

Автор: korob2001 10.3.2006, 10:13
А почему бы не связаться с Support и не попросить их установить нужный модуль? Image::Magick уменьшает изображения без потери качества, ну точнее потеря такая же как и у PhotoShop'a. Если нужно, могу запостить код, которым я уменьшаю изображения с Image::Magick

Автор: rcdimon 10.3.2006, 10:28
да, давай, пости smile

Автор: korob2001 10.3.2006, 12:11
Здесь я заюзал ещё и Image::Size, его можно установить сначала на свой локальный копмпьютер, а затем вручную создать на сервере каталог Image и скопировать в него каталог /Size и файл Size.pm из локального каталога библиотеки. Затем добавить в @INC путь к новой библиотеки, либо заюзать use lib ();
Проверял лично, всё чудесно работатет.
Код

#!/usr/bin/perl -w
use strict;
use Image::Size;
use Image::Magick;


file_reparation("D:", "120x80", "tmpx.jpg", "small.jpg");

sub file_reparation {
    my($img_dir,$to_size,$original_file,$new_file) = @_;

    # Узнаём ширину и высоту оригинала
    my( $width, $height ) = imgsize("$img_dir/$original_file");

    # Если не удалось получить ширину и высоту оригинала, вернём false
    return 0 unless $width or $height;

    # Создаём объект Image::Magick
    my $image   = Image::Magick->new();
    # Считываем оригинал
    my $img_obj = $image->Read("$img_dir/$original_file");

    # Разбиваем полный размер на ширину и высоту до которых нужно изменить изображение
    my( $to_width, $to_height ) = split("x", $to_size);

    # Вычисляем ширину если хотим уменьшить высоту до 200, это
    # необходимо для сохранения пропоций изображения.
    my $x_width = eval{ $width / $height * $to_height };

    # Уменьшаем изображение
    $image->Resize( width => $x_width, height => $to_height );

    # Если ширина получилась больше необходимой, то урезаем изображение.
    if ( $x_width > $to_width ) {
         # Вычисляем откуда нужно резать изображение
         my $x_cut = int( ( $x_width - $to_width ) / 2 );
         # Задаём позицию, с которой будем резать изображение
         $image->Crop(x => $x_cut, y => 0);
         # Режем изображение
         $image->Crop( $to_size );
    }

    # Сохраняем изображение
    $image->Write("$img_dir/$new_file");
    return 1;
}

Подпрограмма получает 4 параметра:
1) Путь к каталогу где находится изображение.
2) Размер до которого нужно уменьшить изображение в формате "120x80"
3) Имя файла оригинала.
4) Имя нового файла.

У этого алгоритма сохранения пропорций, есть один недостаток. Если высота изображения больше ширины, то может получиться не совсем то, что нужно. Но это очень легко исправить, а у меня как-то руки не доходят до этого. ;(((((( Может кто-нить из вас возьмётся сделать это? Вот что я имею ввиду:

1) После того как мы узнали размер оригинала:
Код

# Узнаём ширину и высоту оригинала
my( $width, $height ) = imgsize("$img_dir/$original_file");

Было бы не плохо создать условие
Код

if ( высота > ширины ) {
     # Вот здесь нужно сделать впринципе то же самое, но наоборот, сначала
     # вместо $x_width, поулить $x_height, т.е. взять за основу не ширину, а высоту
     # Это сделать дастаточно легко имея код выше.
} else {
     # Здесь код как и прежде, сохраняем пропорции отталкиваясь от ширины
}


Если например нам не нужен оригинал, то вызвать данную подпрограмму, можно так:
Код

if ( file_reparation("D:", "120x80", "tmpx.jpg", "small.jpg") ) {
     unlink("D:/tmpx.jpg") or warn "Can't remove file: $!\n";
} else {
     warn "Can't resize file, because file is not image :(((\n";
}

Так же, внутрь подпрограммы, можно добавить ещё один параметр, путь к каталогу, в который нужно сохранять новое изображение. Зачастую так и нужно делать, очень редко нужно сохранять изображение в тот же каталог, где лежит оригинал.

Вобщем пробуйте. ;))))))

Автор: Vaneska 20.3.2006, 11:47
А не лучше узнавать размер изображения напрямую через Image::Magick?

Автор: korob2001 20.3.2006, 13:41
Цитата(Vaneska @ 20.3.2006, 08:47 Найти цитируемый пост)
А не лучше узнавать размер изображения напрямую через Image::Magick?

А не лучше ли взять, да запостить сюда пример, вмето того, что бы задавать подобные вопросы? smile

Автор: Vaneska 20.3.2006, 14:05
Исправляюсь ... smile

Код

my $width = $img->Get('columns');
my $height = $img->Get('rows');


Документация лежит здесь:
http://imagemagick.org/script/perl-magick.php

Автор: korob2001 20.3.2006, 14:14
Спасибо, подправил:
Код

#!/usr/bin/perl -w
use strict;
use Image::Magick;

file_reparation("D:", "120x80", "100_1189.jpg", "small.jpg");

sub file_reparation {
    my($img_dir,$to_size,$original_file,$new_file) = @_;

    # Создаём объект Image::Magick
    my $image   = Image::Magick->new();

    # Считываем оригинал
    my $img_obj = $image->Read("$img_dir/$original_file");

    # Узнаём ширину и высоту оригинала
    my $width   = $image->Get('columns');
    my $height  = $image->Get('rows');

    # Если не удалось получить ширину или высоту оригинала, вернём false
    return 0 unless $width or $height;

    # Разбиваем полный размер на ширину и высоту до которых нужно изменить изображение
    my( $to_width, $to_height ) = split("x", $to_size);

    # Вычисляем ширину если хотим уменьшить высоту до 200, это
    # необходимо для сохранения пропоций изображения.
    my $x_width = eval{ $width / $height * $to_height };

    # Уменьшаем изображение
    $image->Resize( width => $x_width, height => $to_height );

    # Если ширина получилась больше необходимой, то урезаем изображение.
    if ( $x_width > $to_width ) {
         # Вычисляем откуда нужно резать изображение
         my $x_cut = int( ( $x_width - $to_width ) / 2 );
         # Задаём позицию, с которой будем резать изображение
         $image->Crop(x => $x_cut, y => 0);
         # Режем изображение
         $image->Crop( $to_size );
    }

    # Сохраняем изображение
    $image->Write("$img_dir/$new_file");
    return 1;
}

Автор: nitr 20.3.2006, 14:21
А разве не подходят модули http://search.cpan.org/~lgoddard/Image-Magick-Thumbnail-0.04/Thumbnail.pm ?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)