I'm using the newest version of Prestashop (1.6.1.5), and I've got some problems with quality of product images.
While resizing (creating thumbnails like large_default, home_default etc) grey stripes appears on destination image.
I followed prestashop code and noticed that it happens after imagecopyresized() function, I tried to replace it with imagecopyresampled() but it doesn't help much.
Here is a link to the original image http://postimg.org/image/ib42bh81t, and here is a link to resized one (the one with grey stripes) http://postimg.org/image/i3tpda7sx
Prestashop resize() method:
public static function resize($src_file, $dst_file, $dst_width = null, $dst_height = null, $file_type = 'jpg',
$force_type = false, &$error = 0, &$tgt_width = null, &$tgt_height = null, $quality = 5,
&$src_width = null, &$src_height = null)
{
if (PHP_VERSION_ID < 50300) {
clearstatcache();
} else {
clearstatcache(true, $src_file);
}
if (!file_exists($src_file) || !filesize($src_file)) {
return !($error = self::ERROR_FILE_NOT_EXIST);
}
list($tmp_width, $tmp_height, $type) = getimagesize($src_file);
$rotate = 0;
if (function_exists('exif_read_data') && function_exists('mb_strtolower')) {
$exif = #exif_read_data($src_file);
if ($exif && isset($exif['Orientation'])) {
switch ($exif['Orientation']) {
case 3:
$src_width = $tmp_width;
$src_height = $tmp_height;
$rotate = 180;
break;
case 6:
$src_width = $tmp_height;
$src_height = $tmp_width;
$rotate = -90;
break;
case 8:
$src_width = $tmp_height;
$src_height = $tmp_width;
$rotate = 90;
break;
default:
$src_width = $tmp_width;
$src_height = $tmp_height;
}
} else {
$src_width = $tmp_width;
$src_height = $tmp_height;
}
} else {
$src_width = $tmp_width;
$src_height = $tmp_height;
}
// If PS_IMAGE_QUALITY is activated, the generated image will be a PNG with .jpg as a file extension.
// This allow for higher quality and for transparency. JPG source files will also benefit from a higher quality
// because JPG reencoding by GD, even with max quality setting, degrades the image.
if (Configuration::get('PS_IMAGE_QUALITY') == 'png_all'
|| (Configuration::get('PS_IMAGE_QUALITY') == 'png' && $type == IMAGETYPE_PNG) && !$force_type) {
$file_type = 'png';
}
if (!$src_width) {
return !($error = self::ERROR_FILE_WIDTH);
}
if (!$dst_width) {
$dst_width = $src_width;
}
if (!$dst_height) {
$dst_height = $src_height;
}
$width_diff = $dst_width / $src_width;
$height_diff = $dst_height / $src_height;
$ps_image_generation_method = Configuration::get('PS_IMAGE_GENERATION_METHOD');
if ($width_diff > 1 && $height_diff > 1) {
$next_width = $src_width;
$next_height = $src_height;
} else {
if ($ps_image_generation_method == 2 || (!$ps_image_generation_method && $width_diff > $height_diff)) {
$next_height = $dst_height;
$next_width = round(($src_width * $next_height) / $src_height);
$dst_width = (int)(!$ps_image_generation_method ? $dst_width : $next_width);
} else {
$next_width = $dst_width;
$next_height = round($src_height * $dst_width / $src_width);
$dst_height = (int)(!$ps_image_generation_method ? $dst_height : $next_height);
}
}
if (!ImageManager::checkImageMemoryLimit($src_file)) {
return !($error = self::ERROR_MEMORY_LIMIT);
}
$tgt_width = $dst_width;
$tgt_height = $dst_height;
$dest_image = imagecreatetruecolor($dst_width, $dst_height);
// If image is a PNG and the output is PNG, fill with transparency. Else fill with white background.
if ($file_type == 'png' && $type == IMAGETYPE_PNG) {
imagealphablending($dest_image, false);
imagesavealpha($dest_image, true);
$transparent = imagecolorallocatealpha($dest_image, 255, 255, 255, 127);
imagefilledrectangle($dest_image, 0, 0, $dst_width, $dst_height, $transparent);
} else {
$white = imagecolorallocate($dest_image, 255, 255, 255);
imagefilledrectangle($dest_image, 0, 0, $dst_width, $dst_height, $white);
}
$src_image = ImageManager::create($type, $src_file);
if ($rotate) {
$src_image = imagerotate($src_image, $rotate, 0);
}
if ($dst_width >= $src_width && $dst_height >= $src_height) {
imagecopyresized($dest_image, $src_image, (int)(($dst_width - $next_width) / 2), (int)(($dst_height - $next_height) / 2), 0, 0, $next_width, $next_height, $src_width, $src_height);
} else {
ImageManager::imagecopyresampled($dest_image, $src_image, (int)(($dst_width - $next_width) / 2), (int)(($dst_height - $next_height) / 2), 0, 0, $next_width, $next_height, $src_width, $src_height, $quality);
}
$write_file = ImageManager::write($file_type, $dest_image, $dst_file);
#imagedestroy($src_image);
return $write_file;
}
I also tried to change quality parameter to 100 or even changed image format to PNG in prestashop - no changes.
What else can I change to fix this quality issues? Any ideas?
Related
I found a PHP script online which helps me to create a thumbnail of an uploaded image, there is only one problem: I don't know how to change the outcome size of the thumbnail. I found the tutorial at: http://www.w3schools.in/php/image-upload-and-generate-thumbnail-using-ajax-in-php/
Can anyone help me to change the outcome size of the thumbnail?
Here is my code so far:
<?php
function createDir($path){
if (!file_exists($path)) {
$old_mask = umask(0);
mkdir($path, 0777, TRUE);
umask($old_mask);
}
}
function createThumb($path1, $path2, $file_type, $new_w, $new_h, $squareSize = ''){
/* read the source image */
$source_image = FALSE;
if (preg_match("/jpg|JPG|jpeg|JPEG/", $file_type)) {
$source_image = imagecreatefromjpeg($path1);
}
elseif (preg_match("/png|PNG/", $file_type)) {
if (!$source_image = #imagecreatefrompng($path1)) {
$source_image = imagecreatefromjpeg($path1);
}
}
elseif (preg_match("/gif|GIF/", $file_type)) {
$source_image = imagecreatefromgif($path1);
}
if ($source_image == FALSE) {
$source_image = imagecreatefromjpeg($path1);
}
$orig_w = imageSX($source_image);
$orig_h = imageSY($source_image);
if ($orig_w < $new_w && $orig_h < $new_h) {
$desired_width = $orig_w;
$desired_height = $orig_h;
} else {
$scale = min($new_w / $orig_w, $new_h / $orig_h);
$desired_width = ceil($scale * $orig_w);
$desired_height = ceil($scale * $orig_h);
}
if ($squareSize != '') {
$desired_width = $desired_height = $squareSize;
}
/* create a new, "virtual" image */
$virtual_image = imagecreatetruecolor($desired_width, $desired_height);
// for PNG background white----------->
$kek = imagecolorallocate($virtual_image, 255, 255, 255);
imagefill($virtual_image, 0, 0, $kek);
if ($squareSize == '') {
/* copy source image at a resized size */
imagecopyresampled($virtual_image, $source_image, 0, 0, 0, 0, $desired_width, $desired_height, $orig_w, $orig_h);
} else {
$wm = $orig_w / $squareSize;
$hm = $orig_h / $squareSize;
$h_height = $squareSize / 2;
$w_height = $squareSize / 2;
if ($orig_w > $orig_h) {
$adjusted_width = $orig_w / $hm;
$half_width = $adjusted_width / 2;
$int_width = $half_width - $w_height;
imagecopyresampled($virtual_image, $source_image, -$int_width, 0, 0, 0, $adjusted_width, $squareSize, $orig_w, $orig_h);
}
elseif (($orig_w <= $orig_h)) {
$adjusted_height = $orig_h / $wm;
$half_height = $adjusted_height / 2;
imagecopyresampled($virtual_image, $source_image, 0,0, 0, 0, $squareSize, $adjusted_height, $orig_w, $orig_h);
} else {
imagecopyresampled($virtual_image, $source_image, 0, 0, 0, 0, $squareSize, $squareSize, $orig_w, $orig_h);
}
}
if (#imagejpeg($virtual_image, $path2, 90)) {
imagedestroy($virtual_image);
imagedestroy($source_image);
return TRUE;
} else {
return FALSE;
}
}
?>
the function gets called by the following lines of code:
<?php
include('./functions.php');
/*defined settings - start*/
ini_set("memory_limit", "99M");
ini_set('post_max_size', '20M');
ini_set('max_execution_time', 600);
define('IMAGE_SMALL_DIR', './uploades/small/');
define('IMAGE_SMALL_SIZE', 50);
define('IMAGE_MEDIUM_DIR', './uploades/medium/');
define('IMAGE_MEDIUM_SIZE', 250);
/*defined settings - end*/
if(isset($_FILES['image_upload_file'])){
$output['status']=FALSE;
set_time_limit(0);
$allowedImageType = array("image/gif", "image/jpeg", "image/pjpeg", "image/png", "image/x-png" );
if ($_FILES['image_upload_file']["error"] > 0) {
$output['error']= "Error in File";
}
elseif (!in_array($_FILES['image_upload_file']["type"], $allowedImageType)) {
$output['error']= "You can only upload JPG, PNG and GIF file";
}
elseif (round($_FILES['image_upload_file']["size"] / 1024) > 4096) {
$output['error']= "You can upload file size up to 4 MB";
} else {
/*create directory with 777 permission if not exist - start*/
createDir(IMAGE_SMALL_DIR);
createDir(IMAGE_MEDIUM_DIR);
/*create directory with 777 permission if not exist - end*/
$path[0] = $_FILES['image_upload_file']['tmp_name'];
$file = pathinfo($_FILES['image_upload_file']['name']);
$fileType = $file["extension"];
$desiredExt='jpg';
$fileNameNew = rand(333, 999) . time() . ".$desiredExt";
$path[1] = IMAGE_MEDIUM_DIR . $fileNameNew;
$path[2] = IMAGE_SMALL_DIR . $fileNameNew;
if (createThumb($path[0], $path[1], $fileType, IMAGE_MEDIUM_SIZE, IMAGE_MEDIUM_SIZE,IMAGE_MEDIUM_SIZE)) {
if (createThumb($path[1], $path[2],"$desiredExt", IMAGE_SMALL_SIZE, IMAGE_SMALL_SIZE,IMAGE_SMALL_SIZE)) {
$output['status']=TRUE;
$output['image_medium']= $path[1];
$output['image_small']= $path[2];
}
}
}
echo json_encode($output);
}
?>
I saw that you found the answer to your own problem. I wanted to add some additional insight.
The Right Way
Ideally you should be passing a param to the method as you can reset it if desired:
$imageSize = 100; // size
createThumb($path[0], $path[1], $fileType, $imageSize, $imageSize, $imageSize);
The Wrong Way
The script above is using constants. They are outlined with the define method. IE.
define('IMAGE_SMALL_SIZE', 50);
define('IMAGE_MEDIUM_SIZE', 250);
Change the number to your desired size. Ie
define('IMAGE_SMALL_SIZE', 150);
In this particular use case, the constants are still being passed into the function which defeats the need for a constant.
I have this PHP code
if (!isset($_POST["imageSource"])) {
$_POST["imageSource"] = "test.jpg";
}
list($width, $height) = getimagesize($_POST["imageSource"]);
$viewPortW = $_POST["viewPortW"];
$viewPortH = $_POST["viewPortH"];
$pWidth = $_POST["imageW"];
$pHeight = $_POST["imageH"];
$ext = end(explode(".",$_POST["imageSource"]));
$function = returnCorrectFunction($ext);
$image = $function($_POST["imageSource"]);
$width = imagesx($image);
$height = imagesy($image);
// Resample
$image_p = imagecreatetruecolor($pWidth, $pHeight);
setTransparency($image,$image_p,$ext);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $pWidth, $pHeight, $width, $height);
imagedestroy($image);
$widthR = imagesx($image_p);
$hegihtR = imagesy($image_p);
$selectorX = $_POST["selectorX"];
$selectorY = $_POST["selectorY"];
if($_POST["imageRotate"]){
$angle = 360 - $_POST["imageRotate"];
$image_p = imagerotate($image_p,$angle,0);
$pWidth = imagesx($image_p);
$pHeight = imagesy($image_p);
//print $pWidth."---".$pHeight;
$diffW = abs($pWidth - $widthR) / 2;
$diffH = abs($pHeight - $hegihtR) / 2;
$_POST["imageX"] = ($pWidth > $widthR ? $_POST["imageX"] - $diffW : $_POST["imageX"] + $diffW);
$_POST["imageY"] = ($pHeight > $hegihtR ? $_POST["imageY"] - $diffH : $_POST["imageY"] + $diffH);
}
$dst_x = $src_x = $dst_y = $src_y = 0;
if($_POST["imageX"] > 0){
$dst_x = abs($_POST["imageX"]);
}else{
$src_x = abs($_POST["imageX"]);
}
if($_POST["imageY"] > 0){
$dst_y = abs($_POST["imageY"]);
}else{
$src_y = abs($_POST["imageY"]);
}
$viewport = imagecreatetruecolor($_POST["viewPortW"],$_POST["viewPortH"]);
setTransparency($image_p,$viewport,$ext);
imagecopy($viewport, $image_p, $dst_x, $dst_y, $src_x, $src_y, $pWidth, $pHeight);
imagedestroy($image_p);
$selector = imagecreatetruecolor($_POST["selectorW"], $_POST["selectorH"]);
setTransparency($viewport,$selector,$ext);
imagecopy($selector, $viewport, 0, 0, $selectorX, $selectorY, $_POST["viewPortW"], $_POST["viewPortH"]);
if (isset($_GET["destino"]) && !empty($_GET["destino"])) {
$file = "../../".$_GET["destino"];
} else {
$file = "test".time().".".$ext;
}
parseImage($ext,$selector,$file);
imagedestroy($viewport);
//Return value
echo $file;
/* Functions */
function determineImageScale($sourceWidth, $sourceHeight, $targetWidth, $targetHeight) {
$scalex = $targetWidth / $sourceWidth;
$scaley = $targetHeight / $sourceHeight;
return min($scalex, $scaley);
}
function returnCorrectFunction($ext){
$function = "";
switch($ext){
case "png":
$function = "imagecreatefrompng";
break;
case "jpeg":
$function = "imagecreatefromjpeg";
break;
case "jpg":
$function = "imagecreatefromjpeg";
break;
case "gif":
$function = "imagecreatefromgif";
break;
}
return $function;
}
function parseImage($ext,$img,$file = null){
switch($ext){
case "png":
imagepng($img,($file != null ? $file : ''));
break;
case "jpeg":
imagejpeg($img,($file ? $file : ''),100);
break;
case "jpg":
imagejpeg($img,($file ? $file : ''),100);
break;
case "gif":
imagegif($img,($file ? $file : ''));
break;
}
}
function setTransparency($imgSrc,$imgDest,$ext){
if($ext == "png" || $ext == "gif"){
$trnprt_indx = imagecolortransparent($imgSrc);
// If we have a specific transparent color
if ($trnprt_indx >= 0) {
// Get the original image's transparent color's RGB values
$trnprt_color = imagecolorsforindex($imgSrc, $trnprt_indx);
// Allocate the same color in the new image resource
$trnprt_indx = imagecolorallocate($imgDest, $trnprt_color['red'], $trnprt_color['green'], $trnprt_color['blue']);
// Completely fill the background of the new image with allocated color.
imagefill($imgDest, 0, 0, $trnprt_indx);
// Set the background color for new image to transparent
imagecolortransparent($imgDest, $trnprt_indx);
}
// Always make a transparent background color for PNGs that don't have one allocated already
elseif ($ext == "png") {
// Turn off transparency blending (temporarily)
imagealphablending($imgDest, true);
// Create a new transparent color for image
$color = imagecolorallocatealpha($imgDest, 0, 0, 0, 127);
// Completely fill the background of the new image with allocated color.
imagefill($imgDest, 0, 0, $color);
// Restore transparency blending
imagesavealpha($imgDest, true);
}
}
}
Comes Cropzoom tool
Currently I generated JPG images with black background color.
I need to modify it so you can change (from the code) background color of the generated image in JPG format
All other things are working properly.
I have solved the problem.
I used this to give background color on all parts that I considered necessary
$backgroundColor = "FF0000"; // Red, for example
$backgroundColor= '0x'.$backgroundColor;
imagefilledrectangle($FinalImage, 0 , 0 , $width , $height , ($backgroundColor*1));
The full code
// Set the Background color
$background_color = "FFFFFF";
$background_color = "0x".$background_color;
if (!isset($_POST["imageSource"])) {
$_POST["imageSource"] = "test.jpg";
}
list($width, $height) = getimagesize($_POST["imageSource"]);
$viewPortW = $_POST["viewPortW"];
$viewPortH = $_POST["viewPortH"];
$pWidth = $_POST["imageW"];
$pHeight = $_POST["imageH"];
$ext = end(explode(".",$_POST["imageSource"]));
$function = returnCorrectFunction($ext);
$image = $function($_POST["imageSource"]);
$width = imagesx($image);
$height = imagesy($image);
// Modified to set background color
$image_p = imagecreatetruecolor($pWidth, $pHeight);
// ****************************************************************
// ********** NEXT LINE IS NEW TO SET BACKGROUND COLOR **************
// ****************************************************************
imagefilledrectangle($viewport, 0, 0, $pWidth, $pHeight, ($background_color * 1));
setTransparency($image,$image_p,$ext);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $pWidth, $pHeight, $width, $height);
imagedestroy($image);
$widthR = imagesx($image_p);
$hegihtR = imagesy($image_p);
$selectorX = $_POST["selectorX"];
$selectorY = $_POST["selectorY"];
if($_POST["imageRotate"]){
$angle = 360 - $_POST["imageRotate"];
$image_p = imagerotate($image_p,$angle,0);
$pWidth = imagesx($image_p);
$pHeight = imagesy($image_p);
//print $pWidth."---".$pHeight;
$diffW = abs($pWidth - $widthR) / 2;
$diffH = abs($pHeight - $hegihtR) / 2;
$_POST["imageX"] = ($pWidth > $widthR ? $_POST["imageX"] - $diffW : $_POST["imageX"] + $diffW);
$_POST["imageY"] = ($pHeight > $hegihtR ? $_POST["imageY"] - $diffH : $_POST["imageY"] + $diffH);
}
$dst_x = $src_x = $dst_y = $src_y = 0;
if($_POST["imageX"] > 0){
$dst_x = abs($_POST["imageX"]);
}else{
$src_x = abs($_POST["imageX"]);
}
if($_POST["imageY"] > 0){
$dst_y = abs($_POST["imageY"]);
}else{
$src_y = abs($_POST["imageY"]);
}
$viewport = imagecreatetruecolor($_POST["viewPortW"],$_POST["viewPortH"]);
// ****************************************************************
// ********** NEXT LINE IS NEW TO SET BACKGROUND COLOR **************
// ****************************************************************
imagefilledrectangle($viewport, 0, 0, $_POST["viewPortW"], $_POST["viewPortH"], ($background_color * 1));
setTransparency($image_p,$viewport,$ext);
imagecopy($viewport, $image_p, $dst_x, $dst_y, $src_x, $src_y, $pWidth, $pHeight);
imagedestroy($image_p);
$selector = imagecreatetruecolor($_POST["selectorW"], $_POST["selectorH"]);
setTransparency($viewport,$selector,$ext);
imagecopy($selector, $viewport, 0, 0, $selectorX, $selectorY, $_POST["viewPortW"], $_POST["viewPortH"]);
if (isset($_GET["destino"]) && !empty($_GET["destino"])) {
$file = "../../".$_GET["destino"];
} else {
$file = "test".time().".".$ext;
}
parseImage($ext,$selector,$file);
imagedestroy($viewport);
//Return value
echo $file;
/* Functions */
function determineImageScale($sourceWidth, $sourceHeight, $targetWidth, $targetHeight) {
$scalex = $targetWidth / $sourceWidth;
$scaley = $targetHeight / $sourceHeight;
return min($scalex, $scaley);
}
function returnCorrectFunction($ext){
$function = "";
switch($ext){
case "png":
$function = "imagecreatefrompng";
break;
case "jpeg":
$function = "imagecreatefromjpeg";
break;
case "jpg":
$function = "imagecreatefromjpeg";
break;
case "gif":
$function = "imagecreatefromgif";
break;
}
return $function;
}
function parseImage($ext,$img,$file = null){
switch($ext){
case "png":
imagepng($img,($file != null ? $file : ''));
break;
case "jpeg":
imagejpeg($img,($file ? $file : ''),100);
break;
case "jpg":
imagejpeg($img,($file ? $file : ''),100);
break;
case "gif":
imagegif($img,($file ? $file : ''));
break;
}
}
function setTransparency($imgSrc,$imgDest,$ext){
if($ext == "png" || $ext == "gif"){
$trnprt_indx = imagecolortransparent($imgSrc);
// If we have a specific transparent color
if ($trnprt_indx >= 0) {
// Get the original image's transparent color's RGB values
$trnprt_color = imagecolorsforindex($imgSrc, $trnprt_indx);
// Allocate the same color in the new image resource
$trnprt_indx = imagecolorallocate($imgDest, $trnprt_color['red'], $trnprt_color['green'], $trnprt_color['blue']);
// Completely fill the background of the new image with allocated color.
imagefill($imgDest, 0, 0, $trnprt_indx);
// Set the background color for new image to transparent
imagecolortransparent($imgDest, $trnprt_indx);
}
// Always make a transparent background color for PNGs that don't have one allocated already
elseif ($ext == "png") {
// Turn off transparency blending (temporarily)
imagealphablending($imgDest, true);
// Create a new transparent color for image
$color = imagecolorallocatealpha($imgDest, 0, 0, 0, 127);
// Completely fill the background of the new image with allocated color.
imagefill($imgDest, 0, 0, $color);
// Restore transparency blending
imagesavealpha($imgDest, true);
}
}
}
It is modified after "NEXT LINE IS NEW TO SET BACKGROUND COLOR" and all the tests I've done, it works correctly
iam trying to resize an imageto a thumbnail with php! I get no errors but it won't save the thumbnail on my server. The code is:
#Resize image
function resize($input_dir, $cur_file, $newwidth, $output_dir)
{
$filename = $input_dir.'/'.$cur_file;
$format='';
if(preg_match("/.jpg/i", $filename))
{
$format = 'image/jpeg';
}
if (preg_match("/.gif/i", $filename))
{
$format = 'image/gif';
}
if(preg_match("/.png/i", $filename))
{
$format = 'image/png';
}
if($format!='')
{
list($width, $height) = getimagesize($filename);
$newheight=$height*$newwidth/$width;
switch($format)
{
case 'image/jpeg':
$source = imagecreatefromjpeg($filename);
break;
case 'image/gif';
$source = imagecreatefromgif($filename);
break;
case 'image/png':
$source = imagecreatefrompng($filename);
break;
}
$thumb = imagecreatetruecolor($newwidth,$newheight);
imagealphablending($thumb, false);
imagecopyresized($thumb, $source, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
imagejpeg($thumb, 'thumb_'.$cur_file);
}
}
My function looks like:
resize(plugins_url().'/MyImagePlugin/img', 'testimg.jpg', "200");
The Image is in the Folder "img" in my Plugin Dic. The wired thing is ,that i don't get any erros?! CHMOD is 777 for img-folder.
Any help would be appreciated.
You are not using any path when you save the image in the line:
imagejpeg($thumb, 'thumb_'.$cur_file);
$cur_file is set to testing.jpg.
You should add the path to the filename or it will be attempoting to create it in whatever the current directory is.
Changes are something like :
function resize($input_dir, $cur_file, $newwidth, $output_dir = "" )
{
if($output_dir == "") $output_dir = $input_dir;
.....
imagejpeg($thumb, $output_dir.'/thumb_'.$cur_file);
}
}
I know that this is not your way of doing but iam sure it can help you.
if (isset($_FILES['image']['name']))
{
$saveto = "dirname/file.jpg";
move_uploaded_file($_FILES['image']['tmp_name'], $saveto);
$typeok = TRUE;
switch($_FILES['image']['type'])
{
case "image/gif": $src = imagecreatefromgif($saveto); break;
case "image/jpeg": // Both regular and progressive jpegs
case "image/pjpeg": $src = imagecreatefromjpeg($saveto); break;
case "image/png": $src = imagecreatefrompng($saveto); break;
default: $typeok = FALSE; break;
}
if ($typeok)
{
list($w, $h) = getimagesize($saveto);
$max = 500;
\\ you can change this to desired product for height and width.
$tw = $w;
$th = $h;
if ($w > $h && $max < $w)
{
$th = $max / $w * $h;
$tw = $max;
}
elseif ($h > $w && $max < $h)
{
$tw = $max / $h * $w;
$th = $max;
}
elseif ($max < $w)
{
$tw = $th = $max;
}
$tmp = imagecreatetruecolor($tw, $th);
imagecopyresampled($tmp, $src, 0, 0, 0, 0, $tw, $th, $w, $h);
imageconvolution($tmp, array( // Sharpen image
array(-1, -1, -1),
array(-1, 16, -1),
array(-1, -1, -1)
), 8, 0);
imagejpeg($tmp, $saveto);
imagedestroy($tmp);
imagedestroy($src);
}
}
Im facing a very annoying problem in PHP when Im trying to watermark the full size images on my website. The watermark was working fine for weeks but all the sudden it started showing this error : the image "bla bla" cannot be displayed because it contains errors
I checked everything and everything seems to be working just fine! I'm stuck and I dont know what to do.
Here is my watermarking php file:
require_once "maincore.php";
if (isset($_GET['photo_id']) && isnum($_GET['photo_id'])) {
$result = dbquery("SELECT td.*, tc.* FROM ".DB_PRODUCTS." td LEFT JOIN ".DB_PRODUCT_CATS." tc ON td.product_cat=tc.cat_id WHERE product_id='".$_GET['photo_id']."'");
$data = dbarray($result);
define("PHOTODIR", BASEDIR."downloads/images/");
$parts = explode(".", $data['product_image']);
$wm_file1 = $parts[0]."_w1.".$parts[1];
$wm_file2 = $parts[0]."_w2.".$parts[1];
if (!isset($_GET['full'])) {
$wm_file = PHOTODIR.$wm_file1;
} else {
$wm_file = PHOTODIR.$wm_file2;
}
header("Content-type: image/jpg");
$img = PHOTODIR.$data['product_image'];
$cop = BASEDIR.$settings['photo_watermark_image'];
if (preg_match("/.jpg/i", strtolower($img)) || preg_match("/.jpeg/i", strtolower($img))) {
$image = imagecreatefromjpeg($img);
} else if (preg_match("/.png/i", strtolower($img))) {
$image = imagecreatefrompng($img);
} else if (preg_match("/.gif/i", strtolower($img))) {
$image = imagecreatefromgif($img);
$sizeX = imagesx($image);
$sizeY = imagesy($image);
$image_tmp = imagecreatetruecolor($sizeX, $sizeY);
$ica = imagecolorallocate($image_tmp, 255, 255, 255);
imagefill($image_tmp, 0, 0, $ica);
if ($settings['thumb_compression'] == "gd2") {
imagecopyresampled($image_tmp, $image, 0, 0, 0, 0, $sizeX, $sizeY, $sizeX, $sizeY);
} else {
imagecopyresized($image_tmp, $image, 0, 0, 0, 0, $sizeX, $sizeY, $sizeX, $sizeY);
}
$tmp = PHOTODIR.md5(time().$img).'.tmp';
imagejpeg($image_tmp, $tmp);
imagedestroy($image_tmp);
$image = imagecreatefromjpeg($tmp);
unlink($tmp);
}
if (file_exists($cop) && preg_match("/.png/i", strtolower($cop)) && $settings['photo_watermark']) {
$image2 = false;
$image_dim_x = imagesx($image);
$image_dim_y = imagesy($image);
$copyright = imagecreatefrompng($cop);
$copyright_dim_x = imagesx($copyright);
$copyright_dim_y = imagesy($copyright);
$where_x = $image_dim_x - $copyright_dim_x - 5;
$where_y = $image_dim_y - $copyright_dim_y - 5;
imagecopy ($image, $copyright, $where_x, $where_y, 0, 0, $copyright_dim_x, $copyright_dim_y);
$thumb_w = 0; $thumb_h = 0;
if (!isset($_GET['full'])) {
if ($image_dim_x > $settings['photo_w'] || $image_dim_y > $settings['photo_h']) {
if ($image_dim_x $image_dim_y) {
$thumb_w = $settings['photo_w'];
$thumb_h = round(($image_dim_y * $settings['photo_w']) / $image_dim_x);
} else {
$thumb_w = $settings['photo_w'];
$thumb_h = $settings['photo_h'];
}
} else {
$thumb_w = $image_dim_x;
$thumb_h = $image_dim_y;
}
$image2 = imagecreatetruecolor($thumb_w, $thumb_h);
if ($settings['thumb_compression'] == "gd2") {
imagecopyresampled($image2, $image, 0, 0, 0, 0, $thumb_w, $thumb_h, $image_dim_x, $image_dim_y);
} else {
imagecopyresized($image2, $image, 0, 0, 0, 0, $thumb_w, $thumb_h, $image_dim_x, $image_dim_y);
}
imagedestroy($image);
}
}
//create image
if ($settings['photo_watermark_save']) { imagejpeg(($image2 ? $image2 : $image), $wm_file); }
imagejpeg((isset($image2) && $image2 ? $image2 : $image));
imagedestroy((isset($image2) && $image2 ? $image2 : $image));
if (isset($copyright) && is_resource($copyright)) { ImageDestroy($copyright); }
} else {
redirect("index.php");
}
Please Help ME! Thank you!
Is php.ini set with display_errors turned on? If so, your code may be throwing a warning or notice which is getting incorporated into the binary image data and corrupting it.
Check your PHP error log for new entries.
Another possibility is that an include file is outputting whitespace by having multiple blank lines in the bottom below the closing PHP tag.
Final: I've decided to basically use this: http://shiftingpixel.com/2008/03/03/smart-image-resizer/
As it handles everything, Ive turned caching off and do this in the admin controllers:
$image = file_get_contents(SITE_ADMIN_IMAGE.'/SmartImage.php?width='.$this->thumb_width.'&height='.$this->thumb_height.'&image=/images/'.$this->image_directory.'/'.$formData['image_url'].'');
file_put_contents(ROOT_PATH.'/public/images/'.$this->image_directory.'/thumb/'.$formData['image_url'], $image);
EDIT: I found this works, however it creates very sharp edges, it doesn't look right.
imagecolortransparent($dstImage, $background);
imagealphablending($dstImage, false);
$colorTransparent = imagecolorallocatealpha($dstImage, 0, 0, 0, 127);
imagefill($dstImage, 0, 0, $colorTransparent);
imagesavealpha($dstImage, true);
imagepng($dstImage, $toWhere);
Ideas?
Hello,
I have two issues with my class, basically the quality of the jpeg images is quite poor, but I'm not sure if thats down to my ratio resizing. Ideally I'd like this class to be strict with image sizes and crop into them, but I cant get my head around it.
My main issue is that pngs always have a black bg, does anyone have experience with this happening?
<?php
class OpenSource_ImageResize {
function __construct($theFile, $toWhere, $mime, $extension, $newWidth, $newHeight) {
if ($mime == NULL) {
$mime = getimagesize($theFile);
$mime = $mime['mime'];
}
if ($mime == 'image/jpeg') {
$size = getimagesize($theFile);
if ($size[0] > $newWidth || $size[1] > $newHeight) {
$sourceImage = imagecreatefromjpeg($theFile);
} else {
return copy($theFile, $toWhere);
throw new exception('Could not create jpeg');
return false;
}
} else if ($mime == 'image/png') {
$size = getimagesize($theFile);
if ($size[0] > $newWidth || $size[1] > $newHeight) {
$sourceImage = imagecreatefrompng($theFile);
} else {
return copy($theFile, $toWhere);
//throw new exception('Could not create png');
return false;
}
} else if ($mime == 'image/gif') {
$size = getimagesize($theFile);
if ($size[0] > $newWidth || $size[1] > $newHeight) {
$sourceImage = imagecreatefromgif ($theFile);
} else {
return copy($theFile, $toWhere);
//throw new exception('Could not create gif');
return false;
}
} else {
throw new exception('Not a valid mime type');
return false;
}
$oldX = imageSX($sourceImage);
$oldY = imageSY($sourceImage);
if ($newWidth == NULL) {
$thumbHeight = $newHeight;
$thumbWidth = round($newHeight/($oldY/$oldX));
} else
if ($oldX > $oldY) {
$thumbWidth = $newWidth;
$thumbHeight = $oldY * ($newHeight/$oldX);
}
if ($oldX < $oldY) {
$thumbWidth = round($newHeight/($oldY/$oldX));
$thumbHeight = $newHeight;
}
if ($oldX == $oldY) {
$thumbWidth = $newWidth;
$thumbHeight = $newHeight;
}
if (!gd_info()) {
$dstImage = ImageCreate($thumbWidth, $thumbHeight);
imagecopyresized($dstImage, $sourceImage, 0, 0, 0, 0, $thumbWidth, $thumbHeight, $oldX, $oldY);
} else {
$dstImage = ImageCreateTrueColor($thumbWidth, $thumbHeight);
imagecopyresampled($dstImage, $sourceImage, 0, 0, 0, 0, $thumbWidth, $thumbHeight, $oldX, $oldY);
}
if ($mime == 'image/png') {
$xparent = imagecolorresolvealpha($dstImage, 255,2,240, 0) ;
imagecolortransparent($dstImage,$xparent);
imagealphablending($dstImage,true);
imagepng($dstImage, $toWhere);
} else if ($mime == 'image/jpeg') {
imagejpeg($dstImage, $toWhere);
} else if ($mime == 'image/gif') {
imagegif ($dstImage, $toWhere);
}
imagedestroy($dstImage);
imagedestroy($sourceImage);
return true;
}
}
Regarding JPEG image quality you need to make use of the third argument in imagejpeg():
imagejpeg($dstImage, $toWhere, 90); // any value above 85 should be fine
Regarding PNG transparency, you're doing it wrong. Your script is horrible and has fundamental problems, I'm gonna leave you with a revised one that fixes both of your problems. It can still be further optimized but I choose to leave some of your original less important mistakes so you don't feel lost:
class OpenSource_ImageResize
{
// $extension is not used?
function __construct($theFile, $toWhere, $mime, $extension, $newWidth, $newHeight)
{
$sourceImage = ImageCreateFromString(file_get_contents($theFile));
if (is_resource($sourceImage))
{
$info = getimagesize($theFile);
if (is_null($mime))
{
$mime = $info['mime'];
}
if ($info[0] <= $newWidth && $info[1] <= $newHeight)
{
imagedestroy($sourceImage);
return copy($theFile, $toWhere);
}
if (is_null($newWidth))
{
$thumbHeight = $newHeight;
$thumbWidth = round($newHeight/($info[1]/$info[0]));
}
else if ($info[0] > $info[1])
{
$thumbWidth = $newWidth;
$thumbHeight = $info[1] * ($newHeight/$info[0]);
}
if ($info[0] < $info[1])
{
$thumbWidth = round($newHeight/($info[1]/$info[0]));
$thumbHeight = $newHeight;
}
if ($info[0] == $info[1])
{
$thumbWidth = $newWidth;
$thumbHeight = $newHeight;
}
$dstImage = ImageCreateTrueColor($thumbWidth, $thumbHeight);
/* fix PNG transparency issues */
ImageFill($dstImage, 0, 0, IMG_COLOR_TRANSPARENT);
ImageSaveAlpha($dstImage, true);
ImageAlphaBlending($dstImage, true);
imagecopyresampled($dstImage, $sourceImage, 0, 0, 0, 0, $thumbWidth, $thumbHeight, $info[0], $info[1]);
switch ($mime)
{
case 'image/png':
imagepng($dstImage, $toWhere, 9); // compress it (level 1 to 9)
break;
case 'image/jpeg':
imagejpeg($dstImage, $toWhere, 90); // quality = 90 (1 to 100, default is "about" 75)
break;
case 'image/gif':
imagegif($dstImage, $toWhere);
break;
}
imagedestroy($dstImage);
imagedestroy($sourceImage);
return true;
}
}
}
I'm sorry for not explicitly pointing out your mistakes but they are so many and it's 3 AM here, need to get some sleep - study it and read the manual, if you have any doubts let me know.
Musty define in your class png background color.You can also change the background color of jpg and other files after defining the background color.
this link will take you to a simple function that will either crop-to-fit, or letter box the image during resize based on the function's arguments. it also has a pretty thorough explaination as to what the function is doing.
http://www.spotlesswebdesign.com/blog.php?id=1
Edit: fixed link.