마이크로소프트사의 딥줌 이미지(Deep Zoom Image)포맷

사용자 삽입 이미지
위의 툴은 딥줌 이미지 데이터를 만들어주는 마이크로소프트 사의 Deep Zoom Composer입니다. 여기서 말하는 Deep Zoom이란.. 매우 큰 크기의 이미지를 인터넷 상에서 빠르게 보여주도록 하는 형식입니다.

딥줌 형식으로 이미지를 구성해 놓으면 .NET을 이용해 인터넷에서 쉽게 방대한 크기의 이미지를 빠르게 서비스할 수 있기 때문에.. GIS 분야에서 지도 서비스에 응용해 볼만한 기술로 생각됩니다. 비록 지도 좌표계의 개념이 없고.. 방대한 크기라고는 하나.. 크기에 제약이 있는 것으로 판단되는 단점이 있기는 하지만 말입니다.

GIS에서는 이미 타일맵이라는 형식으로 이 딥줌의 기술을 대체해.. 아니 딥줌보다 그 이전부터 사용되어 왔습니다. 하지만.. 딥줌은 마이크로소프트에서 최적화된 뷰어 자체를 제공하며 SilverLight를 통해 인터넷으로 쉽게 서비스할 수 있다는 매우 큰 장점을 가지고 있다고 생각됩니다.

이 글은.. 위에서 보여드린 Deep Zoom Composer를 통해 딥줌 이미지들을 만드는 것이 아닌.. Deep Zoom Composer가 없을지라도 딥줌 이미지들을 만들어 내기 위해 딥줌 이미지들의 구조를 파악해 보는 글입니다. 딥줌 이미지의 구조이므로.. Deep Zoom Composer가 만들어 낸 결과 샘플을 가지고 설명해 보겠습니다.

사용자 삽입 이미지
결과로 만들어진 딥줌의 폴더 구조입니다. 폴더 2개와 4개의 파일이 만들어 집니다. 이 구조는 어떠한 입력 이미지에 대해서도 항상 동일합니다. 그럼 다시 2개의 폴더 내부를 살펴보겠습니다. 먼저 dzc_output_files 폴더 구조입니다.

사용자 삽입 이미지
dzc_output_files 폴더 내부의 서브 폴더입니다. 역시 어떠한 입력 이미지에 대해서도 항상 동일하게 9개의 폴더가 만들어 집니다. 9개에 대한 모든 폴더, 즉 0 폴더에서 8번 폴더 안에는 0_0.png(또는 jpg)라는 이름의 이미지 파일 하나만이 존재합니다. 옵션을 지정하지 않았다면 256×256 크기의 이미지로 0 펄더에는 입력 이미지를 1×1 픽셀 크기로 만들어 놓은 것이고 2폴더는 2×2 픽셀 크기의 이미지가 3번 폴더는 4×4, 그리고 4번 폴더는 8×8 크기의 이미지와 같은 식으로 존재합니다. 다음은 dzc_ouput_images입니다. 이 폴더의 내부 내용은 다음과 같습니다.

사용자 삽입 이미지
입력 이미지 파일명으로 조합된 폴더 하나의 xml 파일 하나입니다. 먼저 xml 파일의 내부를 살펴보면 다음과 같습니다.

사용자 삽입 이미지
매우 단순한 내용이지만 중요한 정보를 담고 있는데요. 타일이미지의 크기와 이미지 형식 그리고 입력 이미지의 전체 크기에 대한 정보 등을 담고 있습니다. 이제 폴더 내부(02726_purplemurmur_2560x1440_files)를 살펴보겠습니다.

사용자 삽입 이미지
이 폴더는 흔히 GIS에서의 타일 구조 형식입니다. 0 폴더 안에는 1×1 픽셀 크기의 이미지 하나가 존재하며 최종적으로 12폴더에서는 입력 이미지를 256×256 크기의 타일 이미지들로 구성해 놓고 있습니다. 타일 이미지의 이름은 Row_Column.png(또는 jpg)로써 예를 들어 아래와 같이 구성되어져 있습니다.

사용자 삽입 이미지
여기서 Row 인덱스 0의 기준은 입력 이미지의 좌상단입니다. 이상으로 간단히 마이크로소프트사에의 딥줌 이미지의 포맷에 대해 설명드렸습니다.

[OpenMP] 이해가 않되는 스레드 흐름

#include "stdafx.h"
#include 
#include 

int _tmain(int argc, _TCHAR* argv[])
{
    int a = 1;
#pragma omp parallel
    {
#pragma omp sections firstprivate(a) lastprivate(a)
        {
#pragma omp section
            {
                Sleep(1000);
                printf("section 1: a 초기값 = %d\n", a);
                a = 2;
                printf("section 1: a 수정값 = %d\n", a);
            }
#pragma omp section
            {
                printf("section 2: a 초기값 = %d\n", a);
                a = 3;
                printf("section 2: a 수정값 = %d\n", a);
            }
        }
    }

    printf("a 최종값 = %d\n", a);

    return 0;
}

