I have a PHP application which generates PDF files that may contain images. When generating the PDF file I can't open it because it is corrupted or not PDF format. If I omit the image everything works fine. Long ago this thing worked nicely I don't remember if I changed anything about the handling of images. I use small images so not the imagesize is what causes the problem. Here is my code:
if($cell['type'] == "custom_image"){ // Uploaded image
$imgxploded = explode('.', $cell['img']);
$imgext = end($imgxploded);
$imgfile = $root_directory.'uploads/'.$cell['img'];
$this->Image($imgfile, $blockInternalX, $blockInternalY, $cell['width'], $cell['height'], strtoupper($imgext));
}
Any ideas about what goes wrong?
edit: I use FPDF class to manage/produce PDF files
Related
I'm working with the PHP ImageMagick Library to convert uploaded pdf files to single png files so I can display the pdf as a single image on my Laravel webpage. So far I'm able to convert an entire pdf to a single image with this code:
<?php
$imagick = new Imagick();
$file = new File;
// other lines of code
// ...
$imgPath = Storage::path($file->file_path);
$imgSavePath = Storage::path('uploads/buffer/'.Str::beforeLast($file->name, '.').'.png');
$imagick->readImage($imgPath);
$imagick->resetIterator();
$imagick = $imagick->appendImages(true);
$imagick->writeImages($imgSavePath, true);
This works by producing a single png image. However, I find this to be resource intensive (storage wise) and time consuming because I'm delivering the functionality through an ajax call.
I want my web application to convert only the first n pages of the pdf (say first 5 pages) into a single image to act as a preview on the site - thereafter the user can download the entire pdf to view on their local system. The function should work regardless of the number of pages in an uploaded pdf document.
So far, I only find in the documentation where I can read a page at a particular index from the Imagick object and convert to an image using:
...
$imgPath = Storage::path($file->file_path);
$index = 5;
$imagick->readImage($imgPath. '[' . $index . ']');
However, I'm finding it difficult to refactor this so that the application can read the first n pages.
Intuitively, the readImage() function seems to work in a similar way as the command line syntax. Thanks to the hint from #MarkSetchell in the comments:
<?php
$imagick = new Imagick();
$file = new File;
// other lines of code
// ...
$imgPath = Storage::path($file->file_path);
$imgSavePath = Storage::path('uploads/buffer/'.Str::beforeLast($file->name, '.').'.png');
$imagick->readImage($imgPath.'[0-4]'); // read only the first 5 pages
$imagick->resetIterator();
$imagick = $imagick->appendImages(true);
$imagick->writeImages($imgSavePath, true);
I'm using ImageMagick 6.9.10-68 and PHP 8.1.12
I am trying to convert a multi-page pdf into a single image with all pages in the pdf stacked. I am trying to use the Imagick() class. I found similar questions but none have helped the issue. Here is the code I am using.
$img = new Imagick();
$img->setResolution(300, 300);
$img->readImage(example.pdf);
$img->resetIterator();
$imga = $img->appendImages(true);
$imga->setImageFormat('jpg');
$imga->writeImage("pdfs.jpg");
Only the last page of the pdf is saved in the jpg file the other pages are not.
I am using ImageMagick-7.0.10, PHP 7.3.12 and I am on Windows 10.
You,have to add the index of the pdf page you want.
For the first page :
$img->readImage(example.pdf[0]);
I'm looking to generate animated gif with multipage pdf... not done yet !
I have a PHP script which generates images from PDF pages using PHP Imagick. In which i write a piece of data on top of the image using annotateImage function and take it as output. This is failing recently on some PDF images being selected. I mean when a specific PDF is being given as input to this program the annotateImage function fails to write data where on many other PDF files it is performing well...
this is the following code which run on a loop to generate this images...
$imagick->setResolution(200,200);
$imagick->readImage('files/pdffile.pdf[1]');
$imagick->annotateImage($draw_small, 1250, 100, 10, 'Hello header');
$imagick = $imagick->flattenImages();
$file = fopen("/outputfile.jpg", 'w+');
chmod($folder_in_action."/outputfile.jpg", 0755);
fclose($file);
$imagick->writeImage('/outputfile.jpg');
$imagick->clear();
The code works well and get the exact PDF page as image in the folder but the annotateImage does not works on specific PDF files and so the output comes with no 'Hello header' message.
The same code works perfect on most of the PDF's where i get the specific PDF page with 'Hello header' message written on top as image...
So could not able to guess what could be the issue...
PDF file which does not allow annotateImage to write text is here:
http://wikisend.com/download/143652/notworking.pdf
PDF which is working (usually most of the pdf files are working properly...)
http://wikisend.com/download/215044/working.pdf
So I have an XML file that has a base64 encoded data string for a pdf file, which just has an image taken from an iPad.
This pdf file can be excessively large, as much as 14MB with dimensions of 57"x38".
These images are taken from an iPad through a DocuSign session, thus I have no way at the moment of controlling their size or format before they get to my php listener script.
However, my script cannot work with such large files as my CRM's API file size max is 10MB, and I need a way of reducing the file size before I can upload it through my CRM's API.
Now if it was just a jpg, it would be ok as there are plenty of ways to reduce file size in PHP, but it is a PDF. I have found plenty of PHP extensions for making PDFs, but I haven't found any for reading a PDF and extracting an image from it.
So is there a way to extract the image from the PDF through PHP, or perhaps compress the pdf file?
UPDATE
I didn't think about the possibility of converting a pdf into a jpg, which apparently is easier to do with imagick. Having my server admin install it and I will see if I can make it work with my script.
UPDATE 2
So I was able to get imagick working and locally I am able to convert pdf files into jpg, and reduce file size dramatically.
However, I am running into an issue using it with my application. I get the following error from my CRM's API:
Failed to parse XML-RPC request: Invalid byte 1 of 1-byte UTF-8 sequence.
So the process is the following:
XML file has a base64 encoded data stream of the pdf file.
I decode this data
I then convert with imagick and reduce file size
I base64 encode and prep for upload
CODE
$imageBlob = base64_decode((string)$pdf->PDFBytes);
$imagick.$x = new Imagick();
$imagick.$x->readImageBlob($imageBlob);
$imagick.$x->setImageFormat('jpeg');
$imagick.$x->setImageCompressionQuality(60);
$imagick.$x->adaptiveResizeImage(1024,768,true);
$imageBlob = $imagick.$x->getImageBlob();
$PDFdata[] = base64_encode($imageBlob);
I can test the date by using the proper header and I can see the new jpeg fine, so I assume the data is properly formatted.
What I am missing?
Ok, so I figured it out.
Imagick was the way to go, and my use of it was good. I just goofed up on the file name because I wasn't using a proper dynamic variable name. Code should have looked like this:
CODE
$imageBlob = base64_decode((string)$pdf->PDFBytes);
${'imagick'.$x} = new Imagick();
${'imagick'.$x}->readImageBlob($imageBlob);
${'imagick'.$x}->setImageFormat('jpeg');
${'imagick'.$x}->setImageCompressionQuality(60);
${'imagick'.$x}->adaptiveResizeImage(1024,768,true);
$imageBlob = ${'imagick'.$x}->getImageBlob();
$PDFdata[] = base64_encode($imageBlob);
$PDFfile[] = $FormCustomField . $x . '.jpg';
So the error I was getting was because of an invalid file name, because the $x variable in the previous code was getting junk values. Now everything works fine.
I am using plupload to upload file in my php based website, with large file uploading the file becomes a file named 'blob' without any suffix. I know this is a binary file that contains the raw data, question is how to retrieve the data and save it back as an image file, say .png/.jpg or etc? I tried:
$imageString = file_get_contents($blogPath);
$image = imagecreatefromstring($imageString);
But it gives me some 'Data is not in recognized format...' error, any thoughts? Thanks in advance.
Your call to imagecreatefromstring() should work just fine if your file_get_contents() is working. Use var_dump($imageString) to verify. Did you mean to name your variable $blobPath instead of $blogPath?
You don't need to load this image though. Just rename the file.
rename($blobPath, 'new/path/here.jpg');
http://php.net/manual/en/function.rename.php
I am storing the uploaded image files for late use, like attaching them to posts or products(my site is e-commerce CMS). I figured that my image file didn't get fully uploaded to the server, the image before upload is 6mb, but the blob file is just 192kb, so my best guess is that what get uploaded is just a chunk instead of the whole package, and yet that brought up another question: how should I take all the pieces and assemble them as one complete image file? As mentioned earlier, I am using plupload for js plugin and php as backend, the backend php code to handle uploading goes like this:
move_uploaded_file($_FILES["file"]["tmp_name"], $uploadFolder . $_FILES["file"]["name"]);
Instead of doing that you should do this to display image to the browser
<img src="data:image/jpeg;base64,'.base64_encode( $row['blob_image'] ).'"/>
I'm not sure what imagecreatefromsting does or how it encodes the image.
I looked at the documentation for that function; you're missing:
$data = 'iVBORw0KGgoAAAANSUhEUgAAABwAAAASCAMAAAB/2U7WAAAABl'
. 'BMVEUAAAD///+l2Z/dAAAASUlEQVR4XqWQUQoAIAxC2/0vXZDr'
. 'EX4IJTRkb7lobNUStXsB0jIXIAMSsQnWlsV+wULF4Avk9fLq2r'
. '8a5HSE35Q3eO2XP1A1wQkZSgETvDtKdQAAAABJRU5ErkJggg==';
$data = base64_decode($data); <--- this operation