page = 0; $this->n = 2; $this->buffer = ''; $this->pages = array(); $this->PageInfo = array(); $this->fonts = array(); $this->FontFiles = array(); $this->encodings = array(); $this->cmaps = array(); $this->images = array(); $this->links = array(); $this->InHeader = false; $this->InFooter = false; $this->lasth = 0; $this->FontFamily = ''; $this->FontStyle = ''; $this->FontSizePt = 12; $this->underline = false; $this->DrawColor = '0 G'; $this->FillColor = '0 g'; $this->TextColor = '0 g'; $this->ColorFlag = false; $this->WithAlpha = false; $this->ws = 0; $this->CoreFonts = array('courier', 'helvetica', 'times', 'symbol', 'zapfdingbats'); if($unit=='pt') $this->k = 1; elseif($unit=='mm') $this->k = 72/25.4; elseif($unit=='cm') $this->k = 72/2.54; elseif($unit=='in') $this->k = 72; else $this->Error('Incorrect unit: '.$unit); $this->StdPageSizes = array( 'a3'=>array(841.89,1190.55), 'a4'=>array(595.28,841.89), 'a5'=>array(420.94,595.28), 'letter'=>array(612,792), 'legal'=>array(612,1008) ); $size = $this->_getpagesize($size); $this->DefPageSize = $size; $this->CurPageSize = $size; $orientation = strtolower($orientation); if($orientation=='p' || $orientation=='portrait') { $this->DefOrientation = 'P'; $this->w = $size[0]; $this->h = $size[1]; } elseif($orientation=='l' || $orientation=='landscape') { $this->DefOrientation = 'L'; $this->w = $size[1]; $this->h = $size[0]; } else { $this->Error('Incorrect orientation: '.$orientation); } $this->CurOrientation = $this->DefOrientation; $this->wPt = $this->w*$this->k; $this->hPt = $this->h*$this->k; $this->CurRotation = 0; $margin = 28.35/$this->k; $this->SetMargins($margin,$margin); $this->cMargin = $margin/10; $this->LineWidth = .567/$this->k; $this->SetAutoPageBreak(true,2*$margin); $this->SetDisplayMode('default'); $this->SetCompression(true); $this->metadata = array('Producer'=>'FPDF 1.86'); $this->PDFVersion = '1.3'; } function SetMargins($left, $top, $right=null) { $this->lMargin = $left; $this->tMargin = $top; if($right===null) $right = $left; $this->rMargin = $right; } function SetAutoPageBreak($auto, $margin=0) { $this->AutoPageBreak = $auto; $this->bMargin = $margin; $this->PageBreakTrigger = $this->h-$margin; } function SetDisplayMode($zoom, $layout='default') { $this->ZoomMode = $zoom; $this->LayoutMode = $layout; } function SetCompression($compress) { $this->compress = $compress; } function AddPage($orientation='', $size='', $rotation=0) { if($this->state==3) $this->Error('The document is closed'); $family = $this->FontFamily; $style = $this->FontStyle.($this->underline ? 'U' : ''); $fontsize = $this->FontSizePt; $lw = $this->LineWidth; $dc = $this->DrawColor; $fc = $this->FillColor; $tc = $this->TextColor; $cf = $this->ColorFlag; if($this->page>0) { $this->InFooter = true; $this->Footer(); $this->InFooter = false; $this->_endpage(); } $this->_beginpage($orientation,$size,$rotation); $this->_out('2 J'); $this->LineWidth = $lw; $this->_out(sprintf('%.2F w',$lw*$this->k)); if($family) $this->SetFont($family,$style,$fontsize); $this->DrawColor = $dc; if($dc!='0 G') $this->_out($dc); $this->FillColor = $fc; if($fc!='0 g') $this->_out($fc); $this->TextColor = $tc; $this->ColorFlag = $cf; $this->InHeader = true; $this->Header(); $this->InHeader = false; if($this->LineWidth!=$lw) { $this->LineWidth = $lw; $this->_out(sprintf('%.2F w',$lw*$this->k)); } if($family) $this->SetFont($family,$style,$fontsize); if($this->DrawColor!=$dc) { $this->DrawColor = $dc; $this->_out($dc); } if($this->FillColor!=$fc) { $this->FillColor = $fc; $this->_out($fc); } $this->TextColor = $tc; $this->ColorFlag = $cf; } function Header() {} function Footer() {} function PageNo() { return $this->page; } function Image($file, $x=null, $y=null, $w=0, $h=0, $type='', $link='') { if($this->state!=2) return; if(!isset($this->images[$file])) { if($type=='') { $pos = strrpos($file,'.'); if(!$pos) $this->Error('Image file has no extension: '.$file); $type = substr($file,$pos+1); } $type = strtolower($type); if($type=='jpeg') $type = 'jpg'; $info = $this->_parsejpg($file); $info['i'] = count($this->images)+1; $this->images[$file] = $info; } else { $info = $this->images[$file]; } if($w==0 && $h==0) { $w = -96; $h = -96; } if($w<0) $w = -$info['w']*72/$w/$this->k; if($h<0) $h = -$info['h']*72/$h/$this->k; if($w==0) $w = $h*$info['w']/$info['h']; if($h==0) $h = $w*$info['h']/$info['w']; if($y===null) { if($this->y+$h>$this->PageBreakTrigger && !$this->InHeader && !$this->InFooter && $this->AcceptPageBreak()) { $x2 = $this->x; $this->AddPage($this->CurOrientation,$this->CurPageSize,$this->CurRotation); $this->x = $x2; } $y = $this->y; $this->y += $h; } if($x===null) $x = $this->x; $this->_out(sprintf('q %.2F 0 0 %.2F %.2F %.2F cm /I%d Do Q', $w*$this->k,$h*$this->k,$x*$this->k,($this->h-($y+$h))*$this->k,$info['i'])); } function AcceptPageBreak() { return $this->AutoPageBreak; } function Output($dest='', $name='', $isUTF8=false) { if($this->state<3) $this->Close(); if(is_bool($dest)) $dest = $dest ? 'D' : 'F'; $dest = strtoupper($dest); if($dest=='') { if($name=='') { $name = 'doc.pdf'; $dest = 'I'; } else { $dest = 'F'; } } if(!$isUTF8) $name = utf8_encode($name); switch($dest) { case 'I': $this->_checkoutput(); if(PHP_SAPI!='cli') { if(headers_sent()) $this->Error('Some data already output'); header('Content-Type: application/pdf'); header('Content-Disposition: inline; filename="'.$name.'"'); header('Cache-Control: private, max-age=0, must-revalidate'); header('Pragma: public'); } echo $this->buffer; break; case 'D': $this->_checkoutput(); if(headers_sent()) $this->Error('Some data already output'); header('Content-Type: application/pdf'); header('Content-Disposition: attachment; filename="'.$name.'"'); header('Cache-Control: private, max-age=0, must-revalidate'); header('Pragma: public'); echo $this->buffer; break; case 'F': $f = fopen($name,'wb'); if(!$f) $this->Error('Unable to create output file: '.$name); fwrite($f,$this->buffer,strlen($this->buffer)); fclose($f); break; case 'S': return $this->buffer; default: $this->Error('Incorrect output destination: '.$dest); } return ''; } protected function _getpagesize($size) { if(is_string($size)) { $size = strtolower($size); if(!isset($this->StdPageSizes[$size])) $this->Error('Unknown page size: '.$size); $a = $this->StdPageSizes[$size]; return array($a[0]/$this->k, $a[1]/$this->k); } else { if($size[0]>$size[1]) return array($size[1], $size[0]); else return $size; } } protected function _beginpage($orientation, $size, $rotation) { $this->page++; $this->pages[$this->page] = ''; $this->state = 2; $this->x = $this->lMargin; $this->y = $this->tMargin; $this->FontFamily = ''; if($orientation=='') $orientation = $this->DefOrientation; else $orientation = strtoupper($orientation[0]); if($size=='') $size = $this->DefPageSize; else $size = $this->_getpagesize($size); if($orientation!=$this->CurOrientation || $size[0]!=$this->CurPageSize[0] || $size[1]!=$this->CurPageSize[1]) { if($orientation=='P') { $this->w = $size[0]; $this->h = $size[1]; } else { $this->w = $size[1]; $this->h = $size[0]; } $this->wPt = $this->w*$this->k; $this->hPt = $this->h*$this->k; $this->PageBreakTrigger = $this->h-$this->bMargin; $this->CurOrientation = $orientation; $this->CurPageSize = $size; } if($orientation!=$this->DefOrientation || $size[0]!=$this->DefPageSize[0] || $size[1]!=$this->DefPageSize[1]) $this->PageInfo[$this->page]['size'] = array($this->wPt, $this->hPt); if($rotation!=0) { if($rotation%90!=0) $this->Error('Incorrect rotation value: '.$rotation); $this->CurRotation = $rotation; $this->PageInfo[$this->page]['rotation'] = $rotation; } } protected function _endpage() { $this->state = 1; } protected function _parsejpg($file) { $a = getimagesize($file); if(!$a) $this->Error('Missing or incorrect image file: '.$file); if($a[2]!=2) $this->Error('Not a JPEG file: '.$file); if(!isset($a['channels']) || $a['channels']==3) $colspace = 'DeviceRGB'; elseif($a['channels']==4) $colspace = 'DeviceCMYK'; else $colspace = 'DeviceGray'; $bpc = isset($a['bits']) ? $a['bits'] : 8; $data = file_get_contents($file); return array('w'=>$a[0], 'h'=>$a[1], 'cs'=>$colspace, 'bpc'=>$bpc, 'f'=>'DCTDecode', 'data'=>$data); } protected function _out($s) { if($this->state==2) $this->pages[$this->page] .= $s."\n"; elseif($this->state==1) $this->_put($s); elseif($this->state==0) $this->Error('No page has been added yet'); elseif($this->state==3) $this->Error('The document is closed'); } protected function _put($s) { $this->buffer .= $s."\n"; } protected function _putpages() { $nb = $this->page; for($n=1;$n<=$nb;$n++) $this->PageInfo[$n]['n'] = $this->n+1+2*($n-1); for($n=1;$n<=$nb;$n++) $this->_putpage($n); $this->_put('1 0 obj'); $this->_put('<PageInfo[$n]['n'].' 0 R '; $this->_put($kids.']'); $this->_put('/Count '.$nb); if($this->DefOrientation=='P') { $w = $this->DefPageSize[0]; $h = $this->DefPageSize[1]; } else { $w = $this->DefPageSize[1]; $h = $this->DefPageSize[0]; } $this->_put(sprintf('/MediaBox [0 0 %.2F %.2F]',$w*$this->k,$h*$this->k)); $this->_put('>>'); $this->_put('endobj'); } protected function _putpage($n) { $this->_newobj(); $this->_put('<_put('/Parent 1 0 R'); if(isset($this->PageInfo[$n]['size'])) $this->_put(sprintf('/MediaBox [0 0 %.2F %.2F]',$this->PageInfo[$n]['size'][0],$this->PageInfo[$n]['size'][1])); if(isset($this->PageInfo[$n]['rotation'])) $this->_put('/Rotate '.$this->PageInfo[$n]['rotation']); $this->_put('/Resources 2 0 R'); $this->_put('/Contents '.($this->n+1).' 0 R>>'); $this->_put('endobj'); $this->_newobj(); $p = $this->pages[$n]; $this->_put('<>'); $this->_putstream($p); $this->_put('endobj'); } protected function _putimages() { foreach(array_keys($this->images) as $file) { $this->_putimage($this->images[$file]); unset($this->images[$file]['data']); } } protected function _putimage(&$info) { $this->_newobj(); $info['n'] = $this->n; $this->_put('<_put('/Subtype /Image'); $this->_put('/Width '.$info['w']); $this->_put('/Height '.$info['h']); $this->_put('/ColorSpace /'.$info['cs']); if($info['cs']=='DeviceCMYK') $this->_put('/Decode [1 0 1 0 1 0 1 0]'); $this->_put('/BitsPerComponent '.$info['bpc']); if(isset($info['f'])) $this->_put('/Filter /'.$info['f']); $this->_put('/Length '.strlen($info['data']).'>>'); $this->_putstream($info['data']); $this->_put('endobj'); } protected function _newobj() { $this->n++; $this->offsets[$this->n] = strlen($this->buffer); $this->_put($this->n.' 0 obj'); } protected function _putstream($data) { $this->_put('stream'); $this->_put($data); $this->_put('endstream'); } protected function _checkoutput() { if(PHP_SAPI!='cli') { if(headers_sent($file,$line)) $this->Error("Some data has already been output, can't send PDF file (output started at $file:$line)"); } if(ob_get_length()) { if(preg_match('/^(\xEF\xBB\xBF)?\s*$/',ob_get_contents())) { ob_end_clean(); } else { $this->Error("Some data has already been output, can't send PDF file"); } } } function SetFont($family, $style='', $size=0) { $family = strtolower($family); if($family=='') $family = $this->FontFamily; if($family=='arial') $family = 'helvetica'; $this->FontFamily = $family; $this->FontStyle = strtoupper($style); if($size==0) $size = $this->FontSizePt; $this->FontSizePt = $size; $this->FontSize = $size/$this->k; $this->CurrentFont = array('family'=>$family,'style'=>$this->FontStyle,'size'=>$size); } function Close() { if($this->state==3) return; if($this->page==0) $this->AddPage(); $this->InFooter = true; $this->Footer(); $this->InFooter = false; $this->_endpage(); $this->_putimages(); $this->_putpages(); $this->_putresources(); $this->_putinfo(); $this->_putcatalog(); $this->_putheader(); $this->_puttrailer(); $this->state = 3; } protected function _putresources() { $this->_put('2 0 obj'); $this->_put('<<'); $this->_putfonts(); $this->_putimagedict(); $this->_put('>>'); $this->_put('endobj'); } protected function _putfonts() { $this->_put('/Font <<'); $this->_put('/F1 <<'); $this->_put('/Type /Font'); $this->_put('/Subtype /Type1'); $this->_put('/BaseFont /Helvetica'); $this->_put('>>'); $this->_put('>>'); } protected function _putimagedict() { if(!empty($this->images)) { $this->_put('/XObject <<'); foreach($this->images as $image) $this->_put('/I'.$image['i'].' '.$image['n'].' 0 R'); $this->_put('>>'); } } protected function _putinfo() { $info = '<<'; foreach($this->metadata as $key=>$value) $info .= '/'.$key.' '.$this->_textstring($value); $info .= '/CreationDate '.$this->_textstring('D:'.@date('YmdHis')); $info .= '>>'; $this->_put($info); } protected function _putcatalog() { $this->_put('/Type /Catalog'); $this->_put('/Pages 1 0 R'); } protected function _putheader() { $this->buffer = '%PDF-'.$this->PDFVersion."\n".$this->buffer; } protected function _puttrailer() { $this->_put('xref'); $this->_put('0 '.($this->n+1)); $this->_put('0000000000 65535 f '); for($i=1;$i<=$this->n;$i++) $this->_put(sprintf('%010d 00000 n ',$this->offsets[$i])); $this->_put('trailer'); $this->_put('<<'); $this->_put('/Size '.($this->n+1)); $this->_put('/Root '.$this->n.' 0 R'); $this->_put('/Info '.($this->n-1).' 0 R'); $this->_put('>>'); $this->_put('startxref'); $this->_put(strlen($this->buffer)); $this->_put('%%EOF'); $this->state = 3; } protected function _textstring($s) { return '('.$this->_escape($s).')'; } protected function _escape($s) { $s = str_replace('\\','\\\\',$s); $s = str_replace('(','\(',$s); $s = str_replace(')','\)',$s); $s = str_replace("\r",'\r',$s); return $s; } function Error($msg) { throw new Exception('FPDF error: '.$msg); } } // ============================================================================ // PDF CONVERTER CLASS // ============================================================================ class PDFConverter { private $inputPdf; private $outputDir; private $prefix; private $dpi; private $quality; private $jpegFiles = []; private $errors = []; public function __construct($inputPdf, $dpi = 300, $quality = 95, $outputDir = null, $prefix = null) { if (!extension_loaded('imagick')) { throw new Exception("Imagick extension not installed. Install with: sudo apt-get install php-imagick"); } if (!file_exists($inputPdf)) { throw new Exception("PDF file not found: $inputPdf"); } $this->inputPdf = $inputPdf; $this->dpi = max(72, min(1200, $dpi)); $this->quality = max(1, min(100, $quality)); $this->outputDir = $outputDir ?? dirname($inputPdf); if (!is_dir($this->outputDir)) { mkdir($this->outputDir, 0755, true); } $this->prefix = $prefix ?? pathinfo($inputPdf, PATHINFO_FILENAME); } public function convertToJpegs() { try { $imagick = new Imagick(); $imagick->setResolution($this->dpi, $this->dpi); $imagick->readImage($this->inputPdf); $imagick = $imagick->coalesceImages(); $pageNum = 1; foreach ($imagick as $page) { $page->setImageFormat('jpeg'); $page->setImageCompression(Imagick::COMPRESSION_JPEG); $page->setImageCompressionQuality($this->quality); $page->setImageBackgroundColor('white'); $page = $page->flattenImages(); $filename = sprintf("%s_page_%03d.jpg", $this->prefix, $pageNum); $filepath = $this->outputDir . DIRECTORY_SEPARATOR . $filename; $page->writeImage($filepath); $this->jpegFiles[] = $filepath; $pageNum++; } $imagick->clear(); $imagick->destroy(); return $this->jpegFiles; } catch (Exception $e) { throw new Exception("Error converting PDF to JPEGs: " . $e->getMessage()); } } public function createPdfFromJpegs($pageSize = 'auto') { if (empty($this->jpegFiles)) { throw new Exception("No JPEG files to convert."); } $outputPdf = $this->outputDir . DIRECTORY_SEPARATOR . $this->prefix . "_reconstructed.pdf"; try { $pdf = new FPDF(); foreach ($this->jpegFiles as $index => $jpegFile) { list($imgWidth, $imgHeight) = getimagesize($jpegFile); if ($pageSize === 'auto') { $pageWidth = ($imgWidth / $this->dpi) * 25.4; $pageHeight = ($imgHeight / $this->dpi) * 25.4; $orientation = $pageWidth > $pageHeight ? 'L' : 'P'; } elseif ($pageSize === 'letter') { $pageWidth = 215.9; $pageHeight = 279.4; $orientation = 'P'; } elseif ($pageSize === 'A4') { $pageWidth = 210; $pageHeight = 297; $orientation = 'P'; } else { $pageWidth = 210; $pageHeight = 297; $orientation = 'P'; } $pdf->AddPage($orientation, [$pageWidth, $pageHeight]); $margin = 5; $maxWidth = $pageWidth - (2 * $margin); $maxHeight = $pageHeight - (2 * $margin); $imgRatio = $imgWidth / $imgHeight; $pageRatio = $maxWidth / $maxHeight; if ($imgRatio > $pageRatio) { $scaledWidth = $maxWidth; $scaledHeight = $maxWidth / $imgRatio; } else { $scaledHeight = $maxHeight; $scaledWidth = $maxHeight * $imgRatio; } $x = ($pageWidth - $scaledWidth) / 2; $y = ($pageHeight - $scaledHeight) / 2; $pdf->Image($jpegFile, $x, $y, $scaledWidth, $scaledHeight); } $pdf->Output('F', $outputPdf); return $outputPdf; } catch (Exception $e) { throw new Exception("Error creating PDF: " . $e->getMessage()); } } public function convert($skipReconstruction = false, $pageSize = 'auto') { $jpegs = $this->convertToJpegs(); $pdf = null; if (!$skipReconstruction) { $pdf = $this->createPdfFromJpegs($pageSize); } return ['jpegs' => $jpegs, 'pdf' => $pdf]; } public function getJpegFiles() { return $this->jpegFiles; } } // ============================================================================ // COMMAND LINE INTERFACE // ============================================================================ if (php_sapi_name() === 'cli') { $options = getopt("", [ "input:", "dpi::", "quality::", "output-dir::", "prefix::", "skip-reconstruction", "pagesize::", "help" ]); if (isset($options['help']) || !isset($options['input'])) { echo <<convertToJpegs(); echo "✓ Created " . count($jpegs) . " JPEG file(s)\n"; foreach ($jpegs as $jpeg) { echo " - " . basename($jpeg) . "\n"; } if (!isset($options['skip-reconstruction'])) { echo "\nCreating PDF from JPEGs...\n"; $pdf = $converter->createPdfFromJpegs($options['pagesize'] ?? 'auto'); echo "✓ Created PDF: " . basename($pdf) . "\n"; } echo "\n" . str_repeat("=", 70) . "\n"; echo "✓ Conversion completed successfully!\n"; echo str_repeat("=", 70) . "\n\n"; } catch (Exception $e) { echo "\n✗ Error: " . $e->getMessage() . "\n\n"; exit(1); } exit(0); } // ============================================================================ // WEB INTERFACE // ============================================================================ $message = ''; $messageType = ''; $files = []; if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['pdf_file'])) { try { if ($_FILES['pdf_file']['error'] !== UPLOAD_ERR_OK) { throw new Exception('File upload error'); } $uploadedFile = $_FILES['pdf_file']; $finfo = finfo_open(FILEINFO_MIME_TYPE); $mimeType = finfo_file($finfo, $uploadedFile['tmp_name']); finfo_close($finfo); if ($mimeType !== 'application/pdf') { throw new Exception('Only PDF files are allowed'); } $dpi = isset($_POST['dpi']) ? (int)$_POST['dpi'] : 300; $quality = isset($_POST['quality']) ? (int)$_POST['quality'] : 95; $prefix = isset($_POST['prefix']) && $_POST['prefix'] !== '' ? $_POST['prefix'] : null; $skipReconstruction = isset($_POST['skip_reconstruction']); $pageSize = isset($_POST['pagesize']) ? $_POST['pagesize'] : 'auto'; $outputDir = __DIR__ . '/converted'; if (!is_dir($outputDir)) { mkdir($outputDir, 0755, true); } $tempFile = $outputDir . '/' . basename($uploadedFile['name']); move_uploaded_file($uploadedFile['tmp_name'], $tempFile); $converter = new PDFConverter($tempFile, $dpi, $quality, $outputDir, $prefix); $result = $converter->convert($skipReconstruction, $pageSize); foreach ($result['jpegs'] as $jpeg) { $files[] = [ 'name' => basename($jpeg), 'path' => 'converted/' . basename($jpeg), 'size' => filesize($jpeg), 'type' => 'image' ]; } if ($result['pdf']) { $files[] = [ 'name' => basename($result['pdf']), 'path' => 'converted/' . basename($result['pdf']), 'size' => filesize($result['pdf']), 'type' => 'pdf' ]; } unlink($tempFile); $message = 'Conversion completed successfully!'; $messageType = 'success'; } catch (Exception $e) { $message = 'Error: ' . $e->getMessage(); $messageType = 'error'; } } ?> PDF to JPEG to PDF Converter

📄 PDF to JPEG Converter

All-in-One PHP Tool - No Dependencies Required

How it works: Upload a PDF and convert each page to high-quality JPEG images. Optionally combine them back into a single PDF.
300 DPI recommended (higher = better quality, larger files)
95 recommended (1-100, higher = better quality)
Generated Files:
Command Line Usage:
php --input=document.pdf --help