php - optimize image file size - php

I'm making a web application for online comic. My biggest difficulty things are how to save the disk space when store the images (i don't have money ^^). I try to use GD2 to resize the image, convert to jpg, reduce the qualities...but the file size of each image still around 100kb.
For example: MY IMAGE with 650x900 px with some character, text.., no color, just black & white, the file size is 100kb.
But, when i making a NEW BLANK file with the same dimensions in photoshop and fill it all black (i think black color will make the file size more higher), then save on jpg, this new file size just only 8kb.
The question is, why the file size of MY IMAGE (with less black pixel) is higher than the NEW BLANK image with more black pixel? Is there anything inside the image source? And any solution to reduce the file size?
Thank all.

Basically question one is what format are you using.
I suggest you use PNG for black and white images. If it is possible use 1bit PNG.
Image compression i a complex thing. But no not the black pixels make the file size, but the variation of the pixels. But it is really a complex question.
see: http://en.wikipedia.org/wiki/Image_compression and http://en.wikipedia.org/wiki/Portable_Network_Graphics for some info on the subject.
For the best results if your images are currently JPEG-s then you need to apply somekind of noise reduction. For truly black-and-white (not grayscale) bumping up the contrast might help with that. Also strip out all meta information from the image.

One helpful tool to lower file size of images without reducing the quality is TinyPNG. This can cut the file size by up to about 80% without making any noticeable changes to the image itself. It has helped me to cut down my file sizes by an average of about 70%, and I hope it can help you too!

Related

PHP imagecopyresampled + how to get the best results

I have the following working fine:
User uploads an image and the image is resized using imagecopyresampled and imagejpeg (keeping the proportions) so it fits the cropping DIV.
The user then crops the image with JCrop and then the resized above image is then cut into the 5 required crop sizes using imagecopyresampled and imagejpeg.
The problem I've found is by cropping from the resized image doesn't take advantage of the very original image that is often larger and better quality.
So I want to display an image that fits the DIV but crop from the very original image to get the best quality.
When I just change the cropping to the original image the crop is of the wrong part of the image as the sizing is different. This is obvious I assume. Diff sized images.
How can I display an image that fits the DIV for Jcrop but then actually crop off the original which is often larger?
Ideas I'm testing:
displaying the original image in the DIV (not resized by php but resized by CSS). I'm not sure if this will make any difference.
try to use some math based equation to get the correct crop. Unsure how I'll do this currently.
Ideas would be great...
thx
Personally I would go with the maths based solution if you have to work with the full sized image server side. Re-scaling in the browser directly or through CSS is not ideal IMO and differs greatly between browsers. If you use the math based option you could calculate the co-ordinates on the smaller image crop and scale that up to get the right portion of the original image.
On a side note you may find (depending on the image sizes and image types you allow uploaded) that copying and resizing on the PHP side is very CPU and memory intensive. A png file for example of roughly 1024 x 768 in high resolution can take up to 60MB to 80MB of RAM just to resize (per image re-sample due to compression on the png file) and that is regardless of which PHP image manipulation modules (ImageMagick, etc) you use. There is no perfect way to handle image uploads from the PHP server end (other than throwing heaps of memory and CPU at the task). There are some good jQuery solutions however that resize on the client side before the upload (e.g. Plupload, etc) which means you will only be working with a reduced size image on the server side. There are also some JQuery client side cropping scripts which are good. Either way a combination of PHP and jQuery would be the best IMO.

How can I estimation the file size of an image using its width and height?

