Tech/WPF2011. 5. 3. 17:26

WPF에서 GDI를 이용하여 이미지를 생성할 수 있다.
Graphics객체를 통해, 도형이나 선, 텍스트, 이미지 등을 그릴 수 있다.

참고 (http://msdn.microsoft.com/ko-kr/library/system.drawing.graphics.aspx)

아래의 예제는 파일목록들을 얻어와서 1000*1000크기의 Bitmap객체에 이미지들을 추가하여 이미지를 생성하는 코드이다.

 private void Button_Click(object sender, RoutedEventArgs e)
         {
            Bitmap bitmap = new Bitmap(1000, 1000);
             Graphics g = Graphics.FromImage(bitmap);

            float x = 0;
            float y = 0;
            DateTime start = System.DateTime.Now;
            for(int i = 0; i< this.imageList.Count; i++)
             {
                try
                {
                    System.Drawing.Image image = System.Drawing.Image.FromFile(this.imageList[i]);

                    g.DrawImage(image, x, y, 100, 100);
                     x += 20;
                    y += 20;
                    bitmap.Save(System.IO.Path.Combine(this.outputFolderPath, "test" + i.ToString() + ".png"));
                 }
                catch (Exception)
                {
                    //파일 경로중 이미지가 아닌 파일의 경우 Image객체를 생성할 때, 예외가 발생한다.
                     continue;
                }
            }
            
            System.Diagnostics.Debug.WriteLine("elapsed :" + System.DateTime.Now.Subtract(start).TotalSeconds.ToString());
}

 

'Tech > WPF' 카테고리의 다른 글

WPF 화면에 보여지는 이미지 삭제하기  (1) 2010.10.29
[WPF 3D UI 구현하기 - 3]  (1) 2009.11.12
[WPF 3D UI 구현하기 - 2]  (0) 2009.11.12
[WPF 3D UI 구현하기 - 1]  (2) 2009.11.11
Posted by 알 수 없는 사용자
Tech/WPF2010. 10. 29. 17:06
WPF에서 이미지를 보여줄 때 Image 태그의 Source를 설정해서 보여주는 방식을 사용한다.

이때 로딩된 이미지 파일을 삭제하려고 하면, Exception이 발생한다.
이것은 이미지의 Source를 null로 설정하여도 동일하게 발생하는데 
이를 해결하기 위해서 이미지 Source의 Cache 옵션을 설정하여 해결할 수 있다.

1
2
3
4
string filepath = @"c:\test.jpg";
this.img.Source = new BitmapImage(new Uri(filepath, UriKind.RelativeOrAbsolute));
this.img.Source = null;
File.Delete(filepath);
!!!Exception 발생


1
2
3
4
5
6
7
8
9
10
11
string filepath = @"c:\test.jpg";

BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.CacheOption = BitmapCacheOption.OnLoad;
bi.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
bi.UriSource = new Uri(filepath);
bi.EndInit();
img.Source = bi;

File.Delete(filepath);
정상적으로 파일이 삭제됨

'Tech > WPF' 카테고리의 다른 글

WPF에서 그래픽을 이용하여 이미지 생성하기.  (0) 2011.05.03
[WPF 3D UI 구현하기 - 3]  (1) 2009.11.12
[WPF 3D UI 구현하기 - 2]  (0) 2009.11.12
[WPF 3D UI 구현하기 - 1]  (2) 2009.11.11
Posted by 알 수 없는 사용자
Tech/WPF2009. 11. 12. 17:34
이전글 : [WPF 3D UI 구현하기 - 2]

이제 물체가 어떤 방식으로 빛을 반사하게 될 지를 결정하는 Material을 알아보도록 하자.
Material은 총 세 가지 종류로 되어 있다.
1. DiffuseMaterial
2. SpecularMaterial
3. EmissiveMaterial

Blend에서 한 번 확인해 볼까?



ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ..ㅋ.ㅋㅋㅋㅋㅋㅋㅋㅋ.....
ㅋ.
..
발광 재질 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ 발광 ㅋㅋㅋㅋㅋㅋㅋㅋ ... ㅋ...ㅋ....

나만 재밌었나보다... -ㅅ-)... 어흠

