본문 바로가기

Programming

JPG Image 파일에 Geo Tagging 하기 Image에 GPS 정보를 추가하는 목적은 이미지 정합 시 위치 정확도를 더 높이기 위함이다. 이것 외에도 다른 용도가 있을 수도 있지만 지금은 이 목적때문에 C#으로 해당 기능을 구현했다. 디지털 카메라로 촬영하면 기본적인 카메라 정보들이 이미지에 포함되어 저장된다. 이러한 정보들은 이미지 파일의 메타데이터에 저장되며 EXIF Properties 라고한다. 여기에 GPS 정보를 추가해야한다. 하지만 현재 .NET에서는 EXIF Property를 직접적으로 접근해서 값을 수정하는 기능은 지원하지 않는다. 때문에 각각의 property ID와 그에 따른 Type을 적절히 맞춰서 원하는 데이터를 저장해야 한다. 다음 표는 현재 추가하려는 GPS 정보의 EXIF Property 정보이다. (latitude, .. 더보기
시리얼 포트 열기 C# 시리얼 포트 열기 예제 using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;using System.IO.Ports; namespace mavlink_test{ public partial class Form1 : Form { SerialPort serial_port = new SerialPort(); internal delegate void SerialDataReceivedEventHandl.. 더보기
배열 1차원 배열을 함수의 인자로 넘기는 방법 int average(int a[], int n) // = int average(int *a, int n){ int sum = 0; int i; for(i = 0; i < n; i++) sum += a[i]; return (sum/n);} C에서 배열의 크기는 메모리 공간을 할당할 때만 필요하지 실행시에는 배열의 크기에 대해서 컴파일러가 신경써주지 않는다. 그래서 함수가 배열을 인자로 받을 때 그 배열이 몇 개의 쇼고를 가지는지는 전혀 알 방법이 없다. 이런 이유로 average() 함수는 n이라는 배열의 크기를 인자로 따로 받는다. 그리고 인자로 받는 배열 a에도 []로 배열 표시만 했지 크기를 명시하지 않았다. 물론 배열 자체에 배열의 끝을 나타내는 요소가 있.. 더보기
데이터형에 관계없는 swap() 함수 memcpy(a, b, c);a : 복사될 메모리 주소b : 복사할 메모리 주소c : 복사할 크기 #include#include //malloc(), free()#include //memcpy() void swap(void *a, void *b, int n){ void *t; t = malloc(n); //임시 영역 t에 n만큼의 공간을 확보 memcpy(t, a, n); //t = a memcpy(a, b, n); //a = b memcpy(b, t, n); //b = t free(t); //t에 할당된 메모리를 해제} void main(void){ char c1 = 'A', c2 = 'B' int i1 = 100, i2 = 200; float f1 = 3.14, f2 = 2.71; printf("\n.. 더보기
void포인터, 함수 포인터 void 포인터 void 포인터란 포인터의 두 가지 요소중 둘째 요소인 가리키는 데이터형이 정해지지 않은 포인터를 의미한다. void 포인터의 정의는 가리키는 데이터형이 없으므로 데이터형 자리에 void라는 예약어를 기술하면 된다. void *vptr; void 포인터는 주소만 저장하는 포인터인데 그로 인해서 포인터 연산자를 사용할 때 주의해야 할 점이 있다. 첫째로 포인터가 가리키는 곳의 내용을 읽어내는 역참조(dereference, *) 연산자를 사용하지 못한다는 것이다. 참조를 하려면 가리키는 데이터형을 알아야 적절하게 해석을 한다. void 포인터는 가리키는 데이터형이 정해지지 않았으므로 참조가 불가능하다. 하지만 형변환 연산자를 이용하여 다른 형의 포인터로 강제 형변환을 하면 참조가 가능하다. .. 더보기
포인터의 포인터 C에서는 다른 언어와는 달리 문자열이라는 데이터형이 없다. 대신 C에서는 char형의 포인터로 문자열을 나타낸다. 다음의 예를 보자. char str1[] = "This is string.";char *str2 = "This also is string."; 위의 str1은 배열의 형식으로 str2는 포인터의 형식으로 문자열을 나타내었지만 두 형식은 비슷한 의미를 지니고 있다. 다른점이 있다면 str1은 배열의 이름이기 때문에 자체의 주소를 저장하기 위한 공간을 갖지 않는 상수라는 것이다. 반면에 str2는 포인터이기 때문에 주소를 저장하기 위한 공간을 할당받는다. 그러므로 내용인 주소값을 얼마든지 변경이 가능하다. 이 점만 재외하면 포인터와 배열은 마치 동일한 것으로 취급해도 된다. ""는 사이에 있는 .. 더보기
포인터 연산자 포인터 연산자 포인터를 지원하기 위한 연산자는 변수의 주소를 구성하는 &(address of) 연산자, 가리키는 주소의 내용을 참조하는 *(dereference) 연산자, 그리고 현재의 주소에 가리키는 데이터형을 참조하여 주소를 옮겨주는 +, - 연산자, 그리고 구조체의 포인터와 작용해서 구조체의 포인터 멤버들을 지정하게 하는 -> 연산자가 있다. 우선 변수의 주소를 구하는 & 연산자는 사용이 간단하다. & 연산자 뒤에 변수명을 써주면 그 변수의 주소를 리턴한다. int *itpr; //정수형을 가리키는 포인터iptr = &i; 포인터가 가리키는 주소의 내용을 참조하는 * 연산자는 포인터의 정의에서도 쓰이기 때문에 혼돈이 없어야 한다. * 연산자 뒤에는 반드시 포인터가 와야하며 결과로는 포인터가 가리키는.. 더보기
최적화에 대하여... 최적화(Optimization)란 프로그램을 좀 더 빨리, 좀 더 작게 개선하는 과정을 의미한다. 최적화 기법 최적화를 위한 방법의 제일 첫째는 좋은 알고리즘을 선택하라는 것이다. 10,000개의 정수 배열을 정렬하라는 문제에서 버블 정렬을 사용하는 것과 퀵 정렬을 사용하는 것은 엄청난 차이가 있다. 같은 문제를 해결하는 여러가지의 알고리즘 중에서 가장 효율적인 것을 선택하는 것이 가장 근본적인 최적화 방법이다. 둘째, 함수를 적절히 사용하라. 함수를 사용하는 것은 사용하지 않는 것보다 분명히 속도면에서 불리하다. 왜냐하면 같은 역할을 하더라도 함수를 사용하면 함수 호출을 위한 사전절차가 더 포함되기 때문이다. 이를 오버헤드(Overhead) 현상이라고 한다. 반면에 함수 호출의 장점이라면 컴파일 결과 .. 더보기