(Crystal)(PNG) CrystalでPNG画像の幅と高さをヘッダの部分から取得する

Crystalで PNG画像ファイルの幅と高さをヘッダの部分から取得します、
ヘッダ部分を見て、PNG画像のヘッダかどうかの判断もするようになっています、
実際に画像データを読み込むわけではないのでデータが壊れていないなどの保証は出来ません、
その分、情報の取得速度は非常に高速です。
ヘッダの構造を読み替えれば、その他の情報や その他のファイル形式にも応用できます。

# png_picture_size <filename> [0|1] [both|cols|rows]
# 0 or 1  カウントを始める数、省略時は 1 
# (座標として扱う時は0、 幅や高さとして扱う時は1の方が扱いやすい)
# cols 幅だけ、rows 高さだけ、省略 または both 両方。
# 0, 1 および both, cols, rows を複数指定した場合は 最後のものが有効
# (例:「png_picture_size ./data.png both cols 0 rows 1」は「rows と 1」のオプションが有効)
# 取得に成功した時は 標準出力で数値を返します (幅高さ両方の時は 半角スペース区切りです)
# 取得に失敗した時は ERRORLEVEL に 1を設定するのでそれを参照するか
# 標準出力に 長さ0の文字列 "" を返すのでそれで判断してください
(
  #puts("no option")
  exit(1)
) if ARGV.size < 1
png_file = File.expand_path(ARGV[0])
(
  #puts("file not found")
  exit(1)
) if !File.exists?(png_file)
count_decrement = 0
cols_rows = 0 # 0=両方 1=colsのみ 2=rowsのみ
(1..(ARGV.size-1)).each{|c|
  case ARGV[c]
    when "0" then
      count_decrement = 1
    when "1" then
      count_decrement = 0
    when "both" then
      cols_rows = 0
    when "cols" then
      cols_rows = 1
    when "rows" then
      cols_rows = 2
  end
}
# 画像の幅や高さの情報は IHDRチャンク内にあり場所は固定なので、その部分を取得すれば値を得られます
# PNGファイルシグネチャ   8byte [0..7] -> 0x89 0x50 0x4E 0x47 0x0D 0x0A 0x1A 0x0A ならPNG形式
# IHDRチャンク     25byte  [8..32]
#   Length         4byte  -> ChunkDataLength   0x0d (13)で固定   [8..11]
#   ChunkType      4byte  -> 0x49 0x48 0x44 0x52 (IHDRのASCIIコード)で固定   [12..15]
#   ChunkData      4byte  -> Width   [16..19]
#   ChunkData      4byte  -> Height   [20..23]
#   ChunkData      1byte  -> BitDepth   [24]
#   ChunkData      1byte  -> ColorType   [25]
#   ChunkData      1byte  -> Compression   [26]
#   ChunkData      1byte  -> Filter   [27]
#   ChunkData      1byte  -> Interlace   [28]
#   CRC            4byte  -> ChunkTypeとChunkDataから算出される   [29..32]
# 以降、IDATチャンク IENDチャンクが続く
File.open(png_file){|f|
  begin
    bin = Slice(UInt8).new(24)
    f.read(bin)
    exit(1) if bin[0..7].hexstring != "89504e470d0a1a0a"
    width = bin[16..19].hexstring.to_i(16)
    height = bin[20..23].hexstring.to_i(16)
    print(
      case cols_rows
        when 0
          "#{width-count_decrement} #{height-count_decrement}"
        when 1
          "#{width-count_decrement}"
        when 2
          "#{height-count_decrement}"
      end
    )
  rescue
    #puts("some kind of error has occurred")
    exit(1)
  end
}