PHP GD Library cannot Merge to image using function - php

This is my php class to merge to images
mergepic.php
class mergepic{
public function merge_barchart_drawing($object,$obj)
{
$src = imagecreatefrompng($obj->barchart());
$dest = imagecreatefrompng($object->drawing());
//$src = imagecreatefrompng('http://localhost/graph/barchart.php?barchart='.$_GET['barchart'].'&max='.$_GET['max'].'&digit='.$_GET['digit']);
//$dest = imagecreatefrompng('http://localhost/graph/drawing.php?drawings='.$_GET['drawings'].'&max='.$_GET['max'].'&digit='.$_GET['digit']);
imagealphablending($dest, false);
imagesavealpha($dest, true);
imagecopymerge($dest, $src, 10, 9, 0, 9, 700, 500, 100); //have to play with these numbers for it to work for you, etc.
header('Content-Type: image/png');
imagepng($dest);
imagedestroy($dest);
imagedestroy($src);
}
}
creating_obj,php
<?
include('drawing.php');
include('barchart.php');
include('mergepic_class.php');
$draw = new drawgraph();
$barchart = new barchart_graph();
$merge_draw = new mergepic();
$merge_draw_bar = $merge_draw->merge_barchart_drawing($draw,$barchart);
?>
If i run createing_obj.php i am geting only one image file its not mergeing two images. Instead of class if i use url inside imagecreatefrompng() it working fine.
Any idea please ?

function barchart(){
return $canvas;
}
OR (If you want to save this layer image to disk):
function barchart(){
$path = {path where to save file};
$filename = {filename to save and extension};
imagepng($canvas,$path.$filename);
return $path.$filename;
}
Do this same for the other(drawing) class too..

Related

How add image created in GD to template

I am looking for help with one problem. I would like to create an image using imageJpeg. And this image add to template using openTBS.
template:
[b.image;ope=changepic;from=[val];default=current;adjust]
php:
$TBS = $this->get('opentbs');
$TBS->NoErr = TRUE;
$TBS->LoadTemplate('template.odt', OPENTBS_ALREADY_UTF8);
$image = imageCreate(300,200);
$colorRed = imageColorAllocate($image, 255,0,0);
$colorYellow = imageColorAllocate($image, 255,255,0);
imageFilledRectangle($image, 50, 50, 250, 150, $colorYellow);
$cccc=imageJpeg($image);
imageDestroy($image);
$data = array('image'=>$cccc);
$TBS->MergeField('b', $data);
$TBS->Show(OPENTBS_DOWNLOAD, 'file_name.odt');
However, image does not fit in the template sizes. After opening the file, only generated image is visible.
According to the documentation, imageJpeg() creates the image and return a boolean.
So a nice solution is to use a temporary file :
...
$tmp = tempnam(sys_get_temp_dir(), 'tbs');
$cccc=imageJpeg($image, $tmp);
imageDestroy($image);
$data = array('image'=>$tmp);
$TBS->MergeField('b', $data);
$TBS->Show(OPENTBS_DOWNLOAD, 'file_name.odt');

PHP Imagick black areas after converting PDF to JPG

