I am working in PHP and trying to use iMagick library to do an image conversion from SVG to JPG using shell_exec command. All seems to work, but the output JPG comes out very distorted. I almost get a feeling that the image is first converted and then resized.
I tried using "resize" and "scale" with same results.
Here is the command:
"-resize 800x800 -quality 95 image.svg image.jpg"
Any insights? Thanks in advance.
For anyone looking for a solution to this. Someone was able to come up with the following hack (with some of my edits):
createThumbnail("input.svg", "output.jpg", 500, 500, $cdn_container);
function createThumbnail($filename, $thname, $width=100, $height=100, $cdn=null)
{
try {
$extension = substr($filename, (strrpos($filename, '.')) + 1 - strlen($filename));
$fallback_save_path = "images/designs";
if ($extension == "svg") {
$im = new Imagick();
$svgdata = file_get_contents($filename);
$svgdata = svgScaleHack($svgdata, $width, $height);
//$im->setBackgroundColor(new ImagickPixel('transparent'));
$im->readImageBlob($svgdata);
$im->setImageFormat("jpg");
$im->resizeImage($width, $height, imagick::FILTER_LANCZOS, 1);
$raw_data = $im->getImageBlob();
(is_null($cdn)) ? file_put_contents($fallback_save_path . '/' . $thname, $im->getImageBlob()) : '';
} else if ($extension == "jpg") {
$im = new Imagick($filename);
$im->stripImage();
// Save as progressive JPEG
$im->setInterlaceScheme(Imagick::INTERLACE_PLANE);
$raw_data = $im->resizeImage($width, $height, imagick::FILTER_LANCZOS, 1);
// Set quality
// $im->setImageCompressionQuality(85);
(is_null($cdn)) ? $im->writeImage($fallback_save_path . '/' . $thname) : '';
}
if (!is_null($cdn)) {
$imageObject = $cdn->DataObject();
$imageObject->SetData( $raw_data );
$imageObject->name = $thname;
$imageObject->content_type = 'image/jpg';
$imageObject->Create();
}
$im->clear();
$im->destroy();
return true;
}
catch(Exception $e) {
return false;
}
}
function svgScaleHack($svg, $minWidth, $minHeight)
{
$reW = '/(.*<svg[^>]* width=")([\d.]+px)(.*)/si';
$reH = '/(.*<svg[^>]* height=")([\d.]+px)(.*)/si';
preg_match($reW, $svg, $mw);
preg_match($reH, $svg, $mh);
$width = floatval($mw[2]);
$height = floatval($mh[2]);
if (!$width || !$height) return false;
// scale to make width and height big enough
$scale = 1;
if ($width < $minWidth)
$scale = $minWidth/$width;
if ($height < $minHeight)
$scale = max($scale, ($minHeight/$height));
$width *= $scale*2;
$height *= $scale*2;
$svg = preg_replace($reW, "\${1}{$width}px\${3}", $svg);
$svg = preg_replace($reH, "\${1}{$height}px\${3}", $svg);
return $svg;
}
Related
I tried 2 implementations, shown below. Both are working well but when I tried to mix them it is not working anymore.
$output['status']=FALSE;
set_time_limit(0);
$allowedImageType = array("image/gif", "image/jpeg", "image/pjpeg", "image/png", "image/x-png" );
if ($_FILES['image_file_input']["error"] > 0) {
$output['error']= "File Error";
}
elseif (!in_array($_FILES['image_file_input']["type"], $allowedImageType)) {
$output['error']= "Invalid image format";
}
elseif (round($_FILES['image_file_input']["size"] / 1024) > 4096) {
$output['error']= "Maximum file upload size is exceeded";
} else {
$temp_path = $_FILES['image_file_input']['tmp_name'];
$file = pathinfo($_FILES['image_file_input']['name']);
$fileType = $file["extension"];
$photo_name = $productname.'-'.$member_id."_".time();
$fileName1 = $photo_name . '-125x125' . ".jpg";
$fileName2 = $photo_name . '-250x250' . ".jpg";
$fileName3 = $photo_name . '-500x500' . ".jpg";
$small_thumbnail_path = "uploads/large/";
createFolder($small_thumbnail_path);
$small_thumbnail = $small_thumbnail_path . $fileName1;
$medium_thumbnail_path = "uploads/large/";
createFolder($medium_thumbnail_path);
$medium_thumbnail = $medium_thumbnail_path . $fileName2;
$large_thumbnail_path = "uploads/large/";
createFolder($large_thumbnail_path);
$large_thumbnail = $large_thumbnail_path . $fileName3;
$thumb1 = createThumbnail($temp_path, $small_thumbnail,$fileType, 125, 125 );
$thumb2 = createThumbnail($temp_path, $medium_thumbnail, $fileType, 250, 250);
$thumb3 = createThumbnail($temp_path, $large_thumbnail,$fileType, 500, 500);
if($thumb1 && $thumb2 && $thumb3) {
$output['status']=TRUE;
$output['small']= $small_thumbnail;
$output['medium']= $medium_thumbnail;
$output['large']= $large_thumbnail;
}
}
echo json_encode($output);
Function File
function createFolder($path)
{
if (!file_exists($path)) {
mkdir($path, 0755, TRUE);
}
}
function createThumbnail($sourcePath, $targetPath, $file_type, $thumbWidth, $thumbHeight){
$source = imagecreatefromjpeg($sourcePath);
$width = imagesx($source);
$height = imagesy($source);
$tnumbImage = imagecreatetruecolor($thumbWidth, $thumbHeight);
imagecopyresampled($tnumbImage, $source, 0, 0, 0, 0, $thumbWidth, $thumbHeight, $width, $height);
if (imagejpeg($tnumbImage, $targetPath, 90)) {
imagedestroy($tnumbImage);
imagedestroy($source);
return TRUE;
} else {
return FALSE;
}
}
Aspect ratio code, which is another one I tried to mix this code. But I was unsuccessful
$fn = $_FILES['image']['tmp_name'];
$size = getimagesize($fn);
$ratio = $size[0]/$size[1]; // width/height
$photo_name = $productname.'-'.$member_id."_".time();
{
if( $ratio > 1) {
$width1 = 500;
$height1 = 500/$ratio;
}
else {
$width1 = 500*$ratio;
$height1 = 500;
}
$src = imagecreatefromstring(file_get_contents($fn));
$dst = imagecreatetruecolor($width1,$height1);
$fileName3 = $photo_name . '-500x500' . ".jpg";
imagecopyresampled($dst,$src,0,0,0,0,$width1,$height1,$size[0],$size[1]);
imagedestroy($src);
imagepng($dst,$fileName3); // adjust format as needed
imagedestroy($dst);
if( $ratio > 1) {
$width2 = 250;
$height2 = 250/$ratio;
}
else {
$width2 = 250*$ratio;
$height2 = 250;
}
$src = imagecreatefromstring(file_get_contents($fn));
$dst = imagecreatetruecolor($width2,$height2);
$fileName2 = $photo_name . '-250x250' . ".jpg";
imagecopyresampled($dst,$src,0,0,0,0,$width2,$height2,$size[0],$size[1]);
imagedestroy($src);
imagepng($dst,$fileName2); // adjust format as needed
imagedestroy($dst);
}
What I need is to save my image after resizing but in second code there is no condition check, and I can't get image upload folder path. That's why I need to merge these 2 codes.
Basically I need need to save my image in 3 size formats: 500x500,250x250 and 125x125. Width is fixed, but height is set as per aspect ratio and set upload folder and condition in second code block.
Try this thumbnail function, which takes your source image resource and thumbnail size, and returns a new image resource for the thumbnail.
function createThumbnail($src, int $width = 100, int $height = null) {
// Ensure that src is a valid gd resource
if (!(is_resource($src) && 'gd' === get_resource_type($src))) {
throw new InvalidArgumentException(
sprintf("Argument 1 of %s expected type resource(gd), %s supplied", __FUNCTION__, gettype($src))
);
}
// Extract source image width, height and aspect ratio
$source_width = imagesx($src);
$source_height = imagesy($src);
$ratio = $source_width / $source_height;
// We know that width is always supplied, and that height can be null
// We must solve height according to aspect ratio if null is supplied
if (null === $height) {
$height = round($width / $ratio);
}
// Create the thumbnail resampled resource
$thumb = imagecreatetruecolor($width, $height);
imagecopyresampled($thumb, $src, 0, 0, 0, 0, $width, $height, $source_width, $source_height);
return $thumb;
}
Given your code above, you can now use the function like this
// Get uploaded file information as you have
// Create your source resource as you have
$source = imagecreatefromstring(file_get_contents($fn));
// Create thumbnails and save + destroy
$thumb = createThumbnail($source, 500);
imagejpeg($thumb, $thumb500TargetPath, 90);
imagedestroy($thumb);
$thumb = createThumbnail($source, 250);
imagejpeg($thumb, $thumb250TargetPath, 90);
imagedestroy($thumb);
$thumb = createThumbnail($source, 125);
imagejpeg($thumb, $thumb125TargetPath, 90);
imagedestroy($thumb);
// Don't forget to destroy the source resource
imagedestroy($source);
I'm using Imagick PHP extension for resizing GIF images to several sizes. When I trying with a GIF image of 3mb size, it doesn't get resized. But for images less than 1mb, they are getting resized successfully.
If anyone else has faced this problem, please advise!
Here my code
if ($extension === 'gif') {
$imagick = new Imagick($_FILES['file']['tmp_name']);
foreach ($imageFolders as $imageFolder => $size) {
if ($imagick->getImageWidth() > $size['minWidth']) {
$width = $size['maxWidth'];
$height = $size['maxWidth'];
} else {
$width = $imagick->getImageWidth();
$height = $imagick->getImageHeight();
}
$imagick->coalesceImages();
do {
$imagick->scaleImage($width, $height, Imagick::FILTER_BOX, 1);
} while ($imagick->nextImage());
$imagick = $imagick->deconstructImages();
$imagick->writeImages($imagePath, true);
}
$imagick->clear();
$imagick->destroy();
}
Result : convert list resource
File Area Memory Map Disk Thread Time
-------------------------------------------------------------------------------
768 7.951GB 3.7025GiB 7.4049GiB unlimited 2 unlimited
$imagick = new Imagick($_FILES['file']['tmp_name']);
foreach ($imageFolders as $imageFolder => $size) {
if ($imagick->getImageWidth() > $size['minWidth']) {
$width = $size['maxWidth'];
$height = $size['maxWidth'];
} else {
$width = $imagick->getImageWidth();
$height = $imagick->getImageHeight(
}
$imagick = $imagick->coalesceImages();
foreach($imagick as $frame){
$frame->thumbnailImage($width , $height );
$frame->setImagePage($width , $height , 0, 0);
}
$imagick = $imagick->deconstructImages();
$imagick->writeImages($imagePath, true);
}
$imagick->clear();
$imagick->destroy();
I am attempting to create and save a squared version (thumb) of an uploaded image file with php. My current script crops it as it should, but the image is completely black. Here is my code:
if ($_FILES['profile_pic']['type'] == "image/png") {
$is_image = true;
$newImage = imagecreatefrompng($img);
} else if ($_FILES['profile_pic']['type'] == "image/jpeg") {
$is_image = true;
$newImage = imagecreatefromjpeg($img);
} else if ($_FILES['profile_pic']['type'] == "image/gif") {
$is_image = true;
$newImage = imagecreatefromgif($img);
} else {
$is_image = false;
}
$img = $_FILES["profile_pic"]['tmp_name'];
$min_width = 100;
$min_height = 100;
$width = 0;
$height = 0;
if ($is_image) {
list($width, $height) = getimagesize($img);
}
if ($is_image && $height >= $min_height && $width >= $min_width) {
$img = $_FILES["profile_pic"]['tmp_name'];
$imgPath = "../img/profile_pics/{$member_id}.png";
// Resize
$aspect_ratio = $width / $min_width;
$new_height = $height * $aspect_ratio;
$canvas1 = imagecreatetruecolor($min_width, $new_height);
imagecopyresampled($canvas1, $newImage, 0, 0, 0, 0, $min_width, $new_height, $width, $new_height);
// Crop
$canvas2 = imagecreatetruecolor($min_width, $min_height);
imagecopyresampled($canvas2, $newImage, 0, 0, 0, 0, $min_width, $min_height, $min_width, $min_height);
imagejpeg($canvas2, $imgPath, 80);
imagedestroy($canvas1);
}
I realise that there this question has been asked before, but for some reason I can't seem to make my own script work.
You're initializing $img after you try to create it via imagecreatefrompng($img) or similar. Might be the reason why it fails.
I'm also not sure you want to save all your images into a *.png file, regardless of their source type: you might want to implement something more flexible instead.
i want to resize my images on upload i found on the web verot class.upload.php
but unfortunately it doesn't work with me , no uploads , no resizes , ..
so my question is does this api requires some sort of installations,
cause i have only uploaded class.upload.php to my server
and my function is like that
public function myImageR()
{
$foo = new Upload($_FILES['img']);
if ($foo->uploaded) {
// save uploaded image with no changes
$foo->Process('/public/images/aa/');
if ($foo->processed) {
$a = true;
} else {
$a = false;
}
// save uploaded image with a new name
$foo->file_new_name_body = 'foo';
$foo->Process('/public/images/aa/');
if ($foo->processed) {
$a = true;
} else {
$a = false;
}
// save uploaded image with a new name,
// resized to 100px wide
$foo->file_new_name_body = 'image_resized';
$foo->image_resize = true;
$foo->image_convert = gif;
$foo->image_x = 100;
$foo->image_ratio_y = true;
$foo->Process('/public/images/aa/');
if ($foo->processed) {
$a = true;
$foo->Clean();
} else {
$a = false;
}
}
}
but it it doesn't work at all i am working on localhost with xammp
You need install the GD lib... Example if you are using ubuntu:
sudo apt-get install php5-gd
Then restart the Apache
sudo /etc/init.d/apache2 restart
Anyway, I use this to resize images I use this:
To upload:
$uploaded_filename = '/www/html/picts/yourfoto.jpg';
if(isset($_FILES['your_files_field_name'])){
if (move_uploaded_file($_FILES['your_files_field_name']['tmp_name'], $uploaded_filename)) {
chmod($uploaded_filename, 0755);
return $nome; // OK
} else {
return "ERROR";
}
}
To Resize:
<?php
$w = 40; // set width
$h = 40; // set height
$path = './'; // path
$image_file = (string) filter_input(INPUT_GET, 'img');
$image_path = $path . $image_file;
$img = null;
$ext = #strtolower(end(explode('.', $image_path)));
if ($ext == 'jpeg') {
$img = imagecreatefromjpeg($image_path);
} else if ($ext == 'jpg') {
$img = imagecreatefromjpeg($image_path);
} else if ($ext == 'png') {
$img = imagecreatefrompng($image_path);
} elseif ($ext == 'gif') {
$img = imagecreatefromgif($image_path);
} elseif ($ext == 'bmp') {
$img = imagecreatefromwbmp($image_path);
} else {
exit("File type not found: " . $ext);
}
if ($img) {
$width = imagesx($img);
$height = imagesy($img);
$scale = min($w / $width, $h / $height);
if ($scale < 1) {
$new_width = floor($scale * $width);
$new_height = floor($scale * $height);
$tmp_img = imagecreatetruecolor($new_width, $new_height);
imagecopyresampled($tmp_img, $img, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
imagedestroy($img);
$img = $tmp_img;
}
}
if (!$img) {
$img = imagecreate($w, $h);
imagecolorallocate($img, 204, 204, 204);
$c = imagecolorallocate($img, 153, 153, 153);
$c1 = imagecolorallocate($img, 0, 0, 0);
imageline($img, 0, 0, $w, $h, $c);
imageline($img, $w, 0, 0, $h, $c);
imagestring($img, 2, 12, 55, 'IMAGE ERROR', $c1);
}
header('Content-type: ' . 'image/png');
imagejpeg($img);
If you want to save the resized file in disk:
$file = '/www/html/picts/yourfoto.jpg';
$save = imagejpeg($img, $file); // save the file
I hope this help!
I have been trying to get a PNG to upload with a clean, 24 bit alpha transparency. After doing a lot of research, I have managed to get it sort of working, however the transparency seems to be low quality 8 bit as you can see here in this screenshot:
http://cozomo.com/apple.png
Any help to achieve a clean PNG upload and resize with 24 bit smooth transparency would be much appreciated. My current code is below.
if($extension=="png")
{
$uploadedfile = $_FILES['photo']['tmp_name'];
$src = imagecreatefrompng($uploadedfile);
}
$dest_x = 1400;
$dest_y = 1200;
if ($width > $dest_x or $height > $dest_y) {
if ($width >= $height) {
$fullSize_x = $dest_x;
$fullSize_y = $height*($fullSize_x/$width);
} else {
$fullSize_x = $width*($fullSize_y/$height);
$fullSize_y = $dest_y;
}
}
$fullSize=imagecreatetruecolor($fullSize_x,$fullSize_y);
//TEST
$black = imagecolorallocate($fullSize, 0, 0, 0);
imagecolortransparent($fullSize, $black);
//TEST END
// OUTPUT NEW IMAGES
imagecopyresampled($fullSize,$src,0,0,0,0,$fullSize_x,$fullSize_y,$width,$height);
imagepng($fullSize, "/user/photos/".$filename);
imagedestroy($fullSize);
[1]: http://i.stack.imgur.com/w8VBI.png
To save the full alpha channel you'll have to use imagesavealpha, put this before you save the png
imagealphablending($fullSize, false);
imagesavealpha($fullSize, true);
Here is the revised code thanks to Musa for anyone having the same issue
function processPNG($pngImage) {
$black = imagecolorallocate($pngImage, 0, 0, 0);
imagecolortransparent($pngImage, $black);
imagealphablending($pngImage, false);
imagesavealpha($pngImage, true);
}
if($extension=="png")
{
$uploadedfile = $_FILES['photo']['tmp_name'];
$src = imagecreatefrompng($uploadedfile);
}
$dest_x = 1400;
$dest_y = 1200;
if ($width > $dest_x or $height > $dest_y) {
if ($width >= $height) {
$fullSize_x = $dest_x;
$fullSize_y = $height*($fullSize_x/$width);
} else {
$fullSize_x = $width*($fullSize_y/$height);
$fullSize_y = $dest_y;
}
}
$fullSize=imagecreatetruecolor($fullSize_x,$fullSize_y);
if ($extension == "png") processPNG($fullSize);
// OUTPUT NEW IMAGES
imagecopyresampled($fullSize,$src,0,0,0,0,$fullSize_x,$fullSize_y,$width,$height);
imagepng($fullSize, "/user/photos/".$filename);
imagedestroy($fullSize);