I am trying to integrate two small Imagick codes into one. The first code splits a sentence into words, then them into images. The second code appends these images, making a whole image-based sentence. In the first code, I save individual word-based-images in a directory, which is then fetched by the second code using PHP's globe function. Now, I do not want to write images in the directory, instead I supply them to the second code in run-time and append. I need an idea how to do that. I am thinking about Clone() function, building an image index, but I am not sure about that and I need your feedback.
// First Code
$text = "Some sample senetnces";
$words = explode(' ', $text);
$imageout = new \Imagick();
foreach ($words as $no => $word)
{
$draw = new \ImagickDraw();
# $draw->setStrokeColor($strokeColor);
$draw->setFillColor('black');
# $draw->setStrokeWidth(2);
$draw->setFontSize(36);
$draw->setFont(DOCROOT . "/Congenial-Bold.ttf");
$draw->annotation(50, 50, $word);
$imagick = new \Imagick();
$imagick->newImage(500, 300, 'DeepSkyBlue');
$imagick->setImageFormat("png");
$imagick->drawImage($draw);
$imagick->trimImage(0);
$imagick->setImageBackgroundColor('DeepSkyBlue');
$imagick->spliceImage(10, 0, $imagick->getImageWidth(), $imagick->getImageHeight());
$imagick->writeImage(DOCROOT . '/tem634/fonts-' . $no . '.png');
# $images[] = $imagick->Clone();
}
// Second Code
$images = glob( DOCROOT . "/tem634/*.png");
$canvas = new Imagick();
foreach ($images as $image) {
$im = new Imagick($image);
$canvas->addImage($im);
}
// append the images into one
$canvas->resetIterator();
$combined = $canvas->appendImages(false);
$combined->setImageformat("png");
$combined->writeImage(DOCROOT . '/append.png');
Related
I am using MPDF library to generate pdf files .I have created two PDF files in my root directory as follows :
$invoice_nos = ['0'=>'ISE-00000014Y18','1'=>'ISE-00000005Y18'];
foreach ($invoice_nos as $key => $invoice_no) {
$html = 'Invoice No - '.$invoice_no;
$pdf_file_name = $invoice_no.'.pdf';
$pdf_file_path = ROOT . '/app/webroot/Service_Invoices/'. DS .$pdf_file_name ;
ob_start();
$mpdf = new \mPDF('utf-8', 'A4' ,'','',5,5,36,10,5,4);
$mpdf->WriteHTML($html,2);
ob_clean();
$mpdf->Output($pdf_file_name,'f');
}
Now I want to merge these two files into a single file with different pages. How can I do this? I have searched many examples of it but nothing is working.
mPDF is not the best tool to merge PDF files. You'll be better off with GhostScript:
gs -dBATCH -dSAFER -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile=combined.pdf invoice1.pdf invoice2.pdf
Alternatively, generate both invoices directly to one file:
$invoice_nos = ['0' => 'ISE-00000014Y18', '1' => 'ISE-00000005Y18'];
$mpdf = new \mPDF('utf-8', 'A4', '', '', 5, 5, 36, 10, 5, 4);
foreach ($invoice_nos as $key => $invoice_no) {
$html = 'Invoice No - ' . $invoice_no;
$mpdf->WriteHTML($html, 2);
$mpdf->WriteHTML('<pagebreak>');
}
$pdf_file_name = $invoice_no . 'invoices.pdf';
$mpdf->Output($pdf_file_name, 'f');
Hi There so i actually used this code to Flatten a PDF that had editable forms but i believe we can change it to merge the pdf's together.
This solution uses php's Imagick() which should be part of your hosting environment.
So here is the code, i have tried to comment it as best possible. you will call the mergePdf() and put the destination folder (where your files are and where you will save the new file) and an array of the files (Just there names) to be merged, and then a new file name. once done it will save the new file in the destination folder.
/**
* mergePdf()
*
* #param mixed $destinationPath
* #param array $files
* #param mixed $newFileName
* #return
*/
public function mergePdf($destinationPath, $files, $newFileName){
//Create array to hold images
$array_images = array();
//Loop through to be merged
foreach($files as $file){
//Firstly we check to see if the file is a PDF
if(mime_content_type($destinationPath.$file)=='application/pdf'){
// Strip document extension
$file_name = pathinfo($file, PATHINFO_FILENAME);
// Convert this document
// Each page to single image
$im = new imagick();
//Keep good resolution
$im->setResolution(175, 175);
$im->readImage($destinationPath.$file);
$im->setImageFormat('png');
$im->writeImages($destinationPath.$file_name.'.png',false);
//loop through pages and add them to array
for($i = 0; $i < $im->getNumberImages(); $i++){
//insert images into array
array_push($array_images, $destinationPath.$file_name.'-'.$i.'.png');
}
//Clear im object
$im->clear();
$im->destroy();
}else{
return false;
}
}
//Now that the array of images is created we will create the PDF
if(!empty($array_images)){
//Create new PDF document
$pdf = new Imagick($array_images);
$pdf->setImageFormat('pdf');
if($pdf->writeImages($destinationPath.$newFileName, true)){
$pdf->clear();
$pdf->destroy();
//delete images
foreach($array_images as $image){
unlink($image);
}
return true;
}else{
return false;
}
}else{
return false;
}
}
public function getMergePdf(){
$destinationPath = "/your/destination/to/the/file/goes/here/";
//put the files in the order you want them to be merged
$files = array('file1.pdf','file2.pdf','file3.pdf');
$this->mergePdf($destinationPath, $files, "NewPdf.pdf");
}
i am using php imagick to create a image and than convert to pdf. using php imagick. i coded this:
$image = new Imagick();
$height = 800; //height of the page;
$image->newImage(794, $height, "#f5f5f5");
$image->setImageFormat("jpg");
$card = new Imagick('card.jpg'); ; //get single card
$l_align = 190; //left alignment
for($i=0; $i < 4; $i++) //for creating multiple cards on a page
{
$image->compositeImage($card, Imagick::COMPOSITE_DEFAULT,10, ($l_align*$i)+10);
$image->compositeImage($card, Imagick::COMPOSITE_DEFAULT, 390, ($l_align*$i)+10);
}
$image->setResolution(72, 72);
$image->resetIterator();
$combined = $image->appendImages(true);
$image->setImageFormat("pdf");
$combined->writeImages( 'card.pdf', true );
header("Content-Type: application/pdf");
header('Content-Disposition: attachment; filename="card.pdf"');
echo file_get_contents('card.pdf');
and get something like this
in pdf format . Now i want to page break after every 6 cards print in pdf . i am using imagick . please help me. thanks in advance.
You are using the wrong function for adding images as new pages. You should be using addImage which adds the new image as a separate page, rather than append which just tacks them onto the bottom of the current image.
An example of this working is:
$combined = null;
$images = [
'../../../images/Source1.jpg',
'../../../images/Source2.png',
];
foreach ($images as $image) {
if ($combined == null) {
$combined = new Imagick(realpath($image));
}
else {
$card = new Imagick(realpath($image)); ; //get single card
$combined->addImage($card);
}
}
$combined->setImageFormat("pdf");
$combined->writeImages( './card.pdf', true );
btw there is weird stuff going on in your code example - you're only even attempting to add one image, and what is 'resetIterator' doing in there?
I'm trying to get the dimensions of images that i converted with imagick. This is my code:
$imagick = new \Imagick();
$imagick->setresolution(300,300);
$imagick->readimage($this->uploadPath . '/original/test.pdf');
$imagick->writeImages($this->uploadPath . "/large/preview-%d.jpg", false);
So i'm reading a multipage pdf file and i'm converting it to seperate jpg files.
What i want is to retrieve the jpg file dimensions from each image. Can i do this in an easy way? Or do i first need to write the images to the disc and then loop through each of them again?
What about Imagick::getImageGeometry? (http://www.php.net/manual/en/imagick.getimagegeometry.php)
In your case it should look something like this:
$imagick = new \Imagick();
$imagick->setresolution(300,300);
$imagick->readimage($this->uploadPath . '/original/test.pdf');
$geometryInfo = $imagick->getImageGeometry();
// now $geometryInfo is an associative array with 'width' and 'height' items in it
$imagick->writeImages($this->uploadPath . "/large/preview-%d.jpg", false);
Update:
If you want to read concrete page from multipage PDF, try to use such trick:
$pageIndex = 0; // you can create "for/foreach" loop to go through all pages
$imagick->readimage($this->uploadPath . '/original/test.pdf[' . $pageIndex . ']');
I currently have this snippet which spits out a random image
$imgDir = 'images/';
$images = glob($imagesDir . '*.{jpg}', GLOB_BRACE);
$randimg = $images[array_rand($images)];
but I want the image to be a certain width (600px), rather then warping images by using CSS is there a way the image width can be checked using PHP incorporating the code snippet above?
Yes, you can go through each individual file and check its size with getimagesize.
That's of course a very expensive operation to do every time. Instead, do this once and make the size part of the filename (e.g. foobar_500.jpg) and glob for that, or use a database to organize your images to begin with where you can save such metadata and query for it.
This will make sure you only select a random images from the images that have width 600
$imgDir = 'images/';
$images = glob($imgDir . '*.{jpg}', GLOB_BRACE);
$arr_images_600 = array();
foreach ($images as $img)
{
list($width, $height, $type, $attr) = getimagesize($img);
if ($width == 600) { $arr_images_600[] = $img; }
}
$randimg = $images[array_rand($arr_images_600)];
I am trying to convert a multipage PDF File to images by using PHP Image magic extension.The problem is that instead of getting images corresponding to each page of the file, I am getting the last page of pdf as the output image. Here is the code:
$handle = fopen($imagePath, "w");
$img1 = new Imagick();
$img1->setResolution(300,300);
$img1->readImage(path to pdf file);
$img1->setColorspace(imagick::IMGTYPE_GRAYSCALE);
$img1->setCompression(Imagick::COMPRESSION_JPEG);
$img1->setCompressionQuality(80);
$img1->setImageFormat("jpg");
$img1->writeImageFile($handle);
What am I doing wrong?The convert command on commandline with the same parameters works.
Try something like this instead:
$images = new Imagick("test.pdf");
foreach($images as $i=>$image) {
$image->setResolution(300,300);
//etc
$image->writeImage("page".$i.".jpg");
}
Try writeImages function. It creates each page as one image and it gives file names for multiple images like this: yourimagename, yourimagename-1, yourimagename-2.... It increases automatically from 0 to your numberofpagesinPdf-1.
The code looks like this:
$imagick = new Imagick($file_handle);
$imagick->readImage();
$imagick->writeImages($yourImagename.'.jpg', false);
This will work for pdf having multiple pages as well as the single page.
$pdf_file = 'path/to/pdf/file.php';
$image = new imagick();
$image->setResolution(300,300);
$image->readImage($pdf);
$image->setImageFormat('jpg');
// Set all other properties
$pages = $image->getNumberImages();
if ($pages) {
foreach($image as $index => $pdf_image) {
$pdf_image->writeImage('destination/path/' . $index . '-image_file.jpg');
}
} else {
echo 'PDF doesn\'t have any pages';
}
Try something like this if you know number of pages of your pdf:
$images = new Imagick();
foreach ($pages as $p){
$im->readImage($PdfFile."[".$p."]"); //yourfile.pdf[0], yourfile.pdf[1], ...
$im->setCompression(Imagick::COMPRESSION_JPEG);
$im->setCompressionQuality(82);
$im->setImageFormat( "jpg" );
//...
$image_out = "image_".$p.".jpg";
$im->writeImage($image_out);
}
$im->clear();
$im->destroy();
If you dont know number of pages, you could do something like this:
$images = new Imagick();
$im->readImage($PdfFile);
$pages = (int)$im->getNumberImages();
this worked for me
$file = "./path/to/file/name.pdf";
$fileOpened = #fopen($archivo, 'rb');
$images = new Imagick();
$images->readImageFile($fileOpened);
foreach ($images as $i => $image) {
$image->setResolution(300, 300);
$image->setImageFormat("jpg");
$image->setImageCompression(imagick::COMPRESSION_JPEG);
$image->setImageCompressionQuality(90);
$image->setImageUnits(imagick::RESOLUTION_PIXELSPERINCH);
$data_blob = $image->getImageBlob();
$ouput="./path/images/files/page" . $i . ".jpg";
file_put_contents($ouput, $data_blob);
}
#fclose($fileOpened);
I hope I can help you too