在PostgreSQL bytea中,我们正在尝试使用Imagick读取和回写映像文件


From PostgreSQL bytea, we're trying to read - and write back - an image file using Imagick

从PostgreSQL,我试图读取图像文件到Imagick对象-并简单地将相同的文件重写回另一个bytea字段。目标是完全理解PHP和Imagick中使用的字符串处理和转换。

这是在PostgreSQL 9上,所以本机bytea_output是十六进制;我一直在遵循注释将bytea_output更改为转义以供PHP处理。

最终,目标是将该文件转换为任何ImageMagick支持的格式。

事情开始得很好!在对其进行转义之后,$imagestring恰好是磁盘上文件的长度。到目前为止,一切顺利。事情很快就失去了控制……

我找不到任何字符串来写回,这将重新构成文件-以相同的长度-回到DB。

这里怎么了?

// an entire image file is stored in the bytea col: bfile
$query = "SET bytea_output = 'escape'";
$result = spi_exec($query);
# Run the query and get the $result object.
$result = spi_exec($query);
# Fetch the row from the $result.
$row = spi_fetch_row($result);
$content = $row['bfile'];
// pg_unescape it to make it usable?
$unescaped   = pg_unescape_bytea($content);
// Image is read into imagestring
$imagestring = substr($unescaped,12); // remove Mac file header?
$length_image = strlen($imagestring); // 330,494 (EXACTLY length on disk)
// Create Imagick object
$im = new Imagick();
// Convert image into Imagick
$im->readimageblob($imagestring);
// Imagick::getImageSize is deprecated. use Imagick::getImageLength
// - here things get weird....
$image_in_length = $im->getImageLength(); // 330,897
// =============  DO WORK HERE  ====================================
/* Set format to pdf, or png, or... */
// THIS IS THE OBJECTIVE, of course!
// $im->setImageFormat( 'pdf' );
// =================================================================
// FOR THE TIME BEING, would like to simply re-write the same file
// Output the image
$output = $im->getimageblob(); 
//IS THIS RIGHT? ouput length is shorter?
$length_output = strlen($output); // 39,654
$escaped = pg_escape_bytea($output);
$length_escaped = strlen($escaped); // 182,720
// FINALLY: Re-concatenate the strings, and write back to blobtest:destfile:
// ALL of these produce the same result:
$query = "UPDATE blobtest SET destfile = '".$escaped."' WHERE pkey = '" .$args[0]. "'";
$result = spi_exec($query);
$length = getImageLength($image);
//return $inputtype;
$query = "SET bytea_output = 'hex'";
$result = spi_exec($query);
return $length;

我认为ImageMagick不记得它读取的确切图像数据-它会在运行readImageBlob()时将其转换为其内部格式,并在运行getImageBlob()时将其转换为输出格式。

即使它是相同的格式-例如PNG输入和PNG输出-相同的图像可以以数百种方式保存-取决于例如压缩设置等。对于有损格式,如JPG,你甚至无法得到相同的图像—这只是近似值。

在任何图像处理程序中尝试同样的方法,例如Gimp -打开在网上找到的一些PNG,以PNG形式保存到另一个文件名-您将得到两个不同的文件表示相同的图像。

我想这就是为什么你得到不同的数据大小