Resize image directly from Rackspace Cloud Files 'object' without downloading? - php

I have moved my images to Rackspace Cloud Files and am using their PHP API. I am trying to do the following:
Get an image from my "originals" container
Resize it, sharpen it, etc.
Save the resized image to the "thumbs" container
My problem is with #2. I was hoping to resize without having to copy the original to my server first (since the images are large and I'd like to resize dynamically), but can't figure out how. This is what I have so far (not much):
$container = $conn->get_container("originals");
$obj = $container->get_object("example.jpg");
$img = $obj->read();
Part of the problem is I don't fully understand what is being returned by the read() function. I know $img contains the object's "data" (which I was able to print out as gibberish), but it is neither a file nor a url nor an image resource, so I don't know how to deal with it. Is it possible to convert $img into an image resource somehow? I tried imagecreatefromjpeg($img) but that didn't work.
Thanks!

First, you cannot resize an image without loading it into memory. Unless the remote server offers some "resize my image for me, here are the parameters" API, you have to load the image in your script to manipulate it. So you'll have to copy the file from the CloudFiles container to your server, manipulate it, then send it back into storage.
The data you receive from $obj->read() is the image data. That is the file. It doesn't have a file name and it's not saved on the hard disk, but it is the entire file. To load this into gd to manipulate it, you can use imagecreatefromstring. That's analogous to using, for example, imagecreatefrompng, only that imagecreatefrompng wants to read a file from the file system by itself, while imagecreatefromstring just accepts the data that you have already loaded into memory.

You can try to dump the content of the $img variable into a writable file as per the below:
<?php
$filename = 'modifiedImage.jpg';
/*
* 'w+' Open for reading and writing; place the file pointer at the beginning of the file and truncate
* the file to zero length. If the file does not exist, attempt to create it.
*/
$handle = fopen($filename, 'w+');
// Write $img to the opened\created file.
if (fwrite($handle, $img) === FALSE) {
echo "Cannot write to file ($filename)";
exit;
}
echo "Success, wrote to file ($filename)";
fclose($handle);
?>
More details:
http://www.php.net/manual/en/function.fopen.php
http://www.php.net/manual/en/function.fwrite.php
Edit:
You might also want to double check the type of data returned by the read() function, because if the data is not a jpg image, if it's for example a png, the extension of the file needs to be changed accordingly.

Related

PHP: How to output image files?

I would like to add images to a dynamically generated page (I use my own template system) with PHP.
NOTE: I regulate image access for security reason.
The folder that contains the images is above the site root, therefore not accessible by HTML links.
I believe there is a method in which PHP returns a file as a resource, specifying the type in a header, and (correct me if I am wrong) a function specifically designed for that imagejpeg().
Please advise, and if possible write a simple example.
What you need to do to output image files is in order:
PHP loads the image from the file, this is file_get_contents or otherwise fopen to open and access the file itself. If the file is a specific image file you can open the file with imagecreatefromjpeg() which will do just that, generate an image file from a JPEG source.
Then, once the file is loaded from anywhere on your filesystem, including directories outside of your web root, PHP can output the data caught in point 1, above, with some HTTP Headers and direct reference to the loaded image.
NOTE: this means that the sole output of this PHP file is the image,
so file.php === image.jpg in this case.
So a brief example:
image is stored in /home/images/image1.jpg
PHP file runs from /home/site/imagecall.php
PHP file says:
<?php
if (file_exists('/home/images/image1.jpg')){
$image = imagecreatefromjpeg('/home/images/image1.jpg');
if ($image){
header('Content-Type: image/jpeg');
imagejpeg($image);
imagedestroy($image);
}
else {
die("Image could not be loaded");
}
}
This is a starting point for you and by no means an absolute guide. Explore.
Useful references:
http://php.net/manual/en/function.imagecreatefromjpeg.php
http://php.net/manual/en/function.file-get-contents.php

how to retrieve blob file to image in php?