여하튼, Blend에서도 저 3가지 종류의 Material을 설정할 수 있도록 되어 있다. 싱기방기.
내가 사용한 Material은 DiffuseMaterial인데 이 아이는 조명에 영향을 많이 받는다. 조명(Light)으로부터 들어오는 빛의 각도와 물체의 각도가 좁을수록 반사되는 빛이 많아지고, 각도가 클수록 반사되는 빛의 양이 적어진다. 때문에 빛을 덜 받는 부분은 자연스럽게 명암이 생긴다.
그런데 내가 만든 앞면 Panel은 평면이기 때문에 회전하지 않은 이상 정면에서 조명을 받게 되면 명암이 생길 이유가 없다. ㅎ.


<Viewport2DVisual3D.Material>
<DiffuseMaterial Viewport2DVisual3D.IsVisualHostMaterial="True" Brush="White"/>
</Viewport2DVisual3D.Material>

IsVisualHostMaterial을 이 곳에서 True로 설정해주어 쌩뚱맞다고 생각할지도 모르겠다.
이 아이에 대해 msdn에 물어보면

"재질이 대화형이어야 하는지 여부를 지정하는 값을 가져오거나 설정합니다."
http://msdn.microsoft.com/ko-kr/library/system.windows.media.media3d.viewport2dvisual3d.isvisualhostmaterial.aspx

라고 대답할 것이다. 즉 지금 표현할 2차원 물체의 재질이 사용자와 상호작용을 할 놈인지 아닌지를 설정해주는 것이라고 생각하면 될 것 같다.
이것을 false로 설정한다면 ? 직접 해 보면 알겠지만 안 보인다.
물체가 반사할 색상은 White로 설정하였다. 사실 Geometry를 이용해서 물체를 그린 것이 아니고 이미 앞면 Panel을 만들어 놓은 상태에서 그것을 불러오기 때문에 굳이 반사할 색상을 정해주지 않아도 된다.

이제 실제 나타날 물체의 정보를 적어주면 되는데...
아주 간단하다.
<Viewport2DVisual3D.Visual> 같은 Visual에 대해 선언할 필요도 없이 바로 그냥 물체를 나타내는 XAML코드를 적어주면 된다.

1
<local:FrontPanel x:Name="FrontPan"/>

새로운 UserControl을 추가 생성하여 그 곳에 앞면 Panel을 만든 후에 정보를 불러왔기 때문에 별다른 정의 없이 위와 같은 방법으로 로드하면 된다.
예를 들어, 버튼을 Visual로 설정하려고 한다면

1
<Button x:Name="myButton" Width="100" Height="30" Content="Ok" />

이와 같이 한 줄만 추가하면 될 것이다.

자, 이제 뒷면 Panel을 추가해줘야 한다. 비로소 내가 화면에 보여주고 싶은 애들은 다 끄집어 낸 거다. (고작 2개뿐이지만...)
이 아이도 앞면 Panel과 같은 방식으로 Viewport2DVisual3D를 사용하여 만들어주면 되는데, 다른 점은 Transform 에서 미리 Y축으로 180도 회전 시킨 상태여야 한다는 것이다.

1
2
3
<RotateTransform3D.Rotation>
<AxisAngleRotation3D Angle="180" Axis="0,1,0"/>
</RotateTransform3D.Rotation>

위와 같이 앞면 Panel과는 다르게 RotateTransform의 Angle 정보가 바뀌어져 있다.
이렇게만 설정해 주면 뒷면 Panel은 앞면 Panel과 반대 방향으로 뒤집혀져 있게 될 것이다.

-ㅁ-) 후아.. 드디어 두 Panel들을 3D로 변환시켰다.

