.NET MAUI - 画像保存をプラットフォームに合わせて動作させる方法のアイキャッチ画像

.NET MAUI – 画像をプラットフォームに合わせて保存する方法について

.NET MAUIで画像保存する方法を紹介していきます。

.NET MAUIではプラットフォームごとに処理を分けることができます。当記事ではプラットフォーム別に画像保存する方法を紹介していきます。

対応環境

当記事は以下の環境で作成しています。

  • Visual Studio 2022
  • .Net 7

はじめに

プラットフォーム別に画像保存する方法を紹介していきます。画像はByte配列に変換されていることを想定しています。

プラットフォーム別に処理を行いたい場合、以下の記事を参考にしてください。以下の記事はDIを利用してプラットフォーム別に処理を分けています。

DIのインターフェイス

DIに利用するインターフェイスは、次のようになります。

// 名前空間はプロジェクトに合わせてください。
namespace SampleDrawing.DI;

internal interface IImageWriter
{
    Task WriteAsync(string fileName, byte[] imageBytes);
}

画像保存(Windows版)

Windowsの画像保存する方法は次のようになります。Byte配列をMemoryStreamクラスに変換してBitmapクラスで画像保存を行います。

Bitmapクラスは「System.Drawing.Common」のパッケージをインストールする必要があります。

保存場所を「ピクチャ\アプリ名」にしていますが、変更しても問題ありません。

using System.Drawing;

// 本記事の場合
using SampleDrawing.DI;

// 名前空間はプロジェクトに合わせてください。
namespace SampleDrawing.Platforms.Windows.DI;

internal class ImageWriter : IImageWriter
{
    public Task WriteAsync(string fileName, byte[] imageBytes)
    {
        // 拡張子付与
        fileName = Path.ChangeExtension(fileName, ".png");

        // 「ピクチャ\アプリ名」のパスを指定
        string pictures = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), AppInfo.Current.Name);
        // 「アプリ名」フォルダが無い時に作成
        if (!Directory.Exists(pictures))
        {
            Directory.CreateDirectory(pictures);
        }

        // 画像保存
        using MemoryStream memoryStream = new(imageBytes);
        Bitmap bitmap = new(memoryStream);
        bitmap.Save(Path.Combine(pictures, fileName), System.Drawing.Imaging.ImageFormat.Png);
        return Task.CompletedTask;
    }
}

「System.Drawing.Common」のパッケージをインストールする方法

ソースから「System.Drawing.Common」のパッケージをインストールする方法を紹介します。この方法を利用する場合、「using System.Drawing;」の行は削除しておいてください。

まずは、以下のようサンプルソースをコピーし、ソース内の「Bitmap」にカーソルを合わせます。次に電球マークが表示されますので選択します。

「System.Drawing.Common」のパッケージをインストール手順①、手順②

次に、「パッケージ ‘System.Drawing.Common’ のインストール」を選択し、展開されたメニューから「最新バージョンの検索とインストール」を選択します。

「System.Drawing.Common」のパッケージをインストール手順➂、手順➃

少し待つと以下のようになっていればパッケージのインストールは完了になります。

「System.Drawing.Common」のパッケージをインストール完了

画像保存(Android版)

Androidの画像保存する方法は次のようになります。

画像保存にはMediaStore APIを利用しています。MediaStoreAPIを利用することでメディアファイルに保存されます。

MediaStoreAPIはAndroid 10(APIレベル 29)以降で利用できます。Android 9(APIレベル 28)以前では利用できません。

using Android.Content;
using Android.OS;
using Android.Provider;
using Java.IO;
using Uri = Android.Net.Uri;

// 本記事の場合
using SampleDrawing.DI;

// 名前空間はプロジェクトに合わせてください。
namespace SampleDrawing.Platforms.Android.DI;

internal class ImageWriter : IImageWriter
{
    public async Task WriteAsync(string fileName, byte[] imageBytes)
    {
        // 拡張子付与
        fileName = Path.ChangeExtension(fileName, ".png");

        // メディアファイルの準備
        ContentValues contentValues = new();
        contentValues.Put(MediaStore.IMediaColumns.DisplayName, fileName);
        contentValues.Put(MediaStore.IMediaColumns.MimeType, "image/png");
        contentValues.Put(MediaStore.IMediaColumns.RelativePath, $"DCIM/{AppInfo.Current.Name}");

        ContentResolver contentResolver = Platform.CurrentActivity.ContentResolver;
        Uri imageUri = contentResolver.Insert(MediaStore.Images.Media.ExternalContentUri, contentValues);
        using (ParcelFileDescriptor parcelFile = contentResolver.OpenFileDescriptor(imageUri, "w"))
        {
            // 画像保存
            using (FileOutputStream fileOutput = new(parcelFile.FileDescriptor))
            {
                await fileOutput.WriteAsync(imageBytes, 0, imageBytes.Length);
            }
        }
    }
}

