When running Page Speed in Google Chrome it suggests to optimize/compress the images. These images are mostly uploaded by users, so I would need to optimize them during uploading. What I find about optimizing jpeg images with php is something like using the following GD functions:
getimagesize()
imagecreatefromjpeg()
imagejpeg()
Since I am resizing the images after upload I'm already pulling the image through these functions and in addition I use imagecopyresampled() after imagecreatefromjpeg() to resize it.
But then, Page Speed is still telling me these images can be optimized. How can I accomplish this optimisation in a php script? Set the quality lower in imagejpeg() doesn't make a difference either.
The imagejpeg function is where you assign the quality. If you're already setting that to an appropriate value then there is little else you can do.
Page speed probably considers all images above a certain size to be "needing compression", perhaps just ensure they are all as small as reasonable (in terms of height/width) and compressed.
You can find more about page speed and it's compression suggestions on the pagespeed docs http://code.google.com/speed/page-speed/docs/payload.html#CompressImages which describes some of the techniques/tools to compress appropriately.
I've also just read the following:
Several tools are available that perform further, lossless compression on JPEG and PNG files, with no effect on image quality. For JPEG, we recommend jpegtran or jpegoptim (available on Linux only; run with the --strip-all option). For PNG, we recommend OptiPNG or PNGOUT.
So perhaps (if you really want to stick to Google's suggestions) you could use PHP's exec to run one of those tools on files as they are uploaded.
To compress with php you do the following (sounds like you are already doing this):
Where $source_url is the image, $destination_url is where to save and $quality is a number between 1 and 100 choosing how much jpeg compression to use.
function compressImage($source_url, $destination_url, $quality) {
$info = getimagesize($source_url);
if ($info['mime'] == 'image/jpeg') $image = imagecreatefromjpeg($source_url);
elseif ($info['mime'] == 'image/gif') $image = imagecreatefromgif($source_url);
elseif ($info['mime'] == 'image/png') $image = imagecreatefrompng($source_url);
//save file
imagejpeg($image, $destination_url, $quality);
//return destination file
return $destination_url;
}
Repaired function:
function compressImage($source_url, $destination_url, $quality) {
//$quality :: 0 - 100
if( $destination_url == NULL || $destination_url == "" ) $destination_url = $source_url;
$info = getimagesize($source_url);
if ($info['mime'] == 'image/jpeg' || $info['mime'] == 'image/jpg')
{
$image = imagecreatefromjpeg($source_url);
//save file
//ranges from 0 (worst quality, smaller file) to 100 (best quality, biggest file). The default is the default IJG quality value (about 75).
imagejpeg($image, $destination_url, $quality);
//Free up memory
imagedestroy($image);
}
elseif ($info['mime'] == 'image/png')
{
$image = imagecreatefrompng($source_url);
imageAlphaBlending($image, true);
imageSaveAlpha($image, true);
/* chang to png quality */
$png_quality = 9 - round(($quality / 100 ) * 9 );
imagePng($image, $destination_url, $png_quality);//Compression level: from 0 (no compression) to 9(full compression).
//Free up memory
imagedestroy($image);
}else
return FALSE;
return $destination_url;
}
You could use Imagick class for this. Consider following wrapper function:
<?php
function resizeImage($imagePath, $width, $height, $blur, $filterType = Imagick::FILTER_LANCZOS, $bestFit = false)
{
//The blur factor where > 1 is blurry, < 1 is sharp.
$img= new \Imagick(realpath($imagePath));
$img->setCompression(Imagick::COMPRESSION_JPEG);
$img->setCompressionQuality(40);
$img->stripImage();
$img->resizeImage($width, $height, $filterType, $blur, $bestFit);
$img->writeImage();
}
?>
Read more on how to resize images with Imagick at:
http://php.net/manual/en/class.imagick.php
http://php.net/manual/en/imagick.resizeimage.php
http://php.net/manual/en/imagick.constants.php#imagick.constants.filters
it is very important to optimize your images. Several CMS platforms out there have modules or plugins to preform this process. However if you are programming it yourself there is a complete php tutorial located at this page https://a1websitepro.com/optimize-images-with-php-in-a-directory-on-your-server/ You will be shown how to implement the imagecreatefromjpeg($SrcImage); and imagecreatefrompng($SrcImage); and imagecreatefromgif($SrcImage); There are written and video instruction on the page.
Related
I've a local server running a website with IIS.
When i run (move_uploaded_file($tempfile, $uploadfile)) all goes well (POST method used).
Now i wish to compress the image, here is the code:
// Compress image
function compressImage($source, $destination, $quality) {
$info = getimagesize($source);
if ($info['mime'] == 'image/jpeg') {
$image = imagecreatefromjpeg($source);
} elseif ($info['mime'] == 'image/gif') {
$image = imagecreatefromgif($source);
} elseif ($info['mime'] == 'image/png') {
$image = imagecreatefrompng($source);
}
imagejpeg($image, $destination, $quality);
}
$foo= compressImage($tempfile, $uploadfile, 75);
who gives me 500 error.
Should i enable some plugin on the server side? I've tried a bunch of code, it still doesn't work (i've played also with dir names.. actually they goes well with move_uploaded_file)
edit: strange thing, the $tempfile content is: C:WindowsTempphp92AF.tmp without slashes, but it works moving the file....
$uploadfile instead, is: ../../../Users/admin/Documents/uploads/2image.png
And so.. i've figured out!
request tracing was not so useful (for me). Instead i've added those 2 small lines to my php code to log errors:
ini_set('display_errors',1);
error_reporting(E_ALL);
The first was
Fatal error: Uncaught Error: Call to undefined function
imagecreatefromjpeg() in C:\inet
Resolved with:
extension=php_gd.dll
in php.ini. Then another error about the permissions.
FYI
Essentially I would like to upload an image to a web server and also convert it from JPG to PNG with as much compression as possible.
The following is what I currently have to upload a JPG image from a mobile device:
<?PHP
if(!empty($_FILES['uploaded_file']))
{
$path = "uploads/";
$path = $path . basename( $_FILES['uploaded_file']['name']);
if(move_uploaded_file($_FILES['uploaded_file']['tmp_name'], $path)) {
echo "The file ". basename( $_FILES['uploaded_file']['name']).
" has been uploaded";
} else{
echo "There was an error uploading the file, please try again!";
}
}
?>
This works well but I must now convert the file to a PNG and compress - for this I have tried working with code like this, but I do not understand how to implement it and also add compression.
$image = imagecreatefromjpeg( "image.jpg" );
imagealphablending($image, true);
imagepng($image, "image.png");
Is something converting and compressing possible?
In official php documentation: https://www.php.net/imagepng
It is stated that the function signature for imagepng is:
imagepng ( resource $image , mixed $to = null , int $quality = -1 , int $filters = -1 ) : bool
Parameter quality:
- quality
Compression level: from 0 (no compression) to 9.
The default (-1) uses the zlib compression default.
For more information see the » zlib manual.
Therefore when you save the image as PNG in below code, it's already compressed:
$image = imagecreatefromjpeg( "image.jpg" );
imagealphablending($image, true);
imagepng($image, "image.png");
If you want higher compression (i.e.: smaller size, worse image quality), then you just need to put higher number in quality parameter (closer to 9 = heavier compression)
$image = imagecreatefromjpeg( "image.jpg" );
imagealphablending($image, true);
imagepng($image, "image.png", 9); // heavily compressed
You need to be careful though that imagejpeg https://www.php.net/imagejpeg also have quality parameter, but that one ranges from 0 (worst quality, smaller file) to 100 (best quality, biggest file).
I have some images in my S3 bucket on AWS. I am trying to get the images and send them to my android app (along with other information from my database). My current setup works fine but I would like to reduce the image file sizes (currently around 1-1.5mb) before I send them to the app.
I have tried to use this code:
function compress($source, $destination, $quality) {
$info = getimagesize($source);
if ($info['mime'] == 'image/jpeg')
$image = imagecreatefromjpeg($source);
elseif ($info['mime'] == 'image/gif')
$image = imagecreatefromgif($source);
elseif ($info['mime'] == 'image/png')
$image = imagecreatefrompng($source);
imagejpeg($image, $destination, $quality);
return $destination;
}
$image_file = Storage::disk('s3_upload')->get("s3bucketpath");
$new_image_file = $this->replace_extension($image->filename, '.jpg');
$this->compress($image_file,$new_image_file, 50);
I get
failed to open stream: No such file or directory in file
error from
$info = getimagesize($source);
I have checked the file path and it is in the bucket and exists and I have var-dumped source and gotten
����JFIF��C$<'$!!$J58,<XM\[VMUSam�vag�hSUy�z������^t�����������C$ $G''G�dUd����������������������������������������������������#0"����A!1A"Q2aq#B���3R�$4b�rC���%S���5D�����#!1A2"Q#��?��HS-� B�#)( #�
#!#������(��(� �
#�UF�LHU#�d ��
# �)#RB�(R�E]��(
(� #B'...
What is the best way to go about doing this.
Try http://image.intervention.io/ to compress file.
It is simple and efficient.
Compression details:
http://image.intervention.io/api/encode
How to start? Simply:
// include composer autoload
require 'vendor/autoload.php';
// import the Intervention Image Manager Class
use Intervention\Image\ImageManager;
// create an image manager instance with favored driver
$manager = new ImageManager(array('driver' => 'imagick'));
// to finally create image instances
$image = $manager->make('public/foo.jpg')->resize(300, 200);
If you are really serious about compressing and resizing your images, you can use libraries like PNGQuant for PNG compression without losing the quality and jpegoptim for jpeg images.
Here is the function that compress image file.
function compress_image($source_url, $destination_url, $quality) {
$info = getimagesize($source_url);
if ($info['mime'] == 'image/jpeg'){
$image = imagecreatefromjpeg($source_url);
}elseif ($info['mime'] == 'image/gif') {
$image = imagecreatefromgif($source_url);
}elseif ($info['mime'] == 'image/png') {
$image = imagecreatefrompng($source_url);
}imagejpeg($image, $destination_url, $quality);
return $destination_url;
}
$filename = compress_image($_FILES["home_image"]["tmp_name"], $_FILES["home_image"]["name"], 80);
$buffer = file_get_contents($_FILES["home_image"]["name"]);
Here is my code that want to move the compressed image to my specific folder
move_uploaded_file($_FILES["home_image"]["tmp_name"][$i],"../../../Test/image/home_banner/" .$filename);
But the image that move to the folder is still remain the original size without compress.
Am I doing the mistake..?
I think move_uplodaded_file() is not appropriate here, because you change the uploaded file contents:
This function checks to ensure that the file designated by filename is
a valid upload file (meaning that it was uploaded via PHP's HTTP POST
upload mechanism). If the file is valid, it will be moved to the
filename given by destination.
Use rename() instead.
I'm also not 100% if you can edit the uploaded file directly..
I made a function to handle jpg and png files, but i get error when trying to upload a png file.
this is the function:
function createImg ($type, $src, $dst, $width, $height, $quality) {
$newImage = imagecreatetruecolor($width,$height);
if ($type == "jpg/jpeg") {
//imagecreatefromjpeg() returns an image identifier representing the image obtained from the given filename.
$source = imagecreatefromjpeg($src);
}
else if ($type == "png") {
//imagecreatefrompng() returns an image identifier representing the image obtained from the given filename.
$source = imagecreatefrompng($src);
}
imagecopyresampled($newImage,$source,0,0,0,0,$width,$height,getWidth($src),getHeight($src));
if ($type == "jpg/jpeg") {
//imagejpeg() creates a JPEG file from the given image.
imagejpeg($newImage,$dst,$quality);
}
else if ($type == "png") {
//imagepng() creates a PNG file from the given image.
imagepng($newImage,$dst,$quality);
}
return $dst;
}
works as it should with jpg, but with png i get this error msg:
Warning: imagepng() [function.imagepng]: gd-png: fatal libpng error: zlib failed to initialize compressor -- stream error in E:...\php\functions.upload.php on line 48
Warning: imagepng() [function.imagepng]: gd-png error: setjmp returns error condition in E:...\php\functions.upload.php on line 48
EDIT :
i just changed removed the imagepng(); and used only imagejpeg and it worked like this, i just want jpg files saved anyways. thanks!
The problem is because imagejpeg quality can be up to 100, whereas imagepng maximum quality is 9.
try this
else if ($type == "png") {
//imagepng() creates a PNG file from the given image.
$q=9/100;
$quality*=$q;
imagepng($newImage,$dst,$quality);
}
What value are you using for the quality setting? imagepng() uses values 0-9, whereas imagejpeg() uses 0-100.
Johnny Craig's answer is correct except one thing, it has inverse relationship. 9 - is the most possible compression, and 0 - no compression, so the most possible quality.
if ($type == 'png') {
$quality = round((100 - $quality) * 0.09);
}