I have a lot of jpeg images which I want to optimize for web but I need a process which can also be done for incoming images in real time. In other words I don't want to use a service like Smush.it or drop them into photoshop for manipulation but I do want to know what I can do in php. I would prefer a solution which only requires php image processing functions but if necessary and it would provide significant improvement then a command line tool like jpegcrush could be used as well.
I have read that simply by making the image in php the EXIF data is stripped. What other things can I do without degrading the actual quality? When I save in photoshop using the 'save for web' feature, the savings are significant without a noticeable quality loss so I was wondering if anyone knew exactly what operations are done in there. One other thing I have noticed is that images from youtube are normally much larger area-wise than they need to be but they have very small file sizes... does anyone know what is going on there or is this some secret technique?
If it makes any difference the images I am working with are mostly 320x320 and I want to make them progressive jpg. Thanks in advance.
I'd use the PHP GD library to create a jpg with quality set to around 80:
imagejpeg ( resource $image [, string $filename [, int $quality ]] )
If you want to output Progressive JPEGs, you need to set interlacing on with imageinterlace().
Are you looking for something more than this?
Assuming "optimizing for the web" is converting to GIF, PEAR does it if i'm not mistaken. You don't need fancy functions to do this.
check this question:
Convert jpg image to gif, png & bmp format using PHP
Related
I'm currently trying to speed up the websites we develop. The part I'm working on now is to optimise the images so that they are as small (filesize, not dimensions) as possible without losing quality.
Our customers can upload their own images to the website through our custom CMS, but images aren't being compressed or optimised at all. My superior explained this is because the customers can upload their own images, and these images could be optimised beforehand through Photoshop or tools like it. If you optimise already optimised images, the quality would get worse. ...right?
We're trying to find a solution that won't require us to install a module or anything. We already use imagejpeg(), imagepng() and imagegif(), but we don't use the $quality parameter because of reasons previously explained. I've seen some snippets, but they all use imagejpg() and the like.
That being said, is there a sure-fire way of optimising images without the risk of optimising previously optimised images? Or would it be no problem at all to use imagejpeg(), imagepng() and imagegif(), even if it would mean optimising already optimised images?
Thank you!
"If you optimise already optimised images, the quality would get worse. "
No if you use a method without loose.
I don't know for method directly in php but if you are on linux server you can use jpegtran or jpegoptim ( with --strip-all) for jpeg and OptiPNG or PNGOUT for png.
Going from your title, I am going to assume compression
So, lets say a normal jpg of 800x600 is uploaded by your customers.
The customers jpg is 272kb because it has full details and everything.
You need to set tresholds for filesizes at dimensions what is acceptable.
Like:
if $dimensions->equals(800,600) and file_type($image) =='jpg' and file_size($image) > 68kb
then schedule_for_compression($image)
and that way you set up parameters for what is acceptable as an upper limit of file size. If the dimensions match, and the filesize is bigger, then its not optimised.
But without knowing more details what exactly is understood about optimising, this is the only thing I can think of.
If you are using a low number of images to compress, you might find an external service, such as: https://tinypng.com/developers might be of assistance.
I've used their on-line tools for reducing filesize on both JPG and PNG file manually but they do appaear to offer a free API service for the first 500 images per month.
Apologies if this would be better as a comment than an answer, I'm fairly new to stackoverflow and haven't got enough points yet, but felt this may be a handy alternative solution.
Saving a JPEG with the same or higher quality setting will not result in a noticeable loss in quality. Just re-save with your desired quality setting. If the file ends up larger, just discard it and keep the original. Remove metadata using jpegran or jpegoptim before you optimize so it doesn't affect the file size when you compare to the original.
PNG and GIF wont't lose any quality unless you reduce the number of colors. Just use one of the optimizers Gyncoca mentioned.
I've been doing some speed optimization on my site using Page Speed and it gives recommendations like so:
Optimizing the following images could reduce their size by 35.3KiB (21% reduction).
Losslessly compressing http://example.com/.../some_image.jpg could save 25.3KiB (55% reduction).
How are the calculations done to get the file size reduction numbers? How can I determine if an image is optimized in PHP?
As I understand it, they seem to base this on the image quality (so saving at 60% in Photoshop or so is considered optimized?).
What I would like to do is once an image is uploaded, check if the image is fully optimized, if not, then optimize it using a PHP image library such as GD or ImageMagick. If I'm right about the number being based on quality, then I will just reduce the quality as needed.
How can I determine if an image is fully optimized in the standards that Page Speed uses?
Chances are they are simply using a standard compression or working on some very simple rules to calculate image compression/quality. It isn't exactly what you were after but what I often use on uploaded images etc etc dynamic content is a class called SimpleImage:
http://www.white-hat-web-design.co.uk/blog/resizing-images-with-php/
this will give you the options to resize & adjust compression, and I think even change image type (by which I mean .jpg to .png or .gif anything you like). I worked in seo and page optimization was a huge part of my Job I generally tried to make the images the size the needed to be no smaller or bigger. compress JS & CSS and that's really all most people need to worry about.
It looks like you could use the PageSpeed Insights API to get the compressions scores: https://developers.google.com/speed/docs/insights/v1/reference, though I'm guessing you'd want to run a quality check/compression locally, rather than sending everything through this API.
It also looks like they've got a standalone image optimizer available at http://code.google.com/p/page-speed/wiki/DownloadPageSpeed?tm=2, though this appears to be a Windows binary. They've got an SDK there as well, though I haven't looked into what it entails, or how easy it would be to integrate into an existing site.
Let me explain what I am trying to do, I am building a command line tool with PHP that uses these programs to optimize images for the web...
imagemagick to determine file type and convert non-animated gif's to png
gifsicle to optimize Animated Gif images
jpegtran to optimize jpg images
pngcrush to optimize png image
pngquant to optimize png images to png8 format
pngout to optimize png images to png8 format
This is a pretty heavy process to be running, luckily it is done very infrequently but I would still like to optimize as much as I can.
Right now to process around 12 images takes roughly 76 seconds. So you can see it is a slow process, imagine 100 images.
I would really like to somehow, mark an image as optimized somehow, so when I am loading a batch of images, the first thing it does is run through ImageMagick to get the exact file type, would be nice if I could somehow embed a message that says this image is already optimized as much as it can be, and then when I am reading images in, if it detects a message it will know to not waste valuable time running that particular image through all the other programs, if this is possible, it could greatly increase speed.
Please help me, I am not used to working with images like this, is this possible even, if it is what is it called and how could I achieve it?
Thanks for any help
If you were to include a flag in the image itself then that would be served to the clients. It would add to the filesize of your images thus negating some of your optimisation.
Suggestions
Keep a reference of the status
Keep a catalog in a file in the same directory - much like the Windows Thumbs.db file.
Another option would be to keep the record in a database or datastore such as Redis or Memcached.
Move after processing
You could move the files to a different directory once they are processed (as #Jordan mentions).
Change the filename to indicate it is processed
Another option would be to append an extra "extension" onto the file name for example:
my_image.processed.jpg
Embedding data in images
Steganography
Usually this is used for attempting to hide covert data in an image and it is called Steganography. It is not really suited to this use case however.
EXIF data
You could write it into the EXIF data of an image, but this would be JPEG and TIFF only as far as I am aware. There is a PHP library available called PEL for writing and reading EXIF data.
You could use the Comment field to tag your image as already optimised, like this:
convert x.jpg -set comment "Optimised" x.jpg
Then, when you are processing, you can extract it like this:
identify -format "%c" x.jpg
Optimised
Currently i am using gd to converting the image uploaded in jpg with
imagjpeg($data,NULL,85)
and storing it in a blob mysql field. Problem is the quality. Yes the quality is just awful. A screenshot of a window with some text inside becomes pretty hugly. (While with a game screenshot the quality is passable)
Should I use other lib than GD?
Should I use other gd format? (imagepng?)
ps. please note: this is not a duplicate.. i am not asking how to save an img to db
ps2. note that if i should change my currently format/method I have to convert something like 5000-6000 images already stored as jpg in my db
ps3. i use 85 for imagejpeg, can't use a higher value because the image size would grow more than the original version
ps4. I need to store image in db, please stay in topic
Thanks all
================================
REFORMULATING THE QUESTION
I save image (mostly software screenshots, sometime games screenshots) in BLOB field after doing an imagejpeg($resourceFromImageCreateFromString,NULL,85);
Problem I am experiencing is the image uploaded looks pretty bad in confront of the original even if it's the same size. (sometime it gets bigger because of 85)
Is the imagejpeg implementations that sucks?
ps. my simple upload script does the follow calls:
upload file
open it with "rb" (binary)
pass the data to imagecreatefromstring
pass the result to imagejpeg
Thanks again
Is there a special reason you want to store your image inside a BLOB?
What quality argument did you pass to imagejpeg()?
You can set the quality of your output with the 3rd parameter to imagejpeg(). The problem is that JPEG is not the best format for images with a lot of text - you have to choose between turning down the quality and getting a lot of artifacts in your image, or turning up the quality and having a large file size. You might consider using PNG instead.
my first recommendation would be to try saving it as a png as the quality is better.
my second recommendation is to try the quality parameter in imagejpeg($image, $filename, $quality).
recommendation #3 - I worked on a site that I had to rewrite the image storage system because they implemented just what you are doing, storing images as BLOBs in the database. Their system only had about 20K images in it and it was crashing weekly because the database could not handle the load.
The conversion process for 5-6K images should not take more than a couple hours no matter how large the images. When I converted my images to disk storage from db storage, I ran 1K images at a time and each run took 5-10 minutes.
Why do you re-code anyway if it already IS a jpeg? To save space? Well, but then you already have your answer, in part - to save space from jpg to jpg you have to save in lower quality.
You cannot specify quality with imagecopyresampled, with imagejpeg you can. Use a high(er) value for the quality parameter.
Please note that JPEG is a format optimized for storing FOTOS. Images with large areas of the same color, straight lines etc. are much better stored in a lossless format like PNG. Of course, if you have a screenshot taken from a screen with fotos as desk background you have elements of both - so choose your format according to what you want. If the foto-part is more important and you don't care as much about fonts and lines, go with jpeg. Of course JPEG can be just as good quality as PNG for screenshots as well, but then you miss out on most of its compression capabilities, you have to use a 90+% quality setting. At 100% JPEG too is lossless, but by then a PNG might actually be of smaller (file)size.
I want my site to have a feature for users to upload images, but I want to do it safely. Namely, I want to strip the EXIF data and any malicious code that could be in their image. I was thinking of a way to do this involving direct manipulation of the file, but it struck me, would it make more sense to just convert the image they provide to BMP and then convert that back to the original format? It would suffer a generational loss, but I believe that would meet my project's requirements. BMP doesn't contain EXIF, does it? And the reprocessing should strip any malicious content.
It wouldn't even have to be BMP: You could use PHP's GD functions, open the image using imagecreatefrom[xyz], copy it unresized, and write it back out in the original format.
That should be pretty watertight, save for the remote (and negligeable) possibility of course that a vulnerability is one day discovered in GD itself.
Limitations and caveats I can think of:
Images with transparency may be an issue, especially transparent GIFs would probably require special treatment (allocating the transparent colour in the new image etc., not sure)
Animated GIFs would be destroyed this way, GD can't deal with them
This method would be limited by PHP's memory limit (you'll need at least {image width} x
{ image height } x 3 bytes for the resize operation)
More exotic sub-formats like progressive JPG, CMYK JPG may cause trouble, but that's okay IMO - the latter woulnd't show in IE anyway