1. 程式人生 > >用Unity做簡易的影象處理軟體(二)

用Unity做簡易的影象處理軟體(二)

這一次添加了水平翻轉、垂直翻轉、順時針旋轉、逆時針旋轉,關閉影象,儲存,退出功能;對RT的建立和銷燬做了一些更改。 介面如下: 演示 儲存演示 儲存 關於選擇的C#部分

public void clockwise()
    {
        clockw = true;
        rotate();
    }
    public void anticlockwise()
    {
        anclockw = true;
        rotate();
    }

private void rotate()//旋轉shader更新
    {
        if (Gamevars.
textureisable) { rotatematerial.SetInt("_Clockwise", clockw ? 1 : 0); rotatematerial.SetInt("_AnuiClockwise", anclockw? 1:0); RenderTexture Disttexture =RenderTexture.GetTemporary(texture.height, texture.width, 0);//因為旋轉之後寬高對調 Graphics.Blit(texture,
Disttexture, rotatematerial); int width = Disttexture.width; int height = Disttexture.height; Gamevars.imagewidth = width; Gamevars.imageheight = height;//更新控制結構體 Viewtexture = new Texture2D(width, height, TextureFormat.ARGB32, false); RenderTexture.
active = Disttexture; Viewtexture.ReadPixels(new Rect(0, 0, width, height),0, 0); Viewtexture.Apply(); RenderTexture.active = null; RenderTexture.ReleaseTemporary(Disttexture); texture = Viewtexture; updateBSC(); image.GetComponent<RectTransform>().sizeDelta = new Vector2(width,height); Sprite sprite = Sprite.Create(Viewtexture, new Rect(0, 0,width, height), new Vector2(0.5f, 0.5f)); image.sprite = sprite; Refresh(); } clockw = false; anclockw = false; }

shader部分非常簡單

Shader "myshaders/rotate"
{
	Properties
	{
		_MainTex ("_MainTex", 2D) = "white" {}
	}
		SubShader
		{
			Pass
			{
				ZTest Always Cull Off ZWrite Off
				CGPROGRAM
				#pragma vertex vert
				#pragma fragment frag
				#include "UnityCG.cginc"
				sampler2D _MainTex;
				int _Clockwise;
				int _AnuiClockwise;
			struct v2a
			{
				float4 vertex : POSITION;
				float2 texcoord : TEXCOORD0;
			};

			struct v2f
			{
				float2 uv : TEXCOORD0;
				float4 pos : SV_POSITION;
			};
			v2f vert (v2a v)
			{
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				o.uv = v.texcoord;
				return o;
			}
			fixed4 frag (v2f i) : SV_Target
			{
			if(_Clockwise==1){
				i.uv=mul(float2x2(0,-1,1,0),i.uv);
			}
			if(_AnuiClockwise==1){
				i.uv=mul(float2x2(0,1,-1,0),i.uv);
			}
			fixed4 renderTex = tex2D(_MainTex,i.uv);
			return fixed4(renderTex);
			}
			ENDCG
		}
	}
			Fallback Off
}

翻轉的C#部分

public void horizon()
    {
        overturnX = true;
        Overturn();
    }
    public void vertical()
    {
        overturnY = true;
        Overturn();
    }
 private void Overturn()//翻轉shader更新
    {
        if (Gamevars.textureisable)
        {
            overturnmaterial.SetInt("_Horizon", overturnX ? 1 : 0);
            overturnmaterial.SetInt("_Vertical", overturnY ? 1 : 0);
            RenderTexture Disttexture = RenderTexture.GetTemporary(texture.width, texture.height, 0);
            Graphics.Blit(texture, Disttexture, overturnmaterial);
            int width = Disttexture.width;
            int height = Disttexture.height;
            Viewtexture = new Texture2D(width, height, TextureFormat.ARGB32, false);
            RenderTexture.active = Disttexture;
            Viewtexture.ReadPixels(new Rect(0, 0, width, height), 0, 0);
            Viewtexture.Apply();
            RenderTexture.active = null;
            RenderTexture.ReleaseTemporary(Disttexture);
            texture = Viewtexture;//因為旋轉之後,仍需要其他shader參與
            updateBSC();
            image.GetComponent<RectTransform>().sizeDelta = new Vector2(Viewtexture.width, Viewtexture.height);
            Sprite sprite = Sprite.Create(Viewtexture, new Rect(0, 0, Viewtexture.width, Viewtexture.height), new Vector2(0.5f, 0.5f));
            image.sprite = sprite;
            Refresh();
        }
        overturnX = false;
        overturnY = false;
    }

翻轉的shader部分

Shader "myshaders/overturn"
{
	Properties
	{
		_MainTex ("_MainTex", 2D) = "white" {}
	}
		SubShader
		{
			Pass
			{
				ZTest Always Cull Off ZWrite Off
				CGPROGRAM
				#pragma vertex vert
				#pragma fragment frag
				#include "UnityCG.cginc"
				sampler2D _MainTex;
				int _Horizon;
				int _Vertical;
			struct v2a
			{
				float4 vertex : POSITION;
				float2 texcoord : TEXCOORD0;
			};

			struct v2f
			{
				float2 uv : TEXCOORD0;
				float4 pos : SV_POSITION;
			};
			v2f vert (v2a v)
			{
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				o.uv = v.texcoord;
				return o;
			}
			fixed4 frag (v2f i) : SV_Target
			{
			if(_Horizon==1){
				i.uv.x=1-i.uv.x;
			}
			if(_Vertical==1){
				i.uv.y=1-i.uv.y;
			}
			fixed4 renderTex = tex2D(_MainTex,i.uv);
			return fixed4(renderTex);
			}
			ENDCG
		}
	}
			Fallback Off
}

這兩個功能的實現都非常簡單,尤其是shader部分,但是我現在遇到了一個問題,當對一張圖片進行大量操作之後,記憶體佔用量很大 現在我的方法是在關閉影象的時候趁機重新載入一次scene

public void fileclose()
    {
        if (Gamevars.textureisable)
        {
            Gamevars.textureisable = false;
            selectfile.gameObject.SetActive(true);
            Gamevars.size = 1;
            size1.text = ((int)(Gamevars.size * 100)).ToString() + "%";
            image.color = new Color32(255, 255, 255, 0);
            image.transform.position = new Vector3(0, 720, 0);
            slider1.value = 1;
            slider2.value = 1;
            slider3.value = 1;
            SceneManager.LoadScene(0);
        }
    }

關於記憶體佔用問題有什麼好方法的話,還請大佬給我留言 最後儲存程式碼

public void savefile()
    {
        if (Gamevars.textureisable)
        {
            
            SaveFileDialog dialog = new SaveFileDialog();
            dialog.Title = "請選擇儲存位置";
            dialog.Filter = "影象檔案(*.png)|*.png";
            if (dialog.ShowDialog() == DialogResult.OK)
            {
                byte[] bytes = Viewtexture.EncodeToPNG();
                File.WriteAllBytes(dialog.FileName, bytes);
            }

        }
    }

目前只能儲存為PNG格式。。 在下一次,我會新增裁剪功能,和解決記憶體佔用問題。上課去了。。。