从 PostgreSQL bytea,我们尝试使用 Imagick 读取并写回图像文件
我尝试从 PostgreSQL 将图像文件读入 Imagick 对象 - 并简单地将相同的文件重新写回另一个 bytea 字段。目标是充分理解 PHP 和 Imagick 中使用的字符串处理和转换。
这是在 PostgreSQL 9 上,因此本机 bytea_output 是十六进制;我一直在按照注释将 byteea_output 更改为转义以便由 PHP 处理。
最终的目标是将此文件转换为 ImageMagick 支持的任何格式。
事情开始得很好!取消转义后,$imagestring 正是磁盘上文件的长度。到目前为止,一切都很好。此后不久事情就失去了控制......
我找不到任何可写回的字符串,它将重新构成文件(以相同的长度)返回数据库。
这里看起来有什么问题吗?
// 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;
From PostgreSQL, am trying to read an image file into an Imagick object - and simply re-write the same file back into another bytea field. Objective is to fully understand the string handling and conversions used in PHP and Imagick.
This is on PostgreSQL 9, so the native bytea_output is hex; I've been following notes to change bytea_output to escape for handling by PHP.
Ultimately, objective is to convert this file into any of ImageMagick's supported formats.
Things start out well enough! After unescaping it, the $imagestring is exactly the length of the file on disk. So far, so good. Things get out of control shortly thereafter...
I can't find any string to write back which will re-constitute the file - at the same length - back to the DB.
What looks wrong here?
// 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;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为 ImageMagick 不记得它所读取的确切图像数据 - 它会在运行
readImageBlob()
时将其转换为其内部格式,并在运行getImageBlob()
时将其转换为输出格式代码>.即使它是相同的格式 - 例如 PNG 输入和 PNG 输出 - 相同的图像可以以数百种方式保存 - 例如取决于压缩设置等。对于有损格式,如 JPG,你甚至不会得到相同的图像图像 - 只是它的近似值。
在任何图像处理程序中尝试相同的操作,例如 Gimp — 打开在网络上找到的一些 PNG,另存为 PNG 到另一个文件名 — 您将得到代表同一图像的两个不同文件。
我认为这就是为什么你会得到不同的数据大小。
I think ImageMagick does not remember exact image data it has read — it will convert it while running
readImageBlob()
to its internal format, and converts it to output format while runninggetImageBlob()
.Even if it is the same format — for example PNG input and PNG output — the same image can be saved in hundreds of ways — depending for example on compression settings etc. For lossy formats, like JPG, you'll not even get the same image — only it's approximation.
Try the same in any image processing program, for example Gimp — open some PNG found on the web, save as PNG to another file name — you'll get two different files representing the same image.
I think that's why you're getting different data sizes.