Вопрос

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;
Это было полезно?

Решение

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 running getImageBlob().

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.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top