image compression in php - php

I am compressing an image using following class..
<?php
class SimpleImage {
var $image;
var $image_type;
function load($filename) {
$image_info = getimagesize($filename);
$this->image_type = $image_info[2];
if( $this->image_type == IMAGETYPE_JPEG ) {
$this->image = imagecreatefromjpeg($filename);
} elseif( $this->image_type == IMAGETYPE_GIF ) {
$this->image = imagecreatefromgif($filename);
} elseif( $this->image_type == IMAGETYPE_PNG ) {
$this->image = imagecreatefrompng($filename);
}
}
function save($filename,$image_type=IMAGETYPE_JPEG,$compression=75,$permissions=null){
if( $image_type == IMAGETYPE_JPEG ) {
imagejpeg($this->image,$filename,$compression);
} elseif( $image_type == IMAGETYPE_GIF ) {
imagegif($this->image,$filename);
} elseif( $image_type == IMAGETYPE_PNG ) {
imagepng($this->image,$filename);
}
if( $permissions != null) {
chmod($filename,$permissions);
}
}
function output($image_type=IMAGETYPE_JPEG) {
if( $image_type == IMAGETYPE_JPEG ) {
imagejpeg($this->image);
} elseif( $image_type == IMAGETYPE_GIF ) {
imagegif($this->image);
} elseif( $image_type == IMAGETYPE_PNG ) {
imagepng($this->image);
}
}
function getWidth() {
return imagesx($this->image);
}
function getHeight() {
return imagesy($this->image);
}
function resizeToHeight($height) {
$ratio = $height / $this->getHeight();
$width = $this->getWidth() * $ratio;
$this->resize($width,$height);
}
function resizeToWidth($width) {
$ratio = $width / $this->getWidth();
$height = $this->getheight() * $ratio;
$this->resize($width,$height);
}
function scale($scale) {
$width = $this->getWidth() * $scale/100;
$height = $this->getheight() * $scale/100;
$this->resize($width,$height);
}
function resize($width,$height) {
$new_image = imagecreatetruecolor($width, $height);
imagecopyresampled($new_image,$this->image,0,0,0,0,$width,$height,$this->getWidth(),$this->getHeight());
$this->image = $new_image;
}
}
?>
And my php code looks like..
include_once(ROOT.'/library/SimpleImage.php')
$image = new SimpleImage();
$image->load($image_name);
$image->resizeToWidth(100);
$image->save($image_name);
Now the problem is that my images are getting compressed, but their original color combination get lost...
Don't know what to do..??
Please suggest another class for image compression.

This is a function I coded a long time ago, it's not realy optimized but it should do the trick. Works for various mime types and allows you to save the modified image into a new location. You can easily simplify it if you need less features.
public function resizePicture($path, $new_path, $new_width, $new_height, $proportion = false) {
$size = getimagesize($path);
$x = 0;
$y = 0;
switch($size['mime']) {
case 'image/jpeg':
$picture = imagecreatefromjpeg($path);
break;
case 'image/png':
$picture = imagecreatefrompng($path);
break;
case 'image/gif':
$picture = imagecreatefromgif($path);
break;
default:
return false;
break;
}
$width = $size[0];
$height = $size[1];
$frame = imagecreatetruecolor($new_width, $new_height);
if($size['mime'] == 'image/jpeg') {
$bg = imagecolorallocate($frame, 255, 255, 255);
imagefill($frame, 0, 0, $bg);
} else if($size['mime'] == 'image/gif' or $size['mime'] == 'image/png') {
imagealphablending($picture, false);
imagesavealpha($picture, true);
imagealphablending($frame, false);
imagesavealpha($frame, true);
}
if($width < $new_width and $height < $new_height) {
$x = ($new_width - $width) / 2;
$y = ($new_height - $height) / 2;
imagecopy($frame, $picture, $x, $y, 0, 0, $width, $height);
} else {
if($proportion and $width != $height) {
if($width > $height) {
$old_height = $new_height;
$new_height = $height * $new_width / $width;
$y = abs($old_height - $new_height) / 2;
} else {
$old_width = $new_width;
$new_width = $width * $new_height / $height;
$x = abs($old_width - $new_width) / 2;
}
}
imagecopyresampled($frame, $picture, $x, $y, 0, 0, $new_width, $new_height, $width, $height);
}
switch($size['mime']) {
case 'image/jpeg':
imagejpeg($frame, $new_path, 85);
break;
case 'image/png':
imagepng($frame, $new_path, 8);
break;
case 'image/gif':
imagegif($frame, $new_path);
break;
default:
return false;
break;
}
}