I'm using Imagick to generate JPG thumbnails for PDFs files but some of them generate with black areas (http://i.imgur.com/fKBncKw.jpg) – I'm assuming it's caused by transparency in the PDFs but can anything be done about it?
Code I'm using to generate these:
$imagick = new Imagick($filename);
$imagick->setIteratorIndex(0);
$imagick->setImageFormat('jpg');
return $imagick->getImageBlob();
Is there a way to flatten the PDF and/or add a white background so that the black areas don't appear?
Here is a solution which will only work for PNG to JPG.
This code adds a white background to the transparent areas in PNG and converts it to JPG.
What it does?
This code takes all PNG images from a folder, converts them to JPG's with white backgrounds and saves them in another folder.
<?php
ini_set('max_execution_time', 3000);
$dir = 'transparent/';
$arr = scandir($dir);
for($i=0;$i<count($arr);$i++)
{
if($i==0 || $i==1)
{
}
else{
$input_file = "transparent/".$arr[$i];
$output_file = "White/".str_replace('.png','.jpg',$arr[$i]);
$input = imagecreatefrompng($input_file);
list($width, $height) = getimagesize($input_file);
$output = imagecreatetruecolor($width, $height);
$white = imagecolorallocate($output, 255, 255, 255);
imagefilledrectangle($output, 0, 0, $width, $height, $white);
imagecopy($output, $input, 0, 0, 0, 0, $width, $height);
imagejpeg($output, $output_file);
}
}
?>
Its Image Processing and GD in PHP.
PHP Manual
Hope it helps, you can change it as you want.
Try this code: Imagick::setCompressionQuality
$im = new imagick(realpath($file).'[0]');
$im->setCompression(Imagick::COMPRESSION_JPEG);
$im->setCompressionQuality(100);
$im->setImageFormat("jpeg");
$im->writeImage("imagename.jpg");
Alternative solution: this may help:
<?php
//Note that the function returns an Imagick object and does not modify the existing object. Below is my code for converting a PNG with transparency into a JPG with a background color. This code illustrates the difference.
$im = new Imagick($filename);
$im->setImageBackgroundColor('white');
$im->flattenImages(); // This does not do anything.
$im = $im->flattenImages(); // Use this instead.
$im->setImageFormat('jpg');
$im->writeImage('image.jpg');
?>
use like this
class ImageConvertorLib{
private $CI;
/**
* loading codeIgniter instance
*/
public function __construct(){
$this->CI =& get_instance();
}
public function pdfToJpg($param){
$filename = $param['filename'];
$image_name = $param['image_name'];
$path = $param['path'];
$db_path = $param['db_path'];
$im = new Imagick();
$im->setResolution(220,220);
$im->readimage($filename."[0]");
$im->setImageFormat('jpeg');
$im->setImageBackgroundColor('#ffffff');
$im->flattenImages();
$image_name = $image_name.".jpg";//"save_as_name.jpg";
$imageprops = $im->getImageGeometry();
/*if ($imageprops['width'] <= 175 && $imageprops['height'] <= 300) {
// don't upscale
} else {
$im->resizeImage(175,300, imagick::FILTER_LANCZOS, 0.9, true);
}*/
$im->writeImage($path.$image_name);
if($im){
$Img = array();
$Img['status'] = 1;
$Img['image'] = ($db_path.$image_name);
return $Img;
}
$im->clear();
$im->destroy();
}
}
After endless attempts to append a pdf file with a jpeg image without getting black areas, I found the solution: the function transformImageColorspace
Used in this order works perfectly:
$im = new Imagick();
$im->readImage("file.pdf");
$im->transformImageColorspace(Imagick::COLORSPACE_SRGB);
$im->setImageFormat('jpeg');
$im->writeImage('image.jpg');

Upload script too long to execute

So, i have a script for resize, save a gif and save a preview image of this gif on my server.
This is my script :
public function createImageGif($gif, $x, $y, $w, $h)
{
$image = new Imagick();
$decoded = base64_decode($gif);
$image->readimageblob($decoded);
$image = $image->coalesceImages();
$image_name = uniqid(rand()).'.gif';
foreach ($image as $frame) { //gif creation
$frame->cropImage($w, $h, $x, $y);
$frame->thumbnailImage(117, 135);
$frame->setImagePage(117, 135, 0, 0);
}
$image = $image->deconstructImages();
$image->writeImages('uploads/profiles/'.$image_name, true);
//preview creation
$im = imagecreatefromstring($decoded);
if ($im !== false) {
header('Content-Type: image/gif');
$newimage = imagecreatetruecolor(117, 135);
imagecopyresampled($newimage, $im, 0, 0, $x, $y, 117, 135, $w, $h);
imagegif($newimage, 'uploads/profiles-preview/'.$image_name.'', 100);
imagedestroy($newimage);
imagedestroy($im);
}
return $image_name;
}
So, $gif is at first a long string blob (about 2 000 000 characters). At the end, gif size on my server is approximatly 300ko.
This script take more of 20s to execute. I have a good connexion and a good server.
How can i optimize this script ? Any ideas ?
Edit : this is my script for the creation of my data in javascript :
var base64data;
var img = document.createElement('img');
var reader = new window.FileReader();
reader.readAsDataURL(blob);
reader.onloadend = function() {
base64data = reader.result;
img.src = base64data;
}
Why your script uses a blob binary64 encoded as input? There are many sound reasons to do this thing, but are you sure it's necessary? Can't you just load the image from PHP temp's folder?
Maybe, you're uploading an image from a javascript function, through ajax, base-64 encoding an image (created on the fly from canvas?) and sending it as a string in a POST parameter
Also, I see that you first save your image, then re-open it for sending back the reply to the client. Why don't you send back the image you just resized (the one contained in the $image variable)

Resize and crop image into square with white background - using GD

