defmodule PNG do
@moduledoc """
PNG イメージを作成します
cf. https://en.wikipedia.org/wiki/Portable_Network_Graphics
"""
@magic_number [0x89, "PNG", 0x0D, 0x0A, 0x1A, 0x0A]
@width 32
@height 8
@depth 8
@color_type 3
@compression_method 0
@filter_method 0
@interlace_method 0
@header <<
@width::32,
@height::32,
@depth,
@color_type,
@compression_method,
@filter_method,
@interlace_method
>>
@palette [
0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF
]
@image [
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0,
1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0 ],
[ 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1 ],
[ 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0,
1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1 ],
[ 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0,
1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1 ],
[ 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0,
1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 ],
[ 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0,
1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 ],
[ 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0,
0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1 ]
]
@scanline_filter_none 0
def write_image(filename) do
rows =
Enum.map(@image, fn row ->
[@scanline_filter_none, row]
end)
File.open(filename, [:write], fn io ->
IO.binwrite(io, @magic_number)
write_chunk(io, "IHDR", @header)
write_chunk(io, "PLTE", @palette)
write_chunk(io, "IDAT", compress(rows))
write_chunk(io, "IEND", "")
end)
end
def write_chunk(io, type, data) do
length = :erlang.iolist_size(data)
crc = :erlang.crc32([type, data])
IO.binwrite(io, <<length::big-size(32)>>)
IO.binwrite(io, type)
IO.binwrite(io, data)
IO.binwrite(io, <<crc::big-size(32)>>)
end
@doc """
Erlang の zlib モジュールを利用してデータを圧縮します
see http://erlang.org/doc/man/zlib.html
"""
def compress(data) do
zip = :zlib.open()
:ok = :zlib.deflateInit(zip)
compressed = :zlib.deflate(zip, data, :finish)
:ok = :zlib.deflateEnd(zip)
:ok = :zlib.close(zip)
compressed
end
end
$ elixirc png.ex
$ elixir -e 'PNG.write_image("emattsan.png")'