Xamarin Bitmapを作成して保存する

こんにちは。レモンティーです。

今回は、Bitmapを作成して保存します。

ユーザーの描いた絵を保存したい時とかですね。
今回はAndroid.GraphicsのBitmapを使うので
もしFormsから使う場合はDependencyServiceで呼ぶことになります。
www.sawalemontea.com


さっそく作成と保存をやっていきます。
まず

using Android.Graphics;
using System.IO;

としておいて
Bitmapを作成

var bitmap = Bitmap.CreateBitmap(colors,width,height, Bitmap.Config.Argb8888);

Bitmapを保存

 using (var filestream = new FileStream(filepath,FileMode.Create))
 {
     bitmap.Compress(Bitmap.CompressFormat.Png, 100, filestream);
 }

でできます。

以下、作成時の引数を補足します。

Bitmap.CreateBitmap(colors,width,height,Bitmap.Config.Argb8888)

width height は作成されるBitmapの大きさです。

そしてそのwidth*height個のマスにセットされる
色のデータのint配列がcolorsです。

色のデータのint配列、と言いましたが
色をどのようにintで表現するのでしょうか。
それを指定するのがBitmap.Configです。

たとえばArgb8888では、あるマスの色を
アルファ値、赤、緑、青
の4つの要素で表現し、
それぞれが8ビット…つまり0~255の256段階で表されます。

各要素は16進数二桁なので、
これをARGBの順に並べて10進数に直せば
colorsのそのマスの分のintが求まります。
例えば 
ff8b33ca は 4287312842 です…
…が、変な手間がかかってるので
もっといいやりかたがあるかもしれません。

一応、この考え方の場合の
colors用の色のintデータの求め方を以下に書いておきますが、
ちゃんとしたい場合は調べてみてください…

private int GetIntColor(byte a,byte r,byte g,byte b)
    {
        var a2 = a % 16;
        var a1 = (a - a2) / 16;
        var r2 = r % 16;
        var r1 = (r - r2) / 16;
        var g2 = g % 16;
        var g1 = (g - g2) / 16;
        var result = 268435456 * a1 + 16777216 * a2 +
            1048576 * r1 + 65536 * r2 +
            4096 * g1 + 256 * g2 +
            b;
        return result;
    }

268435456とかは16の○乗です。やばいですね。
あるいはこんなとか…?

private int GetIntColor(byte a,byte r,byte g,byte b)
    {
        return 16777216 * a + 65536 * r + 256 * g + b;
    }

ちなみに、Xamarin.FormsのColorから変換する場合は
A,R,G,Bプロパティをそれぞれ255倍してから同様に変換すればできます。


なので例えば以下のようにすると
グラデーションのBitmapが作成and保存できます。

var width = 128;
var height = 128;
var colors = new List<int>();            

for (int h = 0; h < height; h++)
{
    for (int w = 0; w < width; w++)
    {
        colors.Add(GetIntColor(255,(byte)(h%256),(byte)(w%256),0));
    }
}

var bitmap = Bitmap.CreateBitmap(colors.ToArray(),width,height, Bitmap.Config.Argb8888);

using (var filestream = new FileStream(filepath,FileMode.Create))
{
    bitmap.Compress(Bitmap.CompressFormat.Png, 100, filestream);
}

f:id:sawalemontea:20180423182937p:plain

たしかに青はずっと0、アルファはずっと255で
右ほど緑が強く、下ほど赤が強くでていますね。

今回はこれでおしまいです。
www.sawalemontea.com

www.sawalemontea.com