끗--------------------------!!
... 이라고 말하고 싶지만 아직 한 가지가 남았다.
조명 =ㅍ=) !!!!!! ... OTL
이전에도 말했겠지만 조명이 없으면 그대는 내내 시커먼 물체를 멀뚱멀뚱 바라보는 수밖에 없을 것이다.

간단하게 조명을 붙여주자.

1
2
3
4
5
<ModelVisual3D x:Name="Light">
<ModelVisual3D.Content>
<DirectionalLight Color="White" Direction="0,0,-1"/>
</ModelVisual3D.Content>
</ModelVisual3D>

나는 Panel의 일부만을 비출 것도 아니기 때문에 DirectionalLight나 AmbientLight 둘 중에 하나를 고를 수 있는데, AmbientLight는 모든 각도에서 빛을 비추기 때문에 Panel을 회전시켰을 때에 명암이 발생하지 않게 된다. 때문에 여기선 DirectionalLight를 사용하기로 한다.

Light의 Direction은 0의 값을 가지면 비추지 않는다. Direction의 "0,0,-1"은 기본값이다. 빛의 세기를 조절하고 싶다면 살짝살짝 수치를 조정해주면 된다. Color는 조명색을 의미하는데 빨간색으로 변경하면 정육점 분위기를 연출할 수 있다.

자! 이제 조명을 비춰주었기 때문에 내가 원하는 Panel의 모습이 보인다!

만쉐~~!! ' ㅁ')/

이제 남은 것은 Panel에 있는 버튼을 이용하여 회전하는 문제인데,
이것은 Storyboard를 이용한 애니메이션 효과이기 때문에 여기선 언급하지 않겠다.

오늘은 여기까지~ ^ㅁ^)v


Posted by 알 수 없는 사용자
Tech/WPF2009. 11. 12. 13:23
이전글 : [WPF 3D UI 구현하기 - 1]

우선 내가 WPF 3D를 이용하여 구현해보고 싶은 것은 앞면 뒷면 Panel 두 개를 만들어 버튼을 누르면 180도로 회전하여 뒤집기가 가능한 형태이다.



위와 같은 Panel 두 개를 만들어 놓았다고 가정했을 때, Front Panel에 우측 상단에 있는 노란색 버튼을 누르면 Front Panel이 180도 회전하면서 Back Panel이 뒤집어져 나와야 할 것이고, Back Panel 중앙에 있는 노란색 버튼을 누르면 반대로 180도 회전하면서 Front Panel이 뒤집어져 나와야 할 것이다.

자 이제 XAML 코드에서 Viewport3D 객체를 생성하고 카메라를 돌려보자!
이전에 두 종류의 Camera에 대해 말했을 것이다.
OrthographicCamera와 PerspectiveCamera가 있는데 그 둘의 차이를 쉽게 이해하기 위해 밑의 그림을 msdn에서 따왔다.




http://msdn.microsoft.com/ko-kr/library/system.windows.media.media3d.perspectivecamera.aspx

나는 PerspectiveCamera를 이용하도록 하겠다.

1
2
3
<Viewport3D.Camera>
    <PerspectiveCamera Position="0,0,4" />
</Viewport3D.Camera>

정면에서 비출 것이기 때문에 Position만 설정하였다.
Z축으로 물체로부터 4만큼 떨어져 있는 상태라고 보면 된다. 숫자가 작아질수록 물체에 근접한 상태라고 보면 된다.

이제 앞면 패널을 표현해보자.
패널에는 회전을 위한 버튼이 있기 때문에 Viewport2DVisual3D를 이용할 것이다.
Viewport2DVisual3D에서 설정해주면 되는 것은 Transform, Geometry, Material, Visual 4 가지이다.
코드 상에서만 확인을 하면 눈에 띄게 속성을 이해하기 어렵기 때문에 Blend를 열고 속성을 확인해보도록 하자.