I've got a script which caches images from an external feed and stores them in a directory on my server when the image is viewed on site.
At the moment it is working great - storing the original image on my server and also creating two additional thumbnails, with their widths re-sized at 300px and 150px.
I'd like to change this slightly so that the following occurs:
Full/Original image is stored on server (as normal)
Both a square 300x300px & 150x150px .jpg thumbnail are created
However, is it possible, so that once the image width/height is resized, the additional canvas width/height is then added to make it completely square? I guess one of the issues here is determining if the image is a 'portrait' or 'landscape' first?
Also, currently I'm getting a black background with transparent PNG images. Is there any way to overcome this and fill the background with white instead?
Thank you very much for any help!! :)
Here is the code which is doing the resizing (imageCache.php):
<?php
function cacheFetch($url,$size,$age)
{
// directory in which to store cached files, must be writable by PHP
$cacheDir = "cache/";
// cache filename constructed from MD5 hash of URL
$filename = $cacheDir.md5($url);
// append size to filename if not 0
if ($size) $filename .= "_".$size;
// default to fetch the file
$fetch = true;
// but if the file exists, don't fetch if it is recent enough
if (file_exists($filename))
{
$fetch = (filemtime($filename) < (time()-$age));
}
// fetch the file if required
if ($fetch)
{
if (substr($url,0,4)=="http")
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
$data = curl_exec($ch);
curl_close($ch);
if (strlen($data))
{
$fp = fopen($filename,"w");
fwrite($fp,$data);
fclose($fp);
$error = false;
}
else
{
$error = true;
}
}
else
{
copy($url,$filename);
$error = false;
}
}
// return the filename only if wget did not fail
if (!$error)
{
if ($size)
{
$src = file_get_contents($filename);
$oldImage = imagecreatefromstring($src);
$oldX = imagesx($oldImage);
$oldY = imagesy($oldImage);
if ($oldX && $oldY)
{
$newX = $size;
$xFactor = ($newX / $oldX);
$newY = intval($oldY * $xFactor);
$newImage = imagecreatetruecolor($newX,$newY);
imagecopyresized($newImage, $oldImage, 0,0,0,0, $newX, $newY, $oldX, $oldY);
imagejpeg($newImage,$filename);
}
}
return $filename;
}
else
{
// as an error occured, delete the empty file so it is retried next time
unlink($filename);
// return false
return false;
}
}
require("includes/common.php");
$id = $_GET["id"];
$size = $_GET["size"];
$sql = "SELECT image_url FROM `".$config_databaseTablePrefix."products` WHERE id='".database_safe($id)."'";
if (database_querySelect($sql,$rows))
{
$src = $rows[0]["image_url"];
$src = cacheFetch($src,$size,604800);
$img = file_get_contents($src);
header("Content-Type: image");
print $img;
}
?>
and here is the .htaccess bit with sizes:
RewriteRule ^fullimage/(.*).jpg$ imageCache.php?id=$1&size=0 [L]
RewriteRule ^smallimage/(.*).jpg$ imageCache.php?id=$1&size=150 [L]
RewriteRule ^mediumimage/(.*).jpg$ imageCache.php?id=$1&size=300 [L]
EDIT: Re-worked code:
if ($size)
{
$src = file_get_contents($filename);
$oldImage = imagecreatefromstring($src);
$oldX = imagesx($oldImage);
$oldY = imagesy($oldImage);
if ($oldX && $oldY)
{
$color = imagecolorallocate($newImage, 255,255,255); //The three parameters are R,G,B
imagefilledrectangle ($newImage, 0, 0, $newX, $newY,$color);
$size = max($newX,$newY);
$newImage = imagecreatetruecolor($newX,$newY);
imagecopyresized($newImage, $oldImage, ($size-$newX)/2,($size-$newY)/2,0,0, $newX, $newY, $oldX, $oldY); //Just the coordinates was changed
imagejpeg($newImage,$filename);
Sorry, I will not add my sugestions to your code, because its is too complicated. SO just the hints.
1. How to make resised image square?
Obviously, we must create square of size of bigger dimension of original image. Here I assume the image has already been resized.
$resized = /*We hae resized image downloaded from the site [note1]*/;
$size = max(imagesx($resized), imagesy($resized)); //Make the square so the thumbnail fits in it
$thumbNail = imagecreate($size, $size); //Square.
imagecopy($thumbNail,
($size-imagesx($resized))/2, //Put the image in the middle of the square
($size-imagesy($resized))/2,
0,
0,
imagesx($resized),
imagesy($resized)
);
[note1] Alternativelly, you can just compute dimensions to make $size and copyresize image on the square. This will be faster, but is more complicated to make pseudocode for it.
2. How to change background of new images
This is no real mystery - you just draw rectangle over whole image:
$color = imagecolorallocate($thumbNail, 255,255,255);
imagefilledrectangle ($thumbNail, 0, 0, imagesx($thumbNail), imagesy($thumbNail),$color);
You can even have a transparent background:
$color = imagecolorallocatealpha($thumbNail, 255,255,255,127);
imagealphablending($thumbNail, false); //[note2]
imagefilledrectangle ($thumbNail, 0, 0, imagesx($thumbNail), imagesy($thumbNail),$color);
imagealphablending($thumbNail, true); //If you use it
[note2] Turn off blending, because transparent+black = black again
3. Code related to answer
First the resizing, copying. In the original code, we have the computed new height and width in $newX and $newY. I will use theese as of the new image sizes.
$size = max($newX,$newY);
$newImage = imagecreatetruecolor($size, $size);
imagecopyresized($newImage, $oldImage, ($size-$newX)/2,($size-$newY)/2,0,0, $newX, $newY, $oldX, $oldY); //Just the coordinates was changed
Then he background. Obviously, you should firs set the background, then copy the image. However, I'm separating theese steps so you can see what function does what.
$newImage = imagecreatetruecolor($newX,$newY);
$color = imagecolorallocate($newImage, 255,255,255); //The three parameters are R,G,B
imagefilledrectangle ($newImage, 0, 0, $newX, $newY,$color);

Fabric.js canvas.toDataURL() sent to PHP by Ajax

I have a problem here when I need create a image with transparent background. I still don´t know if the problem is with fabricjs or with php. Everything works fine when I sent a image with colored background. The problem occurs when I send a image with transparent background.
The generated image is created with black background.
So, let me explain better:
When the user click in save button, I´m sending the string representation of the canvas to php in the server-side, to be generated the image of the canvas. So I´m using the follow function to sending the string representation of the canvas by Ajax (POST function of jQuery):
function sendStringRepresentation(){
var strDataURI = canvas.toDataURL();
strDataURI = strDataURI.substr(22, strDataURI.length);
$.post("action/createImage.php",
{
str: strDataURI
},
function(data){
if(data == "OK"){
$("#msg").html("Image created.");
}
else{
$("#msg").html("Image not created.");
}
});
}
In PHP file I´m using the follow code to generate the image:
// createImage.php
$data = base64_decode($_POST["str"]);
$urlUploadImages = "../uploads/img/";
$nameImage = "test.png";
$img = imagecreatefromstring($data);
if($img) {
imagepng($img, $urlUploadImages.$nameImage, 0);
imagedestroy($img);
// [database code]
echo "OK";
}
else {
echo 'ERROR';
}
Again, the problem is just with background transparent canvas. With colored background everything works fine.
The last step is quite the opposite:
imagecopyresampled( $img, $alpha_image, 0, 0, 0, 0, $w, $h, $w, $h );
And voila! The image is transparent!
Why did you use GD for this? You can use file_put_contents for save png file from your canvas.
// createImage.php
$data = base64_decode($_POST["str"]);
$urlUploadImages = "../uploads/img/test.png";
file_put_contents($urlUploadImages, $data);
I don't know if this is exactly the problem you're experiencing, but some of the GD library's imagecreate* functions create images without the alpha channel.
The workaround I've found is to create an image using imagecreatetruecolor and copy your transparent image onto it.
Try a process like this:
$img = imagecreatefromstring($data);
$w = imagesx($img);
$h = imagesy($img);
$alpha_image = imagecreatetruecolor( $w, $h );
imagecopyresampled( $alpha_image, $img, 0, 0, 0, 0, $w, $h, $w, $h );
That should ensure that you end up with a "true color" image with the proper alpha channel.
JPG toDataURL transforms transparent background to black.
I had the exact same problem and added this
imageAlphaBlending($img, true);
imageSaveAlpha($img, true);
to rodrigopandini's code and it works perfect now.:)
// createImage.php
$data = base64_decode($_POST["str"]);
$urlUploadImages = "../uploads/img/";
$nameImage = "test.png";
$img = imagecreatefromstring($data);
imageAlphaBlending($img, true);
imageSaveAlpha($img, true);
if($img) {
imagepng($img, $urlUploadImages.$nameImage, 0);
imagedestroy($img);
// [database code]
echo "OK";
}
else {
echo 'ERROR';
}

Categories