Pdf thumb driver

i want to extend the imagemagick thumbs driver to generate jpgs from pdfs. i have my custom thumbs driver as plugin calling ghostscript using exec(). my thumbdriver it get loaded fine, but code is not called for two reasons:

  1. pdf-files because thumb() calls image->thumb() which calls image->isWebsave() which rejects the pdf as source.
    ghostscript code works fine – tested outside of driver.


  1. creating thumb rejects non images as well.
    https://github.com/getkirby/toolkit/blob/master/lib/thumb.php#L67

i would like to keep thumbs driver and not create files on my own, recreating thumbs output logic.
other code in thumbs class should work with pdfs too.
dimension will return 0w 0h.

any ideas how to allow pdfs as valid images as far as thumbs are concerned?

Hm, I guess the intention of thumbs was to make thumbnails with the same image format (JPG becomes a JPG thumb, PNG becomes a PNG thumb), which is why creating thumbs of non-images does not make sense.

What you could do though is to override the thumb component. You can then apply special treatment to PDFs:

class PdfThumb extends Kirby\Component\Thumb {
  public function create($file, $params) {
    if($file->extension() == 'pdf') {
      // special treatment
    }
    
    return parent::create($file, $params);
  }
}

i see. so instead of twisting the thumbs-function you are right maybe i really should create a ‘converter’ to create a raw jpg first (like with 300dpi) and then create a thumb of that one (with my resizing, cropping etc).

but i will take a look at the components anyway. thx.

Not necessarily. You could also do your Ghostscript magic there without a step in between. :slight_smile:

oh its quiet tiny magic actually.

/* NOTES
   should check if file does not exist already using !f::exists($outPath))
   and prepare path if needed using dir::make(dirname($outPath));
*/
$command = array();
$command[] = 'gs';
$command[] = '-sDEVICE=jpeg';
$command[] = '-r'.$dpi.'x'.$dpi; // like 72, 96 or 300
$command[] = '-dNOPAUSE';
$command[] = '-sOutputFile="'.$outPath.'"'; // like $site->roots()->thumbs().DS.$file->uri()
$command[] = '"'.$file->root().'"';
exec(implode(' ', $command));

I’ve recently done this as discussed here: Create Preview from PDF-File . So I defined new file method in /site/plugins/methods.php:

file::$methods['preview'] = function($file, $size='800', $page='0') {

		$key  = 'preview_'. md5($file->root());
		$thumb = kirby()->roots()->thumbs() .DS. $key;

		if (f::exists($thumb))
		{

			if ( (f::modified($thumb) > $file->modified())) {
				return new Asset(kirby()->urls()->thumbs() .'/'. $key);
			}
			f::remove($thumb);

	  }

	  $image = new Imagick($file->root().'['.$page.']'); // which page? First by default
		$image->setImageBackgroundColor('white');
		$image->setImageAlphaChannel(imagick::ALPHACHANNEL_REMOVE);
		$image->mergeImageLayers(imagick::LAYERMETHOD_FLATTEN);
		$image->setImageFormat('jpg');
		$image->setImageCompression(Imagick::COMPRESSION_JPEG);
	  $image->setImageCompressionQuality(80);
		$image->thumbnailImage($size, 0);
		$image->writeImage($thumb);

		return new Asset(kirby()->urls()->thumbs() .'/'. $key);

    };

That does require imageMagick instead of GD, but I don’t think it even needs GhostScript.
So in your template you can call $file->preview() to create a jpg, and then in theory use the thumb plugin on it after.

@lukasbestle if you override the thumb component, does it completely replace the standard thumb methods, or can we just extend them?

1 Like

thank you @tobystokes. i decided to go for GS since php imagick is not available and can not be enabled on the server i am using. but exec(‘convert…’) works.

 echo extension_loaded('imagick') || class_exists("Imagick") ? 'has':'not'; // = not

and Ghostscript yields better results when dealing with high resolution vector pdfs – as far as i can tell. 1MB+ vector pdfs.

about the component. see code from @lukasbestle above. he suggest to me just to extend the create function (which is calling it parent class as return value. so everything is the same, just create function does a little more.

Kirby does not actually require the Imagick PHP extension, it uses exec('convert') internally, so Imagick could actually work for you here.

using convert would work if i can find out how to ‘convert’ a pdf to jpg on my server. i could not find a example that worked on my server. maybe imagick is configured without pdf support – i do not know (yet).

convert -density 300 image.pdf -resize 25% image.png

Well, if Ghostscript works for you, you don’t need to use Imagick. :slight_smile: