반응형

유니티에서 드로우 구현 중 그려진 텍스쳐를 UI 쪽으로 옮겨오는 과정

1. 드로우되는 머트리얼의 RenderTexture를 화면 사이즈로 ReadPixels 하여 Texture2D로 가져온다.

2. ReadPixels로 가져와진 Texture2D에 각 픽섹들을 GetPixel 해서 상하 좌우 필요 없는 부분의 여백을 찾아낸다.

3. 여백많큼 다시 GetPixel 하여 크롭 된 컬러 데이터를 만들어 리사이즈된 Texture2D로 만든다.

4. Sprite.Create로 크롭된 데이터를 Sprite로 만들어준 후 UI Image에 넣어준다.

끝.

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.UI;

public class ScreenShot : MonoBehaviour {
	public EP_DrawPadRT DrawPad;

	private int resWidth;
	private int resHeight;
	public GameObject Pref;
	static int startX, startY, endX, endY;
	static int _width, _height;
	Texture2D screenshot, resizeTexture;
	Image img;
	Rect rect;
	public GameObject GO_Dim;

	private Material DrawMat;

	//===================== Test =======================
	public Button Btn_Capture;
	public GameObject GO_Image;

	// Use this for initialization
	void Start () {
		startX = Screen.width;
		startY = 0;
		endX = 0;
		endY = Screen.height;
		resWidth = Screen.width;
		resHeight = Screen.height;
		if (Btn_Capture)
			Btn_Capture.onClick.AddListener (TakeScreenshot);

		DrawMat = DrawPad.GetComponent<Renderer> ().material;
	}
	bool takeScreenshotOnNextFrame;

	Texture2D toTexture2D (RenderTexture rTex) {
		Texture2D tex = new Texture2D (resWidth, resHeight, TextureFormat.RGBA32, false);

		RenderTexture.active = rTex;
		tex.ReadPixels (new Rect (0, 0, rTex.width, rTex.height), 0, 0);
		return tex;
	}

	Color[] destPix;
	public float warpFactor = 1.0f;

	public void TakeScreenshot () {
		startX = Screen.width;
		startY = 0;
		endX = 0;
		endY = Screen.height;
		resWidth = Screen.width;
		resHeight = Screen.height;

		screenshot = toTexture2D (DrawMat.mainTexture as RenderTexture);

		for (int x = 0; x < resWidth - 2; x++) {
			for (int y = 0; y < resHeight - 2; y++)
				if (screenshot.GetPixel (x, y).a > 0.3f) {
					if (startX > x)
						startX = x;
					if (endY > y)
						endY = y;
				}
		}
		for (int x = resWidth - 2; x > 0; x--) {
			for (int y = resHeight - 2; y > 0; y--)
				if (screenshot.GetPixel (x, y).a > 0.3f) {
					if (endX < x)
						endX = x;
					if (startY < y)
						startY = y;
				}
		}
		_width = endX - startX + 4;
		_height = startY - endY + 4;

		resizeTexture = new Texture2D (_width, _height, TextureFormat.RGBA32, false);

		#region Bilinear-----------------------
		// /*
		destPix = new Color[_width * _height];

		for (int x = 0; x < resWidth; x++) {
			for (int y = 0; y < resHeight; y++) {
				if (x >= startX - 2 && x < endX + 2) {
					if (y >= endY - 2 && y < startY + 2) {
						/*
						// Calculate the fraction of the way across the image
						// that this pixel positon corresponds to.
						float xFrac = x * 1.0f / (resWidth - 1);
						float yFrac = y * 1.0f / (resHeight - 1);

						// Take the fractions (0..1)and raise them to a power to apply
						// the distortion.
						float warpXFrac = Mathf.Pow (xFrac, warpFactor);
						float warpYFrac = Mathf.Pow (yFrac, warpFactor);

						destPix[(y - (endY - 2)) * _width + (x - (startX - 2))] = screenshot.GetPixelBilinear (warpXFrac, warpYFrac);

						// */
						destPix[(y - (endY - 2)) * _width + (x - (startX - 2))] = screenshot.GetPixel (x, y);
						/*
						if (screenshot.GetPixel (x, y).a == 1f) {

							destPix[(y - (endY - 2)) * _width + (x - (startX - 2))] = screenshot.GetPixel (x, y);

						} else if (screenshot.GetPixel (x, y).a > 0 && screenshot.GetPixel (x, y).a < 1f) {
							for (int i = -2; i < 3; i++) {
								for (int j = -2; j < 3; j++) {
									Color col = screenshot.GetPixel (x + i, y + j);
									try {
										if (col.a == 1) {
											if (col.r > 0f || col.g > 0f || col.b > 0f) {
												destPix[(y - (endY - 2)) * _width + (x - (startX - 2))] = new Vector4 (col.r, col.g, col.b, screenshot.GetPixel (x, y).a);
											}
											break;
										}
									} catch (Exception e) {
										Debug.LogError (e);
									}
								}
							}
						} else {
							destPix[(y - (endY - 2)) * _width + (x - (startX - 2))] = new Vector4 (0, 0, 0, 0);
						}
						// */
					}
				}
			}
		}
		resizeTexture.SetPixels (destPix);
		resizeTexture.Apply ();
		screenshot = null;
		Destroy (screenshot);
		// */
		#endregion //Bilinear-----------------------

		GameObject go = Instantiate (Pref);
		go.transform.SetParent (Pref.transform.parent);
		go.transform.localScale = Vector3.one;
		go.transform.localPosition = Vector3.zero;
		go.SetActive (true);

		go.tag = "Editable";
		if (GO_Dim)
			go.GetComponent<PinchMover> ().GO_Dim = GO_Dim;

		rect = new Rect (0, 0, _width, _height);
		img = go.GetComponent<Image> ();
		img.sprite = Sprite.Create (resizeTexture, rect, new Vector2 (0.5f, 0.5f), 100.0f, 0, SpriteMeshType.FullRect, Vector4.zero);
		// img.sprite.
		img.GetComponent<RectTransform> ().SetSizeWithCurrentAnchors (RectTransform.Axis.Horizontal, _width);
		img.GetComponent<RectTransform> ().SetSizeWithCurrentAnchors (RectTransform.Axis.Vertical, _height);
		img.GetComponent<RectTransform> ().anchoredPosition = new Vector2 (startX + _width / 2 - resWidth / 2 - 1, startY - _height / 2 - resHeight / 2 + 3);

		// 로컬에 파일로 저장
		// byte[] bytes = resizeTexture.EncodeToPNG ();
		// fileName = "drawing" + DateTime.Now.TimeOfDay + ".png";
		// System.IO.File.WriteAllBytes (Application.dataPath + "/Resources/" + fileName, bytes);

		if (DrawPad)
			DrawPad.OnClickClear ();

		if (GO_Image)
			GO_Image.SetActive (false);
	}
}

public static class TextureExtentions {
	public static Texture2D ToTexture2D (this Texture texture) {
		return Texture2D.CreateExternalTexture (
			texture.width,
			texture.height,
			TextureFormat.RGBA32,
			false, false,
			texture.GetNativeTexturePtr ());
	}
}
반응형

+ Recent posts