I use SimpleImage.php and find it a helpful little script, but I had to change the value of $compression to 100 in save function.
Perhaps compressing certain formats reduces number of colors, but by setting $compression to a 100 you tell the script "Don't compress!"
After that the images look like they suppose to.

Related

Resize image without lose quality when image is bigger

I use img uploader on my ftp.
If image large to 1024x768 i use script for resize.
But after resize lose quality.
Code from uploader.php:
if(#move_uploaded_file($_FILES['myfile']['tmp_name'], "$upload_folder/" . $newname))
if($width>1024 || $height>768) {
require './image_resize.php';
echo (image_resize("$upload_folder/" . $newname, "$upload_folder/" . $newname, 1024, 768));
}
Code prom image_resize.php:
<?php ini_set('memory_limit','500M');
function image_resize($src, $dst, $width, $height, $crop=0){
if(!($pic = #getimagesize($src)))
return false;
$w = $pic[0];
$h = $pic[1];
$type = substr($pic['mime'], 6);
$func = 'imagecreatefrom' . $type;
if(!function_exists($func))
return false;
$img = $func($src);
if($crop){
if($w < $width && $h < $height)
return false;
$ratio = max($width/$w, $height/$h);
$h = $height / $ratio;
$x = ($w - $width / $ratio) / 2;
$w = $width / $ratio;
}
else{
if($w < $width && $h < $height)
return false;
$ratio = min($width/$w, $height/$h);
$width = $w * $ratio;
$height = $h * $ratio;
$x = 0;
}
$new = imagecreatetruecolor($width, $height);
if($type == "gif" || $type == "png"){
imagecolortransparent($new, imagecolorallocatealpha($new, 0, 0, 0, 127));
imagealphablending($new, false);
imagesavealpha($new, true);
}
imagecopyresampled($new, $img, 0, 0, $x, 0, $width, $height, $w, $h);
$save = 'image' . $type;
$save($new, $dst);
return true;
}
It is impossible to reduce the size without losing quality :(
I found script for resize, working fine. I think this is a what I need :)
http://sanchiz.net/blog/resizing-images-with-php
But, one problem and please correct for me: If need resize PNG with transparent background this script remove transparent and add black background.
In comments posted modified script, but with this code not working compress function
I need modify this code for resize PNG without remove transparent background:
class SimpleImage {
public $image;
public $image_type;
public function load($filename) {
$image_info = getimagesize($filename);
$this->image_type = $image_info[2];
if ($this->image_type == IMAGETYPE_JPEG) {
$this->image = imagecreatefromjpeg($filename);
} elseif ($this->image_type == IMAGETYPE_GIF) {
$this->image = imagecreatefromgif($filename);
} elseif ($this->image_type == IMAGETYPE_PNG) {
$this->image = imagecreatefrompng($filename);
}
}
public function save($filename, $image_type = IMAGETYPE_JPEG, $compression = 100, $permissions = NULL) {
if ($image_type == IMAGETYPE_JPEG) {
imagejpeg($this->image, $filename, $compression);
} elseif ($image_type == IMAGETYPE_GIF) {
imagegif($this->image, $filename);
} elseif ($image_type == IMAGETYPE_PNG) {
imagepng($this->image, $filename);
}
if ($permissions != NULL) {
chmod($filename, $permissions);
}
}
public function output($image_type = IMAGETYPE_JPEG) {
if ($image_type == IMAGETYPE_JPEG) {
imagejpeg($this->image);
} elseif ($image_type == IMAGETYPE_GIF) {
imagegif($this->image);
} elseif ($image_type == IMAGETYPE_PNG) {
imagepng($this->image);
}
}
public function resizeToHeight($height) {
$ratio = $height / $this->getHeight();
$width = $this->getWidth() * $ratio;
$this->resize($width, $height);
}
public function getHeight() {
return imagesy($this->image);
}
public function getWidth() {
return imagesx($this->image);
}
public function resize($width, $height) {
$new_image = imagecreatetruecolor($width, $height);
imagecopyresampled($new_image, $this->image, 0, 0, 0, 0, $width, $height, $this->getWidth(), $this->getHeight());
$this->image = $new_image;
}
public function resizeToWidth($width) {
$ratio = $width / $this->getWidth();
$height = $this->getheight() * $ratio;
$this->resize($width, $height);
}
public function scale($scale) {
$width = $this->getWidth() * $scale / 100;
$height = $this->getheight() * $scale / 100;
$this->resize($width, $height);
}
Thank you
Since the default API may not be really effective when it comes to image handling, i suggest you use a library. Take a look at grafika
You can also use an external service for images resizing such as this repo
Flyimg.

image resizing png adding black colour in background

I am resizing images using the code below, but their is problem with resizing png images with transparent background that it fills the background with black color.
Below is the full code of image resizing:
function store_uploaded_image($html_element_name, $new_img_width, $new_img_height ,$size ,$target_dir) {
$target_file = $target_dir .'image-'.$size.'.png';
$image = new SimpleImage();
$image->load($_FILES[$html_element_name]['tmp_name']);
$image->resize($new_img_width, $new_img_height);
$image->save($target_file);
return $target_file; //return name of saved file in case you want to store it in you database or show confirmation message to user
}
class SimpleImage {
var $image;
var $image_type;
function load($filename) {
$image_info = getimagesize($filename);
$this->image_type = $image_info[2];
if( $this->image_type == IMAGETYPE_JPEG ) {
$this->image = imagecreatefromjpeg($filename);
} elseif( $this->image_type == IMAGETYPE_GIF ) {
$this->image = imagecreatefromgif($filename);
} elseif( $this->image_type == IMAGETYPE_PNG ) {
$this->image = imagecreatefrompng($filename);
}
}
function save($filename, $image_type=IMAGETYPE_PNG, $compression=75, $permissions=null) {
if( $image_type == IMAGETYPE_JPEG ) {
imagejpeg($this->image,$filename,$compression);
} elseif( $image_type == IMAGETYPE_GIF ) {
imagegif($this->image,$filename);
} elseif( $image_type == IMAGETYPE_PNG ) {
imagepng($this->image,$filename);
}
if( $permissions != null) {
chmod($filename,$permissions);
}
}
function output($image_type=IMAGETYPE_JPEG) {
if( $image_type == IMAGETYPE_JPEG ) {
imagejpeg($this->image);
} elseif( $image_type == IMAGETYPE_GIF ) {
imagegif($this->image);
} elseif( $image_type == IMAGETYPE_PNG ) {
imagepng($this->image);
}
}
function getWidth() {
return imagesx($this->image);
}
function getHeight() {
return imagesy($this->image);
}
function resizeToHeight($height) {
$ratio = $height / $this->getHeight();
$width = $this->getWidth() * $ratio;
$this->resize($width,$height);
}
function resizeToWidth($width) {
$ratio = $width / $this->getWidth();
$height = $this->getheight() * $ratio;
$this->resize($width,$height);
}
function scale($scale) {
$width = $this->getWidth() * $scale/100;
$height = $this->getheight() * $scale/100;
$this->resize($width,$height);
}
function resize($width,$height) {
$new_image = imagecreatetruecolor($width, $height);
imagecopyresampled($new_image, $this->image, 0, 0, 0, 0, $width, $height, $this->getWidth(), $this->getHeight());
$this->image = $new_image;
}
}
EDIT:
as #Marc B suggested, using imagealphablending and imagesavealpha before imagecopyresampled made it to work.
imagealphablending( $targetImage, false );
imagesavealpha( $targetImage, true );

Function to resize jpg file compresses it too

I have a script which resizes images on server side before loading it to the client side.
Issue with this script is it compresses the file too, and that ends up in bad quality images.
Have a look at the script:
Image_Resize.php
var $image;
var $image_type;
function load($filename) {
$image_info = getimagesize($filename);
$this->image_type = $image_info[2];
if( $this->image_type == IMAGETYPE_JPEG ) {
$this->image = imagecreatefromjpeg($filename);
} elseif( $this->image_type == IMAGETYPE_GIF ) {
$this->image = imagecreatefromgif($filename);
} elseif( $this->image_type == IMAGETYPE_PNG ) {
$this->image = imagecreatefrompng($filename);
}
}
function save($filename, $image_type=IMAGETYPE_JPEG, $compression=0, $permissions=null) {
if( $image_type == IMAGETYPE_JPEG ) {
imagejpeg($this->image,$filename,100);
} elseif( $image_type == IMAGETYPE_GIF ) {
imagegif($this->image,$filename);
} elseif( $image_type == IMAGETYPE_PNG ) {
imagepng($this->image,$filename);
}
if( $permissions != null) {
chmod($filename,$permissions);
}
}
function output($image_type=IMAGETYPE_JPEG) {
if( $image_type == IMAGETYPE_JPEG ) {
imagejpeg($this->image);
} elseif( $image_type == IMAGETYPE_GIF ) {
imagegif($this->image);
} elseif( $image_type == IMAGETYPE_PNG ) {
imagepng($this->image);
}
}
function getWidth() {
return imagesx($this->image);
}
function getHeight() {
return imagesy($this->image);
}
function resizeToHeight($height) {
$ratio = $height / $this->getHeight();
$width = $this->getWidth() * $ratio;
$this->resize($width,$height);
}
function resizeToWidth($width) {
$ratio = $width / $this->getWidth();
$height = $this->getheight() * $ratio;
$this->resize($width,$height);
}
function scale($scale) {
$width = $this->getWidth() * $scale/100;
$height = $this->getheight() * $scale/100;
$this->resize($width,$height);
}
function resize($width,$height) {
$new_image = imagecreatetruecolor($width, $height);
if ($this->image_type == IMAGETYPE_PNG){
imagealphablending($new_image, false);
imagesavealpha($new_image, true);
$transparent = imagecolorallocatealpha($new_image, 255, 255, 255, 127);
imagefilledrectangle($new_image, 0, 0, $width, $height, $transparent);
}
imagecopyresampled($new_image, $this->image, 0, 0, 0, 0, $width, $height, $this->getWidth(), $this->getHeight());
$this->image = $new_image;
}
}
?>
Photo.php
<?php
require 'Image_Resize.php';
header('Content-Type: image/jpeg');
$imagenew=$_GET['id'];
$name=substr($imagenew,1);
if(file_exists($name)){
$image = new ResizeImage();
$image->load($imagenew);
$image->resize($_GET['width'], $_GET['height']); //25-width, 30-height
$image->output();
}
?>
I tried passing quality parameter to function imagejpeg in output function in Image_resize.php file. It's like this: imagejpeg($this->image,$filename,100);
But it's not working either(still outputs poor result than the original image). Anybody help?

PHP Resize Images and Save to Server [duplicate]

This question already has answers here:
php - resize and save an image? [duplicate]
(3 answers)
Closed 9 years ago.
I'm resizing and saving multiple images from a URL and was wondering how I can compress these images more as the images that are saving in the 640x320 folder are 400kb which is too big and was wondering how I can compress these images more, thanks in advance for any advice!
PHP RESIZE AND SIZE HANDLER
include("../includes/picture-resize.php");
$image = $_POST['thumbnail'];
$slug = $_POST['slug'];
$images = $_POST['screenshots'];
$list = explode(",", $images);
$listlength = count($list);
$i = 0;
$image = $_POST['thumbnail'];
$path = parse_url($image, PHP_URL_PATH);
$filename = $slug.'-'.$i;
$extension = pathinfo($path, PATHINFO_EXTENSION);
$file = $filename.'.'.$extension;
file_put_contents('../tmp/' . $file, file_get_contents($image));
$picture = new pic_resize();
$picture->load('../tmp/'.$file);
$picture->resizeToWidth(125);
mkdir('../images/125x125/'.$slug);
$picture->save('../images/125x125/'.$slug.'/'.$file, $picture->image_type);
unlink('../tmp/'.$file);
$thumbnail = $file;
$new_list = array();
mkdir('../images/640x320/'.$slug);
mkdir('../images/310x205/'.$slug);
while($listlength > $i) {
$path = parse_url($list[$i], PHP_URL_PATH);
$filename = $slug.'-'.$i;
$extension = pathinfo($path, PATHINFO_EXTENSION);
$file = $filename.'.'.$extension;
file_put_contents('../tmp/' . $file, file_get_contents($list[$i]));
$picture = new pic_resize();
$picture->load('../tmp/'.$file);
$picture->resizeToWidth(640);
$picture->save('../images/640x320/'.$slug.'/'.$file, $picture->image_type);
$picture->resizeToWidth(310);
$picture->save('../images/310x205/'.$slug.'/'.$file, $picture->image_type);
unlink('../tmp/'.$file);
array_push($new_list, $file);
$i++;
}
PHP RESIZE CLASS
class pic_resize{
var $image;
var $image_type;
function load($filename) {
$image_info = getimagesize($filename);
$this->image_type = $image_info[2];
if( $this->image_type == IMAGETYPE_JPEG ) {
$this->image = imagecreatefromjpeg($filename);
} elseif( $this->image_type == IMAGETYPE_GIF ) {
$this->image = imagecreatefromgif($filename);
} elseif( $this->image_type == IMAGETYPE_PNG ) {
$this->image = imagecreatefrompng($filename);
}
}
function save($filename, $image_type, $compression=75, $permissions=null) {
if( $image_type == IMAGETYPE_JPEG ) {
imagejpeg($this->image,$filename,$compression);
} elseif( $image_type == IMAGETYPE_GIF ) {
imagegif($this->image,$filename);
} elseif( $image_type == IMAGETYPE_PNG ) {
imagepng($this->image,$filename,9,PNG_FILTER_PAETH);
}
if( $permissions != null) {
chmod($filename,$permissions);
}
}
function output($image_type=IMAGETYPE_JPEG) {
if( $image_type == IMAGETYPE_JPEG ) {
imagejpeg($this->image);
} elseif( $image_type == IMAGETYPE_GIF ) {
imagegif($this->image);
} elseif( $image_type == IMAGETYPE_PNG ) {
imagepng($this->image);
imagealphablending($this->image, false);
imagesavealpha($this->image, true);
}
}
function getWidth() {
return imagesx($this->image);
}
function getHeight() {
return imagesy($this->image);
}
function resizeToHeight($height) {
$ratio = $height / $this->getHeight();
$width = $this->getWidth() * $ratio;
$this->resize($width,$height);
}
function resizeToWidth($width) {
$ratio = $width / $this->getWidth();
$height = $this->getheight() * $ratio;
$this->resize($width,$height);
}
function scale($scale) {
$width = $this->getWidth() * $scale/100;
$height = $this->getheight() * $scale/100;
$this->resize($width,$height);
}
function resize($width,$height) {
$new_image = imagecreatetruecolor($width, $height);
imagealphablending($new_image, false);
imagesavealpha($new_image, true);
imagecopyresampled($new_image, $this->image, 0, 0, 0, 0, $width, $height, $this->getWidth(), $this->getHeight());
$this->image = $new_image;
}
}
3rd parameter:
JPEG Quality : Compression level: from 0 (most compression) to 100 (least compression).
http://www.php.net/manual/en/function.imagejpeg.php
PNG Quality : Compression level: from 0 (no compression) to 9.
http://www.php.net/manual/en/function.imagepng.php
Note that that the quality/size settings are pretty much different/backwards between jpeg and png

Dynamically resample hotlinked images using php

I have an images directory, some with massive resolutions, so I'd like to serve a much lower resolution version if they get hotlinked and I'm also overlaying a repeating image (like a watermark) informing the viewer that the image is stolen and where they can find the genuine original.
I've got the resampling working fine but when I add the function for the no hotlink image overlay, it doesn't work. The thing is, I know the watermarking script works too, on it's own, because I've used it elsewhere in another file on the site. Unfortunately I can't tell what the error is as the hotlink test sites don't output errors, they just show an empty image placeholder, and my host's log files are all like greek to me.
This is the script I have at the moment:
<?php
ini_set('memory_limit','250M');
$path = $_SERVER['DOCUMENT_ROOT'].$_SERVER['REQUEST_URI'];
class SimpleImage {
var $image;
var $image_type;
function load($filename) {
$image_info = getimagesize($filename);
$this->image_type = $image_info[2];
if( $this->image_type == IMAGETYPE_JPEG ) {
$this->image = imagecreatefromjpeg($filename);
} elseif( $this->image_type == IMAGETYPE_GIF ) {
$this->image = imagecreatefromgif($filename);
} elseif( $this->image_type == IMAGETYPE_PNG ) {
$this->image = imagecreatefrompng($filename);
}
}
function save($filename, $image_type=IMAGETYPE_JPEG, $compression=60, $permissions=null) {
if( $image_type == IMAGETYPE_JPEG ) {
imagejpeg($this->image,$filename,$compression);
} elseif( $image_type == IMAGETYPE_GIF ) {
imagegif($this->image,$filename);
} elseif( $image_type == IMAGETYPE_PNG ) {
imagepng($this->image,$filename);
}
if( $permissions != null) {
chmod($filename,$permissions);
}
}
function output($image_type=IMAGETYPE_JPEG) {
if( $image_type == IMAGETYPE_JPEG ) {
imagejpeg($this->image);
} elseif( $image_type == IMAGETYPE_GIF ) {
imagegif($this->image);
} elseif( $image_type == IMAGETYPE_PNG ) {
imagepng($this->image);
}
imagedestroy($image);
exit();
}
function getWidth() {
return imagesx($this->image);
}
function getHeight() {
return imagesy($this->image);
}
function resizeToHeight($height) {
$ratio = $height / $this->getHeight();
$width = $this->getWidth() * $ratio;
$this->resize($width,$height);
}
function resizeToWidth($width) {
$ratio = $width / $this->getWidth();
$height = $this->getheight() * $ratio;
$this->resize($width,$height);
}
function scale($scale) {
$width = $this->getWidth() * $scale/100;
$height = $this->getheight() * $scale/100;
$this->resize($width,$height);
}
function resize($width,$height) {
$new_image = imagecreatetruecolor($width, $height);
imagecopyresampled($new_image, $this->image, 0, 0, 0, 0, $width, $height, $this->getWidth(), $this->getHeight());
$this->image = $new_image;
}
function nothot() {
$hotlink = imagecreatefrompng('hotlink.png');
$hw = imagesx($hotlink);
$hh = imagesy($hotlink);
$img_paste_x = 0;
$img_paste_x = 0;
while($img_paste_x < $this->getWidth()){
$img_paste_y = 0;
while($img_paste_y < $this->getHeight()){
imagecopy($image, $hotlink, $img_paste_x, $img_paste_y, 0, 0, $hw, $hh);
$img_paste_y += $hh;
}
$img_paste_x += $hw;
}
imagedestroy($hotlink);
}
}
header('Content-Type: image/jpeg');
$image = new SimpleImage();
$image->load($path);
$image->resizeToWidth(600);
$image->nothot();
$image->output();
?>
Thanks for your help.
Change:
imagecopy($image, $hotlink, $img_paste_x, $img_paste_y, 0, 0, $hw, $hh);
to:
imagecopy($this->image, $hotlink, $img_paste_x, $img_paste_y, 0, 0, $hw, $hh);
Also not sure about the way you get the $path, some checks on whether the image exists wouldn't go a miss.

Categories