Merge two PDF files into single one using MPDF - php

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");
}

Related

Displaying bar Code in PDF file on every page of the PDF, in Laravel

I am Using Imagick to Convert PDF to Images
Uploading PDF to Laravel
public function uploadPdf( Request $request )
{
$model = new Attachment();
if ( $request->hasFile('pdf_file_from_request') ) {
Storage::deleteDirectory('3pagerpdf/pdf');
$pdf = $request->file('pdf_file_from_request');
$fileName = time() . '.' . $pdf->getClientOriginalName();
Storage::putFileAs('3pagerpdf/pdf', $pdf, $fileName);
$model->pdf_file_name_in_datebase = $fileName;
$model->save();
flash()->addSuccess('Pdf Added');
return back();
}
}
Converting that PDF to Images
public function convertpdftoimages()
{
$model = Attachment::first();
set_time_limit(300);
// Get the PDF file from the storage folder
$pdfPath = storage_path('app/3pagerpdf/pdf/'.$model->pdf_file_name_in_datebase);
// Create an Imagick object
$imagick = new Imagick();
// Set the resolution and output format
$imagick->setResolution(300, 300);
$imagick->setFormat('jpeg');
// Read the PDF file into the Imagick object
$imagick->readImage($pdfPath);
// Convert each page of the PDF to an image
foreach ( $imagick as $page ) {
$page->writeImage(public_path("/temp_images/page{$page->getImageIndex()}.jpg"));
}
flash()->addSuccess('Convertion Successfull');
return back();
}
Adding bar code to those images
public function add_bar_code_to_images2()
{
$files = File::files('temp_images');
foreach ( $files as $file ) {
// Generate a barcode image for the file
$barcodeGenerator = new BarcodeGeneratorPNG();
$data = '';
for ($i = 0; $i < 10; $i++) {
$data .= rand(0, 9);
}
$barcodeString = $barcodeGenerator->getBarcode($data, $barcodeGenerator::TYPE_CODE_128);
// Create an image resource from the barcode string
$barcodeImage = imagecreatefromstring($barcodeString);
// Load the original image
$originalImage = imagecreatefromjpeg($file->getPathname());
// Merge the barcode image with the original image
imagecopy($originalImage, $barcodeImage, imagesx($originalImage) - imagesx($barcodeImage) - 10, 10, 0, 0, imagesx($barcodeImage), imagesy($barcodeImage));
// Save the modified image to a new path
imagejpeg($originalImage, 'modified_images/' . $file->getFilename());
}
flash()->addSuccess('Bar Code Added Succesfuully');
return back();
}
Converting those images Back to pdf
public function convertimagestopdf( )
{
// Create a new Imagick object
$imagick = new Imagick();
// Set the resolution of the PDF
$imagick->setResolution(300, 300);
// Iterate over the images in the "modified_images" directory
foreach (glob("modified_images/*.jpg") as $image) {
// Read the image file
$imagick->readImage($image);
}
// Set the format of the PDF to "application/pdf"
$imagick->setImageFormat('pdf');
// Save the PDF to a file
$imagick->writeImages('modified_pdf/document.pdf', true);
flash()->addSuccess('pdf compileed');
return back();
}
What I want is
I want to add bar code to every single page of a pdf but I dont want to use imagick extenstion it needs to be installed on a system to make it work .
I tried the above code
it is taking too long to execute for small pdf's that code it fine but for the pdf with 60 pages and above it starts to give me time out error
Note I am not generating this pdf
the pdf will be uploaded by random user of my application and it will be already a pdf I just need to add barcode to every single page of the pdf .
I will take any alternative solution
in which i dont have to install any application on my computer
like ghostscript

2 PHP Imagick codes into one

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');

imagick , page break in pdf in php imagick

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?

Saving Each PDF Page to an Image Using Imagick

