Sunday, October 18, 2015 groovy,java2D

画像を指定サイズにリサイズする

複数の画像データを1画像1ページとしてPDFに変換しようと思ったのだが、その前処理として、PNG画像の縦横比がまちまちなので、まずはこれを統一したい。

元画像はこれ.

backpack

その1) サイズを指定してPNG画像をリサイズ

最初のステップとして引数で width,height を指定したらその通りにリサイズするコードを書いてみる。

コード : resizePngStep1.groovy

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

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


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

def inputPngFilename  = args[0]
def outputPngFilename = args[1]
def widthAndHeight = args[2].split(/:/) 

def inputPngFile = new File(inputPngFilename)
def outputPngFile = new File(outputPngFilename)

def img = ImageIO.read(inputPngFile) 
def img2 = toBufferedImg(
    img.getScaledInstance(
       widthAndHeight[0] as int,
       widthAndHeight[1] as int,
       Image.SCALE_SMOOTH) )

ImageIO.write(img2,'PNG',outputPngFile)

実行

$ groovy resizePngStep1 input.png output.png 300:212

あとでPDFにすることを想定して サイズ指定オプションは width:height = Math.sqrt(2):1 の比率に沿って、300:212 にしてみる。

結果

backpack

指定した縦横比が元の比率と異なるので 横に潰れた画像になってしまった。

その2) 元の画像の比率を維持してリサイズ

画像の縦横比率は維持しつつも画像サイズは Math.sqrt(2):1 にして、余った部分は白で塗りつぶす。 横幅基準で計算するため縦横比オプションは指定しない形に変更。

コード : resizePngStep2.groovy

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

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


// BufferedImage へ変換
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 inputPngFilename  = args[0]
def outputPngFilename = args[1]

def inputPngFile = new File(inputPngFilename)
def outputPngFile = new File(outputPngFilename)

def img = ImageIO.read(inputPngFile) 

// width基準でheightを計算
def width  = img.width
def height = width / Math.sqrt(2)

def img2 = toBufferedImg( img.getScaledInstance( width as int, -1, Image.SCALE_SMOOTH) )
def img3 = pasteImg( img2, width as int , height as int )

ImageIO.write(img3,'PNG',outputPngFile)

実行

groovy resizePngStep2 input.png output.png

結果

backpack

元画像の縦横比率に応じて、height を基準に width を決めるか、その逆がよいかの判定があった方がよいが割愛。