I have recently written an image resizing program using php, which works by downloading images off another server, resizing them and saving them to our own.
The bad news is that my Hosting account only allows a php memory limit of 64M, and this is just not set up to resize the HUUUUGE file sizes that my client is uploading (3 - 4mb). It spits out a fatal error if it meets these images and breaks the script.
Even though I have notified said client of this drawback, said client continues to upload large images and script keeps breaking.
I can obtain the width and the height of the image before downloading it using getimagesize(), and if I could use this info to work out the total file size I could break out before the image resizer gets going and suppliment the image with a nice "no image available" alternative.
How can I make an accurate estimation of an images file size using its width and height, assuming it has a bit depth of 24?
An image in memory always weights the same weight compressed in JPEG or GIF or BMP. It's called a BIT-MAP. So, if you want to calculate the size of an image in memory, take the width, the height and the bit size to get the bit weight, divide by 8 and you get the bytesite.
$ByteSize = Width*Heigh*(24/8)
Note that it is possible to get more weight from an image in some parts such as a paletized image, it will have to store the image color palette in memory but most of the time this should weight less than a bitmap.
A multiplication.
Just multiply height by width by 3.
and throw in some spare memory to process all these bytes. say, twice the image size.
It has nothing to do with file size though.
before the upload on the server you can't with php,
but you can use javascript!
https://developer.mozilla.org/en/DOM/File
will work in conjunction of and will instantly provide the filesize using
fileInput.files[0].fileSize
read these:
https://developer.mozilla.org/en/Using_files_from_web_applications
http://hacks.mozilla.org/2009/12/multiple-file-input-in-firefox-3-6/
hope this helps!
The size will always depend on the format. When compressing images, the size of the image itself won't have any effect on the filesize. The only way that you can get a good readout of the filesize is if you use a Bitmap (or simmilar) format.
Example, A JPEG could be 10MB in size, and then when rotated only 1 MB in size because of how the compression works.

Resize an image and maintain quality?

I have a problem with resizing images.
What happens is that if you upload a file larger than the stated parameters, the image is cropped, then saved at 100% quality.
So if I upload a large jpeg which is 272Kb. The image is cropped by 100 odd pixels. The file size then goes up to 1.2Mb.
We are saving images at a 100% quality. I assume that this is what is causing the problem. The image is exported from Photoshop at 30% quality which reduces the file size. Resaving the image at 100% quality creates the same image but I assume with a lot of redundant file data.
Has anyone encountered this before? Does anyone have a solution?
This is what we are using.
$source_im = imagecreatefromjpeg ($file);
$dest_im = imagecreatetruecolor ($newsize_x, $newsize_y);
imagecopyresampled (
$dest_im, $source_im,
0, 0,
$offset_x, $offset_y,
$newsize_x, $newsize_y,
$sourceWidth, $sourceHeight
);
imagedestroy ($source_im);
if ($greyscale) {
$dest_im = $this->imageconvertgreyscale ($dest_im);
}
imagejpeg($dest_im, $save_to_file, $quality);
break;
Saving at 30% then re-saving at 100% will, as you say, create redundant data, whether you crop, resize, whatever.
Unfortunately, JPEG compression accumulates data loss, so compressing at 30%, processing the image, then re-compressing will always look worse than the original compression. The rule of thumb is to avoid compression (especially heavy compression like 30%) until as late in the process as possible. So upload at 100% (or 80ish% if necessary), then compress.
Edit: apparently, jpegtran (google it) can do operations such as cropping without first decompressing the image, as long as the image size follows certain constraints (usually width and height a multiple of 16 pixels). Haven't tried it myself, but it might suite your purposes.
When saving a JPEG with 30% quality, a lot of pixel information is not saved. When opening it again using gd, a new image is created with crisp new pixels. Whether these look good or bad to you (depending on the quality the image was originally saved with) is irrelevant. When saving this new image, you're create a new JPEG file. Setting the quality to 100% will basically save every single pixel, which of course takes a lot of space. (I'm generalizing, but you get the idea.) Whatever quality setting the original was saved at is irrelevant, saving a big image at 100% quality takes a lot of space.
The only solution is to save the image using a lower quality setting; usually something around 70% is virtually indistinguishable from perfect, but saves a lot of bytes. You may also want to try PNG, which is lossless but may (or may not) provide a better compression ratio.
Your assumptions is correct, you are essentially saving it at loss-less. I ran into this with video encoding where I would downsize the resolution but increase it to loss-less and the final size was twice that the original. If it is a small enough image I would save it using a good palette based image type or a type that is native loss-less not jpeg. Either that save it at 50-70% quality and let jpeg do what it is good at.

