Создание изображения без сохранения его как локальный файл - PullRequest
12 голосов
/ 10 октября 2008

Вот моя ситуация - я хочу создать изображение jpeg с измененным размером из загруженного пользователем изображения, а затем отправить его на S3 для хранения, но стараюсь не записывать jpeg с измененным размером на диск и затем повторно загружать его для запроса S3 .

Есть ли способ сделать это полностью в памяти, с данными изображения в формате JPEG, сохраненными в переменной?

Ответы [ 8 ]

12 голосов
/ 01 января 2009

Большинство людей, использующих PHP, выбирают либо ImageMagick , либо Gd2

Я никогда не использовал Imagemagick; метод Gd2:

<?php

// assuming your uploaded file was 'userFileName'

if ( ! is_uploaded_file(validateFilePath($_FILES[$userFileName]['tmp_name'])) ) {
    trigger_error('not an uploaded file', E_USER_ERROR);
}
$srcImage = imagecreatefromjpeg( $_FILES[$userFileName]['tmp_name'] );

// Resize your image (copy from srcImage to dstImage)
imagecopyresampled($dstImage, $srcImage, 0, 0, 0, 0, RESIZED_IMAGE_WIDTH, RESIZED_IMAGE_HEIGHT, imagesx($srcImage), imagesy($srcImage));

// Storing your resized image in a variable
ob_start(); // start a new output buffer
  imagejpeg( $dstImage, NULL, JPEG_QUALITY);
  $resizedJpegData = ob_get_contents();
ob_end_clean(); // stop this output buffer

// free up unused memmory (if images are expected to be large)
unset($srcImage);
unset($dstImage);

// your resized jpeg data is now in $resizedJpegData
// Use your Undesigned method calls to store the data.

// (Many people want to send it as a Hex stream to the DB:)
$dbHandle->storeResizedImage( $resizedJpegData );
?>

Надеюсь, это поможет.

7 голосов
/ 01 января 2009

Это можно сделать с помощью библиотеки GD и буферизации вывода. Я не знаю, насколько это эффективно по сравнению с другими методами, но это не требует явного создания файлов.

//$image contains the GD image resource you want to store

ob_start();
imagejpeg($image);
$jpeg_file_contents = ob_get_contents();
ob_end_clean();

//now send $jpeg_file_contents to S3
6 голосов
/ 10 октября 2008

Когда у вас есть JPEG в памяти (с использованием ImageMagick , GD или выбранной вами графической библиотеки), вам необходимо загрузить объект из памяти в S3 .

Многие классы PHP S3 поддерживают загрузку файлов, но класс Undesigned , кажется, делает то, что нам нужно -

// Manipulate image - assume ImageMagick, so $im is image object
$im = new Imagick();
// Get image source data
$im->readimageblob($image_source);

// Upload an object from a resource (requires size):
$s3->putObject($s3->inputResource($im->getimageblob(), $im->getSize()), 
                  $bucketName, $uploadName, S3::ACL_PUBLIC_READ);

Если вместо этого вы используете GD, вы можете использовать imagecreatefromstring для чтения изображения из потока, но я не уверен, сможете ли вы получить размер результирующего объекта, как требуется s3->inputResource выше - getimagesize возвращает высота, ширина и т. д., но не размер ресурса изображения.

5 голосов
/ 12 октября 2013

Понимаю, что это старая нить, но я потратил некоторое время на то, чтобы биться головой об стену сегодня, и подумал, что смогу найти здесь решение для следующего парня.

Этот метод использует AWS SDK для PHP 2 и GD для изменения размера изображения (можно легко использовать Imagick).

require_once('vendor/aws/aws-autoloader.php');

use Aws\Common\Aws;

define('AWS_BUCKET', 'your-bucket-name-here');

// Configure AWS factory 
$aws = Aws::factory(array(
    'key' => 'your-key-here',
    'secret' => 'your-secret-here',
    'region' => 'your-region-here'
));

// Create reference to S3
$s3 = $aws->get('S3');
$s3->createBucket(array('Bucket' => AWS_BUCKET));
$s3->waitUntilBucketExists(array('Bucket' => AWS_BUCKET));
$s3->registerStreamWrapper();

// Do your GD resizing here (omitted for brevity)

// Capture image stream in output buffer
ob_start();
imagejpeg($imageRes);
$imageFileContents = ob_get_contents();
ob_end_clean();

// Send stream to S3
$context = stream_context_create(
  array(
    's3' => array(
      'ContentType'=> 'image/jpeg'
    )
  )
);
$s3Stream = fopen('s3://'.AWS_BUCKET.'/'.$filename, 'w', false, $context);
fwrite($s3Stream, $imageFileContents);
fclose($s3Stream);

unset($context, $imageFileContents, $s3Stream);
5 голосов
/ 27 июня 2012

Довольно поздно для игры на этом, но если вы используете библиотеку S3, упомянутую ConroyP и Imagick, вы должны использовать метод putObjectString () вместо putObject (), поскольку getImageBlob возвращает строку. Пример, который наконец-то сработал для меня:

$headers = array(
    'Content-Type' => 'image/jpeg'
);
$s3->putObjectString($im->getImageBlob(), $bucket, $file_name, S3::ACL_PUBLIC_READ, array(), $headers);

Я немного боролся с этим, надеюсь, это поможет кому-то еще!

4 голосов
/ 10 октября 2008

Библиотека Imagemagick позволит вам сделать это. Существует множество PHP-оболочек, таких как this , один из них (даже пример кода для того, что вы хотите сделать на этой странице;))

1 голос
/ 02 сентября 2017

Я столкнулся с той же проблемой, используя хранилище объектов openstack и библиотеку php-opencloud .

Вот мое решение, которое не использует функции ob_start и ob_end_clean, но сохраняет изображение в памяти и во временном файле. Размер памяти и временный файл могут быть адаптированы во время выполнения .

// $image is a resource created by gd2
var_dump($image); // resource(2) of type (gd)

// we create a resource in memory + temp file 
$tmp = fopen('php://temp', '$r+');

// we write the image into our resource
\imagejpeg($image, $tmp);

// the image is now in $tmp, and you can handle it as a stream
// you can, then, upload it as a stream (not tested but mentioned in doc http://docs.aws.amazon.com/aws-sdk-php/v2/guide/service-s3.html#uploading-from-a-stream)
$s3->putObject(array(
   'Bucket' => $bucket,
   'Key'    => 'data_from_stream.txt',
   'Body'   => $tmp
));

// or, for the ones who prefers php-opencloud :
$container->createObject([
    'name'  => 'data_from_stream.txt',
    'stream' => \Guzzle\Psr7\stream_for($tmp),
    'contentType' => 'image/jpeg'
]);

О php://temp ( из официальной документации php ):

php: // memory и php: // temp являются потоками для чтения и записи, которые позволяют хранить временные данные в файловой оболочке. Единственное различие между ними состоит в том, что php: // memory всегда будет хранить свои данные в памяти, тогда как php: // temp будет использовать временный файл, как только объем хранимых данных достигнет заранее определенного предела (по умолчанию 2 МБ). Расположение этого временного файла определяется так же, как функция sys_get_temp_dir ().

Предел памяти php: // temp может контролироваться добавлением / maxmemory: NN, где NN - максимальный объем данных, сохраняемых в памяти перед использованием временного файла, в байтах.

0 голосов
/ 10 октября 2008

Май с использованием библиотеки GD .

Существует функция, позволяющая скопировать часть изображения и изменить ее размер. Конечно, эта часть может быть целым изображением, поэтому вы можете только изменить его размер.

см. imagecopyresampled

...