class PDFBeads::PageDataProvider

Represents a set of page images accompanied with auxiliary files needed to build a PDF document.

Public Class Methods

new( files,args ) click to toggle source

Takes a list of file names and a hash containing a set of options.

# File lib/pdfbeads/pdfpage.rb, line 383
def initialize( files,args )
  @pageargs = args

  ext_lossless = [ 'PNG','TIFF?' ]
  ext_jpeg     = [ 'JPE?G' ]
  ext_jpeg2000 = [ 'JP2','JPX' ]

  @exts = Array.new()

  case @pageargs[:bg_format]
  when 'JP2'
    @exts << ext_jpeg2000 << ext_jpeg << ext_lossless
    @pref = Array.new( ext_jpeg2000 )
  when 'JPG'
    @exts << ext_jpeg << ext_jpeg2000 << ext_lossless
    @pref = Array.new( ext_jpeg )
  else
    @exts << ext_lossless << ext_jpeg2000 << ext_jpeg
    @pref = Array.new( ext_lossless )
  end

  # A hack for some Windows versions of RMagick, which throw an error the
  # first time when Magick.formats is accessed
  retries = 2
  begin
    mfmts = Magick.formats
  rescue
    retry if (retries -= 1 ) > 0
  end
  unless mfmts.has_key? 'JP2'
    @exts.delete_if{ |ext| ext_jpeg2000.include? ext }
    @pref = Array.new( ext_jpeg ) if @pref.include? 'JP2'
  end

  for fname in files do
    if /\A([^.]*)\.(TIFF?|PNG)\Z/i.match( fname )
      page = PageData.new( fname,$1,args,@exts,@pref )
      scnt = page.fillStencilArray()
      if scnt > 0
        page.addSupplementaryFiles()
        push( page )
      end
    end
  end
end

Public Instance Methods

jbig2Encode() click to toggle source

A wrapper for the jbig2 encoder. The jbig2 utility is called as many times as needed to encode all pages with the given pages-per-dict value.

# File lib/pdfbeads/pdfpage.rb, line 431
def jbig2Encode()
  per_dict = @pageargs[:pages_per_dict]
  force = @pageargs[:force_update]

  has_jbig2 = false
  if /(win|w)32$/i.match( RUBY_PLATFORM )
    schar = ';'
    ext = '.exe'
    sep = '\\'
  else
    schar = ':'
    ext = ''
    sep = '/'
  end
  ENV['PATH'].split( schar ).each do |dir|
    if File.exists?( dir << sep << 'jbig2' << ext )
      has_jbig2 = true
      break
    end
  end

  unless has_jbig2
    $stderr.puts("JBIG2 compression has been requested, but the encoder is not available.")
    $stderr.puts( "  I'll use CCITT Group 4 fax compression instead." )
    return false
  end

  pidx = 0
  needs_update = force
  toConvert = Array.new()
  each_index do |i|
    p = fetch(i)
    pidx += 1
    p.stencils.each do |s|
      toConvert << s[:path]
      s[:jbig2path] = s[:path].sub( /\.(TIFF?|PNG)\Z/i,'.jbig2' )
      s[:jbig2dict] = toConvert[0].sub( /\.(TIFF?|PNG)\Z/i,'.sym' )
      if needs_update == false
        needs_update = true unless File.exists? s[:jbig2path] and File.exists? s[:jbig2dict]
      end
    end

    if pidx == per_dict or i == length - 1
      # The jbig2 encoder processes a bunch of files at once, producing
      # pages which depend from a shared dictionary. Thus we can skip this
      # stage only if both the dictionary and each of the individual pages
      # are already found on the disk
      if needs_update
        IO.popen("jbig2 -s -p " << toConvert.join(' ') ) do |f|
          out = f.gets
          $stderr.puts out unless out.nil?
        end
        return false if $?.exitstatus > 0

        toConvert.each_index do |j|
          oname = sprintf( "output.%04d",j )
          File.rename( oname,toConvert[j].sub( /\.(TIFF?|PNG)\Z/i,'.jbig2' ) ) if File.exists? oname
        end
        File.rename( 'output.sym',toConvert[0].sub( /\.(TIFF?|PNG)\Z/i,'.sym' ) ) if File.exists? 'output.sym'
      end

      toConvert.clear
      needs_update = force
      pidx = 0
    end
  end
  return true
end