반응형

뻔하디 뻔한 개발 노하누는 가라~

이번에도 쓸만한 내용을 소개해 드릴 까 합니다.

개발을 하다 보면 실제 소스코드 외에도 어떤 텍스트를 resource 에 넣어 두고 소스코드에서 불러와야 하는 경우가 있을 수 있습니다. 저의 경우는 포토샵, 일러스트 등의 프로그램을 연동하여 c# 으로 App 을 만들었을때 실제 수행되는 코드는 jsx 스크립트 파일로 만든 뒤 app 에서 해당 스크립트를 실행하도록 하는데 이때 resource 에 스크립트 파일을 추가해 놓고 실행하는 타이밍에 해당 내용을 불러와 실행하도록 하는 경우가 종종 있습니다.

일단 c# 보다 javascript 로 작성하는게 쉽고 나중에 오류가 생기더라도 app 이 아닌 기능 단위로 만들어진 스크립트만 수정하면 되기 때문인데요.

보통 인터넷에 그런 내용으로 검색해 보면 실행파일이 빌드되는 순간 빌드 폴더에 해당 스크립트 파일이 복사되고 실행 파일 경로를 기준으로 하여 해당 파일을 불러와서 사용하도록 안내하고 있는 예제가 대부분입니다.

해당 스크립트(텍스트)를 굳이 공개하고 싶지 않고 스크립트 코드(텍스트 파일)가 빌드된 실행파일 내에 포함되면서 해당 텍스트를 불러오는 방법을 이번에 소개해 드리겠습니다.

두가지 방법이 있는데요. 두가지 방법을 모두 보시고 본인이 편한 방법을 사용하면 되겠습니다.

 

1. Properties > Resources.resx 내에 추가하는 방법

  1. 개발 디렉토리 내 임의의 폴더를 생성
  2. 생성된 임의의 폴더에 원하는 텍스트 파일 작성
  3. 작성된 텍스트 파일을 Properties > Resources 내에 텍스트 리소스로 추가
  4. 소스코드 내에 리소스를 텍스트(string) 로 가져오는 코드 작성

자 실제 화면을 보면서 설명을 드려보면요

JS 폴더를 생성한 뒤 텍스트 파일을 하나 추가함

위와같이 임의의 폴더를 하나 개발 디렉토리내에 생성한 뒤 필요한 텍스트 파일을 추가 합니다.

저의 경우는 포토샵 스크립트 파일 포멧인 jsx 로 추가하였고요. 좌측 내용을 보면 실행하면 그냥 "hello photoshop" 을 팝업으로 띄워주는 스크립트 입니다. 

그 다음 Properties > Resources.resx 를 더블클릭해서 열어준 뒤 좌측 상단의 리소스 타입을 '파일'로 변경해 줍니다.

리소스 타입을 파일로 변경\

 

그런 다음 리소스 추가 를 누르시고 '기존 파일 추가' 를 선택해 줍니다.

아까 만들어둔 파일을 등록한다

그럼 파일 선택 창이 나타나는데요. 아까 만들어준 JS 폴더 ( 본인이 생성한 폴더) 에 가보시면 생성한 텍스트 파일이 있을 거고요. 해당 파일을 선택해 주시면 됩니다.

01 은 바이너리 라는 뜻

그럼 이렇게 파일이 들어와 있는 것을 보실 수 있는데요. 이 파일이 텍스트 파일이라고 확인을 시켜 주어야 합니다.

우측 아래 속성 텝에 보면 이 파일의 타입이 Binary 로 되어 있는 것을 Text로 변경해 주어야 합니다.

바이너리로 되어 있다
텍스트로 변경

Text 로 변경하고 나면 위와 같이 인코딩을 지정할 수 있으니 나중에 텍스트 오류가 나면 해당 인코딩을 변경해가면서 사용하시면 됩니다.

자 이제 리소스로 추가 하였으니 불러오는 방법을 알아야 겠죠?

리소스로 등록한 텍스트 파일을 문자열로 불러오는 방법

위와 같이 string 문자열을 만들어서 불러오면 됩니다. PSXL_AUTO 는 솔루션 명으로 namespace 에 지정된 이름을 사용하시면 됩니다.

그 뒤로는 Properties 부터 자동완성 되므로 상세한 설명은 생략

MessageBox.Show(myResourceText) 를 이용하여 리소스 텍스트 내용을 불러와보면 

요렇게 잘 불러와 진것을 볼 수 있습니다.

물론 이렇게 하면 자동으로 포함리소스가 되므로 런타임에 별도로 파일을 찾아야 하거나 할 필요가 없습니다. 빌드 폴더에도 역시 별도로 파일이 나오거나 하지 않습니다.

간단하죠?

막상 해보면 간단합니다.

 

2. 그냥 개발 디렉토리 내에 폴더를 생성하고 파일을 추가하는 방법

 

  1. 임의의 폴더를 생성한다
  2. 생성한 폴더에 스크립트 파일을 작성한다
  3. 실행할 때 해당 스크립트를 불러오는 코드를 포함하여 실행한다.

 

요 방법도 제가 자주 사용하는 방법인데요. 별도로 리소스로 등록할 필요가 없어서 스크립트를 만들고 사용하는 과정에서 좀더 간단한 방법이라 할 수 있겠습니다.

물론 실행하는 부분에서 코드가 약간 복잡하기는 하지만 그래도 텍스트를 만들고 또 리소스에 추가하는 과정이 없어 좀더 직관적이라고 할까요? 

임의의 폴더에 스크립트 파일을 추가하였다

이번에도 생성한 폴더에 스크립트 파일을 추가하였습니다.

내용을 구분하기 위하여 hellow 를 bye로 변경하였습니다 ㅎ

속성 텝에서 아래와 같이 포함리소스, 출력디렉토리에 복사 안함 으로 설정해 줍니다.

포함리소스, 복사안함으로 설정 필수

 

자 이제 코드를 불러오는 내용을 작성해야 하는데요. resources 에 추가한 내용을 불러오는 것은 아주 간단했죠?

요건 약간 복잡합니다. 아래 코드를 참고해 주세요.

private string showtextString()
        {
            string myStr = "";
            var assembly = Assembly.GetExecutingAssembly();
            var myScript = "PSXL_Auto.JS.defPSScript.jsx";
            using (Stream stream = assembly.GetManifestResourceStream(myScript))
            {
                using (StreamReader sr = new StreamReader(stream))
                {
                    myStr = sr.ReadToEnd();
                }
            }
            MessageBox.Show(myStr);
            return myStr;
        }

// 또는 

private string showtextString(string txtName)
        {
            string myStr = "";
            var assembly = Assembly.GetExecutingAssembly();
            var myScript = "PSXL_Auto.JS." + txtName;
            using (Stream stream = assembly.GetManifestResourceStream(myScript))
            {
                using (StreamReader sr = new StreamReader(stream))
                {
                    myStr = sr.ReadToEnd();
                }
            }
            MessageBox.Show(myStr);
            return myStr;
        }
        
        
// 실행하는 부분에서
showtextString("defPSScript.jsx");

일단 간단하게 해당 리소스 텍스트를 string 으로 돌려주는 함수처럼 만들었는데요. 코드 내에 "JS" 라는 부분은 사용자가 만든 폴더 명칭이라는 것을 아실 수 있으시죠? 물론 아래와 같이 리소스 파일명을 인자로 받아 해당 텍스트를 리턴해 줄 수 있도록 하면 사용할 때도 간단하게 사용할 수 있을 것입니다.

요렇게 만들어진 함수를 실행해서 메시지 박스로 출력해 보면 

당연히 잘 출력 됩니다.

중간에 bye 로 나오는 것 잘 보이시죠?

당연히 위의 두가지 방법 모두 실행 파일 경로에 해당 텍스트 파일이 따라오지 않고 잘 숨겨져 있게 됩니다.

 

꼭 필요하신 분들께 도움이 되었기를 바라면서 이만 줄입니다~

 

