[C#] 영상 다루기

1. WPF의 System.Windows.Controls.Image 에 이미지 파일 불러오기.

아래의 방법은 프로세스가 파일을 열고 바로 닫는다.

//System.Windows.Controls.Image img_main;
byte[] buffer = System.IO.File.ReadAllBytes(@"file.jpg");  
MemoryStream ms = new MemoryStream(buffer);  
BitmapImage bmi = new BitmapImage();  
bmi.BeginInit();  
bmi.CacheOption = BitmapCacheOption.OnLoad;  
bmi.StreamSource = ms;  
bmi.EndInit();  
img_main.Source = bmi;  

반면, 이 방법은 프로세스가 계속 파일을 핸들링 하고 있다. 따라서 이 방법은 쓰지 않는것을 추천한다.

BitmapImage img = new BitmapImage(new Uri(@"file.jpg"));  
Image.Source = img;  
2. WinForm의 PictureBox.Image 에 이미지 파일 불러오기.

아래의 방법은 프로세스가 파일을 잡고 있지 않는다.

//PictureBox pic_img;
FileStream fs = new FileStream(@"file.jpg", FileMode.Open, FileAccess.Read);  
pic_img.Image = System.Drawing.Image.FromStream(fs);  
fs.Close();  

이 방법은 프로세스가 파일을 계속 핸들링하고 있는다. 비추천한다.

//PictureBox pic_img;
pic_img.Image = System.Drawing.Image.FromFile(@"file.jpg")  
3.System.Drawing.Bitmap 을 byte[] 이미지로 변환.

우선 비트맵 역시 파일에서 불러올때, 아래와 같이 프로세스가 파일을 핸들링 하지 않게 연다.

FileStream fs = new FileStream(@"file.jpg", FileMode.Open, FileAccess.Read);  
System.Drawing.Bitmap bm=(Bitmap)System.Drawing.Image.FromStream(fs);  
fs.Close();  

byte[] 이미지로 변환할때 stride는 제거하는 것이 좋으므로 제거한다. width와 height는 변하지 않는다.
아래의 방법은 임시방편이며, 사실 이미지 포맷에 따라 헤더의 크기를 정확히 잘라야 하는데 아래의 방법은 헤더의 크기가, 이미지의 높이보다 작을꺼란 가정하에 작성된 코드이다.헤더가 이미지 높이보다 크다면 어떻게 될까

byte[] Bitmap2Bytes(Bitmap bm)  
{
    //Bitmap은 상하가 반전되어 있으므로 flip 시킨다.
    bm.RotateFlip(RotateFlipType.RotateNoneFlipY);
    System.IO.MemoryStream stream = new System.IO.MemoryStream();
    bm.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp);
    byte[] bytes = stream.ToArray();
    byte[] newBytes = new byte[bm.Width * bm.Height * 3];

    int rem = (bytes.Length - (bm.Width * bm.Height * 3));  //쓸모없는 바이트 수
    int header = rem % bm.Height;   //bitmap header의 크기
    int stride = rem / bm.Height;  
    for (int h = 0; h < bm.Height; h++)
    {
        int line = header + h * (bm.Width * 3 + stride);
        for (int w = 0; w < bm.Width * 3; w += 3)
        {
            newBytes[h * bm.Width * 3 + w + 0] = bytes[line + w + 0];
            newBytes[h * bm.Width * 3 + w + 1] = bytes[line + w + 1];
            newBytes[h * bm.Width * 3 + w + 2] = bytes[line + w + 2];
        }
    }
    return newBytes;
}