如何转换Cairo至Imager?

时间:2018-02-22 02:02:21

标签: image perl cairo

由于历史原因,我们被迫一起使用Cairo和Imager。

从Cairo转换为Imager并由于某种原因将其转换回Imager会使颜色变得奇怪。

再次转换为Imager的原因是在此之后与另一个Imager对象结合。

# Create a yellow fill image as Cairo object.
# And output as a png file.
my $testSurface = Cairo::ImageSurface->create(
    'argb32',
    $width,
    $height
);

my $testContext = Cairo::Context->create($testSurface);
$testContext->rectangle(0, 0, $width, $height);
$testContext->set_source_rgba(1.0, 1.0, .0, 1);
$testContext->fill();
# This is a yellow png file.
$testSurface->write_to_png("output/fill_yellow.png");

# Convert the Cairo object to an Imager object.

my $testData = $testSurface->get_data;

my $testImager = Imager->new(
    xsize    => $width,
    ysize    => $height,
    channels => 4,
);

my $testRes = $testImager->read(
    data              => $testData,
    type              => "raw",
    xsize             => $width,
    ysize             => $height,
    raw_datachannels  => 4,
    raw_storechannels => 4,
    raw_interleave    => 0,
);

# Output Imager object as a PNG file.
# ! This PNG file becomes blue unexpectedly
$testRes->write(
    file => "output/fill_yellow_imager.png",
    type => "png"
);

1 个答案:

答案 0 :(得分:4)

Cairo正在使用ARGB作为其原始格式,而Imager正在使用RGBA。它们之间的差异是样本存储在每个像素中的顺序。开罗也使用预乘alpha,而Imager使用非预乘alpha。两个图书馆似乎没有任何选择来改变这些事情。

通过重新排序原始图像数据中的字节,可以相当容易地修复样本排序事物,但是预乘事物开始进入不值得打扰的领域。因此,我建议您只需在开罗中保存PNG文件并将其加载到Imager中。它可能稍慢,但很容易理解并认识到它是正确的。

下面:在我意识到预乘的alpha问题之前,建议交换字节顺序的本答案的先前版本的代码:

for (my $i = 0 ; $i < length($testData) ; $i += 4) {
    substr($testData, $i, 4,
        substr($testData, $i+1, 3) . substr($testData, $i, 1)
    );
}

我不建议使用它。