I am using the following code to upload image content to the ECS server
$result = $s3->putObject(array(
'Bucket' => $this->bucket,
'Key' => $Destination_folder,
'Body' => $image_content
));
Earlier I was storying the image to a temporary location and then convering it into 3 images of different size (using Imagick) and then uploading those images individually.
Now I am able to upload the image directly using the image content and I also figured out how to resize the image using the image content. Following is the code for that using Imagick
$imagick->readImageBlob($imageBlob);
$res = $imagick->scaleImage(10, 10, true);
$writeSuccess = $imagick->writeImage("abc-m.jpeg");
But now I want to upload the image directly to the ECS server after resizing but without using temporary loaction.
How can I uplaod the resized image from Imagick to ECS server?
use getImageBlob()
$image_content = $imagick->getImageBlob();
Now upload this image content to the server.
I'm creating a png and uploading immediately to S3, I'd like to log how big that file was without having to do a seperate call to the same file on S3 to work out the size on disk.
Is this possible?
$tile = imagecreatetruecolor($tileImageSize, $tileImageSize);
imagecopy($tile, $resizedMainImage, 0, 0, $currentCoordsX, $currentCoordsY, $tileSize, $tileSize);
$writeStream = fopen("s3://bucket/file.png", 'w');
imagepng($tile, $writeStream, 9); // need filesize of this action
I've tried wrapping the imagepng in ob_start(); ob_get_length(); etc with no joy.
The thing is that you will need to save the image somewhere in order to get the size. To avoid writing to the filesystem, you can use the memory storage of php. I mean something like this:
imagepng($tile, 'php://memory/image.png');
$file_size = filesize('php://memory/image.png');
You can do this before uploading the image to the server to have the information for your log.
I am using phalcon php framework. I have a blog in my application where a user can submit an image attached to his blog post, and it is displayed when viewing the post. I want to display this image on the index page of the blog where each post is listed, however, i want it to be a thumbnail to reduce its size. I was able to use imagick to save a thumbnail at a directory and load the thumbnail from there, however, i need to avoid saving the thumbnail and generate the thumbnails every time just to display them.
Here is the code I used to create the image with imagick
public function thumbnail($img)
{
$maxsize = 100;
$image = new Imagick($img);
// Resizes to whichever is larger, width or height
if($image->getImageHeight() <= $image->getImageWidth())
{
$image->resizeImage($maxsize,0,Imagick::FILTER_LANCZOS,1);
}
else
{
$image->resizeImage(0,$maxsize,Imagick::FILTER_LANCZOS,1);
}
// Set to use jpeg compression
$image->setImageCompression(Imagick::COMPRESSION_JPEG);
// Set compression level (1 lowest quality, 100 highest quality)
$image->setImageCompressionQuality(75);
// Strip out unneeded meta data
$image->stripImage();
// Writes resultant image to output directory
$image->writeImage($uploaddir.'/thumbs/'. basename($_FILES['photo']['name']));
// Destroys Imagick object, freeing allocated resources in the process
$image->destroy();
}
I tried just to remove the last two lines where the image is saved and then the imagick object is destroyed, but couldn't go on to display the image in the index view.
Step 1 - Use the buffer.
Step 2 - Unlink the already saved image after you get its base64 code.
For example consider the following code snippet:
$im = new Imagick();
$im->setResolution(300,300);
$im->readimage('path_to_the_file.pdf');
$im->setImageFormat('jpeg');
$im->writeImages('file_name_to_save.jpg', false);
$im->clear();
$im->destroy();
$dest = imagecreatefromjpeg ('file_name_to_save.jpg');
//Step 1
ob_start();
imagejpeg($dest);
$image_data = ob_get_clean();
imagedestroy($dest);
$img_source = base64_encode($image_data);
//Step 2
unlink('file_name_to_save.jpg');
Now in the $img_source variable you have the base64 of the image that you can use it like this:
'<img src="data:image/jpg;base64,'.$img_source.'" style="max-width: 100%; max-height:100%;" />';
I'm using something similar to this:
public function thumbAction() {
// Generate thumb from image & save it on disk
$image = $this->thumbnail(); // well can be anything that return Imagick
$this->response->setHeader('Content-Type', 'image/jpg');
echo $image;
}
Anyway in above example you don't need to save the image but only echo created thumb to the user.
Also I'm storing an image on some path like thumbs/a/image.jpg. I've configured nginx to check for existing file and if file does not exists it calls Phalcon script.
In Phalcon app I have a route that points to any /thumbs* path to above action. On first call the image is saved on the path thumbs/a/ so on the next call Nginx server returns that image instead of calling PHP.
I am working on building gallery where the user uploads all the images. I had tried to use GD originally but found that it used way too much memory when dealing with images from a digital camera. So I have been looking into ImageMagick and ran into this problem.
My end goal is to resize the image and then upload it. I am not sure if this is possible with ImageMagick or not. I have gotten it to resize the image after upload but it doesn't save the resized image, just the original size.
This is the code I am currently using: ($image is the path to the file on my server)
$resource = NewMagickWand();
MagickReadImage($resource,$image);
MagickSetImageCompressionQuality( $resource, 100);
$resource = MagickTransformImage($resource,'0x0','660x500');
Any input would be appreciated,
Levi
Your code will send the modified image to the client (the web browser), but it will not save it to the server (replacing the original image, for example)
To save the image, use:
MagickWriteImage( $resource, 'new_image.jpg' );
Here's my situation - I want to create a resized jpeg image from a user uploaded image, and then send it to S3 for storage, but am looking to avoid writing the resized jpeg to the disk and then reloading it for the S3 request.
Is there a way to do this completely in memory, with the image data JPEG formatted, saved in a variable?
Most people using PHP choose either ImageMagick or Gd2
I've never used Imagemagick; the Gd2 method:
<?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 );
?>
Hope this helps.
This can be done using the GD library and output buffering. I don't know how efficient this is compared with other methods, but it doesn't require explicit creation of files.
//$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
Once you've got the JPEG in memory (using ImageMagick, GD, or your graphic library of choice), you'll need to upload the object from memory to S3.
Many PHP S3 classes seem to only support file uploads, but the one at Undesigned seems to do what we're after here -
// 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);
If you're using GD instead, you can use
imagecreatefromstring to read an image in from a stream, but I'm not sure whether you can get the size of the resulting object, as required by s3->inputResource above - getimagesize returns the height, width, etc, but not the size of the image resource.
Pretty late to the game on this one, but if you are using the the S3 library mentioned by ConroyP and Imagick you should use the putObjectString() method instead of putObject() due the fact getImageBlob returns a string. Example that finally worked for me:
$headers = array(
'Content-Type' => 'image/jpeg'
);
$s3->putObjectString($im->getImageBlob(), $bucket, $file_name, S3::ACL_PUBLIC_READ, array(), $headers);
I struggled with this one a bit, hopefully it helps someone else!
Realize this is an old thread, but I spent some time banging my head against the wall on this today, and thought I would capture my solution here for the next guy.
This method uses AWS SDK for PHP 2 and GD for the image resize (Imagick could also be easily used).
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);
The Imagemagick library will let you do that. There are plenty of PHP wrappers like this one around for it (there's even example code for what you want to do on that page ;) )
I encounter the same problem, using openstack object store and php-opencloud library.
Here is my solution, which does not use the ob_start and ob_end_clean function, but store the image in memory and in temp file. The size of the memory and the temp file may be adapted at runtime.
// $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'
]);
About php://temp (from the official documentation of php):
php://memory and php://temp are read-write streams that allow temporary data to be stored in a file-like wrapper. The only difference between the two is that php://memory will always store its data in memory, whereas php://temp will use a temporary file once the amount of data stored hits a predefined limit (the default is 2 MB). The location of this temporary file is determined in the same way as the sys_get_temp_dir() function.
The memory limit of php://temp can be controlled by appending /maxmemory:NN, where NN is the maximum amount of data to keep in memory before using a temporary file, in bytes.
Maye by using the GD library.
There is a function to copy out a part of an image and resize it. Of course the part could be the whole image, that way you would only resize it.
see imagecopyresampled