이 코드는 스레드를 2개 사용하고 있습니다. 즉 section 지시어를 통해 13~18번 코드를 실행하는 스레드 하나와 20~24번 코드를 실행하는 스레드 하나입니다. 10번 코드에서 lastprivate(a)라는 보조 지시어를 통해 2개의 스레드에서 연산한 결과 a가 복사됩니다. 14번 코드에 Sleep 함수를 호출함으로써 두개의 스레드 중 a에 2를 할당한 스레드가 가장 마지막에 끝나도록 했습니다. a에 2를 할당한 스레드가 마지막에 종료되니.. 이 2개의 스레드가 끝나면 a 값은 항상 2가 될거라 예상됩니다.

사용자 삽입 이미지
근데.. 보는 바와 같이 a의 최종값이 3이라고 합니다.. ㅡOㅡ;; 실행 흐름을 봐도 가장 먼저 a 수정값으로 3을 할당하고 다음 실행으로 a 수정값으로 2를 할당하는 순서입니다. 실행 순서는 예상과 같은데.. 결과는 반대입니다.. ㅡOㅡ;; 아직 OpenMP를 학습하는 단계인지라.. 이해가 떨어져서 그런 것인지.. 아니면 OpenMP의 BUG인지… 모를 일입니다.. 누구 아시는 분 코칭 부탁드립니다.

[Android] GPS 기능 관련 API 예제

모바일이 이미 충분히 대중화되었음으로 해서.. GIS 분야 중 하나인 LBS(Location Based System; 위치 기반 시스템)을 활용할 수 다양한 앱이 꽃을 피울 기회를 맞이 한지 이미 꽤 오래되었습니다.

이에 안드로이드가 탑재된 모바일 기기의 GPS를 통해 현재 자신의 위치를 얻을 수 있는 안드로이드 API를 활용하는 샘플 코드를 공유해 봅니다. 아래는 샘플 코드에 대한 스크린 샷입니다.

사용자 삽입 이미지
위치(WGS84 타원체에 대한 경위도)는 물론이고 현재 이동 속도과 위치 정확도(휴대용 GPS의 경우 최고의 정확도 오차는 10m로 제한됨) 등을 얻어와 화면에 표시하고 있습니다. 또한 GPS의 원체 데이터 형식인 NMEA0183을 표시하고 있습니다.

GPS에게 위치데이터 힌트를 제공하는 인공위성의 수 역시 제공하고 있는데요. 이 인공위성의 수는 NMEA0183 데이터로부터 얻어올 수 있습니다. 긴 설명보다는 실제 실행 가능한 예제 코드 샘플을 공유합니다.

인터넷 상에서 공유되고 있는 다양한 소스를 취합하여 이 하나의 예제 샘플을 제작했습니다. 안드로이드에서 GPS로부터 위치 데이터 등을 취득하고자 하시는 개발자 분들에게 조금이라도 도움이 되시길 바랍니다.

GPS로부터 수신받은 좌표(WGS84 타원체의 경위도 좌표)를 다른 좌표계로 변환하기 위한 방법은 다음 URL을 통해 살펴보시기 바랍니다.

[Java] 타원체간의 경위도 좌표계 변환 오픈소스 라이브러리

얼마전에 가벼운 좌표변환 오픈소스 라이브러리를 소개한 글(가벼운 좌표변환 오픈소스 라이브러리)을 올렸습니다. 상당히 가볍고 매우 다양한 좌표계 투영이 가능한 라이브러리이지만 서로 다른 타원체 간의 좌표 변환에 있어서 제약이 있는 라이브러리였습니다.

이 글은 그에 대한 해결책으로 서로 다른 타원체 간의 경위도 좌표계 간의 변환을 지원합니다. 먼저 소개해 드린 라이브러리와 이 글에서 소개해 드릴 라이브러리를 조합하면 상당한 정확한 좌표 변환 성과를 얻으실 수 있으리라 확신합니다.

먼저 이 라이브러리를 구성하고 있는 클래스(총 4개)들의 관계도를 살펴보면 다음과 같습니다.