PHP JPEG Crop : Loss of quality?

I'm developing a web-to-print, poster printing application.
I'm considering using PHP to crop user-uploaded images, and we will ultimately print the PHP-cropped image.
My concern is there will be a difference in 'quality' between the original user uploaded image, and image after it is cropped by PHP.
Will PHP affect the quality of the image when handling it? Or does it preserve the image's quality and simply crop the relevant area?
Many thanks,
BK
JPEG is lossy compression. A bit of oversimplification, but it works by analyzing pixels around other pixels to see how similar they are. Not every pixel is stored, and that means it isn't possible to simply chop bytes out of the image data to perform the crop. If you are outputting JPEG, you will be re-compressing an already compressed image, and you will have some loss in quality. However, if you crop the image and your output is a non-lossy format, then you will not have loss of quality.
To be clear, the loss of the quality isn't in the crop operation. It is in the way the image is compressed itself. If the source image is compressed with JPEG, quality has already been lost. When you crop that image, you aren't losing anything more, but if you were to output JPEG again afterwards, this would require a re-compression, and thus more loss.
So in the end, make your final output PNG or something non-lossy and you have nothing to worry about.

Automatically align and resize 3 images into a small image with PHP?

I don't know if this is even possible with PHP, but I figured if it is, someone here will know how. I'm currently working on a project where users can customize a full body main avatar to be used throughout the site. There are a bunch of different face, hair, etc transparent png images that can be selected to make their custom avatar. I have this working great, but here is the hard part. I want to be able to use the face, hair, and beard (if male), and automatically create an 80x80 image that will be used as their small avatar for forum posts, etc.
There are a few obstacles with this. First, all of the images are 187x404 (big amounts of the image are transparent, the character body image is achieved by stacking the images, so a face image isn't actually that big). For this to work, the images would effectively have to be automatically cropped so that all of the extra space was removed and the actual face, hair, or beard part showed in the 80x80 spot.
The second issue is that some of the hair or beards (when placed on the full-size face image) would extend past the 80x80 and be chopped off. So the image would have to be pieced together at full size, and then resized to fit in 80x80.
I know the basic way of combining the 3 images into one (Combine 2-3 transparent PNG images on top of each other with PHP), but that is as far as I've gotten. If I'm crazy and this isn't possible then tell me. I'm probably way overcomplicating this, so if you see and obviously easier way to achieving this, I would love to hear it.
I think you need to decide first, cropping, resizing or a combination of both (cropping to a bigger square and resizing that).
Anyway, if you already have the images combined into one, all three options are easy to do in php. Take a look at imagecopyresampled().
The easiest way is just to always fit the face/hair/beard in the same area of the image. Then just crop that area out.
If you must, you can store extra data for each image specifying a rectangle in the image that must be visible in the small avatar. Then take the maximum extremities of these rectangles in all the images you compose, and crop+shrink that down to your small avatar size.
However, be aware that resizing PNG images by a few pixels (e.g. 83x83 -> 80x80) can substantially reduce the quality, particularly for images with lots of defined edges. This is because there are many pixels in the new image that are [nearly] evenly split between 4 pixels from the original image, and in images with sharp edges this leads to blurring.
So, shrinking an image to fit a portrait is not just difficult but also reduces quality. I'd cut off the beard instead!
I may be oversimplifying this, but can you try:
Keep track of max face size dimensions pre-compositing.
Output the composite image to a temporary file.
Crop square of largest values from step 1
Resize cropped image portion to 80 x 80

Categories