2020.08.11 - [DEV/c#] - [c#] streamreader 를 이용하여 정확한 라인 위치 찾기

 

[c#] streamreader 를 이용하여 정확한 라인 위치 찾기

c# 을 이용하여 streamreader 개체로 텍스트를 읽는 방법은 매우 효율 적이고 손쉽게 작업을 수행하도록 해줍니다. 빠르고 간단하게 개발을 할 수 있어 저도 자주 사용하고는 합니다. 그런데 이번에

diy-dev-design.tistory.com

 

2020.06.03 - [DEV/c#] - C# .net으로 photoshop 연동하기

 

C# .net으로 photoshop 연동하기

저는 회사에서 디자인팀에 있고 전공도 디자인과 출신이며 심지어는 고등학교도 예체능계열 고등학교를 나왔습니다만 지금 회사에서 하는일의 95% 정도는 개발을 하고 있습니다. 실제로 제가

diy-dev-design.tistory.com

 

2020.07.21 - [DEV/c#] - C# 문자열 읽어서 문자열에 해당하는 변수에 값 세팅하기

 

C# 문자열 읽어서 문자열에 해당하는 변수에 값 세팅하기

오늘 소개해드릴 꿀팁은요. 문자열을 읽어 들여서 문자열 내에 들어있는 특정 단어를 이용하여 개발 중인 코드의 변수로 인식하여 해당 변수에 값을 세팅하는 방법을 소개해 드릴까 합니다. 예

diy-dev-design.tistory.com

 

 

반응형
반응형

키움증권에서는 API 를 제공하여 사용자가 자동매수, 매도를 할 수 있는 프로그램을 직접 개발할 수 있도록 제공하고 있습니다. 

키움증권 API 를 이용하여 시작하는 방법은 여러 포스트에서 이미 다루고 있으므로 별도로 다루지는 않을 예정입니다.

많이 어렵지 않으므로 관련 포스트를 따라서 하시면 손쉽게 시작하실 수 있으며 이미 샘플 c# 코드도 키움증권에서 배포하고 있으므로 일일이 내용을 작성하지는 않을 것이고요. 제가 인터넷에서 쉽게 구하지 못한 코드들을 올려보려 합니다.

오늘은 키움증권 API 가 제공하는 전체 종목코드를 받아오는 코드를 소개해 드릴까 합니다.

 

키움증권 API 가 동작하는 방식

  • 필요한 커맨드를 인자와 함께 전달한다.
  • API 는 서버에서 해당 정보를 내려받는다. (이벤트가 발생하는 경우가 있고 직접 결과를 리턴하는 경우가 있다)
    • 결과를 리턴하는 경우 : 바로 처리
    • 이벤트를 발생시키는 경우 : 이벤트 핸들러를 이용하여 함수로 구현하여 처리

대충 이런식인데요. 전체 종목 코드를 받아오는 것은 결과를 바로 리턴해주는 방식 입니다.

 

키움증권에서 배포하는 open API 가이드를 보면 아래와 같은 커맨드가 있음을 알 수 있습니다.

키움 openAPI 개발 가이드에 있는 커맨드 리스트

바로 14번에 해당하는 GetCodeListByMarket 에 해당하는 커맨드죠.

해당 커맨드의 상세한 항목은 아래와 같이 나와 있습니다.

제어함수 명세서에 나와있는 전체 종목 코드 받기 설명

문자열로 결과가 리턴되는 것을 알 수 있고, sMarket 부분에 필요한 주식시장의 종류를 넣을 수 있게 되어 있네요.

전 "장내"에 해당하는 항목을 알아보려 합니다.

바로 한번 구현을 해볼까요?

private AxKHOpenAPILib.AxKHOpenAPI axKHOpenAPI; // 키움 샘플이라면 이건 적을 필요 없음.

private void getAllCodeList()
{
  string codelistResult = axKHOpenAPI.GetCodeListByMarket("0"); // 0: 장내
  //종목간 구분은 ";" 로 한다고 하였으므로 아래와 같이 각각의 종목을 쪼개 줍니다.
  string[] mylist = codelistResult.Split(';');
  foreach (string s in mylist)
  {
      Console.WriteLine("종목코드 : " + s);
  }
}

간단하죠?

이렇게하고 getAllCodeList 함수를 실행해 보면 아래와 같이 출력창에 종목 코드가 출력됩니다.

종목 코드가 받아진 모습

 

그런데 이렇게 하면 전체 코드는 얻었지만 해당 코드가 어떤 종목인지 알수가 없잖아요?

그래서 몇줄 추가해 보겠습니다. 해당 코드의 종목 명칭과 전일가격을 출력해보도록 하겠습니다.

private void getAllCodeList(ref List<string> rList)
{
  rList.Clear();

  string codelistResult = axKHOpenAPI.GetCodeListByMarket("0");
  string[] mylist = codelistResult.Split(';');
  MessageBox.Show("전체 종목 수는 " + mylist.Length.ToString() + "개 입니다");
  foreach (string s in mylist)
  {   
 	rList.Add(s); // rList 에 종목 코드를 넣어준다. (최종 결과 반환용)
    string stName = axKHOpenAPI.GetMasterCodeName(s);    // 종목 명칭 얻기
    string lastPrice = axKHOpenAPI.GetMasterLastPrice(s);  // 종목 전일가 얻기
    Console.WriteLine("종목코드 : " + s + ", 종목 명:" + stName + ", 전일가 :" + lastPrice);
  }
}

몇 줄 추가를 하였습니다. 먼저 rList 라는 리스트를 참조 인자로 받아서 나중에 사용하려고 합니다. 이전 코드와 달라진점은 메시지 팝업으로 전체 종목수를 알려주는 것과 종목 명칭, 종목의 전일가격을 받는 커맨드를 추가하여 콘솔창에 좀더 직관적으로 가격을 보여주도록 한 것이 달라진 점 입니다.

이렇게 하면 출력창에는 아래와 같이 결과가 출력됩니다.

종목 코드와 종목명, 전일가를 한번에 출력해본 모습

어떠신가요? 좀 더 직관적으로 볼 수 있겠죠?

프로그램을 직접 만드는 만큼 재가 가지고 있는 관심 종목만 살펴보기 보다는 전체 종목들의 추이를 보면서 내가 발견하지 못한 좋은 종목을 컴퓨터에게 분석을 시켜보려고 하는데요. 그러기 위해서는 전체 종목을 자동으로 받아오는 함수가 반드시 필요할 것 같아서 구현해 보았습니다. 

 

다음번에는 이벤트 핸들러를 이용하여 결과값을 처리하는 방법을 소개해 드려 보도록 하겠습니다.

다들 돈 많이 버세요~ ㅋ

 

 

2020.08.11 - [DEV/c#] - [c#] streamreader 를 이용하여 정확한 라인 위치 찾기

 

[c#] streamreader 를 이용하여 정확한 라인 위치 찾기

c# 을 이용하여 streamreader 개체로 텍스트를 읽는 방법은 매우 효율 적이고 손쉽게 작업을 수행하도록 해줍니다. 빠르고 간단하게 개발을 할 수 있어 저도 자주 사용하고는 합니다. 그런데 이번에

diy-dev-design.tistory.com

2020.01.03 - [DEV/c#] - [C#] C# APP 에서 엑셀 연동해보기

 

[C#] C# APP 에서 엑셀 연동해보기

엑셀에서 VBA 로 코드를 짜다 보면 막상 특정 엑셀 파일에만 VBA 가 적용이 가능하기 때문에 막상 다른 엑셀 파일에서 동일한 동작을 하려면 또 코드를 복사해 넣고 실행을 해야 하는 경우가 있습

diy-dev-design.tistory.com

 

반응형
반응형

c# 을 이용하여 streamreader 개체로 텍스트를 읽는 방법은 매우 효율 적이고 손쉽게 작업을 수행하도록 해줍니다. 빠르고 간단하게 개발을 할 수 있어 저도 자주 사용하고는 합니다.

그런데 이번에 방대한 크기의 텍스트 파일을 이용해서 작업을 하는 중 고민 거리가 생겼습니다. 미리 텍스트 파일을 읽어서 중간중간 핵심이 되는 ID 별로 위치를 저장해놓고 나중에 ID 에 해당되는 위치로 seek 하여 읽어 들이는 방법을 사용하려고 했습니다.

그런게 steramreader 는 seek 기능이 없더군요. -_-

그래서 streamreader.basestream 으로 들어가보니 seek 도 있고 position 도 있길레 해당 메소드와 프라퍼티로 구현을 해보기로 하였습니다.

long filePos = -1;
using (StreamReader cini = new StreamReader(fs, Encoding.Default))
{
      do
      {
          filePos = cini.BaseStream.Position; //readLine 을 하기 전 위치를 저장한다
          string cline = readline();
          if (cline == "내가 원하는 정보")
          {
              break;
          }
      }while(cini.EndOfStream == false);
}

// filePos 에 저장된 값을 나중에 이용할 경우
using (StreamReader cini = new StreamReader(fs, Encoding.Default))
{
      cini.DiscardBufferedData();
      cini.BasePosition.Seek(filePos, SeekOrigin.Begin);
    
      // 자 이제 읽어 볼까!
      string myResult = cini.readLine();
}

이런 식으로 말이지요..

간단하잖아요? 상식적으로 저렇게 하면 될 것 같기도 하고요...

 

그런데 안됩니다.

 

 

엉터리 값이 나오게 됩니다.

라인 위치도 안맞고 알수 없는 위치의 값들이 튀어 나옵니다.

인터넷을 좀 뒤적거려보니 StreamReader 의 readline 이라는 녀석이 특이한 녀석이더군요.

우리가 생각하는 문자열에서 실제 한줄을 읽어서 반환해주는 게 아닌 어떤 블럭 단위로 데이터를 읽어 들인 뒤 newLine 에 해당하는 기호까지의 데이터를 돌려주는 것으로 블록 안에는 한줄이아닌 여러줄이 들어 있을 수도 있습니다.

 

어쨌든 여기저기 한참을 뒤진 후 완벽하게 구동하는 코드를 찾아 공유합니다.

stackoverflow.com/a/17457085

 

StreamReader and seeking

can you use streamreader to read a normal textfile and then in the middle of reading close the streamreader after saving the current position and then open streamreader again and start reading from...

stackoverflow.com

바로 요 링크에 있는 코드인데요. 사용하기도 편리하게 해당 개발자 분께서 함수로 깔끔하게 구현을 해주셨습니다.

바로 아래코드를 본인의 개발중인 클래스에 포함시킵니다.

public static long GetActualPosition(StreamReader reader)
{
    System.Reflection.BindingFlags flags = System.Reflection.BindingFlags.DeclaredOnly | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.GetField;

    // The current buffer of decoded characters
    char[] charBuffer = (char[])reader.GetType().InvokeMember("charBuffer", flags, null, reader, null);

    // The index of the next char to be read from charBuffer
    int charPos = (int)reader.GetType().InvokeMember("charPos", flags, null, reader, null);

    // The number of decoded chars presently used in charBuffer
    int charLen = (int)reader.GetType().InvokeMember("charLen", flags, null, reader, null);

    // The current buffer of read bytes (byteBuffer.Length = 1024; this is critical).
    byte[] byteBuffer = (byte[])reader.GetType().InvokeMember("byteBuffer", flags, null, reader, null);

    // The number of bytes read while advancing reader.BaseStream.Position to (re)fill charBuffer
    int byteLen = (int)reader.GetType().InvokeMember("byteLen", flags, null, reader, null);

    // The number of bytes the remaining chars use in the original encoding.
    int numBytesLeft = reader.CurrentEncoding.GetByteCount(charBuffer, charPos, charLen - charPos);

    // For variable-byte encodings, deal with partial chars at the end of the buffer
    int numFragments = 0;
    if (byteLen > 0 && !reader.CurrentEncoding.IsSingleByte)
    {
        if (reader.CurrentEncoding.CodePage == 65001) // UTF-8
        {
            byte byteCountMask = 0;
            while ((byteBuffer[byteLen - numFragments - 1] >> 6) == 2) // if the byte is "10xx xxxx", it's a continuation-byte
                byteCountMask |= (byte)(1 << ++numFragments); // count bytes & build the "complete char" mask
            if ((byteBuffer[byteLen - numFragments - 1] >> 6) == 3) // if the byte is "11xx xxxx", it starts a multi-byte char.
                byteCountMask |= (byte)(1 << ++numFragments); // count bytes & build the "complete char" mask
            // see if we found as many bytes as the leading-byte says to expect
            if (numFragments > 1 && ((byteBuffer[byteLen - numFragments] >> 7 - numFragments) == byteCountMask))
                numFragments = 0; // no partial-char in the byte-buffer to account for
        }
        else if (reader.CurrentEncoding.CodePage == 1200) // UTF-16LE
        {
            if (byteBuffer[byteLen - 1] >= 0xd8) // high-surrogate
                numFragments = 2; // account for the partial character
        }
        else if (reader.CurrentEncoding.CodePage == 1201) // UTF-16BE
        {
            if (byteBuffer[byteLen - 2] >= 0xd8) // high-surrogate
                numFragments = 2; // account for the partial character
        }
    }
    return reader.BaseStream.Position - numBytesLeft - numFragments;
}

 

그런 다음 위에서 제가 작성했던 코드에 position 을 기록하는 부분을 위에 소개한 함수를 이용해서 찾는 것이지요.

GetActualPosition 이라는 함수를 이용해서요. 그럼 아래와 같이 되겠죠.

long filePos = -1;
using (StreamReader cini = new StreamReader(fs, Encoding.Default))
{
	do
	{
		filePos = GetActualPosition(cini); //readLine 을 하기 전 위치를 저장한다
		string cline = readline();
		if (cline == "내가 원하는 정보")
		{
			break;
		}
	}while(cini.EndOfStream == false);
}

// filePos 에 저장된 값을 나중에 이용할 경우
using (StreamReader cini = new StreamReader(fs, Encoding.Default))
{
	cini.DiscardBufferedData();
	cini.BasePosition.Seek(filePos, SeekOrigin.Begin);

	// 자 이제 읽어 볼까!
	string myResult = cini.readLine();
}

 

이렇게 해서 결과를 확인해보면 아주 완벽하게 동작이 됩니다.

해당 개발자 분께서 페이지에 그리고 주석으로 상세하게 소개를 하고 있으니 관심 있으신 분께서는 한번 찬찬히 분석해보시는 것도 큰 공부가 될 것 같습니다.

c# 을 이용해 StreamReader 를 사용하시는 분들~

readline 수행 후 정확한 위치를 구해야 하는 문제에 봉착하셨다면 한번 시도해 보세요.

 

그럼 이만~

2023.01.31 - [DEV/c#] - [c#] Resource 에 추가한 텍스트를 소스코드에서 불러오기

2020/07/29 - [DEV/c#] - [C#] 설정 저장하고 재실행 시 저장한 값 불러오기

2020/07/21 - [DEV/c#] - C# 문자열 읽어서 문자열에 해당하는 변수에 값 세팅하기

2020/06/29 - [DIY/Arduino] - C# 에서 아두이노로 시리얼 통신 하기

2020/06/03 - [DEV/c#] - C# .net으로 photoshop 연동하기

반응형
반응형

오늘 소개해 드릴 포스팅은 C# 에서 어플리케이션을 만들때 디렉토리 입력창이나 각종 설정들에 대하여
마지막으로 실행했던 설정이 다음번에 다시 실행했을 때 남아있도록 해주는 기능입니다.

매번 경로나 설정을 바꿀 필요가 없다면 마지막에 설정했던 항목이 남아있는 것이 편리하겠죠. 반대로 프로그램 동작시 마다 매번 경로를 입력하든 설정 값들을 일일이 세팅을 해주어야 한다면 무척 불편한 것입니다.


실제로 일반적인 응용 프로그램들에서도 쉽게 볼수 있는 중요한 기능이기도 합니다.

 

자 한번 만들어 보겠습니다.

먼저 본인이 저장하고 싶은 항목을 구성해야 합니다.
저는 적당히 아래와 같은 의미로 저장을 해보겠습니다.

  • string : 디렉토리 주소
  • boolean : 하위폴더까지 포함 여부
  • integer : 분할 개수


요렇게 각각 하나씩 3가지를 해보기로 하겠습니다.

새로 공부하시는 분은 새로운 프로젝트를 생성해주시고요. 만약 기존 프로젝트에 본 기능을 붙이실 분은 해당 프로젝트를 여신 뒤에 진행하시면 됩니다. 

저는 임시로 새로운 프로젝트를 하나 만들어 보겠습니다. 그리고 위에서 말씀드린 내용을 설정하고 저장해보기 위한 간단한 UI 를 추가했습니다.



그 다음 비주얼 스튜디오 오측 솔루션 탐색기에서 현재 프로젝트의 프라퍼티 쪽을 확인해 주세요. 


프라퍼티 하위에 Settings.settings 라는 항목이 보이시나요?



해당 항목을 더블클릭해 줍니다.

다음에 이 설정을 가져올 수 있다고 써있네요.



그럼 위와 같은 데이터 입력 창이 나오는데요. 제일 좌측은 해당 값의 변수가 될 이름, 
두번째는 데이터의 형식이며 드롭다운 메뉴를 눌러 선택이 가능합니다.
범위는 사용자로 두시면 되고 제일 우측 값 부분에 최초 저장될 값을 임시로 넣어 두면 됩니다.

저는 위의 3가지 설정을 저장할 예정이므로 위와같이 3가지 타입의 변수를 정해 주었습니다.

 

자 이제 Form 이 Load 될 때 이 설정 값들을 가져오도록 해보겠습니다.

먼저 UI 디자인하는 화면에서 타이틀바를 더블클릭 해주면 Form load 함수가 생성이 됩니다. 생성된 함수를 아래와 같이 작성합니다.

private void Form1_Load(object sender, EventArgs e)
{
  textBox1.Text = Properties.Settings.Default.myPath;
  checkBox1.Checked = Properties.Settings.Default.myCheck;
  numericUpDown1.Value = Properties.Settings.Default.myNumber;
}

당연히 본인이 작성한 설정의 이름과 UI 의 이름을 이용하여 작성을 해야겠죠?

이렇게 작성한 뒤 실행해보면 아래와 같이 표시가 됩니다.

위에 settings 에서 입력했던 값이 그대로 표시가 되고 있지요?

이제 해당 값을 변경한뒤에 저장하는 부분을 만들면 됩니다.

저는 일단 버튼을 누를때 현재 각 메뉴에 설정되어 있는 값을 저장하는 것으로 해보겠습니다.

private void button1_Click(object sender, EventArgs e)
{
    Properties.Settings.Default.myPath = textBox1.Text;
    Properties.Settings.Default.myCheck = checkBox1.Checked;
    Properties.Settings.Default.myNumber =Convert.ToInt32(numericUpDown1.Value);
    Properties.Settings.Default.Save();
}

엄청 간단하죠? 불러올때와 반대로 해당 값을 설정에 입력해준 뒤 마지막 줄에 save 해주면 됩니다.

이 코드를 하나의 함수로 묶어서 핵심 기능을 수행할 때나 Form 을 종료할때 넣어주면 되겠습니다.

반응형

 

 

한번 해볼까요?

 

요렇게 설정을 한 뒤에 버튼을 눌러주고 껐다가 다시 실행해 보면 ?

 

당연한 것이지만 이렇게 다시 그상태 그대로 form 이 실행이 됩니다.

 

어떠신가요? 참 쉽죠?

요런 간단한 기능들이 프로그램의 사용성을 크게 높일 수 있습니다. 본인이 개발하는 유틸리티나 어플리케이션에 이러한 기능이 아직 없다면 어렵지 않고 크게 시간도 들지 않는 기능이므로 꼭 한번 넣어보시기 바랍니다.

그럼 이만~

 

뎃글, 공감 은 블로그 작성자에게 큰 힘이 된답니다. 
도움이 되었다 생각되시면  클릭!!  부탁드려요~

2023.01.31 - [DEV/c#] - [c#] Resource 에 추가한 텍스트를 소스코드에서 불러오기

 

[c#] Resource 에 추가한 텍스트를 소스코드에서 불러오기

뻔하디 뻔한 개발 노하누는 가라~ 이번에도 쓸만한 내용을 소개해 드릴 까 합니다. 개발을 하다 보면 실제 소스코드 외에도 어떤 텍스트를 resource 에 넣어 두고 소스코드에서 불러와야 하는 경우

diy-dev-design.tistory.com

2020/08/11 - [DEV/c#] - [c#] streamreader 를 이용하여 정확한 라인 위치 찾기

2020/07/21 - [DEV/c#] - C# 문자열 읽어서 문자열에 해당하는 변수에 값 세팅하기

 

C# 문자열 읽어서 문자열에 해당하는 변수에 값 세팅하기

오늘 소개해드릴 꿀팁은요. 문자열을 읽어 들여서 문자열 내에 들어있는 특정 단어를 이용하여 개발 중인 코드의 변수로 인식하여 해당 변수에 값을 세팅하는 방법을 소개해 드릴까 합니다. 예�

diy-dev-design.tistory.com

2020/06/03 - [DEV/c#] - C# .net으로 photoshop 연동하기

 

C# .net으로 photoshop 연동하기

저는 회사에서 디자인팀에 있고 전공도 디자인과 출신이며 심지어는 고등학교도 예체능계열 고등학교를 나왔습니다만 지금 회사에서 하는일의 95% 정도는 개발을 하고 있습니다. 실제로 제가 ��

diy-dev-design.tistory.com

2020/06/29 - [DIY/Arduino] - C# 에서 아두이노로 시리얼 통신 하기

 

C# 에서 아두이노로 시리얼 통신 하기

카테고리를 c# 으로 해야 할지 Arduino 로 해야할지 조금 고민이 되는 포스트 입니다. 음.... arduino 로 하는게 좋겠네요. 따지고 보면 C# 으로 만든 어플이 중요한게 아니라 아두에노에서 시리얼 통신

diy-dev-design.tistory.com

2020/05/28 - [DEV/c#] - [c#] 주어진 경로가 디렉토리인지 파일인지 확인하는 방법

 

[c#] 주어진 경로가 디렉토리인지 파일인지 확인하는 방법

오늘은 간단하게 주어진 경로가 폴더인지 파일인지 구분하는 방법을 소개해 드리겠습니다. 길게 설명할 것 없이 간단하게 코드나갑니다. FileAttributes chkAtt = File.GetAttributes(_path); if ((chkAtt & FileA..

diy-dev-design.tistory.com

 

반응형
반응형

오늘 소개해드릴 꿀팁은요.

문자열을 읽어 들여서 문자열 내에 들어있는 특정 단어를 이용하여 개발 중인 코드의 변수로 인식하여 해당 변수에 값을 세팅하는 방법을 소개해 드릴까 합니다.

예를 들면 텍스트 파일로 어떤 설정들을 저장해놓고 해당 설정파일을 읽어 들이면 일일이 변수명과 비교하여 맞으면 설정하는 방식이 아닌 바로 설정 파일 자체에 변수명을 넣어두고 변수명 그대로 값을 설정파일에서 읽어 들이는 것이지요.

이렇게 되면 변수가 아주 많은경우 간단하게 코딩을 할 수 있는 장점이 있겠습니다.

 

다시 말하면 aa,bb,cc 라는 변수가 있고 설정 파일 (텍스트파일) 에 다음과 설정이 있다고 하면요.

aa=#FFFcbc
bb=#12cd43
cc=#FF0000
      :
      :

if (읽어들인 문자열 앞부분 == "aa") aa = 읽어들인 문자열 뒷부분;
if (읽어들인 문자열 앞부분 == "bb") bb = 읽어들인 문자열 뒷부분;
if (읽어들인 문자열 앞부분 == "cc") cc = 읽어들인 문자열 뒷부분;
                 :
                 :

이런식으로 하지 않아도 된다는 것이지요. 만약 몇줄 안된다면 상관 없겠지만 20~30 줄 이상이라면 매번 if 로 정확하게 명칭을 따주는 것도 일입니다. 몇 백줄의 설정이 필요하다면 더더욱 그럴 수 밖에 없겠죠.

 

 

 

 

실제 예제를 볼까요?

컨트롤 해야 하는 컬러 설정 파일을 아래와 같이 준비 합니다. txt, ini 같은 그냥 텍스트 파일로요. 

color_A=#cc3333
color_B=#99cc33
color_C=#cccccc
color_D=#006666
color_E=#00ffff
color_F=#6666cc
color_G=#9966cc

 

위의 문자열들에서 color_A 는 제가 아래 올린 코드의 color_a 에 대한 설정 값으로 사용되게 됩니다. 일일이 if 문을 이용하여 color_A == color_a 인지 color_b 인지 확인하지 않고 해당 클래스가 들고 있는 프라퍼티들의 이름 중에 같은 것이 있는지 찾는 방법이지요.

// 제일 상단에 지시문 추가
using System.Reflection;

// 본 클래스는 메인 클래스가 아니어도 상관 없습니다. 
// 예를 들면 Form 클래스내에 기능적인 용도나 구조체로 사용할 클래스 여도 상관 없음
public class MyColorStyle
{
	private string color_a;
	private string color_b;
	private string color_c;
	private string color_f;
	private string color_e;
	private string color_f;
	private string color_g;
	
	// 외부에서 가져가고 세팅할 수 있도록 get set 함수 하나씩 준비
	public string color_A {get { return color_a;} set { color_a= value; } }
	public string color_B {get { return color_b;} set { color_b= value; } }
	public string color_C {get { return color_c;} set { color_c= value; } }
	public string color_D {get { return color_d;} set { color_d= value; } }
	public string color_E {get { return color_e;} set { color_e= value; } }
	public string color_F {get { return color_f;} set { color_f= value; } }
	public string color_G {get { return color_g;} set { color_g= value; } }
	
	public golfMapcolorStyle()
	{
		//생성자 부분에는 초기화 값 넣어 주시고요.. 
	}
	public void setColor(string clrString) // clrString : "color_A=#FFEECC" 형식의 설정 문자열이 줄단위로 기록되어 있는 파일 전체
	{
		string[] tmps = clrString.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries); // 줄바꿈 단위로 분리해준다.
		foreach (string str in tmps)
		{
			string[] tmp = str.Split('='); // = 기호를 기준으로 앞의 문자열은 변수 명칭을 검색, 뒤의 문자열은 값으로 사용 

			foreach (PropertyInfo p in typeof(MyColorStyle).GetProperties())
			{
				if (tmp[0] == p.Name)
				{
					tmp[1] = tmp[1].Trim(); // 잘려진 문자열 뒤에 지저분하게 붙는 경우가 있어서 사용함
					p.SetValue(this, tmp[1], null);
				}
			}
		}
	}
}

 

총 7개의 변수가 있지만 단 하나의 방법으로 설정을 할 수 있게 됩니다. 

만약 변수가 100 개 이상이었다면 위와 같은 방식으로 사용하는게 개발 시간을 크게 단축할 수 있을 것입니다. 오류도 많이 줄어들 것이고요.

위 코드에서 제일 핵심이 되는 부분은 바로 아래 부분입니다.

foreach (PropertyInfo p in typeof(MyColorStyle).GetProperties())
{
	// p 에 대하여 무었인가를 할 수 있음
}

클래스가 가지고 있는 변수를 프라퍼티로 보고 프라퍼티의 이름을 확인하여 뭔가를 할 수 있게 되는 것이죠.

p.SetValue 라는 명령어를 이용하여 p 라는 MyColorStyle 라는 클래스의 프라퍼티(변수) 의 값을 설정하는 것이 이번 포스트의 핵심 내용입니다.

 

 

 

만약 변수가 문자열 뿐만 아니라 int 형식도 존재한다고 하면 아래와 같이 간단하게 구현할 수도 있습니다.

foreach (PropertyInfo p in typeof(golfMapcolorStyle).GetProperties())
{
	if (tmp[0] == p.Name)
	{
		try
		{
			tmp[1] = tmp[1].Trim();
			p.SetValue(this, tmp[1], null);
		}
		catch
		{
			tmp[1] = tmp[1].Trim();
			p.SetValue(this, Convert.ToInt32(tmp[1]), null);
		}
	}
}

 

반대로 현재 설정을 저장하는 등의 기능을 구현 할 때에도 위의 코드를 응용하여 특정 클래스가 갖는 모든 프라퍼티를 정확한 변수명과 값으로 손쉽게 저장하는 것이 가능할 것입니다.

 

그럼 이만~

 

뎃글, 공감 은 블로그 작성자에게 큰 힘이 된답니다. 
도움이 되었다 생각되시면  클릭!!  부탁드려요~

 

2020/08/11 - [DEV/c#] - [c#] streamreader 를 이용하여 정확한 라인 위치 찾기

2020/06/29 - [DIY/Arduino] - C# 에서 아두이노로 시리얼 통신 하기

2020/06/03 - [DEV/c#] - C# .net으로 photoshop 연동하기

2020/05/29 - [DEV/c#] - [C#] .net 프로그램에서 MD5 해시 체크파일 만들기

2019/06/21 - [DEV/c#] - [C#] 마우스 매크로를 위한 마우스 자동 클릭 기능 만들기

2020/01/03 - [DEV/c#] - [C#] C# APP 에서 엑셀 연동해보기

반응형
반응형

저는 회사에서 디자인팀에 있고 전공도 디자인과 출신이며 심지어는 고등학교도 예체능계열 고등학교를 나왔습니다만 지금 회사에서 하는일의 95% 정도는 개발을 하고 있습니다. 실제로 제가 포토샵, 일러스트 및 기타 디자인툴을 다루는 시간을 다 합쳐도 비주얼 스튜디오를 사용하는 시간의 1/10 도 안될거에요.

요즘은 대부분의 개발을 c# 으로 진행하고 있습니다. 포토샵 스크립트를 이용해서 이미지 컨트롤은 할 수 있겠지만 좀더 복잡하고 다양한, 그리고 시스템 차원에서 뭔가를 하기에는 부족한 부분이 있습니다. 하지만 포토샵에는 레이어 컨트롤이나 layer effect 와 같은 놀라운 기능들이 있기 때문에 버리기는 아까운 부분이 있습니다.

그래서 저는 C# 을 이용하여 개발을 하되 포토샵을 이미지 자동화 편집 툴로 사용할때가 종종 있습니다. javascript 로 개발된 이미지 편집용 스크립트를 C# application 에서 포토샵으로 전달하여 자동화를 하는 것이지요.

 

??

 

이게 가능하냐고요? 

예전에 제가 엑셀 비주얼 베이직을 이용하여 엑셀과 포토샵이 연동되는 것을 소개해 드린적이 있는데요, 개념적으로는 크게 다르지 않습니다.

2019/10/01 - [DEV/VBA] - [VBA] 엑셀 VBA로 포토샵 연동이 가능할까?

 

개념적으로는 윈도우의 COM 오브젝트를 이용하는 것과 동일한데요. 연결해주는 방법에 약간 차이가 있고 C# 에서 포토샵 스크립트 작성이 쉽지 않으니 개발은 Extend Script Tool kit 으로 하고 실행만 C#이 하는 역할을 하는 겁니다.

이렇게 되면 C#이 다양한 파일 처리, 관리를 하는 동안 이미지 편집이 필요한 순간에 Photoshop 을 호출하여 이미지를 열고 자동화 편집 스크립트를 통해 이미지 편집을 진행하고 그 다음 나머지 파일 처리를 하는 방식 인 겁니다.

 

 

 

C# 에서 COM 오브젝트 선언하는 방법

Type ptsApp = Type.GetTypeFromProgID("Photoshop.Application");
dynamic psApp = Activator.CreateInstance(ptsApp);
psApp.doJavaScript("alert(\"ds\")"); // 여기에 수행되어야 할 포토샵 스크립트를 문자열로 작성하여 전달

dynamic 개체를 이용하여 선언이 가능하며 .NET4.0 이상의 플랫폼에서 지원합니다.

이렇게 했을 때 빌드를 하게 되면 아래와 같은 오류가 나타나는 경우가 있는데요. 

Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create' 멤버가 필요한 컴파일러가 없습니다

 

우측의 솔루션 탐색기 '참조' 부문에서 마우스 우클릭 후 '참조 추가' 로 참조할 개체를 추가해 주어야 하는데요.

Microsoft.CSharp 

을 추가해주시면 정상적으로 빌드가 진행이 됩니다.

 

막상 포토샵 오브젝트를 추가해 주었지만 실제 실행될 때 C# 에서 포토샵 코드를 작성하는 것이 여간 귀찮은 일이 아닙니다. 그런 경우 미리 javascript 로 필요한스크립트를 작성하여 준뒤 아래와 같이 실행시킬 수 있습니다. 이렇게 하면 실행시 미리 변수를 전달 할 수 있기 때문에 상당히 유연한 개발을 진행할 수 있게 됩니다.

dynamic[] args = new dynamic[2];
args[0] = "test string 1";
args[1] = "test string 2";

dynamic app = Activator.CreateInstance(Type.GetTypeFromProgID("Photoshop.Application"));

String scriptPath = @"D:\test\route_point_extractor_samples\script1.jsx";
string scriptStr = File.ReadAllText(scriptPath);
app.DoJavaScriptFile(scriptPath, args);

변수는 위에 보시는것 과 같이 dynamic 배열 개체를 생성한뒤 필요한 값을 입력해주고 스크립트와 함께 전달하는 방식을 사용하면 됩니다. 

 

 

 

 

포토샵 스크립트 실행 완료 후 반환(리턴) 값이 필요한 경우라면?

무언가 일을 시켰다면 피드백이 있어야 하겠지요? 만들어진 개체의 파일 명이든 무엇이든 간에 어떤 피드백을 받아야 하는 경우 아래와 같이 작성합니다.

 

Javascript (포토샵에서 실행되어야 할 스크립트)

var value1 = arguments[0]; // C# 으로 부터 전달 받는 인자 
var value2 = arguments[1]; // C# 으로 부터 전달 받는 인자

main(value1, value2)

function main (val1, val2)
{
	string myString = "";
    
    // 실제 필요한 계산, 동작을 작성한다.
    
    myString = val1 + "," + val2 ;
	
    return myString; // 이 값이 C# 으로 반환된다.
}

 

C#

dynamic[] args = new dynamic[2];
args[0] = "test string 1";
args[1] = "test string 2";

dynamic app = Activator.CreateInstance(Type.GetTypeFromProgID("Photoshop.Application"));

String scriptPath = @"D:\test\route_point_extractor_samples\script1.jsx";
string scriptStr = File.ReadAllText(scriptPath);

string myResult = app.DoJavaScriptFile(scriptPath, args);

// 결과값은 "test string 1,test string 2" 가 반환된다.

이렇게 해주면 myResult 라는 문자열 변수에 입력한 변수들을 합친 문자열이 반환이 되는것이죠.

어떠신가요? 어렵지 않죠?

 

 

 

 

 

이렇게 하면 C# 으로 빠르고 편리한 이미지 관리 프로그램을 만들어 포토샵으로 강력한 이미지 편집 기능을 함께 이용할 수 있는 기능을 개발 할 수 있습니다. 물론 ImageMagick 과 같은 강력한 이미지 편집 프로그램이 있긴 하지만 이미 만들어져 있는 PSD 파일 등의 레이어속성을 조회하거나 변경하고, 특정 레이어들을 이용하여 어떤 작업을 해야 한다면 ImageMagick 으로는 한계가 있습니다. 

직접 한번 코딩을 해보시면서 테스트 해보시길 바랍니다.

 

궁금하신 부분은 뎃글로 남겨 주시면 답변 드릴 수 있도록 하겠습니다.

이만 포스팅을  마칩니다.

뎃글, 공감 은 블로그 작성자에게 큰 힘이 된답니다. 
도움이 되었다 생각되시면 클릭!!  부탁드려요~

 

 

 

2020/04/03 - [DEV/c#] - ImageMagick 을 이용하여 이미지 컨트롤 해보기

 

ImageMagick 을 이용하여 이미지 컨트롤 해보기

포토샵 없이 이미지를 편집하는 방법이 없을까 고민하다가 알게된 라이브러리, 바로 ImageMagick 입니다. 먼저 포스트에서 ImageMagick 을 프로젝트에 가져오는 방법을 아래와 같이 소개해 드린적이 ��

diy-dev-design.tistory.com

2019/06/21 - [DEV/c#] - [C#] C# .NET 프로젝트에서 ImageMagick 이용하기

 

[C#] C# .NET 프로젝트에서 ImageMagick 이용하기

이미지 관련된 툴을 개발함에 있어 다양한 이미지 포멧을 만들고 변경하기 위한 코어를 개발하는 것은 말도 안되게 힘든 작업입니다. 저는 디자이너라는 타이틀을 가지고 있기 때문에 포토샵이

diy-dev-design.tistory.com

2020/01/03 - [DEV/c#] - [C#] C# APP 에서 엑셀 연동해보기

 

[C#] C# APP 에서 엑셀 연동해보기

엑셀에서 VBA 로 코드를 짜다 보면 막상 특정 엑셀 파일에만 VBA 가 적용이 가능하기 때문에 막상 다른 엑셀 파일에서 동일한 동작을 하려면 또 코드를 복사해 넣고 실행을 해야 하는 경우가 있습�

diy-dev-design.tistory.com

2019/06/10 - [DEV/Adobe Script] - [포토샵 스크립트] 강좌, 무작정 따라해보기

 

[포토샵 스크립트] 강좌, 무작정 따라해보기

어도비 포토샵은 자체 스크립트를 이용하여 다양한 기능을 수행할 수 있는 툴을 지원합니다. 언어는 자바 스크립트 이며 작성된 자바스크립트를 포토샵에서 실행하는 방법과 Extend Script Tool Kit �

diy-dev-design.tistory.com

2020/01/23 - [DEV/Adobe Script] - [포토샵스크립트] 레이어 컨텐츠 영역 선택하기

 

[포토샵스크립트] 레이어 컨텐츠 영역 선택하기

오늘 소개해 드릴 스크립트는 간단한 내용이지만 일반 적인 스크립트상으로 개발이 불가능하기에 경우에 따라는 아주 유용한 스크립트가 되겠습니다. 우리는 작업 중 상당한 빈도로 포토샵 레�

diy-dev-design.tistory.com

 

 

반응형
반응형

프로그래밍을 이용하여 파일을 생성하거나 이동시킬때 md5 와 같은 무결성 검증을 위한 해시체크 파일을 생성해야 할때가 있습니다. 물론 간단한 유틸리티를 내려받아 윈도우 쉘 명령어로 만드는 방법도 있겠지만 굳이 프로그래밍에 의한 결과를 다시 사용자가 손으로 작업하는 것은 효율 적인 방법이라고 하기는 어렵겠죠.

그래서 이번에는 C# 프로그램에서 바로 md5 파일을 생성하는 방법을 소개해 드릴까 합니다.

 

일단 기본은 아래와 같습니다.

// 코드 최 상단에 아래와 같은 using 지시문을 넣어 줍니다.
using System.Security.Cryptography;


// 코드내에 아래의 함수를 추가하여 해시문자열을 받아올 수 있습니다.
// 해시 문자열을 스트링으로 받아오는 함수, 아래 str 은 파일의 경로를 지정한다.
private static string getMD5Hash(string str)
{
  using (var md5 = MD5.Create())
  {
    using (var stream = File.OpenRead(str))
    {
      var hash = md5.ComputeHash(stream);
      return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
    }
  }
}

 

이렇게 하면 getMD5Hash(파일경로) 라는 함수를 이용하여 해시체크용 문자열을 가져올 수 있습니다. 굳이 다른 유틸리티 없이도 본인이 개발중인 프로그램 내에서 md5 체크썸 파일을 만들 수 있는 것이죠.

md5 파일을 만드는것 까지 해보면 아래와 같습니다.

저의 경우에는 디렉토리 하위에 모든 파일에 대한 체크썸 파일이 필요했기 때문에 하위 디렉토리를 돌며 파일 및 폴더를 탐색하는 재귀함수 형태로 제작을 했습니다.

using System.Security.Cryptography;

.
.
.

private static void createmd5(string _path, string md5name)
{
	string dirName = Directory.GetParent(md5name).ToString() + "\\";
	string tmp = "";
	chkDir_md5(ref tmp, _path, dirName);
	
	File.WriteAllText(md5name, tmp);

}

// 지정된 폴더를 탐색하며 하위의 모든 폴더, 파일을 검사 후 문자열 기록
private static void chkDir_md5 (ref string _str, string _path, string _defPath)
{

	FileAttributes att = File.GetAttributes(_path);
	if ((att & FileAttributes.Directory) == FileAttributes.Directory)
	{
		// is a Directories
		string[] tmpPath = Directory.GetDirectories(_path, "*");

		foreach (string s in tmpPath)
		{
			chkDir_md5(ref _str, s, _defPath);
		}

		string[] tmpFiles = Directory.GetFiles(_path, "*.*");

		foreach (string s in tmpFiles)
		{
			chkDir_md5(ref _str, s, _defPath);
		}
	}
	else
	{
		// is a file
		_str += getMD5Hash(_path);
		_str += " *" + _path.Replace(_defPath, "");
		_str += "\n";

	}	
}

private static string getMD5Hash(string str)
{
	using (var md5 = MD5.Create())
	{
		using (var stream = File.OpenRead(str))
		{
			var hash = md5.ComputeHash(stream);
			return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
		}
	}
}

 

찬찬히 보시면 전혀 어려울 것이 없으니 훓어 보시기 바랍니다.

 

md5 파일을 제작하여 원본파일과 함께 배포를 하게 되면 파일을 전달받는 위치에서 해당 파일이 원본과 동일하지를 판단할 수 있으며 압축/압축해제시 또는 웹서버에 올라간 데이터가 네트웍망을 타고 내려오는 동인 손실이 있었는지를 파악하는데 도움이 됩니다.

 

이상으로 c# 에서 MD5 체크썸 파일을 만드는 방법을 소개해 드렸습니다.

 

2020/07/21 - [DEV/c#] - C# 문자열 읽어서 문자열에 해당하는 변수에 값 세팅하기

 

C# 문자열 읽어서 문자열에 해당하는 변수에 값 세팅하기

오늘 소개해드릴 꿀팁은요. 문자열을 읽어 들여서 문자열 내에 들어있는 특정 단어를 이용하여 개발 중인 코드의 변수로 인식하여 해당 변수에 값을 세팅하는 방법을 소개해 드릴까 합니다. 예�

diy-dev-design.tistory.com

 

2020/05/28 - [DEV/c#] - [c#] 주어진 경로가 디렉토리인지 파일인지 확인하는 방법

 

[c#] 주어진 경로가 디렉토리인지 파일인지 확인하는 방법

오늘은 간단하게 주어진 경로가 폴더인지 파일인지 구분하는 방법을 소개해 드리겠습니다. 길게 설명할 것 없이 간단하게 코드나갑니다. FileAttributes chkAtt = File.GetAttributes(_path); if ((chkAtt & FileA..

diy-dev-design.tistory.com

2020/04/03 - [DEV/c#] - ImageMagick 을 이용하여 이미지 컨트롤 해보기

 

ImageMagick 을 이용하여 이미지 컨트롤 해보기

포토샵 없이 이미지를 편집하는 방법이 없을까 고민하다가 알게된 라이브러리, 바로 ImageMagick 입니다. 먼저 포스트에서 ImageMagick 을 프로젝트에 가져오는 방법을 아래와 같이 소개해 드린적이 ��

diy-dev-design.tistory.com

2020/01/03 - [DEV/c#] - [C#] C# APP 에서 엑셀 연동해보기

 

[C#] C# APP 에서 엑셀 연동해보기

엑셀에서 VBA 로 코드를 짜다 보면 막상 특정 엑셀 파일에만 VBA 가 적용이 가능하기 때문에 막상 다른 엑셀 파일에서 동일한 동작을 하려면 또 코드를 복사해 넣고 실행을 해야 하는 경우가 있습�

diy-dev-design.tistory.com

2019/06/21 - [DEV/c#] - [C#] 마우스 매크로를 위한 마우스 자동 클릭 기능 만들기

 

[C#] 마우스 매크로를 위한 마우스 자동 클릭 기능 만들기

사용자의 마우스 컨트롤 없이 자동으로 지정된 위치에서 마우스를 클릭하게 만들어 주는 기능 입니다. 먼저 아래와 같이 DLL 을 불러들여 주어야 하겠습니다. class 정의 바로 아래부분에 넣어 주�

diy-dev-design.tistory.com

 

반응형
반응형

 

오늘은 간단하게 주어진 경로가 폴더인지 파일인지 구분하는 방법을 소개해 드리겠습니다.

길게 설명할 것 없이 간단하게 코드나갑니다.

 

FileAttributes chkAtt = File.GetAttributes(_path);
if ((chkAtt & FileAttributes.Directory) == FileAttributes.Directory)
{
 // 디렉토리일 경우
}
else
{
 // 파일 일 경우
}

 

간단하죠 ?

이렇게 하면  _path 로 주어진 경로가 디렉토리인지 파일인지 구분할 수 있는데요. 폴더를 계속해서 탐색하는 기능을 만들때 유용하게 사용할 수 있답니다.

 

 

예를 들면 아래와 같은 방법으로 하위폴더의 모든 파일에 대한 액션을 할 수 있는 재귀 함수를 만들수 있는 것입니다.

private static void chkDir_recursive (string _path)
{

  FileAttributes chkatt = File.GetAttributes(_path);
  if ((chkatt & FileAttributes.Directory) == FileAttributes.Directory)
  {
    // is a Directories
    string[] tmpPath = Directory.GetDirectories(_path, "*");

    foreach (string s in tmpPath)
    {
    	chkDir_recursive(_path); // 폴더를 만나면 하위로 계속 탐색을 진행
    }

    string[] tmpFiles = Directory.GetFiles(_path, "*.*");

    foreach (string s in tmpFiles)
    {
    	chkDir_recursive(_path); // 파일을 만나도 동일한 함수로 실행 가능함
    }
  }
  else
  {    
    // 파일을 만나게 되면 실제 해야할 액션을 코딩한다

  }

}

 

간단하죠?

 

이상으로 주어진 경로가 폴더인지 파일인지 구분하는 방법을 소개해 드렸습니다~

2020/05/29 - [DEV/c#] - [C#] .net 프로그램에서 MD5 해시 체크파일 만들기

 

[C#] .net 프로그램에서 MD5 해시 체크파일 만들기

프로그래밍을 이용하여 파일을 생성하거나 이동시킬때 md5 와 같은 무결성 검증을 위한 해시체크 파일을 생성해야 할때가 있습니다. 물론 간단한 유틸리티를 내려받아 윈도우 쉘 명령어로 만드�

diy-dev-design.tistory.com

2020/01/03 - [DEV/c#] - [C#] C# APP 에서 엑셀 연동해보기

 

[C#] C# APP 에서 엑셀 연동해보기

엑셀에서 VBA 로 코드를 짜다 보면 막상 특정 엑셀 파일에만 VBA 가 적용이 가능하기 때문에 막상 다른 엑셀 파일에서 동일한 동작을 하려면 또 코드를 복사해 넣고 실행을 해야 하는 경우가 있습�

diy-dev-design.tistory.com

2019/06/21 - [DEV/c#] - [C#] C# .NET 프로젝트에서 ImageMagick 이용하기

 

[C#] C# .NET 프로젝트에서 ImageMagick 이용하기

이미지 관련된 툴을 개발함에 있어 다양한 이미지 포멧을 만들고 변경하기 위한 코어를 개발하는 것은 말도 안되게 힘든 작업입니다. 저는 디자이너라는 타이틀을 가지고 있기 때문에 포토샵이

diy-dev-design.tistory.com

2019/06/21 - [DEV/c#] - [C#] 마우스 매크로를 위한 마우스 자동 클릭 기능 만들기

 

[C#] 마우스 매크로를 위한 마우스 자동 클릭 기능 만들기

사용자의 마우스 컨트롤 없이 자동으로 지정된 위치에서 마우스를 클릭하게 만들어 주는 기능 입니다. 먼저 아래와 같이 DLL 을 불러들여 주어야 하겠습니다. class 정의 바로 아래부분에 넣어 주�

diy-dev-design.tistory.com

2019/06/21 - [DEV/c#] - [C#] Delay 기능

 

[C#] Delay 기능

c# .net 환경 개발시 아래의 함수를 이용하여 Delay 를 구현할 수 있습니다. private static DateTime Delay(int MS) { DateTime ThisMoment = DateTime.Now; TimeSpan duration = new TimeSpan(0, 0, 0, 0, MS);..

diy-dev-design.tistory.com

 

반응형
반응형

포토샵 없이 이미지를 편집하는 방법이 없을까 고민하다가 알게된 라이브러리, 바로 ImageMagick 입니다.

먼저 포스트에서 ImageMagick 을 프로젝트에 가져오는 방법을 아래와 같이 소개해 드린적이 있습니다. 

2019/06/21 - [DEV/c#] - [C#] C# .NET 프로젝트에서 ImageMagick 이용하기

 

[C#] C# .NET 프로젝트에서 ImageMagick 이용하기

이미지 관련된 툴을 개발함에 있어 다양한 이미지 포멧을 만들고 변경하기 위한 코어를 개발하는 것은 말도 안되게 힘든 작업입니다. 저는 디자이너라는 타이틀을 가지고 있기 때문에 포토샵이라는 훌륭한 어플리..

diy-dev-design.tistory.com

 

오늘은 실제 ImageMagick 라이브러리를 이용하여 이미지를 컨트롤 하는 방법을 소개해 드릴 까 합니다.

오늘 컨트롤 해볼 이미지의 속성은 리사이즈, 밝기 조정, 채도 조절, 그리고 이미지의 출력 레벨 조정 입니다.

 

일반 적으로 상단 지시문에 using imageMagick 을 선언해 주었다면 본문에서는 바로 아래와 같이 사용하면 됩니다,

// 파일 오픈 다이얼로그를 통하여 이미지를 열어서 picture box 에 표시하는 방법

openFileDialog1.ShowDialog(); // 이미지 파일을 선택
MagickImage mimg = new MagickImage(openFileDialog1.FileName); //매직 이미지로 열기
pictureBox1.Image = mimg.ToBitmap(); // pivture box 에 이미지 표시하기

기본적인 사용 방법은 위와 같이 MagickImage 개체를 선언해 준 뒤 이미지 파일을 열어주면 됩니다.

그럼 MagickImage 로 지정한 mimg 라는 변수에 각종 ImageMagick 에서 지원하는 기능을 사용할 수 있습니다.

위의 예제는 간단하게 MagickImage 로 불러들인 이미지를 이용하여 picturebox 에 그림을 표시하는 예제가 되겠습니다. 

picturebox 에 표시된 그림

 

ImageMagick 을 이용하여 이미지 크기를 변경하려면?

mimg = new MagickImage(openFileDialog1.FileName);

mimg.Resize(new Percentage(50));

또는
mimg.Resize(new Percentage(50), new Percentage(25));

또는
mimg.Resize(int TargetWidth, int TargetHeight);

 같이 적용하면 됩니다. 비율을 유지하며 변경도 가능하고 각각도 조정이 가능합니다. 변경하는 몇가지 방법이 있습니다. 위와 같이 퍼센테이지로 지정하는 것과 타겟 이미지의 가로, 세로 크기를 직접 설정하여 변환하는 방법을 사용하시면 되는데요. 일반적으로는 퍼센테이지로 변환하는 것이 편리하죠.

물론 지정된 타겟 크기가 있다면 해당 크기로 바로 변환하는것도 가능합니다.

 

이미지 크기를 변경할 때 리사이즈 필터 (안티알리아싱, 선명도 등을 조절) 를 설정하려면??

mimg = new MagickImage(openFileDialog1.FileName);

mimg.FilterType = FilterType.Mitchell;

mimg.Resize(new Percentage(50));

/*
필터 종류들
Point = 1,  Box = 2, Triangle = 3, Hermite = 4, Hann = 5, Hamming = 6, 
Blackman = 7, Gaussian = 8, Quadratic = 9,  Cubic = 10,  Catrom = 11, 
Mitchell = 12,  Jinc = 13, Sinc = 14, SincFast = 15, Kaiser = 16, 
Welch = 17, Parzen = 18, Bohman = 19, Bartlett = 20, Lagrange = 21, Lanczos = 22, 
LanczosSharp = 23, Lanczos2 = 24, Lanczos2Sharp = 25, Robidoux = 26,  
RobidouxSharp = 27, Cosine = 28, Spline = 29, LanczosRadius = 30, CubicSpline = 31

*/

FilterType.Mitchell 부분이 필터를 지정하는 부분인데요. 많은 종류의 필터를 제공하고 있으므로 필요에 따라 적정한 필터를 지정하여 변환에 사용하시면 좋을 것 같습니다. 각각의 필터에 따른 결과의 차이에 대하여도 나중에 한번 분석을 해봐와야 겠습니다. 

 

 

 

 

ImageMagick 을 이용하여 그림의 밝기/채도/대비를 변경하려면?

우선 밝기를 조정하는 방법을 보면 간단하게 아래와 같은 방식으로 가능합니다.

//MagickImage.InverseLevel(max, min)
mImg.InverseLevel(new Percentage(100), new Percentage(0));
// 앞의 것을 내리면 전체적으로 어두워지고, 뒤의 것을 올리면 전체적으로 밝아진다.

InverseLevel 은 포토샵의 Level 과 같은 기능을 수행합니다.

여기서 InverseLevel 의 특성을 아는 것이 중요합니다. 기본적으로 ImageMagick 에서 Level 이라는 밝기 조정을 위한 명령이 존재하지만 제가 InverseLevel 을 사용한 이유는 그림의 전체 밝기, 어둡기를 컨트롤 하고 싶은데 Level 은 그렇지가 않은 결과를 가져다 줍니다. 어디까지를 블랙으로 볼 것이냐를 결정하는 듯한 변화인데요, 아래 그림으로 보시면 이해가 빠르실 거라 생각됩니다.

Level ( blackPointPercentage , whitePointPercentage)

MagickImage.Level (0%, 10%)
MagickImage.Level (0%, 10%)

물론 둘다 100 또는 둘다 0 이 입력되면 완전 흰색/ 검은색으로 표시됩니다.

 

자 그럼 InverseLevel 로 변경한 그림을 볼까요??

InverseLevel( blackPointPercentage , whitePointPercentage)

MagickImage.InverseLevel(90%, 100%)
MagickImage.InverseLevel(0%, 10%)

 

어떠신가요? 일반적인 우리가 생각하는 밝기를 변화하는 방법이랑 좀더 비슷한것 같지않으신가요? 물론 필요에 따라 위의 방법과 아래의 방법을 잘 조합하여 사용하는 것이 필요하겠으나 차이가 있음을 알려드리고자 올렸습니다.

 

그외에도 채도, 콘트라스트 등을 변경하는 것도 위와 크게 차이는 없습니다. 

채도조정 : MagickImage.Modulate( brightness, saturation) 
콘트라스트 : MagickImage.BrightnessContrast( brightness, contrast)

채도와 콘트라스트 조정시에도 밝기를 함께 조절할 수 있지만 저는 각각의 요소를 개별로 컨트롤하는 것이 편리하여 위의 두가지에서 brightness 는 100을 그냥 적용하고 InverseLevel 까지 포함하여 3개의 명령을 각각 사용합니다. 

 

이상으로 간단하게 ImageMagick 을 이용하여 이미지를 컨트롤 하는 예제를 설명 드렸습니다. 

이미지 합성, 레이어링, 알파채널 등의 좀 더 복잡하고 다양한 예제는 다음 강좌에서 소개해 드리도록 하겠습니다.

감사합니다.

 

뎃글, 공감 은 블로그 작성자에게 큰 힘이 된답니다. 

 

2020/07/29 - [DEV/c#] - [C#] 설정 저장하고 재실행 시 저장한 값 불러오기

 

[C#] 설정 저장하고 재실행 시 저장한 값 불러오기

오늘 소개해 드릴 포스팅은 C# 에서 어플리케이션을 만들때 디렉토리 입력창이나 각종 설정들에 대하여 마지막으로 실행했던 설정이 다음번에 다시 실행했을 때 남아있도록 해주는

diy-dev-design.tistory.com

2020/01/03 - [DEV/c#] - [C#] C# APP 에서 엑셀 연동해보기

2019/06/21 - [DEV/c#] - [C#] C# .NET 프로젝트에서 ImageMagick 이용하기

 

[C#] C# .NET 프로젝트에서 ImageMagick 이용하기

이미지 관련된 툴을 개발함에 있어 다양한 이미지 포멧을 만들고 변경하기 위한 코어를 개발하는 것은 말도 안되게 힘든 작업입니다. 저는 디자이너라는 타이틀을 가지고 있기 때문에 포토샵이

diy-dev-design.tistory.com

2019/06/21 - [DEV/c#] - [C#] Delay 기능

2019/06/21 - [DEV/c#] - [C#] 마우스 매크로를 위한 마우스 자동 클릭 기능 만들기

 

[C#] 마우스 매크로를 위한 마우스 자동 클릭 기능 만들기

사용자의 마우스 컨트롤 없이 자동으로 지정된 위치에서 마우스를 클릭하게 만들어 주는 기능 입니다. 먼저 아래와 같이 DLL 을 불러들여 주어야 하겠습니다. class 정의 바로 아래부분에 넣어 주�

diy-dev-design.tistory.com

 

반응형

+ Recent posts