こんそーるすーぷのレシピはこちら

いちおう仕事なのに趣味の人に劣って焦り

【Unity】Windows, Macで画像を印刷する方法

Windows, Macからデフォルトのプリンター設定を呼び出して印刷をやったのでメモとして残します。

検証環境
Unity : 2017.3.0f3
Mac : Sierra 10.12.6
Windows : Windows10, Windows7

はじめに

WindowsでもMacでも画像を印刷する際にパスの指定が必要になるため、画像の保存が必要です。
念のため記載しておきます。

Texture2Dをタイムスタンプをファイル名としてpngで保存します。
保存先はアクセス可能な場所である必要があります。

using UnityEngine;
using System.IO;

public class hogehoge
{
    public string SaveTexture2D(Texture2D texture2D)
    {
        byte[] bytes = texture2D.EncodeToPNG();
        string fileName = "image_" + (System.DateTime.Now.Ticks / 10000000) + ".png";
        string filePath = "hogehoge/hoge/"+fileName;
        if (bytes != null && 0 < bytes.Length) File.WriteAllBytes(filePath, bytes);
        else filePath = null;
        
        return filePath;
    }
}

Macで印刷する方法

Macだとlprコマンドで印刷するのが楽です。

using UnityEngine;
using System.Diagnostics;

public class hogehoge
{
    public delegate void PrintCallBack(string message);

    public void Print(string filePath, PrintCallBack callback)
    {
        if (callback == null) return;
        if (filePath == null)
        {
            callback("filePath is null");
            return;
        }

        string cmd = "lpr "+filePath;
        
        var process = new Process();
        process.StartInfo.FileName = "/bin/bash";
        process.StartInfo.Arguments = "-c \" " + cmd + " \"";
        process.StartInfo.UseShellExecute = false;
        process.StartInfo.RedirectStandardOutput = true;
        process.Start();

        string output = process.StandardOutput.ReadToEnd();
        process.WaitForExit();
        process.Close();
        
        callback();
    }
}

Windows

Windowsだとlprコマンドの場合、ネットワークプリンタのIPと名前が必要だったりと厄介なのでSystem.Drawing.dllを使用します。

以下はdllを使用する上での設定です。

  • Assets以下の階層にPluginsフォルダを作成し、System.Drawing.dllを複製します。
    dllはだいたいここにあります。
    「C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Drawing.dll」
  • File>Build Setting>PlayerSettingsのOther SettingsでOptimizationのApi Compatibility Levelを「.NET2.0」に変更。

もし、VisualStudioが「using System.Drawing」などでエラーを出す場合

ソリューションエクスプローラーのプロジェクト名の下にある参照を開く。
Boo.LangやSystem.hogehogeなどを右クリックし、オブジェクトブラウザーで表示を押す。
オブジェクトブラウザーでSystem.Drawingを選択。
オブジェクトブラウザーの上方にある、+ボタン(ソリューションエクスプローラー内の選択されたプロジェクトに参照を追加)を押す。

using UnityEngine;
using System.Drawing;
using System.Drawing.Printing;

public class hogehoge
{
    public delegate void PrintCallBack(string message);
    private string imagePath = null;
    private PrintCallBack printCallback;

    public void Print(string filePath, PrintCallBack callback)
    {
        if (callback == null) return;
        if (filePath == null)
        {
            callback("filePath is null");
            return;
        }

        imagePath = filePath;
        printCallback = callback;

        //PrintDocumentオブジェクトの作成
        PrintDocument pd = new PrintDocument();

        //PrintPageイベントハンドラの追加
        pd.PrintPage += new PrintPageEventHandler(pd_PrintPage);

        //Print
        pd.EndPrint += new PrintEventHandler(pd_PrintEnd);

        //PrintControllerプロパティをStandardPrintController
        pd.PrintController = new StandardPrintController();
        try
        {
            //印刷を開始する
            pd.Print();
        }
        catch (System.Exception ex)
        {
            if (printCallback != null) printCallback(ex.Message);
            printCallback = null;
        }
    }
    
    //プリントが終了した
    private static void pd_PrintEnd(object sender, PrintEventArgs e)
    {
        if (printCallback != null) printCallback(imagePath);
        printCallback = null;
    }

    //プリント画像を指定する
    private static void pd_PrintPage(object sender, PrintPageEventArgs e)
    {
        //印刷画像を読み込む
        System.Drawing.Image printImg = null;
        if (System.IO.File.Exists(imagePath))
        {
            printImg = System.Drawing.Image.FromFile(imagePath);
            if (printImg != null)
            {
                DrawAspectFillImage(e.Graphics, printImg, new RectangleF(0,//e.PageSettings.PrintableArea.Left,
                                                                         0,//e.PageSettings.PrintableArea.Top, 
                                                                         e.PageSettings.PrintableArea.Width,
                                                                         e.PageSettings.PrintableArea.Height), true);
                printImg.Dispose();
            }
        }
        //次のページがないことを通知する
        e.HasMorePages = false;
    }

    //プリント画像を描画する
    public static void DrawAspectFillImage(System.Drawing.Graphics graphics, Image image, RectangleF rectangle, bool isKeepAspectRatio)
    {
        if (graphics == null) throw new System.ArgumentNullException();
        if (rectangle.Width <= 0 || rectangle.Height <= 0) throw new System.ArgumentOutOfRangeException();
        if (image == null) return;

        Debug.Log("("+rectangle.Left+","+rectangle.Top+") - ("+rectangle.Width+","+rectangle.Height+")");
        var l = rectangle.Left;
        var t = rectangle.Top;
        var w = (float)image.Width;
        var h = (float)image.Height;
        if (isKeepAspectRatio)
        {
            var r = h / w;
            w = rectangle.Height / r;
            h = rectangle.Height;
            if (w > rectangle.Width)
            {
                w = rectangle.Width;
                h = rectangle.Width * r;
            }
            l += (rectangle.Width - w) / 2;
            t += (rectangle.Height - h) / 2;
        }
        graphics.DrawImage(image, l, t, w, h);
    }
}

注意としてはUnityEditorでは動くけど、exeにすると動かない場合は「.NET2.0」の設定を見直してみてください。