사용자 삽입 이미지
보시면.. Ellip2Ellipsoid라는 클래스만이 나머지 클래스와 관계를 맺고 있고 나머지는 독립적입니다. 관계를 맺고 있지 않은 클래스를 먼저 살펴보는 것이 순서이므로.. 순서대로 하나 하나 살펴보면.. 먼저 Ellipsoid는 타원체를 나타냅니다. 장반경과 편평도로 타원체 하나를 정의할 수 있습니다. 그리고 Parameters7은 타원체간의 경위도 좌표 변환을 위한 변환 계수로써 7 Parameters를 의미합니다. Vaues3는 단순히 3개의 값을 담고 있는 클래스로써 경위도값과 높이값을 담는데 사용합니다. 이 클래스는 타원체간의 경위도 좌표 변환의 입력값고 결과값의 타입으로 사용합니다. 끝으로 이 세 클래스와 유일하게 관계를 맺고 있는 Ellip2Ellipsoid는 2개의 상이한 타원체 간의 경위도 좌표를 7개의 변환 계수를 사용해 변환해 주는 주요 클래스입니다.

이제 이 클래스들을 이용하여 실제로 Bessel1841 타원체와 WGS84 타원체 간의 경위도 좌표 변환의 코드를 예로 살펴보겠습니다.

Ellipsoid bessel1841 = new Ellipsoid(6377397.155, 1.0 / 299.152813);
Ellipsoid wgs1984 = new Ellipsoid(6378137, 1.0 / 298.257223563);
Parameters7 params = new Parameters7(
    -115.8, 474.99, 674.11, 
    -1.16, 2.31, 1.63, 
    6.43
);
  
Ellip2Ellipsoid transform = new Ellip2Ellipsoid(bessel1841, wgs1984, params);
  
Values3 src = new Values3(38, 128, 0);
Values3 dst = new Values3();
  
System.out.println("bessel lat/lng -> wgs84 lat/lng");
transform.transfom(src, dst);
System.out.println(src + " -> " + dst + "\n");

System.out.println("wgs84 lat/lng -> bessel lat/lng");
transform.reverseTransform(src, dst);
System.out.println(src + " -> " + dst);

1번와 2번 코드에 앞서 언급했던 2개의 타원체를 정의하고 있습니다. 타원체 정의는 장반경과 편평도값을 통해 가능합니다. 3번 코드는 타원체 간의 변환을 위한 변환계수로써 X, Y, Z의 3개 축에 대한 이동량 그리고 또 3개의 축에 대한 회전량 끝으로 축척차값입니다. 타원체 간의 경위도 좌표 변환은 단번에 이루어지는 것이 아니라 중간 단계로 지심좌표계라는 X, Y, Z축 좌표계로 변환하게 되는데 다시 지심좌표계를 또 다른 타원체로 변환하기 위해 지심좌표계 자체를 3축에 대해 이동하고 회전하며 크기를 조절하는 과정에서 이 7개의 변환 매개변수가 사용됩니다. 9번 코드를 통해 이렇게 생성한 2개의 타원체와 변환 매개변수로써 Ellip2Ellipsoid를 생성합니다. 그리고 11번 코드부터는 실제 각 타원체간의 경위도 좌표계의 변환입니다. 결과는 아래와 같습니다.

사용자 삽입 이미지
만약 다른 프로그램 등을 통해 좌표변환을 수행했을때 위의 결과와 차이를 보인다면 변환 매개변수값으로 다른 값을 사용했기 때문입니다. 즉 위의 코드에서 3번 코드의 Parameters7 클래스의 생성시 사용한 인자값들에 해당합니다. 위의 3번 코드에서 사용한 변환 매개변수를 현재 한국에서 사용하도록 권장하고 있는 매개변수로써 대다수의 좌표변환 툴에서 사용하고 있는 매개변수입니다. 끝으로 본 오픈소스에 대한 다운로드는 아래의 링크를 통해 받으시기 바랍니다.

끝으로 궁금하신 점은 댓글을 통해 남기시면 최대한 답변해 드리겠습니다. 또한 이 오픈소스 라이브러리는 지오서비스에서 개발했으며 LGPL 라이센스를 따릅니다.

Win7 홈(Home)에서 원격데스크탑 기능 추가시키기

Win7 홈 에디션에는 원격데스크탑 기능이 없습니다. 개발자에게 원격데스크탑은 매우 유용한 기능입니다. 물론.. 이 기능이 없다면 자리에서 자주 일어나 이 PC 저 PC로 옮겨다니며 역동적으로 일을 할 수 있겠지만 말입니다.

여튼.. 이 유용한 원격데스크탑 기능을 Win7 홈 에디션에 직접 추가시키는 방법입니다. 저 같은 경우 Windows 7 Home Premium 64 bits 입니다.

먼저 시스템 속성의 원격 탭에서 이 컴퓨터에 대한 원격 지원 연결 허용을 활성화 시킵니다.

사용자 삽입 이미지
다음으로 첨부 파일을 다운받아 압축을  풀고 Install.cmd를 실행해 주면 됩니다. 참고로 이 첨부파일은 Win7의 서비스팩1이 적용된 경우에만 가능합니다.