保存された画像を確認

「ファイル」アプリを利用することで以下のように確認できます。表示方法は端末ごとに異なりますので、お手元の端末で確認してみてください。

androidの「ファイル」アプリの表示例

画像保存(iOS)

iOSの画像保存する方法は次のようになります。画像保存の部分は、macOSと同じ方法になります。

保存場所はアプリに関連付けるためにドキュメントフォルダにしています。

// 本記事の場合
using SampleDrawing.DI;

// 名前空間はプロジェクトに合わせてください。
namespace SampleDrawing.Platforms.iOS.DI;

internal class ImageWriter : IImageWriter
{
    public async Task WriteAsync(string fileName, byte[] imageBytes)
    {
        // 拡張子付与
        fileName = Path.ChangeExtension(fileName, ".png");

        // ドキュメントのパスを指定
        string documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);

        // 画像保存
        using FileStream fileSystem = new(Path.Combine(documents, fileName), FileMode.OpenOrCreate);
        await fileSystem.WriteAsync(imageBytes, 0, imageBytes.Length);
    }
}

iOSの「ファイル」アプリでドキュメントフォルダを確認できるようにするために「Info.plist」に以下の設定を追加します。

  • UIFileSharingEnabled:true
  • LSSupportsOpeningDocumentsInPlace:true

「Info.plist」にUIFileSharingEnabled:trueとLSSupportsOpeningDocumentsInPlace:trueを追加した内容は以下のようになります。

<plist version="1.0">
<dict>
		<!-- ===== 略 ===== -->
	<key>LSSupportsOpeningDocumentsInPlace</key>
	<true/>
	<key>UIFileSharingEnabled</key>
	<true/>
</dict>
</plist>

エディターを利用して「Info.plist」を編集する方法

Visual Studio 2022には、「Info.plist」のアクセス許可を編集するためにGeneric PList Editorが存在します。UIFileSharingEnabled:trueとLSSupportsOpeningDocumentsInPlace:trueを追加するには、以下のようにします。

1.「Info.plist」のコンテキストメニューから「ファイルを開くアプリケーションの選択」を選択します。

「Info.plist」のコンテキストメニューから「ファイルを開くアプリケーションの選択」を選択

2.「Generic PList Editor」を選択し、「OK」を選択します。

「Generic PList Editor」を選択

3.UIFileSharingEnabled:trueとLSSupportsOpeningDocumentsInPlace:trueを以下の画像のように追加します。Valueは「Yes」にすることでtrueになります。

Generic PList EditorでUIFileSharingEnabled:trueとLSSupportsOpeningDocumentsInPlace:trueを選択

保存された画像を確認

保存された画像を確認するためには、「ファイル」アプリを利用します。

まずは、「ファイル」アプリを起動し「ブラウズ」を選択します。次に「このiPhone内」を選択します。

保存した画像の手順①、手順②

次に、以下のようにアプリ名のフォルダが表示されているので選択します。

保存した画像のアプリ名のフォルダを選択

以下のように保存した画像が表示されます。

保存した画像を確認

画像保存(macOS)

macOSの画像保存する方法は次のようになります。画像保存の部分はiOSと同じ方法になります。

保存場所を「書類\アプリ名」にしていますが、変更しても問題ありません。

// 本記事の場合
using SampleDrawing.DI;

// 名前空間はプロジェクトに合わせてください。
namespace SampleDrawing.Platforms.MacCatalyst.DI;

internal class ImageWriter : IImageWriter
{
    public async Task WriteAsync(string fileName, byte[] imageBytes)
    {
        // 拡張子付与
        fileName = Path.ChangeExtension(fileName, ".png");

        // 「書類\アプリ名」のパスを指定
        string documents = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), AppInfo.Current.Name);
        // 「アプリ名」フォルダが無い時に作成
        if (!Directory.Exists(documents))
        {
            Directory.CreateDirectory(documents);
        }

        // 画像保存
        using FileStream fileSystem = new(Path.Combine(documents, fileName), FileMode.OpenOrCreate);
        await fileSystem.WriteAsync(imageBytes, 0, imageBytes.Length);
    }
}

おわりに

今回紹介した画像保存機能を以下の記事で利用してみました。お絵描きした絵を画像として保存しています。良ければ見てください!!

また、保存ダイアログを利用したい場合、以下の記事で紹介していますので良ければ見てください!!