I am using plupload to upload file in my php based website, with large file uploading the file becomes a file named 'blob' without any suffix. I know this is a binary file that contains the raw data, question is how to retrieve the data and save it back as an image file, say .png/.jpg or etc? I tried:
$imageString = file_get_contents($blogPath);
$image = imagecreatefromstring($imageString);
But it gives me some 'Data is not in recognized format...' error, any thoughts? Thanks in advance.
Your call to imagecreatefromstring() should work just fine if your file_get_contents() is working. Use var_dump($imageString) to verify. Did you mean to name your variable $blobPath instead of $blogPath?
You don't need to load this image though. Just rename the file.
rename($blobPath, 'new/path/here.jpg');
http://php.net/manual/en/function.rename.php
I am storing the uploaded image files for late use, like attaching them to posts or products(my site is e-commerce CMS). I figured that my image file didn't get fully uploaded to the server, the image before upload is 6mb, but the blob file is just 192kb, so my best guess is that what get uploaded is just a chunk instead of the whole package, and yet that brought up another question: how should I take all the pieces and assemble them as one complete image file? As mentioned earlier, I am using plupload for js plugin and php as backend, the backend php code to handle uploading goes like this:
move_uploaded_file($_FILES["file"]["tmp_name"], $uploadFolder . $_FILES["file"]["name"]);
Instead of doing that you should do this to display image to the browser
<img src="data:image/jpeg;base64,'.base64_encode( $row['blob_image'] ).'"/>
I'm not sure what imagecreatefromsting does or how it encodes the image.
I looked at the documentation for that function; you're missing:
$data = 'iVBORw0KGgoAAAANSUhEUgAAABwAAAASCAMAAAB/2U7WAAAABl'
. 'BMVEUAAAD///+l2Z/dAAAASUlEQVR4XqWQUQoAIAxC2/0vXZDr'
. 'EX4IJTRkb7lobNUStXsB0jIXIAMSsQnWlsV+wULF4Avk9fLq2r'
. '8a5HSE35Q3eO2XP1A1wQkZSgETvDtKdQAAAABJRU5ErkJggg==';
$data = base64_decode($data); <--- this operation

Uploading PNG file to nginx server via HTTP_RAW_POST_DATA results in corrupted image

I'm trying to debug this issue by posting raw PNG image data to the server with the help of Postman. Here's a screenshot, which might help to understand the issue:
On the server I'm receiving the file as follows:
$png = $GLOBALS["HTTP_RAW_POST_DATA"];
Then I write the data to a new file:
$fh = fopen($myFile, 'w') or die("can't open file");
fwrite($fh, $png);
fclose($fh);
The file gets saved correctly, but it now has a different file size,
417KB instead of 279KB which is the size of the original file.
Now of course, I can't do any image operation as none of the functions (such as getimagesize which returns bool(false)) recognizes the file as a valid image.
I have debugged this process to a point where the issue must be somewhere in the file operations, but I don't understand why the file just doesn't result in the very same file type and size as the original, when the only thing I am doing is using the same raw data.
UPDATE:
I've now compared the encodings of the original file with the uploaded one,
and the former is in ISO-8859-1 and it displays correctly, the latter is in UTF-8 and has about 138kB more in file size.
Now I've achieved to convert the file on the server to ISO-8859-1.
fwrite($fh, iconv("UTF-8", "ISO-8859-1", $png));
The resulting file does now have the same output file size (279kB),
but it is still not recognized as a PNG image, some information seems to still get lost.
UPDATE (1):
I've been able to examine the issue further and found out, that the original file is exactly 4 bytes bigger than the generated file, thus the resulting PNG seems to be corrupted.
UPDATE (2):
I'm now able to save the file and open it as a valid PNG. The following code seems to be saving the image correctly:
$input = fopen("php://input","r+");
$destination = fopen($myFile, 'w+');
stream_copy_to_stream($input, $destination);
fclose($input);
fclose($destination);
However when trying to open the file with the imagecreatefrompng function I get a 500 error. I'm now trying to figure out if it's a memory issue in PHP.
Problem might be the way you test your POST by copying the "binary" data into a text field.
If you paste the same data into a text editor you won't get a valid image file either when saving this with the png extension.
Try to build a simple form with file field to test your upload
I use nginx for uploads and haven't had a problem, but I use the standard PHP way of uploading files as per: http://www.php.net/manual/en/features.file-upload.post-method.php
I would suggest trying that.
Try using: < ?php $postdata = file_get_contents("php://input"); ?>
To get the raw data. I use it some times to get data sent from a ajax post on cake.

base64 Pic Upload and Crop Situation PHP

I am trying to take a pic upload from a mobile device to a server. We are building with PhoneGap (Javascript), so we are having turn it into a string in order to send it to the server. I am having problems once I receive it, to turn it back into a readable image file.
Simply put, I need to take a string and a file name sent to me, decode it, convert it into a .png, then crop it into a circular image.
This is what I have going on currently
if (isset($_POST['file']))
{
//Result variable
$result = false;
$pic = base64_decode($_POST['file']);
$filename = $_POST['filename'];
if (strlen($pic) > 9 )
{
$fh = fopen("/var/www/pics/events/".$filename, 'w') or die("can't open file");
fwrite($fh, $pic);
fclose($fh);
}
}
I think I can get the rest of the code to work if I can figure out what I am doing wrong here that makes it not save properly as a image file? The file uploads correctly, but it stores with out an extension, and when I point to it in my browser, it comes up like it is supposed to be an image file, but never displays the image. That little broken picture icon with the colored shapes is what I get when I direct to it's location.
Do I need to be aware of what image type is being sent during this process at all? How is it knowing if it is a .gif, .jpg/jpeg, .png, etc...?
Thanks in advance for any help!
Nathan
For Security reasons you should sanitize the file name to prevent directory traversal.
On a brighter note, make sure the file is saved with the proper extension; if you are already saving with the correct extension you could have an encoding issue from the app.
If neither of the previous possibilities are the case make sure that your String Size does not exceed the maximum POST size limit in your php.ini; if that is the case increase the size limit.

