Monday, October 19, 2015 groovy,pdf

複数のPNG画像からPDFを生成する

複数の画像データを1画像1ページとしてPDFに変換する話。

対象画像は以下の3つ.

backpack backpack backpack

このエントリーでは groovy と PDFBox を使ってそれを実現するのだが ImageMagick を使えば以下のコマンドを使って PNG から PDF を生成することができる。

convert *.png output.pdf

groovy と PDFBox による PNG から PDF 生成

コード : createPdf.groovy

@Grab(group='org.apache.pdfbox', module='pdfbox', version='1.8.3')

import org.apache.pdfbox.pdmodel.PDDocument
import org.apache.pdfbox.pdmodel.PDPage
import org.apache.pdfbox.pdmodel.edit.PDPageContentStream
import org.apache.pdfbox.pdmodel.graphics.xobject.PDPixelMap
import org.apache.pdfbox.pdmodel.common.PDRectangle

import java.awt.*
import java.awt.image.BufferedImage
import javax.imageio.ImageIO

System.setProperty("java.awt.headless", "true")


def toBufferedImg = { img->
    def retVal = new BufferedImage((int)img.width,(int)img.height,BufferedImage.TYPE_4BYTE_ABGR)
    def g = retVal.graphics
    g.drawImage(img,0,0,null)
    g.dispose()
    return retVal
}

// 中央に配置
def pasteImg = { img, newImageWidth, newImageHeight->
    def retVal = new BufferedImage( newImageWidth, newImageHeight, BufferedImage.TYPE_4BYTE_ABGR)
    def g = retVal.graphics
    g.setColor(Color.WHITE) // 背景を白塗り
    g.fill( new Rectangle(0,0,newImageWidth,newImageHeight) )

    g.drawImage( img, (retVal.width-img.width)/2f as int, (retVal.height-img.height)/2f as int, null)
    g.dispose()

    return retVal
}

def createNewPage = { document, pngFile, pageWidth, pageHeight->
    def img = toBufferedImg( ImageIO.read(pngFile).getScaledInstance(pageWidth,-1,Image.SCALE_SMOOTH) )
    def img2 = pasteImg( img, pageWidth, pageHeight )
    ImageIO.write(img2,'PNG',new File('r.png'))

    def page = new PDPage( new PDRectangle(pageWidth,pageHeight) )
    document.addPage( page )
    def contentStream = new PDPageContentStream(document, page)
    contentStream.drawXObject( new PDPixelMap(document, img2), 0f, 0f, pageWidth as float, pageHeight as float )
    contentStream.close()

    page
}



def inputPngFile1 = new File('png/backpack.png')
def inputPngFile2 = new File('png/car.png')
def inputPngFile3 = new File('png/headphone.png')

def outputPdfFile = new File('output.pdf')

// swap w and h
def pageWidth  = PDPage.PAGE_SIZE_A4.height as int
def pageHeight = PDPage.PAGE_SIZE_A4.width as int


def document = new PDDocument()

[inputPngFile1,inputPngFile2,inputPngFile3].each { File pngFile->
    createNewPage( document, pngFile, pageWidth, pageHeight )
}

document.save( outputPdfFile)
document.close()

結果

concat-png