August 18, 2010

C# Create CSV File using StreamWriter

안녕하세요 이동규(LiveDK)입니다.

 

ListView에 있는 데이터를 파일로 저장하려하는중 엑셀파일을 이용하여 쓰기를 시도하였으나 이는 대상 컴퓨터에 동일한 버전의 Excel 이 설치 되어 있지 않으면 읽고 쓰기에 어려움이 있어 CSV 를 이용하여 파일 작성을 해보았습니다.

 

파일 작성을 위해 StreamWriter 를 이용해보았습니다. 상당히 간단하기 때문에 별다른 설명 없이 코드만 첨부 하겠습니다.

 

StreamWriter sw = new StreamWriter("aa.csv", false, Encoding.Unicode);

foreach (ListViewItem lvi in listView_score.Items)

{

      sw.WriteLine(lvi.Text + "\t" + lvi.SubItems[1].Text);

}

sw.Close();

(코드.1)

 

(출력.1)

 

 

+ 추가1, 각각의 칸이동은(좌우) 탭을 넣어주면됩니다(\t)

+ 추가2, 각줄의 이동은 WriteLine 을 이용하였기 때문에 자동이지요 :) (\r) 하시면 됩니다.

August 4, 2010

Linq to SQL - join Different Data Context

안녕하세요 LiveDK(이동규) 입니다.

 

Linq to SQL을 사용하는중 서로다른 Database 서버에서 DataContext를 가져와 Join 을 하게될 경우가 생겼었습니다. 기존처럼(코드.1) 단순히 Join 을 해서는 아래와 같은 에러가(에러.1) 발생을 하게됩니다.

 

DBDBDataContext DC_ONE = new DBDBDataContext();

LotteDBDataContext DC_TWO = new LotteDBDataContext();

 

var result = from A in DC_ONE.MovieStatisticsDays

            join B in DC_TWO.tbMovieInfos on A.MovieInfoCode equals B.contentsCode

            select B;

 

dataGridView1.DataSource = result;

dataGridView1.Refresh();

(코드.1)

 

한글 : 쿼리에 다른 데이터 컨텍스트에서 정의된 항목에 대한 참조가 포함되어 있습니다.

영문 : The query contains references to items defined on a different data context

(에러.1)

 

Linq 에서 서로다른 Data Context 를 함께 사용하지 못하는듯 합니다. 하지만 아래와 같이(코드.2) 처럼 각각 Data Context를 따로 실행하고 ToList() 를 사용하여 로컬 컴퓨터에서 실행하게 되면 두개의 DataContext를 사용할 수 있습니다. (성능은 장담 못드리네요ㅎ)

 

DBDBDataContext DC_ONE = new DBDBDataContext();

LotteDBDataContext DC_TWO = new LotteDBDataContext();

 

var one = (from A in DC_ONE.MovieStatisticsDays select A).ToList();

 

var two = (from B in DC_TWO.tbMovieInfos select B).ToList();

 

var result = (from A in one

              join B in two on A.MovieInfoCode equals B.contentsCode

              select B).ToList();

(코드.2)

 

 

August 2, 2010

뉴미디어 & WPF - MediaElement Sync

안녕하세요 LiveDK(이동규) 입니다.

 

