Как создать определенное количество эскизов из PDF с помощью Imagick, ImageMagick и PHP?

Я бы хотел использовать PHP, ImageMagick и Imagick (PHP Class) для создания миниатюр PDF. В некоторых PDF-файлах будет только одна страница, а у некоторых будет много. Я хотел бы указать число (N) создаваемых эскизов, по одному для каждой из первых N страниц в PDF.

Приведенный ниже код работает, но создает ошибки, когда в PDF не хватает страниц (потому что я пытаюсь создать экземпляр Imagick на странице PDF, которая не существует). Я также знаю, что ImageMagick может создавать эскизы для всех страниц в PDF при использовании из командной строки. Я хотел бы воспроизвести это поведение наиболее эффективным способом (память и процессор), одновременно контролируя количество созданных больших пальцев … Мне нужно только миниатюру для первых N страниц в больших PDF-файлах.

Я рассмотрел различные методы определения количества страниц в PDF-файле, и все они кажутся ресурсоемкими. Возможно, код ниже – мой лучший выбор. Он выполняет мою задачу, но беспокоит меня, потому что это приводит к некоторым ошибкам … хотя они не влияют на конечный результат.

Вот мой код, который в настоящее время работает (с ошибками, когда в PDF меньше N страниц):

private function create_thumbnails( $num_thumbs = 3 // how many thumbnails to create, defaults to one ) { echo "\n\n creating thumbnails ... "; $num_thumbs_created = 0; while( $num_thumbs_created < $num_thumbs ) { try { // instantiate imagick with the pdf $Image = new Imagick( $this->file_path_pdf . '[' . $num_thumbs_created . ']' ); // define image file $Image->setImageColorspace( 255 ); $Image->setCompression( Imagick::COMPRESSION_JPEG ); $Image->setCompressionQuality( 60 ); $Image->setImageFormat( 'jpg' ); // size the thumbnail // - resized relative to 8.5x11 ( assuming most pdfs are paper sized ) $Image->resizeImage( 180, 232, imagick::FILTER_POINT, 1 ); // save image $Image->writeImage( substr( $this->File->path, 0, -4 ) . '-' . $num_thumbs_created . '.jpg' ); $Image->clear(); $num_thumbs_created++; } catch( Exception $e ) { echo "\n * failed to create some or all thumbnails: " . $e->getMessage(); break; } } $Image->destroy(); echo "done"; } 

Я уверен, что если вы откроете PDF, то Imagick::getNumberImages предоставит вам количество страниц. Аналогично, в этот момент вы можете перебирать их магией, не создавая экземпляров на странице. Однако все это предположение, основанное на документации. Поэтому вы должны проверить и узнать сами:

 private function create_thumbnails( $num_thumbs = 3) { echo "\n\n creating thumbnails ... "; try { $Image = new Imagick( $this->file_path_pdf); $nbCreated = 0; if($num_thumbs > 0) { foreach($Image as $idx => $im) { if($nbCreated < $num_thumbs) { $im->setImageColorspace( 255 ); $im->setCompression( Imagick::COMPRESSION_JPEG ); $im->setCompressionQuality( 60 ); $im->setImageFormat( 'jpg' ); $im->resizeImage( 180, 232, imagick::FILTER_POINT, 1 ); // save image $im->writeImage( $idx . '-' . $nbCreated . '.jpg' ); $im->clear(); $nbCreated++; } else { break; // pop out of loop we have reach our limit and are done } } } $Image->destroy(); } catch( Exception $e ) { echo "\n * failed to create some or all thumbnails: " . $e->getMessage(); $Image->destroy(); } echo "done"; } 

Заметьте, я также изменил, где у вас есть ваш try / catch. IMO лучше заручиться и прекратить создавать изображения вместе, если есть ошибка, потому что если вы имеете дело с одним файлом, вероятность того, что ошибка будет выбрана на каждой итерации, поэтому, вероятно, более эффективно останавливаться на первом исключении. Вы можете легко обернуть его в другом месте, вот как я это сделаю.