【问题标题】:image::Magick perl module - Multiple crop/resize manipulations from one Read and one Write?image::Magick perl 模块 - 一次读取和一次写入的多次裁剪/调整大小操作?
【发布时间】:2017-04-28 06:34:44
【问题描述】:

我有一个 Perl 脚本,它使用 Image::Magick perl 模块从 Web 表单中裁剪现有图像(使用 JCrop 为我提供宽度、高度、x、y)。因为裁剪后的图像将用于响应式设计环境,所以我正在创建多种尺寸的图像以供网站前端使用。尺寸构建在一个数组中(如下面的代码所示),并逐个处理以创建每个图像尺寸。

正如您从下面的代码中看到的那样,我最终必须打开图像 3 次并写入 3 次......这似乎有点过分......所以我希望你们知道更好的方法这个。

我最初尝试使用 Image::Magick 简单地打开文件一次,运行“裁剪、调整大小、裁剪”过程,然后写入一次图像,但结果非常可怕。没有一个坐标被正确翻译,因此图像甚至没有接近用户在网络表单中请求的大小......尽管这些值被完美地读取。

所以我对你们所有人的问题是,是否有人能够完成一次“打开”(对打开的图像进行多次操作),然后使用 Image::Magick perl 执行一次“写入”模块?如果是这样,您能否提供一个与我在下面发布的代码行一样长的示例?我非常感谢可以提供的任何帮助。我的代码的 sn-p 如下。很抱歉评论过多,我想让它尽可能容易地跟随:)

#!/usr/bin/perl

use Image::Magick;
use CGI qw(:cgi-lib);

&ReadParse(*input);

##############################
# Build array of sizes needed
##############################

my @sizes = ("1280","960","640","480","320","160");

foreach $size (@sizes) {
    $resized = "/path/to/size/folders/$size\/$input{image_ID}\.png";

    $image = Image::Magick->new;
    $x = $image->Read("/path/to/fullsize/image");

    #########################
    # Run the requested crop
    #########################

    $x = $image->Crop(width=>$input{w},height=>$input{h},x=>$input{x},y=>$input{y});

    ########################
    # Write cropped version
    ########################

    $x = $image->Write("$resized");

    ###########################
    # Open the cropped version
    ###########################

    $image = Image::Magick->new;
    $x = $image->Read("$resized");

    ###############################################
    # Size the image down to +2 pixels all around
    # to handle border opacity when pixel rounding
    ###############################################

    $temp_width = $size + 2;
    $temp_height = ($temp_width * $input{h}) / $input{w};

    ###########################
    # Resize the cropped image
    ###########################

    $x = $image->Resize(width=>$temp_width, height=>$temp_height);

    ################################
    # Write the newly resized image
    ################################

    $x = $image->Write("$resized");

    ########################################
    # Calculate final dimensions and coords
    ########################################

    $final_height = ($size * $temp_height) / $temp_width;
    $final_x = 1;
    $final_y = 1;

    ###############################
    # Open the newly resized image
    ###############################

    $image = Image::Magick->new;
    $x = $image->Read("$resized");

    #######################################
    # Final crop the image for clean edges
    #######################################

    $x = $image->Crop(width=>$size,height=>$final_height,x=>$final_x,y=>$final_y);

    ########################################
    # Write the final cropped image for use
    ########################################

    $x = $image->Write("$resized");
}

【问题讨论】:

  • 我不确定我是否理解正确,但是您是否尝试过在阅读一次后复制该对象,然后对每个对象进行翻译。
  • 我尝试了 nwellnhof 在下面发布的内容,这与您的建议相似。结果发布在他的评论下方。

标签: perl imagemagick perl-module


【解决方案1】:

您可以使用Clone 方法复制图像。此外,写入图像并在之后立即读取它是多余的。尝试以下方法:

my @sizes = ("1280","960","640","480","320","160");

my $src_image = Image::Magick->new;
$x = $src_image->Read("/path/to/fullsize/image");

#########################
# Run the requested crop
#########################

$x = $src_image->Crop(width=>$input{w},height=>$input{h},x=>$input{x},y=>$input{y});

foreach $size (@sizes) {
    my $image = $src_image->Clone;

    $resized = "/path/to/size/folders/$size\/$input{image_ID}\.png";

    ###############################################
    # Size the image down to +2 pixels all around
    # to handle border opacity when pixel rounding
    ###############################################

    $temp_width = $size + 2;
    $temp_height = ($temp_width * $input{h}) / $input{w};

    ###########################
    # Resize the cropped image
    ###########################

    $x = $image->Resize(width=>$temp_width, height=>$temp_height);

    ########################################
    # Calculate final dimensions and coords
    ########################################

    $final_height = ($size * $temp_height) / $temp_width;
    $final_x = 1;
    $final_y = 1;

    #######################################
    # Final crop the image for clean edges
    #######################################

    $x = $image->Crop(width=>$size,height=>$final_height,x=>$final_x,y=>$final_y);

    ########################################
    # Write the final cropped image for use
    ########################################

    $x = $image->Write("$resized");
}

【讨论】:

  • 我实现了您的建议,但由于某种原因,无论我处理什么图像,数组中的每个图像大小都会在白色背景上生成一个 1x1 图像。如果我注释掉最后的裁剪,它会起作用(每个图像周围都是 +2 像素)......所以它似乎不想处理“调整大小”命令,然后处理最终的“裁剪”命令而不转动图像出于某种原因变成 1x1 图像。我有它们应该被写入日志文件的大小,它们看起来都是正确的。还有什么想法吗?非常感谢您的帮助。
  • 您可能需要在使用$image->Set(page=>'0x0+0+0'); 进行裁剪后“重新分页”图像。
【解决方案2】:

这很晚,但如果它对某人有帮助,这对我有用:

my $imageName = 'picture';
my $file = "tmp/original.jpg";

# Create the image object
my $imageFile = Image::Resize->new($file);

# Resize and save one...
my $image = $imageFile->resize(800, 450);
open(FH, ">$siteroot/user_pics/$imageName\_800x450.jpg");
print FH $image->jpeg();
close(FH);

# Resize and save another...
my $thumb = $imageFile->resize(224, 126);
open(FH, ">$siteroot/user_pics/$imageName\_224x126.jpg");
print FH $thumb->jpeg();
close(FH);

# etc...

unlink ("tmp/original.jpg");

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-15
    • 1970-01-01
    • 1970-01-01
    • 2010-11-02
    • 1970-01-01
    • 2015-07-16
    • 2023-04-04
    • 2018-09-21
    相关资源
    最近更新 更多