I have the following php function below that's converting a local PDF file into images. In short, I want each PDF page to be converted to a separate image.
The function converts the PDF to an image - but only the last page. I want every page of the PDF to be converted to a image and numbered. Not just the last page of the PDF.
Currently, this function converts the last page of example.pdf to example-0.jpg. Issue I'm sure lies within the for method. What am I missing?
$file_name = 'example.pdf'; // using just for this example, I pull $file_name from another function
function _create_preview_images($file_name) {
// Strip document extension
$file_name = basename($file_name, '.pdf');
// Convert this document
// Each page to single image
$img = new imagick('uploads/'.$file_name.'.pdf');
// Set background color and flatten
// Prevents black background on objects with transparency
$img->setImageBackgroundColor('white');
$img = $img->flattenImages();
// Set image resolution
// Determine num of pages
$img->setResolution(300,300);
$num_pages = $img->getNumberImages();
// Compress Image Quality
$img->setImageCompressionQuality(100);
// Convert PDF pages to images
for($i = 0;$i < $num_pages; $i++) {
// Set iterator postion
$img->setIteratorIndex($i);
// Set image format
$img->setImageFormat('jpeg');
// Write Images to temp 'upload' folder
$img->writeImage('uploads/'.$file_name.'-'.$i.'.jpg');
}
$img->destroy();
}
Seems like most of my code was correct. The issue was, I was using $img->flattenImages(); incorrectly. This merges a sequence of images into one image. Much like how Photoshop flattens all visible layers into an image when exporting a jpg.
I removed the above line and the individual files were written as expected.
/* convert pdf file to list image files */
if($_FILES['file_any']['type']=='application/pdf'){
$file_name = str_replace(substr($url,0,strpos($url,$_FILES['file_any']['name'])),'',$url);
$basename = substr($file_name,0,strpos($file_name,'.'));
$abcd = wp_upload_dir();
$delpath = $abcd['path'];
$savepath = $abcd['url'];
$dirpath = substr($savepath,(strpos($savepath,'/upl')+1));
$file_name = basename($file_name, '.pdf');
$img = new imagick($delpath.'/'.$file_name.'.pdf');
$img->setImageBackgroundColor('white');
$img->setResolution(300,300);
$num_pages = $img->getNumberImages();
$img->setImageCompressionQuality(100);
$imageurl = NULL;
$imagedelurl = NULL;
for($i = 0;$i < $num_pages; $i++) {
$imageurl[]=$savepath.'/'.$basename.'-'.$i.'.jpg';
$imagedelurl[] = $delpath.'/'.$basename.'-'.$i.'.jpg';
// Set iterator postion
$img->setIteratorIndex($i);
// Set image format
$img->setImageFormat('jpeg');
// Write Images to temp 'upload' folder
$img->writeImage($delpath.'/'.$file_name.'-'.$i.'.jpg');
}
$img->destroy();
}
There is a much easier way without the loop, just use $img->writeImages($filename,false); and it will make a file per PDF-page. As you said, if you flatten the image first, it only saves 1 page.
first install
imagemagick
in your system or server
and then create
pdfimage
folder and put pdf file in this folder then run the code and upload it file
<?php
$file_name = $_FILES['pdfupload']['name']; // using just for this example, I pull $file_name from another function
//echo strpos($file_name,'.pdf');
$basename = substr($file_name,0,strpos($file_name,'.'));
//echo $_FILES['pdfupload']['type'];
//if (isset($_POST['submit'])){
if($_FILES['pdfupload']['type']=='application/pdf'){
// Strip document extension
$file_name = basename($file_name, '.pdf');
// Convert this document
// Each page to single image
$img = new imagick('pdfimage/'.$file_name.'.pdf');
// Set background color and flatten
// Prevents black background on objects with transparency
$img->setImageBackgroundColor('white');
//$img = $img->flattenImages();
// Set image resolution
// Determine num of pages
$img->setResolution(300,300);
$num_pages = $img->getNumberImages();
// Compress Image Quality
$img->setImageCompressionQuality(100);
$images = NULL;
// Convert PDF pages to images
for($i = 0;$i < $num_pages; $i++) {
$images[]=$basename.'-'.$i.'.jpg';
// Set iterator postion
$img->setIteratorIndex($i);
// Set image format
$img->setImageFormat('jpeg');
// Write Images to temp 'upload' folder
$img->writeImage('pdfimage/'.$file_name.'-'.$i.'.jpg');
}
echo "<pre>";
print_r($images);
$img->destroy();
}
//}
?>

Converting multipage pdf to multi images

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

Categories