Need Help Understanding this PHP Code

i am aware of the basics like what is a function, a class, a method etc. however i am totally confused on what exactly the below code does to read the image, i read it somewhere that we have to read the image in binary format first. i am confused on the process how the php reads the image and loads it for reading. i would like to know the function of each and every code in this class and what is actually happening with the code.
Code :
class Image {
function __construct($filename) {
//read the image file to a binary buffer
$fp = fopen($filename, 'rb') or die("Image $filename doesn't exist");
$buf = '';
while(!feof($fp))
$buf .= fgets($fp, 4096);
//create image
imagecreatefromstring($buf);
}
}
and when i instantiate the object image with the syntax $image = new Image("pic.jpg"); it does not print the image in html, what does the variable $image actually hold, if i want to print that image in html what should i be doing.
Update :
FYI : I understand PHP and HTML, as i was trying to learn OOP in PHP and i came across the article as this particular code was not understood clearly by me so i thought of asking you guys, i highly appreciate your response, i would be thankful if you could try and explain the code instead of asking me to try different code.
My concern is purely meant for learning purpose, i am not implementing it anywhere.
In HTML, all you need to do is refer to the file in an <img> tag.
<img src="/path/to/image/image.jpg" width="600" height="400" alt="Image Name" />
The source needs to be the URL of the image, relative to your webserver root directory.
As for the code, you put up. That would be completely unnecessary for HTML usage, and is also unnecessary for standard image use within PHP, as there are direct methods to load an image from a file, imagecreatefromjpeg() for instance for JPEG files.
As it stands, the constructor of your Image class takes a filename, opens that file and reads the entire contents as binary data in to the string $buf, 4096 bytes at a time. Then it calls imagecreatefromstring($buf) to convert the file data in to an image resource, which can then be used further within PHP with the PHP GD image handling functions.
As I say, none of this is particularly relevant if all you wish to do is display an existing image within HTML. Those commands are designed for image manipulation, inspection and creation.
Your $image would contain an instance of the Image Class.
Your constructor will try to open $filename. If that's not possible, the script will die/terminate with an error message. If $filename can be opened, the file will be read into the $buf variable and a GD image resource will be created.
The code is suboptimal for a number of reasons:
the GD resource created by imagecreatefromstring is not assigned to a property of the Image class. This means, the entire process is pointless, because the resource will be lost after it was created. The work done in the constructor is lost.
calling die will terminate the script. There is no way to get around this. It would be better to throw an Exception to let the developer decide whether s/he wants the script to terminate or catch and handle this situation.
reading a file with fopen and fread works, but file_get_contents is the preferred way to read the contents of a file into a string. It will use memory mapping techniques if supported by your OS to enhance performance.
You should not do work in the constructor. It is harmful to testability.
A better approach would be to use
class Image
{
protected $_gdResource;
public function loadFromFile($fileName)
{
$this->_gdResource = imagecreatefromstring(
file_get_contents($fileName)
);
if(FALSE === $this->_gdResource) {
throw new InvalidArgumentException(
'Could not create GD Resource from given filename. ' .
'Make sure filename is readable and contains an image type ' .
'supported by GD'
);
}
}
// other methods working with $_gdResource …
}
Then you can do
$image = new Image; // to create an empty Image instance
$image->loadFromFile('pic.jpg') // to load a GD resource
PHP's imagecreate* function return a resource. If you want to send it to the client, you'll have to set the appropriate headers and then send the raw image:
header('Content-Type: image/jpeg');
imagejpeg($img);
See the GD and Image Functions documentation for details.
class Image
{
public $source = '';
function __construct($filename)
{
$fp = fopen($filename, 'rb') or die("Image $filename doesn't exist");
$buf = '';
while(!feof($fp))
{
$buf .= fgets($fp, 4096);
}
$this->source = imagecreatefromstring($buf);
}
}
$image = new Image('image.jpg');
/* use $image->source for image processing */
header('Content-Type: image/jpeg');
imagejpeg($image->source);
If you just want to display the image, all of the above is irrelevant. You just need to write out an HTML image tag, e.g.
echo '<img src="pic.jpg" />';
That's it.
The code that you have given takes a very long and inconvenient way to load an image for manipulation using the GD library; that's almost certainly not what you wanted to do, but if you did, then you could use imagecreatefromjpeg instead.

Categories