float配列をbyte[4]と見立ててpng保存する

# 目的
 32bit長のfloatの値を、8bit長に分割して、byte[4]として扱い、RGBAのPNGとして保存する手順です。

需要はあまりないと思いますが、自分の場合、こんな思考でした。
・HDRやEXRフォーマットは避けたい
・自分しか使わないので、解像度など決め打ち
・HeightMapで256階調では足りず、もっと細かくしたい
・表示がおかしくてもOSの標準機能で中身をみれたらなぁ
・float値のバイナリ書き出しだと、みれないしなぁ
・pngなら勝手に圧縮してくれる
・CTのようなボリュームデータも扱えそう。

# float値のバイナリ書き出し
5年前、2021年3月30日の、自分の記事を見つけたので、（ショック！）参考にして、

https://qiita.com/hextomino/items/d272bba7cc5ac0fb4941

# コード「floatの精度を捨ててpngとして保存」
まず、ターゲットとするfloatのデータを決める。
32bitから8bitに丸め込まれるので、精度は落ちる。
```java
PImage img;

float[][] f32 = new float[1024][1024];

size(1024, 1024);
noiseSeed(0);
img = createImage(1024, 1024, ARGB);
for (int y=0; y<1024; y++) {
  for (int x=0; x<1024; x++) {
    f32[x][y] = noise(x*0.02, y*0.02)*256;
    img.set(x, y, color(f32[x][y], 255));
  }
}
img.save("F.png");

image(img, 0, 0);
```

![F.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/2b3296f0-49c8-a353-d5c8-80602247c85e.png)

# コード「floatをバイナリで保存して、読み込んで表示」
さっきのnoiseで生成したfloat配列をバイナリで保存し、
それをfloat配列に読み込み直して、imgに描画し、表示する。

ファイル容量は
1024*1024*32/8 = 4,194,304 Byte

zip圧縮したら
3,686,253 Byte

89%に圧縮できた。

```java
import java.io.*;

size(1024, 1024);
noiseSeed(0);

// Prep
float[][] f32 = new float[1024][1024];
for (int y=0; y<1024; y++) {
  for (int x=0; x<1024; x++) {
    f32[x][y] = noise(x*0.02, y*0.02)*256;
  }
}

// Write
try {
  OutputStream os = createOutput("F32_bin.dat");
  DataOutputStream dos = new DataOutputStream(os);
  for (int y=0; y<1024; y++) {
    for (int x=0; x<1024; x++) {
      dos.writeFloat(f32[x][y]);
    }
  }
  dos.flush();
  dos.close();
}
catch(IOException e) {
  e.printStackTrace();
}

// Load
float[][] tmp = new float[1024][1024];
try {
  InputStream is = createInput("F32_bin.dat");
  DataInputStream dis = new DataInputStream(is);
  for (int y=0; y<1024; y++) {
    for (int x=0; x<1024; x++) {
      tmp[x][y] = dis.readFloat();
    }
  }
  dis.close();
}
catch(IOException e) {
  e.printStackTrace();
}

// Display
PImage img = createImage(1024, 1024, ARGB);
for (int y=0; y<1024; y++) {
  for (int x=0; x<1024; x++) {
    img.set(x, y, color(tmp[x][y], 255));
  }
}
image(img, 0, 0);
```


# コード「floatをintに変換してpng保存して、読み込んで表示」

color型がint型であることを利用し、かつ
Float.floatToIntBits
Float.intBitsToFloat
を駆使して、実装。
中間生成物であるpngファイルは、以下の様に見える。

ファイル容量は
3,688,761 Byte
zip圧縮とほぼ同等サイズになった。

```java
import java.io.*;

size(1024, 1024);
noiseSeed(0);

// Prep
float[][] f32 = new float[1024][1024];
for (int y=0; y<1024; y++) {
  for (int x=0; x<1024; x++) {
    f32[x][y] = noise(x*0.02, y*0.02)*256;
  }
}

// Write
PImage img = createImage(1024, 1024, ARGB);
for (int y=0; y<1024; y++) {
  for (int x=0; x<1024; x++) {
    int i32 = Float.floatToIntBits(f32[x][y]);
    img.set(x, y, i32);
  }
}
img.save("F32.png");

// Load
float[][] tmp = new float[1024][1024];
PImage img2 = loadImage("F32.png");
for (int y=0; y<1024; y++) {
  for (int x=0; x<1024; x++) {
    int c = img2.get(x,y);
    tmp[x][y] = Float.intBitsToFloat(c);
  }
}

// Display
PImage img3 = createImage(1024, 1024, ARGB);
for (int y=0; y<1024; y++) {
  for (int x=0; x<1024; x++) {
    img3.set(x, y, color(tmp[x][y], 255));
  }
}
image(img3, 0, 0);
```

![F32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/d5c38ae4-a78b-18fc-144d-823886d09151.png)