Viewport2DVisual3D 객체의 속성을 살펴보면 위와 같은 모습을 볼 수 있다.
Transform, Geometry, Material, Visual ... 우리가 조작할 속성들이 고대로 보인다.


Transform에서는
1. 좌표 이동
2. 회전
3. 비율 크기 조정
4. 중심점
5. 대칭 이동
을 수정할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
<Viewport2DVisual3D.Transform>
    <Transform3DGroup>
        <TranslateTransform3D OffsetX="0" OffsetY="0" OffsetZ="0"/>
        <ScaleTransform3D ScaleX="1" ScaleY="2" ScaleZ="1"/>
        <RotateTransform3D d:EulerAngles="0,0,0">
            <RotateTransform3D.Rotation>
                <AxisAngleRotation3D Angle="0" Axis="0,1,0"/>
            </RotateTransform3D.Rotation>
        </RotateTransform3D>
        <TranslateTransform3D OffsetX="0" OffsetY="0" OffsetZ="0"/>
        <TranslateTransform3D OffsetX="0" OffsetY="0" OffsetZ="0"/>
    </Transform3DGroup>
</Viewport2DVisual3D.Transform>

XAML상에서는 이런 식으로 표현할 수 있을 것이다.
중심점과 대칭 이동은 특정 용어로 표현되지 않는다. 하지만, Blend에서 확인을 해보면 쉽게 알 수 있다.

앞면 Panel은 Y축으로만 패널의 Scale을 2배로 조정했고, 회전을 시키지 않은채로 Y축으로 회전할 것임을 명시해뒀다.
굳이 ScaleY만을 2로 한 이유는 이 ScaleTransform은 비율로 계산되어 조절되기 때문이다.
즉 ScaleTransform을 (1,1,1)로 하면 바로 뒤에 설명이 나올 Gemetry에서 Y축 Position을 수정하지 않는 이상 1:1비율의 높이와 너비를 가진 정사각형 모양이 된다.
내가 원하는 형태의 앞면 Panel은 너비에 비해 높이가 2배이기 때문에 ScaleY를 2로 설정한 것이다.
만약 Geometry에서 지금의 ScaleTransform에서 ScaleY를 조작한 것처럼 높이를 2배로 설정하고 싶다면, Position에서 Y축에 관련된 좌표값을 2로 설정하면 된다.
그 외 나머지는 손대지 않았다.

Geometry는 대략 -ㅅ-) 세 개의 꼭지점을 정해주고 그 점들을 이어 만든 삼각형을 합쳐서 물체를 표현할 범위를 나타내준다고 생각하면 된다.
Geometry에서 조정할 수 있는 것들은 Positions, TextureCoordinates, TriangleIndices, Normals 들이 있다.
X, Y, Z축을 0,0,0으로 기준을 보았을 때, Positions에서 각 선을 이을 점들을 찍는다고 생각해야 한다.
Positions에서 정한 각 점들을 선으로  이어주는 순서를 정하는 것이 TriangleIndices이다.
그리고 TextureCoordinates가 2D의 좌표를 3D 좌표로 매핑해 준다.
예를 들어, 2D의 shape이 (0,0 0,1 1,0 1,1) 이런식으로 사각형 도형이 있다면 3D상으로 (-1,1,0 -1,1,0 1,-1,0 1,1,0)으로 변환될 수 있다는 말이다.

<Viewport2DVisual3D.Geometry>
    <MeshGeometry3D Positions="-1,1,0 -1,-1,0 1,-1,0 1,1,0" TextureCoordinates="0,0 0,1 1,1 1,0" TriangleIndices="0 1 2 0 2 3"/>
</Viewport2DVisual3D.Geometry>

0번째 점은 (-1,1,0) 이고 1번째 점은 (-1,-1,0), 2번째 점은 (1,-1,0), 3번째 점은 (1,1,0)이다.
0번째와 1번째와 2번째 점을 이어 삼각형을 만들고, 0번째와 2번째 3번째 점을 이어서 또 다른 삼각형을 만들면 두 삼각형이 합쳐서 사각형을 이루게 된다.
이제 앞면 패널이 보이게 될 영역이 확보가 되었다. ^ㅁ^)

