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();
}
//}
?>
Related
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
Here is a code what I am using to create image reducer but not getting solution
this code taking an image from my chosen path from the computer and uploading as is it, like same image size and same quality, but I want to reduce image size at the same ratio
<?php
include '../database/db.php';
include "../includes/session.php";
if(isset($_GET["d"]))
{
$output_dir=($_GET['d']);
$directory=($_GET['fp']);
$pid=($_GET['pid']);
$lid=($_GET['lid']);
$subjecta=($_GET['subject']);
}
if(isset($_FILES["myfile"]))
{
$ret = array();
$error =$_FILES["myfile"]["error"];
//You need to handle both cases
//If Any browser does not support serializing of multiple files using FormData()
if(!is_array($_FILES["myfile"]["name"])) //single file
{
$fileName = $_FILES["myfile"]["name"];
move_uploaded_file($_FILES["myfile"]["tmp_name"],$output_dir.$fileName);
$ret[]= $fileName;
$path = "$directory$fileName";
$query = "INSERT INTO table_name (lid,pid,nots,filename)VALUES('$lid','$pid','$path','$fileName')";
$suc= mysql_query($query);
}else{
$fileCount = count($_FILES["myfile"]["name"]);
for($i=0; $i < $fileCount; $i++)
{
$fileName = $_FILES["myfile"]["name"][$i];
move_uploaded_file($_FILES["myfile"]["tmp_name"][$i],$output_dir.$fileName);
$ret[]= $fileName;
$path = "$directory$fileName";
$query = "INSERT INTO table_name (lid,pid,nots,filename)VALUES('$lid','$pid','$path','$fileName')";
$suc= mysql_query($query);
}
}
echo json_encode($ret);
}
?>
we made this code for a single file and multiple files
you should process the uploaded image on your server using something like ImageMagick, you can read more here http://php.net/manual/en/book.imagick.php
you can find some examples of image manipulation here:
http://php.net/manual/en/imagick.examples-1.php
I'm having a problem when im trying to convert a PDF to images with imagick and PHP (5.5). everything works fine i can create a image for each page in the PDF but i run into the following problems. and have been stuck here for days now.
When i create a image from a PDF file some of them gets a black background even thou i have set setImageBackgroundColor to white
I have tried to set setImageCompressionQuality to get the image in better quality (right not the created image gets pixelated).
also i cannot seem to change the DPI version of the image to a 72 dpi one.
the code is as following:
$file_name = basename($file_name);
$img = new imagick();
$img->readImage($dir.'/'.$file_name);
$img->setImageBackgroundColor('white');
$img->setResolution(72,72);
$img->resampleImage(72,72,imagick::FILTER_LANCZOS,0);
$img->setImageUnits(imagick::RESOLUTION_PIXELSPERINCH);
$img->setImageCompression(imagick::COMPRESSION_JPEG);
$img->setImageCompressionQuality(100);
$img->stripImage();
$num_pages = $img->getNumberImages();
for($i = 0;$i < $num_pages; $i++) {
$img->setIteratorIndex($i);
$img->setImageBackgroundColor('white');
$img->flattenImages();
$img->setImageFormat("jpeg");
$final_name = str_replace(" ", "+", basename(str_replace(".".$file_ext,"", $file_name)));
$final_name = preg_replace("/[^a-zA-Z0-9-+]/", "", $final_name);
$save_to = $pdf_dir."/".str_replace(".".$file_ext,"", $final_name).'-'.$i.'.jpg';
$img->writeImage($save_to);
$file_image = str_replace(dirname(__FILE__)."/../../", "/", $save_to);
$file_images[] = $file_image;
}
$img->destroy();
You had some mistakes in your code.
setResolution needs to be called before loading the PDF
You need to use setBackgroundColor rather than setImageBackgroundColor.
You probably want to set the individual page compression quality, but see below.
So code:
$imagick = new Imagick();
$imagick->setResolution(72, 72);
$imagick->readImage($file_name);
$imagick->setBackgroundColor('white');
$imagick->setImageCompression(imagick::COMPRESSION_JPEG);
$imagick->setImageCompressionQuality(70);
foreach ($imagick as $c => $_page) {
$_page->setBackgroundColor('white');
$_page->setImageCompressionQuality(70);
$_page->setImageFormat('jpg');
$_page->writeImage($file."_background-$c.jpg");
}
btw, the fact that you're using JPEG at 100 quality is disturbing. If that is an image that is going to be sent to a browser, the quality should be lower than 100. If you are using it as an intermediate picture, using PNG as the intermediate format is better as it is lossless and it supports transparency.
That seemed to do the trick, changed to answer a bit as i couldnt get your foreach to work thou, wich made it work as intended:
Thank you for saving me from alot of headache.
$img = new imagick();
$img->setResolution(72, 72);
$img->readImage($dir.'/'.$file_name);
$img->setBackgroundColor('white');
$img->setImageCompression(imagick::COMPRESSION_JPEG);
$img->setImageCompressionQuality(70);
$num_pages = $img->getNumberImages();
for($i = 0;$i < $num_pages; $i++) {
$final_name = str_replace(" ", "+", basename(str_replace(".".$file_ext,"", $file_name)));
$final_name = preg_replace("/[^a-zA-Z0-9-+]/", "", $final_name);
$save_to = $pdf_dir."/".str_replace(".".$file_ext,"", $final_name).'-'.$i.'.jpg';
$img->setIteratorIndex($i);
$img->setBackgroundColor('white');
$img->setImageCompressionQuality(70);
$img->setImageFormat('jpg');
$img->writeImage($save_to);
$file_image = str_replace(dirname(__FILE__)."/../../", "/", $save_to);
$file_images[] = $file_image;
}
I have found a code that pull out a thumbnail from a video and its work!
but when I trying to make the php file to print the image with the Content-Type its return an error, when i tried to save it to the server its work fine!
the code:
<?php
function captureVideoPosterImg($movie_file = '')
{
extension_loaded('ffmpeg');
// Instantiates the class ffmpeg_movie so we can get the information you want the video
$movie = new ffmpeg_movie($movie_file);
// Get The duration of the video in seconds
echo $Duration = round($movie->getDuration(), 0);
// Get the number of frames of the video
$TotalFrames = $movie->getFrameCount();
// Get the height in pixels Video
$height = $movie->getFrameHeight();
// Get the width of the video in pixels
$width = $movie->getFrameWidth();
//Receiving the frame from the video and saving
// Need to create a GD image ffmpeg-php to work on it
$image = imagecreatetruecolor($width, $height);
// Create an instance of the frame with the class ffmpeg_frame
$Frame = new ffmpeg_frame($image);
// Choose the frame you want to save as jpeg
$thumbnailOf = (int) round($movie->getFrameCount() / 2.5);
// Receives the frame
$frame = $movie->GetFrame($thumbnailOf);
// Convert to a GD image
$image = $frame->toGDImage();
// Save to disk.
//echo $movie_file.'.jpg';
header('Content-Type: image/jpeg');
imagejpeg($image,null,100);
}
echo captureVideoPosterImg("smovie.mp4");
?>
the file in convert to UTF8 without bom.
thx!
getNameIndex($i)I am currently using the zip archive function to extract some images, I am looking for a method which gives the filepath of each individual image so I can use getimagesize to get the width and height, below is the method am using to loop through the files.
$chapterZip = new ZipArchive();
if ($chapterZip->open($_FILES['chapterUpload']['tmp_name']))
{
for($i = 0; $i < $chapterZip->numFiles; $i++) {
list($width, $height) = getimagesize(getNameIndex($i));
$imageLocation= "INSERT INTO imageLocation (imageLocation,imageWidth,imageHeight,chapterID) VALUES ('"."Manga/".$_POST['mangaName']."/".$_POST['chapterName']."/".$chapterZip->getNameIndex($i)."',".$width.",".$height.",".$chapterID.")";
getQuery($imageLocation,$l);
}
if($chapterZip->extractTo("Manga/".$_POST['mangaName']."/".$_POST['chapterName']))
{
$errmsg0.="You have successfully uploaded a manga chapter";
$chapterZip->close();
}
}
any help with this would be greatly appreciated !
With PHP's Zip extension's stream wrapper, do not have to manually extract all files:
$size = getimagesize('zip:///path/to/file.zip#path/to/image.jpg');