びったんびったん

ユーザビリティ・プログラミングについて。

入力バイナリから画像を作成するプログラムを公開しました

圧縮する入力バイナリは2次元のradianceのデータなようです。 このデータの画像はnetCDFデータのビューアから見ることができるようで、見るためにはnetCDFデータをビューアで開く、Rad行をダブルクリック、Create a 2D plotを選択します。

f:id:hakomof:20171216003749p:plain

とりあえず入力バイナリがどんなものか理解するために、入力バイナリから同じ画像を作成するプログラムを書きました。動作にはPython3、ライブラリPillowが必要です。(ソースコードはブログ最下部)

py script.py bin_4obs/OR_ABI-L1b-RadC-M3C01_G16_s20172101802185_e20172101804558_c20172101805000.bin

f:id:hakomof:20171216003715p:plain

これで画像が作成されます。色がぜんぜん違いますが、グラデーション色が違うだけでradianceはビューアと一致しています。

入力バイナリは、2次元を1次元につぶした2バイトのunsigned short?のradianceの基本値?が連続しているようです。この基本値にバンドごとに固有の定数(これはビューアからコピペしたので ミスってるかも)をかけて足すと、ビューアのradianceと一致しました。

というわけで適当にお役立てください。また、私はまったく詳しくない人なので間違っているかもしれないです(間違っていたら教えてください、そしてごめんなさい)。

from math import *
import os.path
import struct
import sys
from PIL import Image

def rgb(minimum, maximum, value):
    minimum, maximum = float(minimum), float(maximum)
    ratio = 2 * (value - minimum) / (maximum - minimum)
    b = int(max(0, 255 * (1 - ratio)))
    r = int(max(0, 255 * (ratio - 1)))
    g = 255 - b - r
    return r, g, b

all_scale_factor_and_add_offset = [
    (0.8121064, -25.936647),
    (0.15859237, -20.289911),
    (0.37691253, -12.037643),
    (0.07073108, -4.5223684),
    (0.09580004, -3.0596137),
    (0.030088475, -0.9609507),
    (0.001564351, -0.0376),
    (0.007104763, -0.5586),
    (0.022539102, -0.8236),
    (0.02004128, -0.9561),
    (0.03335779, -1.3022),
    (0.05443998, -1.5394),
    (0.04572892, -1.6443),
    (0.049492206, -1.7187),
    (0.05277411, -1.7558),
    (0.17605852, -5.2392),
]

file = sys.argv[1]
band = int(os.path.basename(file)[19:21])
scale_factor = all_scale_factor_and_add_offset[band - 1][0]
add_offset = all_scale_factor_and_add_offset[band - 1][1]
scale = int(sqrt(os.path.getsize(file) / 7500000))
width = 2500 * scale
height = 1500 * scale
radiances = [[0 for _ in range(width)] for _ in range(height)]
min_radiance = 1e9
max_radiance = -1e9
with open(file, 'rb') as f:
    for i in range(width * height):
        x = i % width
        y = i // width
        p = struct.unpack('H', f.read(2))[0]
        radiance = p * scale_factor + add_offset
        radiances[y][x] = radiance
        min_radiance = min(min_radiance, radiance)
        max_radiance = max(max_radiance, radiance)
image = Image.new('RGB', (width, height))
data = image.load()
for y, rs in enumerate(radiances):
    for x, r in enumerate(rs):
        data[x, y] = rgb(min_radiance, max_radiance, r)
image.save(file[:-3] + 'png')