남은 요소들인 Material, Visual, 중요한 조명을 담당할 Light는 다음으로 소개를 미루도록 하겠다.

슝~ ' ㅁ')/


Posted by 알 수 없는 사용자
Tech/WPF2009. 11. 11. 17:40


WPF는 Silverlight와는 3D 구현이 많이 다르다. Silverlight 에서는 Projection 속성을 이용하여 3D를 구현하는 반면에 WPF는 3차원 도형을 그리거나 모형을 만든 후에, 카메라의 위치와 시선을 조작하거나 그 이외의 각종 요소 등을 변경함으로 원하는 3D 효과를 얻어낸다. Silverlight 외의 3D 구현을 접한 경우가 없었기 때문에 이해하는데 조금 어려워었다.

WPF의 3D 구현은 마치 영화를 촬영하는 것과 느낌이 비슷하다.

우선 Viewport3D 객체를 만들고, Camera를 설정한다.
Viewport3D.Camera의  종류는 두 가지이다.
1. OrthographicCamera : 정사 방식, 거리와는 상관없이 동일한 크기로 물체가 보인다.
2. PerspectiveCamera : 투시 방식, 거리에 따라 물체가 원근감있게 보인다.

Camera 수정할 수 있는 속성
1. Position : 카메라의 위치
2. LookDirection : 카메라 시선
3. UpDirection : 카메라의 방향
4. Width / FieldOfView

자! 카메라는 준비했다.
그런데, 카메라가 있으면 뭐 하나? 주인공이 없는데 -ㅅ-);

귀하신 주인공님은 여러 가지 방법들(Model3D, Visual3D, Viewport2DVisual3D ... )로 표현할 수 있는데,
세부 사항을 제외하고 그 방법들의 큰 속성들은 같은 역할을 한다.
1. Transform : 위치 이동 및 회전
2. Geometry : 물체의 렌더링 결과물을 반영하는 범위를 설정할 수 있다.
3. Material : 카메라에서 물체에 반사시킬 색상과 형태를 설정할 수 있다.
4. Visual : 보여줄 물체의 정보

Model3D는 단순 이미지나 도형들은 이용할 경우에는 괜찮지만, 사용자와의 피드백이 불가능하다.
한 마디로 버튼을 Model3D로 만들었으면, 버튼 클릭을 할 수 없단 얘기다.
때문에 UIElement들 중 사용자와의 상호작용이 필요한 아이들이 있는 경우에는 Viewport2DVisual3D를 사용하길 바란다.

여기까지 다 설정을 완료하였다면, 카메라와 주인공까지 준비된 것이다.
다 된 것 같겠지만, 실제론 그렇지 않다.
바로! ... 조명이 빠졌다 =ㅁ=);

주인공님을 비춰줄 조명이 없으면 그대는 시커먼 물체와 맞닥뜨릴 수 밖에 없을 것이다.
진상이라고 짜증내지 말기를 바란다. 조명(Light)도 입맛따라 선택할 수 있다.
1. DirectionalLight : 평행 방향을 빛을 뿌린다.
2. PointLight : 하나의 포인트로부터 모든 방향으로 일정하게 빛을 뿌린다.
3. SpotLight : 지정된 포인트로부터 지정된 방향으로 빛을 뿌린다.
4. AmbientLight : 모든 면에 빛을 뿌린다.

이제 조명까지 완성되면 -ㅁ-) 주인공님이 쨔잔~! 하고 등장할 것이다.
우와아아아아아아아아아앙~ +ㅍ+)/ 으히히히히히 ... (...)

여기까지 기본내용이고, 실제 XAML에 쓰여지는 코드는 다음 기회로 미루도록 하겠다.
Posted by 알 수 없는 사용자