I use the following code to convert PDF to PNG. As you can see, I use code setImageAlphaChannel(Imagick::ALPHACHANNEL_REMOVE ) to remove the background transparency. But in practice it only works for the last page. Do you think there is a problem with the code? Do you have a better solution with a higher speed?
$PDF = 'test.pdf';
$img = new imagick();
$img->readImage($PDF.'[0-9]'); //Convert 10 pages
$img->setImageAlphaChannel(Imagick::ALPHACHANNEL_REMOVE );
$pages = count($img);
$img->writeImages('./images/'.'pdf.png', true);
This looks like an iterator issue. You can try looping with something like this:
<?php
$PDF = 'test.pdf';
$img = new Imagick();
$img->readImage($PDF. '[0-9]'); //Convert 10 pages
$lastIndex = $img->getIteratorIndex();
$img->resetIterator();
for($i = $img->getIteratorIndex(); $i <= $lastIndex; $i++) {
$img->setIteratorIndex($i);
$img->setImageAlphaChannel(Imagick::ALPHACHANNEL_REMOVE);
}
$pages = count($img); // not sure why you need this
$img->writeImages('./images/'.'pdf.png', true);
You could also get the iterating part down to a simple loop, if you like it more, since the Imagick class implements Iterator:
foreach($img as $i)
{
$img->setImageAlphaChannel(Imagick::ALPHACHANNEL_REMOVE);
}
Related
I've written the following code for merging PDFs using this answer
function merge_pdfs() {
$pdfs_array = array('1.pdf', '2.pdf');
$pdf = new FPDI_Protection();
for ($i = 0; $i < count($pdfs_array); $i++ ) {
$pagecount = $pdf->setSourceFile($pdfs_array[$i]);
for($j = 0; $j < $pagecount ; $j++) {
$tplidx = $pdf->importPage(($j +1), '/MediaBox');
$pdf->addPage('P','A4');
$pdf->useTemplate($tplidx, 0, 0, 0, 0, TRUE);
}
}
$dt = new DateTime(NULL, new DateTimeZone($data->user->timezone));
$pdf->SetTitle('PDF, created: '.$dt->format(MYHMRS_DATETIME_FRIENDLY));
$pdf->SetSubject('PDF subject !');
$output = $pdf->Output('', 'S');
$name = "PDF".'-'.$dt->format('ymd').'.pdf';
$this->output
->set_header("Content-Disposition: filename=$name;")
->set_content_type('Application/pdf')
->set_output($output);
}
So, after this I'm getting the following error message
This document (1.pdf) probably uses a compression technique which is not supported by the free parser shipped with FPDI. (See https://www.setasign.com/fpdi-pdf-parser for more details)
I've checked the link and it suggests to set another PDF Parser ( If I understand right )
But I'm not sure how to make it working with Codeigniter and my example
Should I create library and try to use it?
Or maybe you know another solution for merging PDFs
The issue was related to PDF versions
Edit
If you don't know, the PDFs has versions. Yeah, I was surprised as well. Please check them here PDF versions
So, the problem was that I was trying to merge PDF 1.5 version with PDF 1.6
An example. It is simple.
<?php
require_once __DIR__ . '/vendor/autoload.php';
$mpdf = new \Mpdf\Mpdf();
$mpdf->WriteHTML('<h1>Hello world!</h1>');
$mpdf->AddPage('P');
$mpdf->WriteHTML('<h1>More</h1>');
$mpdf->Output();
?>
I'm trying to do the same that this jQuery function in PHP (FB Open Graph doesn't execute JS Code, so it has to be executed server side) :
<script>captureurl=jQuery('.blog-content').find('img').attr('src');
jQuery('head').append("<meta property='og:image' content="+captureurl+"/></meta>");</script>
I've seen I could get an image attribute like that :
<?php doc = new DOMDocument();
$doc->loadHTMLFile($url);
$xpath = new DOMXpath($doc);
$imgs = $xpath->query("//img");
for ($i=0; $i < $imgs->length; $i++) {
$img = $imgs->item($i);
$src = $img->getAttribute("src");
// do something with $src
} ?>
But how can I target the first image src in the div with .blog-content class?
Thanks for your help :)
Replace $xpath->query("//img") with following:
$imgs = $xpath->query('//img[contains(attribute::class, "blog-content")]'); //here we are querying domdocument to find img which has class .blog-content
For some reason exif_read_data() returns false on every image in the directory even though I know that all my jpeg images have metadata properties.
I am by no means a PHP wizard yet so perhaps I have a syntax error or I'm just missing something fairly obvious to those of you who are PHP wizards.
galleryData.metadata = <?php
$dir_path = "Assets/Images/portfolio/";
if (is_dir($dir_path)) {
$files = scandir($dir_path);
for ($i = 0; $i < count($files); $i++) {
$tempPath = $dir_path + $files[$i];
$metadata[$i] = exif_read_data($tempPath);
}
echo json_encode($metadata);
}
?>;
Thankfully figured it out I wasn't combining my strings properly. Below is my fixed and working code.
galleryData.metadata = <?php
$metadata = array();
if (is_dir($dir_path)) {
for ($i = 0; $i < count($files); $i++) {
$metadata[$i] = exif_read_data("{$dir_path}{$files[$i]}", null, true);
}
echo json_encode($metadata);
}
?>;
might be a solution, but need to have more info real error (error message ?)
exif_read_data() can be buggy prom php version to version:
Bug #75785 Many errors from exif_read_data
The solution might be to use
$img = new \Imagick(DSC01386.jpg);
$allProp = $img->getImageProperties();
$exifProp = $img->getImageProperties("exif:*");
The Imagick class, is quite powerful class (rotations etc).
The full story for that solution here
I am using Intervention Image image manipulation library this library in a project and I am stuck on adding watermark image all over the source image.
Is it possible to repeat the watermark image on all over the source image like in the following example?
I try the following code, but it doesn't work for me.
$thumbnail = $manager->make($name);
$watermark = $manager->make($watermarkSource);
$x = 0;
while ($x < $thumbnail->width()) {
$y = 0;
while($y < $thumbnail->height()) {
$thumbnail->insert($watermarkSource, 'top-left', $x, $y);
$y += $watermark->height();
}
$x += $watermark->width();
}
$thumbnail->save($name, 80);
I've just solved this problem via Intervention Image library using it in Laravel Framework. So here's code snippet.
public function watermarkPhoto(String $originalFilePath,String $filePath2Save ){
$watermark_path='photos/watermark.png';
if(\File::exists($watermark_path)){
$watermarkImg=Image::make($watermark_path);
$img=Image::make($originalFilePath);
$wmarkWidth=$watermarkImg->width();
$wmarkHeight=$watermarkImg->height();
$imgWidth=$img->width();
$imgHeight=$img->height();
$x=0;
$y=0;
while($y<=$imgHeight){
$img->insert($watermark_path,'top-left',$x,$y);
$x+=$wmarkWidth;
if($x>=$imgWidth){
$x=0;
$y+=$wmarkHeight;
}
}
$img->save($filePath2Save);
$watermarkImg->destroy();
$img->destroy(); // to free memory in case you have a lot of images to be processed
}
return $filePath2Save;
}
If you use PHP version prior to 7 remove String type declaration from function arguments. just make it
public function watermarkPhoto($originalFilePath, $filePath2Save ){....}
Also if you are not using Laravel Framework and you don't have File class included just remove redundand check from function.
if(\File::exists($watermark_path))
So the simplest framework-agnostic function would be:
function watermarkPhoto($originalFilePath, $filePath2Save ){
$watermark_path='photos/watermark.png';
$watermarkImg=Image::make($watermark_path);
$img=Image::make($originalFilePath);
$wmarkWidth=$watermarkImg->width();
$wmarkHeight=$watermarkImg->height();
$imgWidth=$img->width();
$imgHeight=$img->height();
$x=0;
$y=0;
while($y<=$imgHeight){
$img->insert($watermark_path,'top-left',$x,$y);
$x+=$wmarkWidth;
if($x>=$imgWidth){
$x=0;
$y+=$wmarkHeight;
}
}
$img->save($filePath2Save);
$watermarkImg->destroy();
$img->destroy();
return $filePath2Save;
}
Also you need watermark image in png format with transparent background.
I'm just adding one thing added to your accepted answer when you try your code and the above-accepted code, the watermark on the images will be very close together and close together with what I tried. like this
So if you want the watermarks like what you want, you need to modify the code with plus numbers on wmarkheight and wmarkwidth like this:
while ($x < $imgWidth) {
$y = 0;
while($y < $imgHeight) {
$imgFileCollection->insert($watermark, 'top-left', $x, $y);
$y += $wmarkHeight+30;
}
$x += $wmarkWidth+40;
}
this line of code is important:
$y += $wmarkHeight+30;
$x += $wmarkWidth+40;
and you will get the result like that below:
I'm converting a table of my DB to PDF and I'm using the TCPDF.
First I have to convert my table to HTML and then I can convert to PDF, which use a lot of memory and I have a few resources on the server (256M for PHP max).
How can I pass a table that may have thousands of records to PDF with 256M memory max in PHP?
Can I create a PDF page by page and in the end concatenate all pages?
I have found a way to concatenate the pdf page from this link.
require_once("tcpdf/tcpdf.php"); //ur workspaces
require_once("fpdi/fpdi.php");
class concat_pdf extends FPDI {
var $files = array();
function setFiles($files) {
$this->files = $files;
}
function concat() {
foreach($this->files AS $file) {
$pagecount = $this->setSourceFile($file);
for ($i = 1; $i <= $pagecount; $i++) {
$tplidx = $this->ImportPage($i);
$s = $this->getTemplatesize($tplidx);
$this->AddPage(’P', array($s['w'], $s['h']));
$this->useTemplate($tplidx);
}
}
}
}
Did you try fpdf (http://www.fdpf.org) or the related mpdf (http://www.mpdf1.com) as an alternative? Maybe they use less resources so they can run on your server. They do a good job in creating HTML to PDF output.