質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

1回答

3916閲覧

デスクトップマスコットの実装に伴うRenderTextureからSystem.Drawing.Imageへの変換

KEEL

総合スコア52

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

1クリップ

投稿2018/08/22 03:51

#実現したいこと
デスクトップマスコットをUnityをベースに作成したい。
透過部分のマウスの挙動は下のウィンドウに反応するようにしたい。
実装はできたがRenderTextureからSystem.Drawing.Imageへの変換処理が重いためできるだけ軽くしたい。
またUnityベースのデスクトップマスコットで同じ挙動の他の方法があれば教えて頂けると幸いです。

#実装
FormCaller.csでTransParentForm.csを呼び、FormCaller.csのOnPostRenderで更新されたRenderTextureを一度Texture2Dに変換し、さらにEncodeToPNGで.pngに変換し、それをSystem.Drawing.ImageのBitmapに変換している。
Profilerを見るとEncodeToPNGが一番重い処理のようでできれば使いたくない。またTexture2Dへの変換でもReadPixelsを使っている。重いのでこれも使いたくない。
できればRenderTextureを一発でBitmapに変換したい。
以下にFormCaller.csとTransParentForm.csとProfilerのスクショを記載する。

cs

1using System.Drawing; 2using System.IO; 3using UnityEngine; 4public class FormCaller : MonoBehaviour 5{ 6 [SerializeField] Vector2 Size; 7 [SerializeField] RenderTexture renderTexture; 8 [SerializeField] Camera mainCam; 9 public System.Drawing.Bitmap Image2paint; 10 TransparentForm f; 11 void Start () 12 { 13 f = new TransparentForm (renderTexture, mainCam); 14 } 15 void OnPostRender () 16 { 17 Texture2D Tex2Paint = new Texture2D (renderTexture.width, renderTexture.height); 18 Tex2Paint.ReadPixels (new Rect (0, 0, renderTexture.width, renderTexture.height), 0, 0); 19 Tex2Paint.Apply (); 20 var img2Paint = new Bitmap (renderTexture.width, renderTexture.height); 21 MemoryStream memoryStream = new MemoryStream (); 22 var img = Tex2Paint.EncodeToPNG (); 23 memoryStream.Write (img, 0, img.Length); 24 25 Image2paint = new System.Drawing.Bitmap (memoryStream); 26 f.Image2paint = Image2paint; 27 } 28 void OnDisable () 29 { 30 f.Close (); 31 } 32}

cs

1using System.Collections; 2using System.Collections.Generic; 3using System.ComponentModel; 4using System.Drawing; 5using System.IO; 6using System.Windows.Forms; 7using UnityEngine; 8 9public class TransparentForm : Form 10{ 11 RenderTexture tex; 12 public System.Drawing.Bitmap Image2paint; 13 Point mousePoint; 14 public TransparentForm (RenderTexture Rendertex, Camera main) 15 { 16 tex = Rendertex; 17 main.targetTexture = tex; 18 19 this.SetStyle (ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw, true); 20 this.SetBounds (0, 0, tex.width, tex.height); 21 22 this.BackColor = System.Drawing.Color.Black; 23 this.TransparencyKey = System.Drawing.Color.Black; 24 this.FormBorderStyle = FormBorderStyle.None; 25 this.TopMost = true; 26 27 this.MouseDown += new MouseEventHandler (Form1_MouseDown); 28 this.MouseMove += new MouseEventHandler (Form1_MouseMove); 29 30 this.Show (); 31 } 32 protected override void OnPaint (PaintEventArgs e) 33 { 34 base.OnPaint (e); 35 e.Graphics.DrawImage (Image2paint, 0, 0, tex.width, tex.height); 36 this.Invalidate (); 37 } 38 private void Form1_MouseDown (object sender, 39 System.Windows.Forms.MouseEventArgs e) 40 { 41 if ((e.Button & MouseButtons.Left)== MouseButtons.Left) 42 { 43 mousePoint = new Point (e.X, e.Y); 44 } 45 } 46 47 private void Form1_MouseMove (object sender, 48 System.Windows.Forms.MouseEventArgs e) 49 { 50 if ((e.Button & MouseButtons.Left)== MouseButtons.Left) 51 { 52 this.Left += e.X - mousePoint.X; 53 this.Top += e.Y - mousePoint.Y; 54 } 55 } 56}

![Profiler画面]

#試したこと
EncodeToPNGをEncodeToJPGに変えてみたがノイズが発生するため不採用。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

自己解決

自己解決したので記載します。
色々試しましたが結局自前でbyte配列を書くのが一番速いです。
RGBAそれぞれのbyteが各ピクセルに必要なのでwidth*heightの4倍サイズのbyte[]を用意します。
bitmapはBGRAなのでそのようにbyte[]を書きます。

cs

1Texture2D Tex2Paint = new Texture2D (renderTexture.width, renderTexture.Tex2Paint.ReadPixels (new Rect (0, 0, renderTexture.width, renderTexture.height), 0, 0, false); 2Tex2Paint.Apply (); 3 4Color32[] pixels = Tex2Paint.GetPixels32 (); 5 6Bitmap bitmap = new Bitmap (renderTexture.width, renderTexture.height); 7BitmapData data = bitmap.LockBits ( 8 new Rectangle (0, 0, bitmap.Width, bitmap.Height), 9 ImageLockMode.ReadWrite, 10 PixelFormat.Format32bppArgb); 11byte[] colorbytes = new byte[renderTexture.width * renderTexture.height * 4]; 12 13Marshal.Copy (data.Scan0, colorbytes, 0, colorbytes.Length); 14for (int i = 0; i < pixels.Length; i++) 15{ 16 colorbytes[4 * i] = pixels[i].b; 17 colorbytes[4 * i + 1] = pixels[i].g; 18 colorbytes[4 * i + 2] = pixels[i].r; 19 colorbytes[4 * i + 3] = pixels[i].a; 20} 21Marshal.Copy (colorbytes, 0, data.Scan0, colorbytes.Length); 22 23bitmap.UnlockBits (data); 24bitmap.RotateFlip (RotateFlipType.Rotate180FlipX); 25f.Image2paint = bitmap;

投稿2018/08/27 15:08

KEEL

総合スコア52

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問