올바른 Bitmap To Texture2D





L사 프로젝트를 하면서 사용자의 옷을 실시간으로 분석하여 컬러를 뽑아 그것을 캐릭터화 하는 작업이 있었는데, GdI의  Bitmap 과 유니티의  Texture2D 의 색상을 완벽히 변경 하지 못하여 억지로 로컬에 저장 하였다가 그것을 WWW 로 불러와 넣었었다. 한번에 할 수 있는것을 엄청 번거러운 작업 이었다.


그때 왜 그랬나 이유는 잘 모르겠지만 그 상황을 재현 한 결과 아래와 같이 기술 하면 된다. 유의 할 점은 GDI 의 Format32bppArgb 와 Texture2D 의 ARGB32 는 엄현히 다르다. 그래서 그것을 그대로 넣어주었다가는 언듯 색상은 비슷하나 ,  RGB 원색이 정확히 표현 되지 않아 정확한 색상 전환이 불가하다.


\




using UnityEngine;
using System.Collections;
using System.Drawing;
using System.Drawing.Imaging;
using System;
using System.Runtime.InteropServices;
using XGraphics = System.Drawing.Graphics;

public class TextureColorTest : MonoBehaviour {

    private static string TestFileName = "testCloth.png";
    private Bitmap canvas;
    private Texture2D textureCanvas;
    private bool IsReady = false;

    public Texture2D TestTexture = null;
    public Material TargetMat;

    void Start () {
        canvas = new Bitmap(TestFileName);
        CreateTexture();
    }

    void OnGUI()
    {
        if (IsReady == true)
        {
            GUI.DrawTexture(new Rect(0,0,256, 256), textureCanvas);
        }
    }


    /// <summary>
    /// 새로운 비트맵(32bit PNG)을 불러와 그 위에 색상테스트를 위하여 R , G , B 의 3색 사각형 을 새롭게 그린다음
    /// byte 배열로 전환하여 Texture2D 에 넣는 과정
    /// </summary>
    private void CreateTexture()
    {
        using (XGraphics g = XGraphics.FromImage(canvas))
        {
            g.FillRectangle(Brushes.Red, new Rectangle(50, 50, 10, 10));
            g.FillRectangle(Brushes.Green, new Rectangle(60, 50, 10, 10));
            g.FillRectangle(Brushes.Blue, new Rectangle(70, 50, 10, 10));
        }
        canvas.Save(@"test2.jpg");
        var data = BitmapToByteUseMarshal(canvas);

        textureCanvas = new Texture2D(canvas.Width, canvas.Height, TextureFormat.ARGB32, false);
        textureCanvas.LoadRawTextureData(data);
        textureCanvas.Apply();

        TargetMat.mainTexture = textureCanvas;

        IsReady = true;
    }



    /// <summary>
    /// 완성된 비트맵을 Texture2D 로 넣기 위하여 byte 배열로 변환함
    /// </summary>
    public byte[] BitmapToByteUseMarshal(Bitmap bitmap)
    {
        BitmapData bmpdata = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, bitmap.PixelFormat);
        Debug.Log("format : " + bitmap.PixelFormat);

        int numbytes = bmpdata.Stride * bitmap.Height;
        byte[] bytedata = new byte[numbytes]; 
        byte[] translateBGRAData = new byte[numbytes];

        IntPtr ptr = bmpdata.Scan0;
        Marshal.Copy(ptr, bytedata, 0, numbytes);

        //변환시 배열 순서 유의
        for (int i = 0; i < bytedata.Length; i += 4)
        {
            translateBGRAData[i + 3] = (byte)(bytedata[i + 0]);

            translateBGRAData[i + 2] = (byte)(bytedata[i + 1]);

            translateBGRAData[i + 1] = (byte)(bytedata[i + 2]);

            translateBGRAData[i + 0] = (byte)(bytedata[i + 3]);// 255
        }

        bitmap.UnlockBits(bmpdata);
        return translateBGRAData;
    }
}

Yamecoder 야매코더_
unity3d 2014.09.10 17:31
Powerd by Tistory, designed by criuce
rss