(그림.1)

 

 저는 현재 뉴미디어쪽에서 새로운것을 배우고 활용하고 있는 곳에서 일을 하고 있습니다. 이 곳에서 프로젝트를 진행중에 두개의 미디어를 동시에 재생하게될 경우가 생겼었습니다. 제가 이방법을 고안하기 전까지 기존에는 이미지 시퀀스라는 방식을 사용해 왔었습니다. 이미지 시퀀스란 동영상을 프레임별로 고화질의 이미지로 저장시키고 이 이미지를 를 빠르게 순서대로 화면에 뿌리는 것입니다. 정해진 순서가 있기때문에(인덱스를 알고 있으므로) 동시에 다른곳에서도 같은 화면을 재생하는것이 쉬웠습니다. 하지만 일반 하드디스크 나아가 SSD를 사용한다 해도 버벅이는 현상을 피할 수가 없습니다. 해결방법으로는 램디스크에 이미지들을 로드하여 플레이 하는것입니다. 이러한 이미지 시퀀스를 통해 동영상의 동기화를 맞추는 방법은 화질이 좋다는 장점이 있지만 그보다 여러 세팅문제,끊김문제등으로 인해 단점이 더 크다고 볼 수 있습니다.

 이러한 문제를 인식하고 동영상 원본을 그대로 활용하여 미디어의 동기화를 맞추는 방법을 생각해 보았습니다. (그림.1)과 같이 WPF를 이용하여 두개의 MediaElement 를 띄워 같은영상을 반으로 자른 영상을 플레이 하는것입니다. 기본틀은 (코드.1)와 같이 그리드 내에 두개의 MediaElement 가 있으며 시간을 표시하기위한 TextBlock이 존재합니다.

 

(코드.1)

 

생각1. MediaElement 의 Position 속성을 이용하여 재생하기

 

동시에 영상을을 재생하기 위해 단순히 생각한 결과는? 그래 동시에 같은 위치를 맞춰주면 되겠지! 라고 생각하여 MediaElement 의 Position 속성을 이용해 보았습니다. (코드.2)와 같이 일정한간격으로 기준이 되는 영상의 현재 Position을 다른 영상에 대입함으로서 같은 재생 위치를 맞추는 것입니다.

 

(코드.2)

 

타이머를 이용하여 1초에 10번을 싱크를 맞추는 코드입니다. 기준이 되는 media_01 의 Position을 media_02에 대입하여 같은 부분을 재생해보려고 하였습니다. 하지만 결과는 굉장히 처참합니다. 오히려 안하니만 못하는 결과를 볼 수 있을 것입니다. 문제점은 바로 Position 속성입니다. 이 속성은 한번 대입하게 되면 바로 적용 되는것이 아니라 인터넷에서 동영상 Seek 하듯이 딜레이가 발생하게 되어 속도가 점점 느려저버리게 됩니다. 혹시 이런 의문이 드신다면? - 최초 한번만 맞추면 되지 않느냐? 대답은 아니요 입니다. 동시에 재생되었다고 하더라고 시간이 지나면 점점 차이가 나게 되며 컴퓨터 프그램이다 보니 플레이 재생상에 딜레이가 발생할 수 있으므로 주기적으로 맞춰줘야 처음부터 끝까지 싱크를 맞출 수 있습니다. 이 방법은 실패로 돌아 갔습니다.

 

생각2. MediaElement 의 SpeedRatio 속성을 이용하여 재생하기

 

MediaElement의 SpeedRatio 속성은 미디어의 재생 속도를 조절 할 수 있습니다. double 형의 값으로 기본값은 1입니다. 이보다 높으면 재생속도가 빨라지면 반대라면 느리게 재생이 되게 됩니다. (코드.3)과 같이 일정한 간격마다 기준영상의 시간과 상대영상의 시간을 비교하여 기준영상보다 빠르다면 SpeedRatio 를 줄여 느리게 재생하고, 기준보다 느리다면 SpeedRatio 를 증가시켜 따라 잡는 알고리즘(?) 입니다.

 

(코드.3)

 

테스트 결과 생각.1 보다 만족하는 결과을 얻을 수 있음을 볼 수 있습니다. 두개의 미디어의 차이를 조금씩 맞춰 나가게 되는데, 좀더 각격을 잘 조절하고 차이값에 따라 SpeedRatio 를 조절한다면 완벽한 미디어 동기화를 만들 수 있을 것입니다.

 

이로서 두개의 미디어 싱크를 맞추는 방법에대해서 알아 보았습니다. 이외에도 다른 방법들로 미디어의 동기화를 맞추는 프로그램이 존재하겠지만 WPF 를 사용하여 간단하게 구현 해 볼 수 있습니다.

 

아래 링크에서 프로젝트 + 샘플영상(2개) 를 받으 실 수 있습니다.