LemonteaのUnity部屋

C#とかのお話です~

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の○乗です。
ちなみに、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