Составьте много изображений одновременно в imagemagick Ruby - PullRequest
0 голосов
/ 04 октября 2018

У меня есть следующий код, который берет файл PDF и объединяет его в одно изображение JPG, которое имеет горизонтальную черную линию между каждым изображением страницы PDF, укладывая страницы PDF.

image = MiniMagick::Image.open(pdf_file)

# create a new blank file which we will use to build a composite image
# containing all of our pages
MiniMagick::Tool::Convert.new do |i|
  i.size "#{image.width}x#{image.layers.size * image.height}"
  i.stroke "black"

  image.layers.count.times.each do |ilc|
    next if ilc.zero?

    top = ilc * (image.height + 1)
    i.draw "line 0,#{top}, #{image.width},#{top}"
  end

  i.xc "white"
  i << image_file_name
end

composite_image = MiniMagick::Image.open(image_file_name)

# For each pdf page, add it to our composite image. We add one so that we
# don't put the image over the 1px black line that was added to separate
# pages.
image.layers.count.times do |i|
  composite_image = composite_image.composite(image.layers[i]) do |c|
    c.compose "Over" # OverCompositeOp
    c.geometry "+0+#{i * (image.height + 1)}"
  end
end

composite_image.format(format)
composite_image.quality(85)
composite_image.write(image_file_name)

Он отлично работает, за исключением того, что 20-страничный файл PDF занимает три минуты.Я ищу лучший способ сделать это.Я подозреваю, что один из этих двух вариантов будет работать:

  1. Создайте все изображения страниц PDF одновременно, хотя я не понял, как это сделать.
  2. Использовать vips,благодаря его конвейерной реализации.

Я бы предпочел остаться с imagemagick, но я открыт в любом случае.Я ищу указатели, как добиться того, что я ищу.

Ответы [ 2 ]

0 голосов
/ 05 октября 2018

У меня был удар в ruby-vips версия:

require 'vips'

# n: is the number of pages to load, -1 means all pages in tall, thin image
image = Vips::Image.pdfload ARGV[0], n: -1

# we can get the number of pages and the height of each page from the metadata
n_pages = image.get 'pdf-n_pages'
page_height = image.get 'page-height'

# loop down the image cutting it into an array of separate pages
pages = (0 ... n_pages).map do |page_number|
  image.crop(0, page_number * page_height, image.width, page_height)
end 

# make a 50-pixel-high black strip to separate each page
strip = Vips::Image.black image.width, 50

# and join the pages again
image = pages.inject do |acc, page|
  acc.join(strip, 'vertical').join(page, 'vertical')
end 

image.write_to_file ARGV[1]

На этом рабочем столе с этой 58-страничной PDF Я вижу:

$ /usr/bin/time -f %M:%e ruby ./pages.rb nipguide.pdf x.jpg
152984:1.08
$ vipsheader x.jpg
x.jpg: 595x50737 uchar, 3 bands, srgb, jpegload

Таким образом, он создает JPG высотой 50 000 пикселей примерно за 1,1 секунды и требует пика в 150 Мб памяти.

Я попробовал умную линию fmaw42 imagemagick:

$ /usr/bin/time -f %M:%e convert nipguide.pdf -background black -gravity south -splice 0x50 -append x.jpg
492244:5.16

так500 мб памяти и 5,2 с.Это делает изображение почти точно такого же размера.

Разница в скорости, по большей части, заключается в библиотеке рендеринга PDF, разумеется: IM отправляется в ghostscript, тогда как ruby-vips вызывает poppler или PDFium напрямую.libvips может выполнять потоковую передачу этой программы, поэтому во время оценки в ней не должно быть более одной страницы одновременно.

JPG имеет ограничение в 65535 пикселей по любой оси, поэтому вы не сможете получить многобольше, чем это.Для более коротких документов вы можете добавить dpi: 300 к загрузке PDF, чтобы получить больше деталей.По умолчанию установлено значение 72 dpi.

Вы должны получить хорошее качество текста без необходимости рендеринга в высоком разрешении.Например, для PDF-файла, на который есть ссылка выше, при запуске:

$ vips pdfload nipguide.pdf x.png --page 12

Чтобы отобразить страницу 12 с разрешением 72 т / д по умолчанию, я получаю:

enter image description here

0 голосов
/ 04 октября 2018

Я не уверен, что это то, что вы хотите, но, как мне кажется из вашего описания, вы хотите добавить изображения.

Я создал 3-страничный PDF из 3 изображений jpg только для тестирования.Затем я добавляю черную рамку (в данном случае 10 пикселей, чтобы показать ее лучше) внизу каждой страницы, а затем добавляю все страницы.

Это было сделано с помощью Imagemagick 6.9.10.12 Q16, но я подозреваю, что Python Wandили minimagick имеет аналогичную функциональность.

convert test.pdf -background black -gravity south -splice 0x10 -append test.jpg


enter image description here

При необходимости вы можете отрезать черную линию внизу последней страницыпосле добавления, используя -chop 0x10.

...