I use a script (http://www.webmotionuk.co.uk/php-jquery-image-upload-and-crop-v11/) that handles an image and then create a thumbnail.
Actually I don't want to store images on the file system but I want to store them in a mysql db in a BLOB field.
I could first store the created thumbnail on the fs, store the file in the DB and after i can delete the thumb from FS.
Is there a way to store directly the image on the DB?
This is the function:
function resizeThumbnailImage($thumb_image_name, $image, $width, $height, $start_width, $start_height, $scale){
list($imagewidth, $imageheight, $imageType) = getimagesize($image);
$imageType = image_type_to_mime_type($imageType);
$newImageWidth = ceil($width * $scale);
$newImageHeight = ceil($height * $scale);
$newImage = imagecreatetruecolor($newImageWidth,$newImageHeight);
switch($imageType) {
case "image/gif":
$source=imagecreatefromgif($image);
break;
case "image/pjpeg":
case "image/jpeg":
case "image/jpg":
$source=imagecreatefromjpeg($image);
break;
case "image/png":
case "image/x-png":
$source=imagecreatefrompng($image);
break;
}
imagecopyresampled($newImage,$source,0,0,$start_width,$start_height,$newImageWidth,$newImageHeight,$width,$height);
switch($imageType) {
case "image/gif":
imagegif($newImage,$thumb_image_name);
break;
case "image/pjpeg":
case "image/jpeg":
case "image/jpg":
imagejpeg($newImage,$thumb_image_name,90);
break;
case "image/png":
case "image/x-png":
imagepng($newImage,$thumb_image_name);
break;
}
chmod($thumb_image_name, 0777);
return $thumb_image_name;
}
How to:
Use file_get_contents() on the returned thumbnail, and then write the results to the database blob field.
$image = file_get_contents($thumbnail);
mysql_query("INSERT INTO tblName (fieldName) VALUES ('{$image}')");
But, you may not want to because:
That being said, I would encourage you to really consider what you're doing. Images pulled from the database won't be cached, from my understanding. Additionally, database connections will remain opened for much longer, using more resources. Also, your database size will grow rapidly, making it more laborious to manage migration down the road.
You can store binary data such as an image into a BLOB field in a database. It's as simple as putting the file contents into an INSERT statement. However, I highly suggest you take a look at some of these threads. Storing an image in a database is usually not the best way to go:
User Images: Database or filesystem storage?
Storing images in database: Yea or nay?
Should I store my images in the database or folders?
Would you store binary data in database or folders?
Store pictures as files or or the database for a web app?
Storing a small number of images: blob or fs?
store image in filesystem or database?
As J. Sampson said, it's not a good way to store images, but it is possible. Do as Jonathan said and then get data out of db, something similar to this:
<?php
$query = mysql_query("SELECT * FROM tbl WHERE id = 'blaa';");
$data = mysql_fetch_array($query);
//Then create image with function
imagecreatefromstring($data['imgdata'])
?>
Related
I was using this call to imageMagick in PHP to merge multiple images horizontally
$combined_image = $images2merge->appendImages(false);
And it works great when I upload the images from my laptop. But when I go to the same page with my android phone browser and use the camera to take the pics to upload, this function ends up merging them vertically.
So I tried to swap it out with this function
$combined_image = $images2merge->montageImage($draw, '6×6+0+0', '+1+1', Imagick::MONTAGEMODE_UNFRAME, 0);
And that does now merge them horizontally when I use my phone, but it rotates them 90 degrees counterclockwise. Again that's different from what happens when I upload from my laptop, in which case it works as expected. It's hard to fix something that behaves inconsistently.
Any suggestions on how to fix this would be greatly appreciated!
After taking photos from any smartphone, please check the orientation value and rotate the image accordingly before further image processing.
So you can use the following autoRotateImage function to handle the auto-rotation:
<?php
function autoRotateImage($image) {
$orientation = $image->getImageOrientation();
switch($orientation) {
case imagick::ORIENTATION_BOTTOMRIGHT:
$image->rotateimage("#000", 180); // rotate 180 degrees
break;
case imagick::ORIENTATION_RIGHTTOP:
$image->rotateimage("#000", 90); // rotate 90 degrees CW
break;
case imagick::ORIENTATION_LEFTBOTTOM:
$image->rotateimage("#000", -90); // rotate 90 degrees CCW
break;
}
// Now that it's auto-rotated, make sure the EXIF data is correct in case the EXIF gets saved with the image!
$image->setImageOrientation(imagick::ORIENTATION_TOPLEFT);
}
?>
For example:
<?php
$image = new Imagick('my-image-file.jpg');
autoRotateImage($image);
// - Do other stuff to the image here -
$image->writeImage('result-image.jpg');
?>
I am trying to use Imagick in my php code to properly orient images, so that I can strip the metadata from them and have them properly show up. I tried the methodology in this post:
Detect EXIF Orientation and Rotate Image using ImageMagick
But it is not working. Using the autorotate function in that post, this is what I am doing:
$working_image = new \Imagick();
$working_image->readImageBlob( $source_data);
$working_image->setImageFormat('jpeg');
autorotate($working_image);
... some resizing code:
$working_image->resizeImage( $width, $height, \Imagick::FILTER_CATROM, .7);
// get rid of metadata
$working_image->stripImage();
$working_image->writeImage( <unique filename> );
$working_image->getImageBlob();
... write out to data file to google
We're using Google's cloud stuff to store our files, hence the "getImageBlob" call.
Problem is that this doesn't seem to work. The resultant images are still oriented the same way they were, but now have no metadata, so the tag won't "fix" them.
What am I doing wrong here? I am using this version of the Imagick PHP object:
[versionNumber] => 1673
[versionString] => ImageMagick 6.8.9-9 Q16 x86_64 2015-01-05 http://www.imagemagick.org
In response to your answer:
Thanks for the clarifications. Looking at one of the specific images that I am having problems with, identify -verbose shows multiple places defining orientation:
Orientation: RightTop
exif:Orientation: 6
exif:thumbnail:Orientation: 6
And this is reflected in my call to Imagick::getImageOrientation in PHP, which returns the "6" value, which then causes my code to call functions like "Imagick::rotateImage("#000", 180);". The problem is that the image is unchanged by these calls. 8-(
The core problem is this: We get these images by the thousands every day from MLS's all over the country. We currently process them (resizing currently) via an automatic process. When they are displayed on our site, everything is currently fine, because the <img> tag seems to be happy to interpret the EXIF data and show the image in proper orientation. BUT... we want to start optimizing images, which means stripping the EXIF info out. So I need to figure out why Imagick->rotateImage() isn't working.
Ok, let's write a whole answer:)
What I meant with the link to ImageMagick's -auto-orient, was to point out, that this kind of auto-orientation depends on EXIF profile and "Orientation" setting. If it's missing or is wrong the auto-orientation will not work as expected. To check whether your images has the EXIF profile with Orientation in tact, you can use several ways:
PHP Imagick (check it with image before you call ->stripImage())
echo 'Orientation is: ', $working_image->getImageOrientation();
PHP (if you have local file)
$exif = exif_read_data('input.jpg');
echo 'Orientation is: ', isset($exif['Orientation']) ? $exif['Orientation'] : 'missing';
Online EXIF reader.
The values you get are described for example here or more about image auto-rotation topic and sample images are here
Or you can use programs like Gimp or Photoshop.
So you're doing nothing wrong, without EXIF this won't work. It's camera that is writing the tags into images, so there is no guarantee all your photos have it.
Perhaps offer image rotation for visitors in your website instead? There is now CSS3 transform: rotate(deg) property that makes it really easy, see....
We can get the current image orientation and can easily update to the original one with Imagick
public function fix_image_orientation()
{
$working_image = new \Imagick();
$working_image->readImageBlob($source_data);
$working_image->setImageFormat('jpeg');
$orientation = $working_image->getImageOrientation();
if (!empty($orientation)) {
switch ($orientation) {
case imagick::ORIENTATION_BOTTOMRIGHT:
$working_image->rotateimage("#000", 180);
break;
case imagick::ORIENTATION_RIGHTTOP:
$working_image->rotateimage("#000", 90);
break;
case imagick::ORIENTATION_LEFTBOTTOM:
$working_image->rotateimage("#000", -90);
break;
}
}
$working_image->setImageOrientation(imagick::ORIENTATION_TOPLEFT);
$working_image->writeImage( <unique filename> );
}
#Satendra Rawat posted a good, but incomplete answer. There is the GitHub repository https://github.com/ianare/exif-samples, where you can see 8 orientation examples. Only 3, 5 and 8 worked correctly.
So here is a update for all the orientations:
public function fix_image_orientation()
{
$working_image = new \Imagick();
$working_image->readImageBlob($source_data);
$working_image->setImageFormat('jpeg');
$orientation = $working_image->getImageOrientation();
if (!empty($orientation)) {
switch ($orientation) {
default:
case imagick::ORIENTATION_TOPLEFT:
break;
case imagick::ORIENTATION_TOPRIGHT:
$working_image->flipImage();
$working_image->rotateImage("#000", 180);
break;
case imagick::ORIENTATION_BOTTOMRIGHT:
$working_image->rotateImage("#000", 180);
break;
case imagick::ORIENTATION_BOTTOMLEFT:
$working_image->flipImage();
break;
case imagick::ORIENTATION_LEFTTOP:
$working_image->rotateImage("#000", -90);
$working_image->flipImage();
break;
case imagick::ORIENTATION_RIGHTTOP:
$working_image->rotateImage("#000", 90);
break;
case imagick::ORIENTATION_RIGHTBOTTOM:
$working_image->rotateImage("#000", 90);
$working_image->flipImage();
break;
case imagick::ORIENTATION_LEFTBOTTOM:
$working_image->rotateImage("#000", -90);
break;
}
}
$working_image->setImageOrientation(imagick::ORIENTATION_TOPLEFT);
$working_image->writeImage( <unique filename> );
}
I making a web app where uploaded photos are stored in /app/storage.
To show the file I am using a route ex: showphoto/{id} (Paths are stored in DB)
public function showphoto($id){
$photo = Photo::findOrFail($id);
return $this->getFile($photo);
}
private function getFile($f){
if($f->path){
$file = storage_path($f->path.'/'.$f->origin_name);
if (File::exists($file)) {
$contents = File::get($file);
switch($f->ext) {
case "gif": $ctype="image/gif"; break;
case "png": $ctype="image/png"; break;
case "jpeg":
case "jpg": $ctype="image/jpeg"; break;
case "pdf": $ctype="application/pdf"; break;
default:
}
$response = Response::make($contents, 200);
$response->header('Content-Type', $ctype);
return $response;
}
}
}
To show image I am using
{{ HTML::image(route('showphoto', $photo->id), $photo->getName(), array('class'=>'img-thumbnail', 'width' => '100', 'height'=>'100')) }}
Question: Some file are more then 2 MB and when I have a list of them they are loading very slowly, So on the list I want to show just a Thumb of the photo.
It is possible to create a temporary thumb that will not be stored anywhere?
Or it is not a good idea to create a temporary thumb each time I load a page.
Thank you in advance.
If you have a bunch of large images that you are going to be processing in some way when a page is loaded you're probably going to have a bad time. All that extra processing is going to really slow everything down.
What you could do is create a thumbnail for an image when it is uploaded and store that somewhere. That way, you need only load your thumbnails instead of the larger images.
Alternatively, if you prefer to be able to specify the size of the thumbnail in your page another solution could be to generate your thumbnails at your specified size when the page loads. You'll need to make sure that you cache these thumbnails so you can use just load them in going forward though. If you opt for this approach the first time you load your page will probably take a while, but after that, subsequent page loads will be much quicker, since it will be using pre-created, cached images.
A great package to use with Laravel when manipulating images is Intervention Image:
http://image.intervention.io/
im writing an script that resize and crops the uploaded images.
all valid files are ok...
but some of my visitors are trying to upload non-valid ones.. for example the file extension is jpg, but in fact its a tiff file .. the uploading file's extension looks gif, but in its exif details writes 'its a jpg'.. etc..
As you can imagine, imagecreatefromXX() functions are all giving error in that case (its not a valid jpg etc)..
do you have any idea, how may i solve this problem?
how must i modify my recent codes?
switch($type) {
case 'gif':
$img = imagecreatefromgif($source);
break;
case 'jpg':
case 'JPEG':
case 'jpeg':
$img = imagecreatefromjpeg($source);
break;
case 'png':
$img = imagecreatefrompng($source);
break;
}
Your best bet would probably be to modify the code that sets $type, rather than the code you've shared (though John Conde's suggestion to have a default case is a good one), and use something like exif_imagetype (which your question suggests might already be in play) to determine the type, rather than trusting the extension (which you may even want to change to the appropriate type when writing the file): the extension is user-supplied data, and as such, the least likely to be accurate and/or useful.
e.g.
$type = exif_imagetype($source);
switch ($type){
case IMAGETYPE_GIF:
$img = imagecreatefromgif($source);
break;
case IMAGETYPE_JPG:
$img = imagecreatefromjpeg($source);
break;
case IMAGETYPE_PNG:
... etc ...
default:
//Fail Gracefully
}
I currently have an image upload input that only accepts PNG, JPG/JPEG, GIF images.
If the file is valid, it then proceeds to create a thumbnail from the image using
imagecreatefrompng()
imagecopy()
imagejpg()
This works fine, but ONLY for png images, obviously.
What is the most logical and efficient way to use "imagecreatefrompng()" except using the proper file format that was submitted? All I can think of is if/else using multiple "imagecreatefrom__()" but that doesn't seem right.
Also, how can my outputted format always be PNG no matter what was submitted instead of the current imagejpg() I have now.
You will have to use a switch and determine the image type like so:
$extension = strtolower(strrchr($file, '.'));
switch ($extension) {
case '.jpg':
case '.jpeg':
$img = #imagecreatefromjpeg($file);
break;
case '.gif':
$img = #imagecreatefromgif($file);
break;
case '.png':
$img = #imagecreatefrompng($file);
break;
default:
$img = false;
break;
}
-EDIT- Didn't see the second part of your question, you just need to save it using imagepng to save it to a PNG, no need to do anything else.
Using imagecreatefromstring( file_get_contents( $filename)) would be the lazy option here.
And if you always want a png output, then just exchanging imagejpg for imagepng would do.