반응형

일을 하다 보면 가끔 업무를 진행하던 경로 하위에 있는 데이들의 리스트를 만들어야 하는 경우가 있습니다. 하나의 폴더라면 어떻게 해보겠는데 그 폴더가 하위 뎁스가 연속해서 있고 저장되어 있는 파일이 불특정으로 다수 있는 경우 이를 리스트로 만드는 일은 정말 끔찍한 일이 아닐 수 없습니다.

이런 경우 손쉽게 리스트로 작성하는 스크립트를 만들어 보았습니다.

폴더 및 하위 폴더의 파일 명칭은 물론 저장된 경로, 파일의 만든날짜, 수정한 날짜 등의 속성을 표시할 수 있도록 하고 파일의 용량과 타입까지 자동으로 리스트로 만들어 보려 합니다.

이러한 코드를 작성하기 위하여 개발을 할 내용을 준비해봅니다.

  1. 엑셀 vba 에서 사용 가능한 File 및 Directory 관련 개체를 알아보자.
  2. 지정한 폴더내에 파일이 있는 경우 파일의 이름과 속성등을 가져와 기록해주자
  3. 파일이 바뀔때마다 줄을 바꾸어 주자
  4. 폴더를 만나게 되면 해당 폴더 하위의 파일을 찾아주자.
  5. 2 ~ 4 번은 하위 폴더를 만날때 마다 계속해서 반복해주어야 하므로 재귀 함수로 동작하도록 구성하자.
    * 재귀함수란 자신이 자신을 호출하는 함수를 말합니다.
  6. 연속해서 위치를 이동시켜야 하므로 range.offset(y,x) 를 이용하되 x, y 는 전역 변수 (public)로 설정해주자

요 정도면 원하던 기능의 구현이 가능할 것 같습니다.

제가 작성한 코드를 아래에 올려보겠습니다.

보시면서 위에 설명드린 동작이 어떤 과정으로 일어나는지 확인해 보세요.

Public fso As Object
Public offsetY As Integer
Public offsetX As Integer
Public stRng As Range

Sub getSubFileList()

    Dim fsoFolder As Object
    Dim aSht As Worksheet
    Dim rootpath As String
    
    rootpath = "C:\Users\mariine\Pictures\excel_test\"
    
    offsetX = 0
    offsetY = 0
    
    Set aSht = ActiveSheet
    
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set fsoFolder = fso.GetFolder(rootpath)

    Set stRng = aSht.Range("B2")

    getDataRecursive fsoFolder
    
End Sub

Sub getDataRecursive(ByVal baseFolder As Object)

    Dim tmpSubFolders As Object
    Dim tmpFiles As Object
    Dim tmpRng As Range
    
    offsetX = offsetX + 1
    
    Set tmpSubFolders = baseFolder.subFolders
    
    Set tmpFiles = baseFolder.Files
    
    For Each c In tmpFiles
        
        stRng.Offset(offsetY, offsetX).Value = c.Name                       ''파일명
        stRng.Offset(offsetY, offsetX - 2).Value = offsetY + 1              ''인덱스
        stRng.Offset(offsetY, offsetX - 1).Value = c.ParentFolder.Path      ''경로명
        stRng.Offset(offsetY, offsetX + 1).Value = c.Size / 1000# & "kb"    ''파일용량
        stRng.Offset(offsetY, offsetX + 2).Value = c.DateCreated            ''만든날짜
        stRng.Offset(offsetY, offsetX + 3).Value = c.DateLastModified       ''수정한날짜
        stRng.Offset(offsetY, offsetX + 4).Value = c.Type                   ''파일타입
        
        offsetY = offsetY + 1
    Next c
    
    offsetX = offsetX - 1
    
    For Each d In tmpSubFolders
        
        Dim tmpSub As Object
        Set tmpSubs = fso.GetFolder(d)

        getDataRecursive tmpSubs
        
    Next d     
    
End Sub

 

제일 상단의 4줄은 이번 코드에서 사용할 전역 변수를 설정해주는 모습입니다.

전역변수를 설정해주면 하위의 어떤 함수에서건 해당 값을 읽고 쓸 수 있게 됩니다. A 함수에서 변경한 전역 변수의 값을 B 함수에서도 그대로 사용이 가능하게 됩니다.

그 다음 만나는 Sub getSubFileList() 함수가 동작을 설정하는 함수가 되겠고요. FileSystemObject 라는 파일 및 디렉토리 작업이 가능한 COM 오브젝트를 선언하여 서브폴더나 폴더, 파일 등에 접근이 가능하도록 하고 있습니다.

그리고 그뒤로 이어지는 재귀 함수인 Sub getDataRecursive(ByVal baseFolder As Object) 를 호출하는 것으로 동작이 시작됩니다. 

그렇게 시작된 재귀함수는 입력받은 폴더내에 파일이 있으면 파일의 이름 및 기타 속성들을 줄을 바꾸어 가며 기록을 진행하고 모든 파일에 대하여 기록이 끝나면 그아래 해당 폴더에 하위 폴더가 있는지 검사한뒤 하위 폴더가 있는 경우 또다시 자신 (폴더내의 파일을 찾아 기록하는 함수) 을 호출하여 주게 되는 겁니다.

이렇게 해주면 하나의 재귀함수로 아무리 깊고 많은 뎁스의 폴더안의 파일들도 모두 탐색이 가능해 지게 되겠습니다.

이렇게 만들어진 리스트는 아래와 같습니다.

 

만약 특정 확장자만 검색하고 싶으시면 실제 파일 속성을 기록하는 For 구문의 바로 첫 행에 IF 문을 이용하여 파일 이름내에 필요한 확장자가 있는지 검사를 진행하면 되겠습니다.

예를 들어 xlsx 파일만 리스트로 만들고 싶다면 해당 For 구문을 아래와 같이 변경하면 되겠습니다.

    For Each c In tmpFiles
        
        If InStr(c.Name, ".xlsx") Then
            stRng.Offset(offsetY, offsetX).Value = c.Name                       '파일명
            stRng.Offset(offsetY, offsetX - 2).Value = offsetY + 1              '인덱스
            stRng.Offset(offsetY, offsetX - 1).Value = c.ParentFolder.Path      '경로명
            stRng.Offset(offsetY, offsetX + 1).Value = c.Size / 1000# & "kb"    '파일용량
            stRng.Offset(offsetY, offsetX + 2).Value = c.DateCreated            '만든날짜
            stRng.Offset(offsetY, offsetX + 3).Value = c.DateLastModified       '수정한날짜
            stRng.Offset(offsetY, offsetX + 4).Value = c.Type                   '파일타입
            offsetY = offsetY + 1
        End If
        
    Next c

어렵지 않죠?

만약 있어서는 안되는 확장자가 들어있다면 눈에 띄게 표시를 하는것도 어렵지 않습니다.

예를 들어 폴더내에 hwp 파일만 있어야 한다고 했을때 해당 폴더에 .doc 파일처럼 또 다른 있는 경우 빨간색으로 셀을 표시할 수 있습니다.

For Each c In tmpFiles
        
        stRng.Offset(offsetY, offsetX).Value = c.Name                       '파일명
        stRng.Offset(offsetY, offsetX - 2).Value = offsetY + 1              '인덱스
        stRng.Offset(offsetY, offsetX - 1).Value = c.ParentFolder.Path      '경로명
        stRng.Offset(offsetY, offsetX + 1).Value = c.Size / 1000# & "kb"    '파일용량
        stRng.Offset(offsetY, offsetX + 2).Value = c.DateCreated            '만든날짜
        stRng.Offset(offsetY, offsetX + 3).Value = c.DateLastModified       '수정한날짜
        stRng.Offset(offsetY, offsetX + 4).Value = c.Type                   '파일타입
        
        If Not InStr(c.Name, ".hwp") Then
            stRng.Offset(offsetY, offsetX).Interior.Color = RGB(255, 0, 0)
        End If
        
        offsetY = offsetY + 1
        
    Next c

참 쉽죠?

 

이렇게 해서 폴더내의 모든 파일을 하위폴더를 포함하여 가져오는 스크립트를 알아보았습니다. 이런식의 작업은 엑셀의 워크시트 함수만을 이용하여 작업하기는 어렵기 때문에 vba를 좀 할줄 알면 아주 많은 시간을 절약하는 것이 가능합니다. 

 

오늘은 여기까지 하도록 하겠습니다.

관련하여 사전 지식이 부족하신 분은 아래 관련 포스트를 링크해 드리니 참고하시면 되겠습니다.

2019/06/01 - [DEV/VBA] - 엑셀 VBA 시작하기

 

엑셀 VBA 시작하기

마이크로 소프트 엑셀은 수많은 기능과 자동화된 연산 처리, 편리한 템플릿 가공, 다양한 그래프 드을 이용한 데이터의 시각화 외에도 아주 많은 유용한 기능을 제공하여 사무 업무의 표준 프로그램이 되었다. 나..

diy-dev-design.tistory.com

2019/08/30 - [DEV/VBA] - [VBA]RGB 색상 값이 들어있는 셀에 셀 색상 지정하기

 

[VBA]RGB 색상 값이 들어있는 셀에 셀 색상 지정하기

이번 강좌에서는 셀에 입력되어 있는 컬러 값을 이용하여 셀의 색상을 지정하는 방법을 알아보도록 하겠습니다. 디자이너 분들이라면 언제가 한번쯤은 엑셀 시트에 자신이 정의한 컬러 값을 정리해서 보내야 하는..

diy-dev-design.tistory.com

2019/07/12 - [DEV/VBA] - [vba] For 구문 이용하기와 offset 사용 해 보기

 

[vba] For 구문 이용하기와 offset 사용 해 보기

엑셀에서 자동화를 한다는건 사실 이유가 뻔 합니다. 처리해야 할 셀이 엄청나게 많거나 일반적인 함수로 연산이 불가한 경우 입니다. 그 중 오늘은 엄청나게 많은 데이터에 대한 자동화 처리를 위하여 반복문을..

diy-dev-design.tistory.com

2019/07/12 - [DEV/VBA] - [vba] 자동화를 위하여 엑셀의 영역 설정하는 방법

 

[vba] 자동화를 위하여 엑셀의 영역 설정하는 방법

엑셀을 사용하는 목적 자체가 근본적으로 문서를 만들기 위함은 아니다 보니 세로 또는 가로로 굉장히 길게 데이터가 나열되어 있는 경우가 많습니다. 우리는 vba 를 이용하여 자동화를 할 것이기 때문에 어디부..

diy-dev-design.tistory.com

 

감사합니다.

 

공감은 블로그 포스팅을 진행하는 블로거에게 큰 힘이 됩니다~

반응형
반응형

Instagram, 요즘 가장 핫한 SNS 가 아닐까 싶습니다. 지하철에서 무심코 주변을 보니 눈에 보이는 핸드폰 화면 마다 Instagram 화면이 보이는 것을 보고 깜짝 놀랐습니다.

난 안하는데...

어쨌든 Instagram 계정을 하나 만들어 보았습니다.

전 SNS 에 취미같은 건 없고 다만 뭔가 하나 만들어 보고 싶었는데 테스트 할 공간이 바로 Instagram 이었다고나 할까.

인스타 그램에 파노라마 사진을 올리면 사진이 다 보이지도 않거니와 얇고 길에 나와 보기에 썩 좋지 않더라고 합니다. 그래서 파노라마로 길게 찍힌 사진을 Instagram에 올리기 적당하게 네모 반듯하게 자동으로 잘라주는 스크립트를 만들어 보았습니다.

폰 app 중에는 Instagram 용 파노라마를 자연스럽게 올릴 수 있도록 잘라주는 APP 들이 있는데 PC 에 있는 사진을 올리고 싶다면 그걸 폰에 올려서 잘라서 업로드 하는게 역시 귀찮더군요. 바로 PC 에서 잘라서 올리면 좋겠다는 생각이 들어 만들어 보기로 하였습니다.

 

이렇게 만들려고 합니다.

  • 인스타용 최적 이미지 사이즈는 1080 x 1080 이라고 한다
  • 가로길이를 1080 으로 나누어 등분할 개수를 구한다. --> N.xx
  • 1080으로 정확히 나누어 떨어질 리 없기 때문에 소숫점 첫자리 기준으로 반올림/내림 한다.
  • 가로길이 : 1080 px x N , 세로길이 : 1080 px 로 리사이즈를 한다.
  • 가로세로 1080 px 씩 좌측부터 selection 을 만들어 이미지를 복사한다.
  • 새로운 1080 x 1080 짜리 document 를 만들어서 복사한 이미지를 붙인다.
  • 이미지와 동일한 명칭의 폴더를 만든 후 복사한 이미지를 저장한다.

요렇게 하면 만들어 질 것 같았습니다.

먼저 테스트용 이미지는 아래와 같습니다.

무려 4664 x 1200 짜리 커다란 이미지. 우도 하고수동 해수욕장에서

대한민국의 보물 '우도' 에 자리잡고 있는 하고수동 해수욕장 되시겠습니다.

가로로 긴 이미지 인데요, 

 

올리면 이렇게 보이게 됩니다.

Instagram 에 파노라마를 직접 올린 사진

 

이렇게 좌우를 자를 수 밖에 없는 상황이 됩니다.

 

그래서 Instagram 이미지 크기에 맞게 가로로 긴 이미지를 스크립트로 자동으로 자르면 어떻게 될까요?

스크립트를 이용하여 이미지를 자동으로 아래와 같이 잘라주게 됩니다. 신기하죠?

자동으로 이미지를 자른 모습 

 

그럼 제가 만든 스크립트로 자른 이미지를 올리면 어떻게 올라가게 될까요..

파노라마가 자연스럽게 연결된 모습

네! 바로 이렇게 됩니다 ㅋㅋ

 

스크립트 다운 로드는 여기서 받으세요.

autoCropForInstagram.jsx
0.00MB

 

자.. 제 블로그가 저런 자랑글 올리는 블로그는 아니니 이제 스크립트를 소개해 드리겠습니다.

// auto crop for instagram (panorama) 
var defUnit = preferences.rulerUnits
preferences.rulerUnits = Units.PIXELS

//JPG 파일저장용 옵션
var jpgOption = new JPEGSaveOptions();
jpgOption.qulity = 8;


var cDoc = app.activeDocument;
var cName = cDoc.name;
cName = cName.replace(".", "_"); // 현재 열린 파일명에서 . 을 _ 로 변경

var cFile = File(cDoc.fullName);
var cPath = cFile.parent; // 현재 열린 이미지의 경로를 구한다.

var cWidth = cDoc.width;
var cHeight = cDoc.height;
var divideStep = 1;

var newWidth = cWidth * (1080 / cHeight); //세로를 1080 으로 변경했을때의 가로 크기
divideStep = newWidth / 1080 ; 

if ((divideStep % 1.0) >= 0.5)
{
    divideStep = Math.ceil(divideStep); // 0.5 보다 크면 올림
    newWidth = 1080 * (divideStep);            
}
else
{
    divideStep = Math.floor(divideStep); // 0.5 보다 작으면 내림
    newWidth = 1080 * (divideStep);  
}

cDoc.resizeImage(newWidth, 1080);


var dDoc = app.documents.add(1080,1080); // 저장용 문서 만들기

for (var k = 0; k < divideStep; k++) // 가로 개수만큼
{
    app.activeDocument = cDoc;
    
    var x1 = 1080 * k;
    var x2 = 1080 * (k+1);
    var y1 = 0;
    var y2 = 1080;
    
    // 1080 x 1080 씩 선택하여 저장용 문서에 붙여 넣는다.
    cDoc.selection.select([[x1,y1], [x2,y1], [x2,y2], [x1,y2]])
    cDoc.selection.copy();
    app.activeDocument = dDoc;
    dDoc.paste();
    
    var sPath = cPath + "\\" + cName + "\\"
    var sFolder = new Folder(sPath)
    try
    {
        sFolder.create(); //파일 이름으로 폴더를 만들어 준뒤
    }catch(e){}
    
    var sFile = new File(sPath + cName + "_" + k + ".jpg");
    //파일 저장
    dDoc.saveAs(sFile, jpgOption, true, Extension.LOWERCASE);
    
}

dDoc.close(SaveOptions.DONOTSAVECHANGES);//저장용 문서 닫기
//cDoc.close(SaveOptions.DONOTSAVECHANGES); // 원래 이미지도 닫으려면 주석 풀기

// 유닛 단위를 원래대로 돌린다.
preferences.rulerUnits = defUnit

 

스크립트 내에 주석을 달아 놓았으니 찬찬히 보시면 이해가 되실거에요.

포토샵에 먼저 파노라마 이미지를 열어 놓은 뒤 실행하셔야 합니다.

실행은 Extend script toolkit 으로 해당 스크립트를 붙여넣기 하신 뒤 실행하셔도 되고요, 해당 스크립트를 다운 받으신 뒤 포토샵에서 스크립트 불러오기 하셔서 실행하셔도 됩니다.

스크립트 실행 방법은 아래의 포스트를 참고하세요~

 

https://diy-dev-design.tistory.com/47

 

[포토샵스크립트] 스크립트 단축키로 실행하기

안녕하세요. 오늘은 자신이 작성하였거나 웹에서 다운로드 받은 스크립트를 간단하고 빠르게 실행하는 방법을 알려드리겠습니다. 우선 스크립트를 실행하는 방법은 몇가지가 있는데 다음과 같습니다. Extend Scrip..

diy-dev-design.tistory.com

 

개발 공부도 함께 하실 분은 아무래도 직접 Extend script toolkit 에 코딩을 해보시는게 좋겠죠?

아래 포스트에 코드를 이용하여 편집해보며 실행할 수 있는 방법이 소개되어 있습니다.

https://diy-dev-design.tistory.com/7

 

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

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

diy-dev-design.tistory.com

 

그럼 이만~

 

참 제 인스타는 제 블로그 이름과 같습니다.

인스타에 올린 파노라마를 직접 보시려면 아래 주소에 가셔서 확인하셔요 ㅋ. 게시글은 달랑 2개.

https://www.instagram.com/p/B5nbnenH3vD/?igshid=1pps3vkv5c1mi

그럼 진짜로 20000

반응형
반응형

포토샵의 가장 중요한 핵심 기능중의 하나가 레이어라는 구조일 것입니다. 이미지를 계층적으로 쌓아 올리고 각각의 이미지간 효과를 적용하거나 투명도등을 조절하여 완성된 하나의 이미지를 만들어 내는 것이죠. 

오늘 강좌에서는 포토샵에 레이어를 생성하고, 이름을 붙이거나, 위치를 이동하는 등의 레이어를 관리하는 기능을 소개해 드릴까 합니다.

오늘 강좌에서 다룰 내용은 아래와 같습니다.

  • 이미 있는 레이어를 복제하기, 위치 조정하기, 투명도 조정하기
  • 이미 있는 레이어의 순서 변경하기(이동하기)

 

먼저 포토샵 스크립트 작성을 위하여 extend script toolkit 을 실행합니다.

그리고 당연히 포토샵 어플리케이션을 열어야 겠죠. 

오늘은 제가 좋아하는 traxxas 로고를 이용하여 코드 연습을 해보겠습니다.

이 로고 이미지를 이용하여 wallpaper 를 한번 만들어 보겠습니다. 손으로 하자면 아주 귀찮을 그림을 만들어 보겠습니다.

//로고파일의 위치를 설정한다
traxxasLogo_250_File = "D:/01_works/용/DIY_HARD_RC/traxxas_LOGO_125x25.png"
var logoFile = new File(traxxasLogo_250_File);

// 포토샵에 새로운 도큐먼트를 생성한다. 크기는 1920 1080
var wallPaperPsd = app.documents.add(1920,1080,72)

// 검정색 컬러를 정의한다
var newColor = new SolidColor();
newColor.rgb.red = 0;
newColor.rgb.green = 0;
newColor.rgb.blue = 10;

// 배경색상을 검정색으로 fill 한다
wallPaperPsd.selection.selectAll();
wallPaperPsd.selection.fill(newColor);
wallPaperPsd.selection.deselect();

// 로고 이미지를 열어서 포토샵으로 복사한다. 
var logoImg = app.open(logoFile);
var newLogoLyr = logoImg.layers[0].duplicate(wallPaperPsd.layers[0], ElementPlacement.PLACEBEFORE);


app.activeDocument = logoImg;
// 로고 파일은 닫는다.
logoImg.close();

app.activeDocument = wallPaperPsd;
//복사한 레이어의 이름을 변경한다.
newLogoLyr.name = "logo_1_1";

오늘 강좌의 핵심이되는 부분은 요 부분입니다.

var newLogoLyr = logoImg.layers[0].duplicate(wallPaperPsd.layers[0], ElementPlacement.PLACEBEFORE);

logoImg 파일의 0번째 레이어를 복사하는 명령어죠. duplicate 뒤에 오는 값들은 어디에 복사할 것인지를 지정합니다. 첫번째 인자는 복제될 대상을 지정합니다. 이번 예제에서는 다른 PSD 파일 (배경화면용 이미지)의 0번째 레이어가 대상이 되었습니다. 그뒤에 오는 인자는 지정한 대상과의 관계인데요. 이번 예제에서 사용한 것은 "대상 예제의 바로 전에 위치시켜라" 라는 명령입니다.

ElementPlacement 라는 개체의 하위 옵션으로 몇가지 옵션을 지정할 수 있는데요. PS 버전이 올라가면서 옵션이 많이 다양해 졌습니다. 필요한 위치에 맞추어 넣으시면 되겠습니다.

ElementPlacement.PLACEAFTER         //cs6 - 대상개체 아래에
ElementPlacement.PLACEATEND         //cs6 - 대상개체의 제일 마지막에
ElementPlacement.PLACEBEFORE        //cs6 - 대상개체의 바로 위에
ElementPlacement.INSIDE             //cc - 대상이 폴더인 경우 폴더 안에
ElementPlacement.PLACEATBEGINNING   //cc - 대상 개체의 제일 처음에

 

어쨌든 요기까지 스크립트를 실행해보면 아래와 같은 그림이 만들어 집니다.

스크립트를 이용해 포토샵 psd 파일에 다른 파일의 이미지를 레이어로 복사한 상태

화면에 로고 이미지가 붙었죠?

요 이미지를 화면에 쫙 깔아 보겠습니다. 손으로 하려면 매우 귀찮은 작업이죠.

위에 작성한 코드를 포함하여 추가한 코드는 아래와 같습니다.

//로고파일의 위치를 설정한다
traxxasLogo_250_File = "D:/01_works/용/DIY_HARD_RC/traxxas_LOGO_125x25.png"
var logoFile = new File(traxxasLogo_250_File);

// 포토샵에 새로운 도큐먼트를 생성한다. 크기는 1920 1080
var wallPaperPsd = app.documents.add(1920,1080,72)

// 검정색 컬러를 정의한다
var newColor = new SolidColor();
newColor.rgb.red = 0;
newColor.rgb.green = 0;
newColor.rgb.blue = 10;

// 배경색상을 검정색으로 fill 한다
wallPaperPsd.selection.selectAll();
wallPaperPsd.selection.fill(newColor);
wallPaperPsd.selection.deselect();

// 로고 이미지를 열어서 포토샵으로 복사한다. 
var logoImg = app.open(logoFile);
var newLogoLyr = logoImg.layers[0].duplicate(wallPaperPsd.layers[0], ElementPlacement.PLACEBEFORE);

app.activeDocument = logoImg;
// 로고 파일은 닫는다.
logoImg.close();

app.activeDocument = wallPaperPsd;
//복사한 레이어의 이름을 변경한다.
newLogoLyr.name = "logo_def";

// 이제 화면에 로고 이미지를 가득 채워 넣자

//각 로고 간의 간격을 설정해주자
var gapWidth = 100;
var gapHeight = 100;

// 로고 이미지의 영역을 구한다. bounds 는 레이어내의 이미지 영역 정보를 가져온다
var logoBounds = newLogoLyr.bounds; //영역 정보는 [left, top, right, bottom] 순으로 들어온다.
var logoWidth = logoBounds[2] - logoBounds[0]; // 레이어의 가로 크기
var logoHeight = logoBounds[3] - logoBounds[1]; // 레이어의 세로크기

// 화면 영역내에 몇개의 로고가 들어갈 수 있는지 계산한다.
var numWidth = wallPaperPsd.width / (logoWidth + gapWidth)
var numHeight = wallPaperPsd.height / (logoHeight + gapHeight)

// 가로, 세로로 로고를 복사하여 붙여 넣는다.
for (var yy = 0; yy < numHeight ; yy++) // 세로 개수만큼 반복
{
    for (var xx = 0; xx < numWidth; xx++) // 가로 개수만큼 반복
    {
        var tmpLyr = newLogoLyr.duplicate(newLogoLyr, ElementPlacement.PLACEBEFORE);
        tmpLyr.translate(xx * (logoWidth + gapWidth), yy * (logoHeight + gapHeight))
        tmpLyr.name = "logo_" + xx + "_" + yy ;
    }    
}

 

로고 이미지를 가로세로로 100px 씩 간격을 띄고 화면에 꽉 채우는 스크립트가 되었습니다.

이렇게하면 아래와 같은 그림이 만들어 집니다.

traxxas 로고로 꽉 채워진 이미지가 만들어 졌다.

네 그런데 약간 아쉬운건 로고가 약간 치우쳐져서 배치가 되었네요.

그리고 약간 단조로워 보이는 듯 합니다. 그리고 바탕화면에 사용할 그림인데 너무 강렬한 감이 있습니다.

자 코드를 좀 수정해 보겠습니다. 이제 코드가 제법 길어지므로 집중해서 보셔야 합니다.

var currentUnitValue = app.preferences.rulerUnits

// 포토샵 유닛을 픽셀로 변경
app.preferences.rulerUnits = Units.PIXELS;



//로고파일의 위치를 설정한다
traxxasLogo_250_File = "D:/01_works/용/DIY_HARD_RC/traxxas_LOGO_125x25.png"
var logoFile = new File(traxxasLogo_250_File);

// 포토샵에 새로운 도큐먼트를 생성한다. 크기는 1920 1080
var wallPaperPsd = app.documents.add(1920,1080,72)

// 검정색 컬러를 정의한다
var newColor = new SolidColor();
newColor.rgb.red = 0;
newColor.rgb.green = 0;
newColor.rgb.blue = 10;

// 배경색상을 검정색으로 fill 한다
wallPaperPsd.selection.selectAll();
wallPaperPsd.selection.fill(newColor);
wallPaperPsd.selection.deselect();

// 로고 이미지를 열어서 배경화면용 포토샵으로 복사한다. 
var logoImg = app.open(logoFile);
var newLogoLyr = logoImg.layers[0].duplicate(wallPaperPsd.layers[0], ElementPlacement.PLACEBEFORE);

app.activeDocument = logoImg;
// 로고 파일은 닫는다.
logoImg.close();

app.activeDocument = wallPaperPsd;
//복사한 레이어의 이름을 변경한다.
newLogoLyr.name = "logo_def";

// 이제 화면에 로고 이미지를 가득 채워 넣자

//각 로고 간의 간격을 설정해주자. 숫자가 작을 수록 촘촘해지고 클수록 듬성듬성 붙는다.
// 포토샵 스크립트 실행 속도가 느리므로 너무 작은 숫자는 넣지 말자.
var gapWidth = 100;
var gapHeight = 100;

// 로고 이미지의 영역을 구한다. bounds 는 레이어내의 이미지 영역 정보를 가져온다
var logoBounds = newLogoLyr.bounds; //영역 정보는 [left, top, right, bottom] 순으로 들어온다.
var logoWidth = logoBounds[2] - logoBounds[0]; // 레이어의 가로 크기
var logoHeight = logoBounds[3] - logoBounds[1]; // 레이어의 세로크기

// 화면 영역내에 몇개의 로고가 들어갈 수 있는지 계산한다.
var numWidth = Math.floor(wallPaperPsd.width / (logoWidth + gapWidth));
var numHeight = Math.floor(wallPaperPsd.height / (logoHeight + gapHeight));

// 가로, 세로로 가득 찼을때 남는 공간을 계산하여 offset 을 만들어 주자
var offsetX = Math.floor(wallPaperPsd.width - (numWidth * (logoWidth + gapWidth) - gapWidth));
offsetX = offsetX * 0.5;

var offsetY = Math.floor(wallPaperPsd.height - (numHeight * (logoHeight + gapHeight) - gapHeight));
offsetY = offsetY * 0.5;

// 투명도를 조절하기 위한 값. 여기서 설정한 값에 의해 투명도가 자동으로 조절되어 아래로 내려갈 수록 투명해 진다. 
var maxOpacity = 50;
var minOpacity = 15;

// 각 단계별 투명도 변이 값을 계산하자.
var opacityStep = (maxOpacity - minOpacity) / numHeight

// 가로, 세로로 로고를 복사하여 붙여 넣는다.
for (var yy = 0; yy < numHeight ; yy++) // 세로 개수만큼 반복
{
    for (var xx = 0; xx < numWidth; xx++) // 가로 개수만큼 반복
    {
        var tmpLyr = newLogoLyr.duplicate(newLogoLyr, ElementPlacement.PLACEBEFORE);
        wallPaperPsd.activeLayer = tmpLyr; // 처음 레이어가 계속 활성화 되는 것을 막기 위하여 활성화된 레이어를 현재 복사된 레이어로 지정
        tmpLyr.translate(-logoBounds[0], -logoBounds[1]); // 복사된 레이어를 0,0 으로 이동시킴
        tmpLyr.translate((xx * (logoWidth + gapWidth)) + offsetX, (yy * (logoHeight + gapHeight)) + offsetY) // 지정된 위치로 이동
        tmpLyr.name = "logo_" + xx + "_" + yy ;
        
        tmpLyr.opacity = maxOpacity - (yy * opacityStep); // 아래로 갈 수록 투명하게
        // tmpLyr.opacity = minOpacity + (yy * opacityStep); // 위로 갈수록 투명하게 하려면 주석을 풀어 줍니다.
    }    
}
//처음에 복사한 레이어는 필요 없으니 숨겨줍니다.
newLogoLyr.visible = false;

//유닛을 스크립트 실행 이전상태로 복구함
app.preferences.rulerUnits = currentUnitValue;




 

이제 스크립트는 아래로 복제해 나가면서 점차 투명도를 주어 서서히 보이지 않도록 하고 있습니다. 이 투명도로 사용자가 설정한 최대값과 최소값을 이용하여 점차 변화하도록 하고 있습니다. 

간격을 조정하여 촘촘하게 배치하거나 듬성듬성 배치하더라도 의도한데로 서서히 변화가 적용될 것 입니다.

적용된 화면을 다시 볼까요?

화면에 격자형으로 배치되지만 아래로 갈수록 투명도가 높은 상태가 되었다.

 

이렇게 하면 스크립트의 일부만 수정하여 다양한 화면을 만드는 것이 가능합니다.

반복하여 붙여넣을 파일의 경로, 반복 간격, 투명화 정도를 설정하는 것으로 다른 이미지에도 동일하게 적용이 가능합니다. 본 예제에서는 1920 1080 사이즈의 이미지로 제작하였지만 다른 사이즈를 입력하여도 아마 정확하게 동작할 것입니다. 

여기에 마지막으로 화면 가운데에 좀 더 커다란 로고를 넣는다면 어떻게 해야 할까요?

직접 한번 도전해 보시면 어떨까요?

[wallpaper] traxxas logo 1920 x 1080
[wallpaper] traxxas UDR 1920 x 1080

 

감사합니다. 그럼 이만~

 

레이어 위치 이동하는 스크립트는 여기에도 있었죠? ^^

https://diy-dev-design.tistory.com/46

 

[포토샵스크립트] 현재 레이어 이미지를 중앙으로 이동시키기

안녕하세요. 오늘은 선택된 레이어를 화면의 중앙으로 이동시키는 포토샵 스크립트를 작성해 보겠습니다. 와이프가 한동안 쇼핑몰 상세페이지 디자인 작업을 재택근무 형식으로 했었는데요. 옆에서 작업하는 것을..

diy-dev-design.tistory.com

 

반응형
반응형

버튼예제.xls
0.04MB

어떤 엑셀 페이지에 늘 사용하는 스크립트를 작성하였으나 매번 실행하기 위하여 vba 창을 눌러 F5를 누르는 것은 사실 본인이 직접 스크립트 코드를 개발하는 입장이라면 조금도 번거로울 것이 없는 것이지만 누군가에게 스크립트를 작성하여 엑셀 파일을 건내 주는 경우라면, 실제 사용하는 사람이 개발과 거리가 있는 사람이라면 더더욱 이와 같은 방법으로 스크립트를 실행시키는 것은 불편한 방법이 됩니다.

게다가 스크립트가 딱 하나가 아니고 어떤 스크립트는 정렬을 해주고, 어떤 스크립트는 불필요한 값을 숨겨주고, 또 어떤 스크립트는 데이터를 새로 읽어 들여 전체 시트를 리프레쉬 하는 등의 여러개의 기능을 개발한 상태라면 vba 창에서 실제 해당 스크립트 위치에 마우스 커서를 가져다 놓는 등의 추가 행위가 필요합니다.

이럴때 버튼을 이용하여 특정 스크립트 (엑셀에서는 매크로라고 합니다) 를 연결하게 되면 지정된 버튼을 누를때 마다 필요한 스크립트가 동작하게 됩니다. 

말하자면 간단한 툴이 만들어 지는 것이죠. 

사실 엑셀의 각 셀은 함수나 계산식을 포함할 수 있으므로 왠만한 복잡한 것들은 워크시트의 함수와 계산식으로 처리가 가능하지만 이미지를 불러온다거나 어떤 데이터의 속성을 알아내거나 약간은 복잡한 관계의 셀 값들을 이용하여 결과값을 얻는다든가 하는 등의 일은 워크시트 함수로는 조금 어려운 부분이 있습니다. 그래서 매크로 스크립트를 작성하는 것이죠. 이런 기능기능이 모여 마치 어떤 툴처럼 제작이 가능합니다.

영업사원들에게는 견적서 프로그램을 만드는 것이 가능할 것이고 세무, 회계부서에서는 각종 세금 관계 계산을 위한 처리가 가능할것입니다. 

오늘은 그렇게 만들어진 스크립트 들을 버튼을 이용하여 동작하도록 하는 방법을 소개해 드릴까 합니다.

 

먼저 제가 초등학교 저학년 학생들을 위한 간단한 덧셈 연산을 자동으로 생성하는 엑셀파일을 만든적이 있습니다. 

https://diy-dev-design.tistory.com/41?category=791049

 

[VBA] 엑셀로 초등학교 저학년 문제집 만들기 (자동버전)

이번 포스트를 통해 꼬마아이들의 공공의적 이 될런지도 모릅니다. 바로 초등 저학년 연산문제를 끝도 없이 만들수 있는 파일을 준비했기 때문입니다. 지난번 포스트에서 연산문제를 만드는 VBA 를 소개해 드렸었..

diy-dev-design.tistory.com

 

해당 파일을 보면 아래와 같은 화면을 볼 수 있는데요. 우측의 버튼을 누를 때 마다 버튼의 텍스트에 해당하는 기능으로 좌측 값이 자동으로 생성이 됩니다. 위 링크된 페이지에 가면 실제 엑셀 파일을 받으실 수 있으니 해당 파일을 받으셔서 참고해보셔도 좋을 것 같습니다.

버튼을 이용하여 다양한 매크로를 동작하도록 만든 엑셀 시트

 

우선 단추(버튼)르르 이용한 동작을 확인할 간단한 스크립트를 작성해 보겠습니다.

  • 첫번째 스크립트로 셀 A1~C1 번에 숫자 1, 2, 3 을 넣어 보겠습니다.
    • 만약 이미 숫자가 들어있다면 현재 들어있는 숫자에 각각 1, 2, 3을 더하도록 해보죠.
  • 두번째 스크립트는 A2 ~ C2 에 A1 + A1, B1 + B1, C1 + C1 까지의 값을 넣는 동작을
  • 세번째 스크립트는 A3 ~ C3 에 A1 * A2, B1 * B2, C1 * C2 의 값을 넣는 동작을
  • 네번째 스크립트는 A4 ~ C4 에 C1 ~ C3 의 값을 이용하여 셀의 색상을 채워 넣어 보겠습니다.
    • 컬러를 지정하기 위한 숫자는 RGB 로 각각 0~255만 가능하므로 255 보다 크면 255로 설정 하겠습니다.
    • 그리고 255보다 값이 커진다면 첫번째 행의 값을 낮은 값으로 바꾸어 보겠습니다.

 

스크립트를 작성해 보겠습니다.

먼저 엑셀을 열고 VBA 창 (alt + F11) 을 실행한 뒤 아래와 같이 입력해 보겠습니다.

Sub function_a()
    
    'cells(rowIndex, columnIndex) 와 같은 형식으로 셀을 지정하는 방법'
    If Len(Cells(1, 1)) Then
        Cells(1, 1).Value = Cells(1, 1).Value + 1
    Else
        Cells(1, 1).Value = 1
    End If
    
    If Len(Cells(1, 2)) Then
        Cells(1, 2).Value = Cells(1, 2).Value + 2
    Else
        Cells(1, 2).Value = 2
    End If
    
    If Len(Cells(1, 3)) Then
        Cells(1, 3).Value = Cells(1, 3).Value + 3
    Else
        Cells(1, 3).Value = 3
    End If

End Sub

Sub function_b()
    
    ' Range(name) 의 형태로 셀을 지정하는 방법'
    
    Range("A2").Value = Range("A1").Value * 2
    Range("B2").Value = Range("B1").Value * 2
    Range("C2").Value = Range("C1").Value * 2
    
End Sub

Sub function_c()
    
    ' range 라는 변수를 설정하여 정의하는 방법'
    
    Dim a3, b3, c3
    
    Set a3 = Range("A3")
    Set b3 = Range("B3")
    Set c3 = Range("C3")
    
    a3.Value = a3.Offset(-2, 0).Value * a3.Offset(-1, 0).Value
    b3.Value = b3.Offset(-2, 0).Value * b3.Offset(-1, 0).Value
    c3.Value = c3.Offset(-2, 0).Value * c3.Offset(-1, 0).Value
    
End Sub

Sub function_d()

    Dim a3, b3, c3, rngAll
    
    Set a3 = Range("A3")
    Set b3 = Range("B3")
    Set c3 = Range("C3")
    
    Set rngAll = Range("A4", "C4")
    
    If a3.Value > 255 Then
        a3.Value = 255
        a3.Offset(-2, 0).Value = 1
    End If
    
    If b3.Value > 255 Then
        b3.Value = 255
        b3.Offset(-2, 0).Value = 2
    End If
    
    If c3.Value > 255 Then
        c3.Value = 255
        c3.Offset(-2, 0).Value = 3
    End If
    
    rngAll.Interior.Color = RGB(a3.Value, b3.Value, c3.Value)
    
End Sub

 

Sub ~ End Sub 까지가 하나의 매크로 스크립트가 되겠습니다. 총 4개의 스크립트가 작성이 되었는데요. 내용은 위에서 기술한 내용데로 작성하였으며 각각의 스크립트에는 셀을 지정하는 방법을 달리하여 작성해 보았습니다. 여러분들도 직접 타이핑 해보시면서 어떤방법으로 셀을 지정하는 것이 편리한지 경험해보시는 것이 도움이 되실 것 같습니다.

끝으로 rngAll 이라는 Range 개체를 만들었는요 현재 시트의 4번째 행의 A~C 열을 한꺼번에 설정해주었습니다. 그리고 한꺼번에 해당 셀의 색상을 변경을 하는 코드를 넣어 봤습니다.

 

자 스크립트를 모두 작성하였으면 이제 단추를 만들어 보아야 겠죠? 

그런데 엑셀의 기본 기능 중에는 단추가 보이지 않습니다. 리본 메뉴가 만들어 지면서 사용하지 않는 기능들은 꺼내져 있지 않기 때문인데요. 사용하기 위하여 꺼내 보겠습니다. 처음 한번만 하시면 됩니다.

파일 메뉴로 가셔서 아래와 같은 창이 나오면 제일 아래 옵션을 선택합니다.

엑셀에서 파일 메뉴를 진입한 화면

그럼 옵션창이 팝업으로 뜨게 됩니다.

팝업으로 뜬 창에서 '리본 사용자 지정' 텝으로 이동해보면 아래와 같이 아주 많은 기능이 나열된 것을 볼 수 있습니다.

위 그림에서 좌측은 엑셀이 가지고 있는 모든 기능을 보여주고 있고 우측은 현재 사용자의 리본메뉴에 추가되어 있는 기능들이라고 생각하시면 되겠습니다.

아래 1번의 드롭다운 메뉴에 리본에 없는 메뉴를 선택하신 뒤 리스트에서 2번 '단추(양식컨트롤)' 이 바로 우리가 필요한 단추를 넣는 기능입니다. 단추라고 하면 좀 이상한데요, 익숙한 용어로는 버튼입니다. 버튼.

우측은 해당 기능을 넣을 리본 메뉴라고 했는데요, 저는 삽입 이라는 탭에 넣을 계획 입니다. 이미 있는 그룹에 넣는 것은 불가능하고 새로운 그룹을 만들어서 넣어야 하기 때문에 3번 삽입 을 선택하여 메뉴를 확장 시킨 뒤 아래 '새 그룹' 이라는 버튼을 이용하여 새로운 그룹을 추가해 줍니다.

엑셀의 옵션창 버전마다 약간의 차이는 있다

새로 추가한 그룹의 이름을 바꾸어 볼 차례 입니다. 저는 제 블로그 이름인 "DIY_DEV_DESIGN" 라고 변경하였습니다. 아래 이름 바꾸기라는 버튼을 이용하여 변경하시면 됩니다.

추가한 그룹의 이름을 바꾸어준 상태

 

이제 단추를 선택한뒤 가운데에 있는 "추가>>" 를 이용하여 방금 만든 그룹에 추가를 해 보겠습니다.

새로 추가한 그룹에 단추 명령을 넣은 상태

자 이제 단추를 추가하는 기능은 완료가 되었습니다. 확인 버튼을 눌러 옵션 창을 닫고 엑셀의 리본메뉴를 살펴보면 아래와 같이 단추가 추가되어 있을 것입니다.

 

이제 해당 버튼을 누르게 되면 엑셀 시트에 단추를 만들수 있게 됩니다.

만드는 방법은 아래와 같습니다. 

  1. 단추 버튼을 누른다
  2. 원하는 위치에 마우스를 클릭한뒤 드래그 하여 필요한 크기가 되면 마우스 버튼을 뗀다
  3. 팝업으로 나오는 매크로 선택창에서 아까 만들어둔 스크립트를 선택해 준다.
  4. 이미 만들어진 단추의 크기나 위치, 레이블을 수정하기 위하여는 마우스 우클릭으로 선택해주면 됩니다.

 

첫번째 단추를 추가하였다.

총 4개의 스크립트를 연결할 것이므로 4개의 스크립트를 차례로 연결해 보겠습니다

 

이제 위의 버튼부터 차례로 눌러 볼까요?

버튼을 누를때마다 해당 스크립트가 동작한다

네 잘 동작되네요.

만약 스크립트를 수정해야 하면 해당 버튼을 마우스 우클릭한 뒤 "매크로 지정" 기능으로 이동하여 설정되어 있는 매크로를 다른 메뉴로 변경하거나 선택되어 있는 매크로에서 "편집" 버튼을 눌러주게 되면 해당 매크로 스크립트를 바로 편집할 수 있는 비주얼 베이직에디터가 나타나게 됩니다.

 

자 이렇게 해서 엑셀에 버튼을 추가하고 스크립트를 연결하는 방법을 알아 보았습니다.

설정창에서 단추 기능을 꺼내는 단계부터 처음하시는 분은 조금 복잡하다고 생각하실 수도 있겠는데요. 막상 해보시면 정말 간단한 작업이고 어렵지 않습니다.

또한 이렇게 단추로 만들어진 스크립트는 매우 실행하기 편리하고 직관적이죠. 

자 여러분도 이제 엑셀을 이용하여 툴을 만들어 보시는 겁니다.

도전해 보시지요.

 

반응형
반응형

미디어 아티스트를 꿈꾸는 디자이너라면 한번 쯤은 관심을 가져 봤을 법한 이미지 또는 영상이 있습니다. 바로 사진을 텍스트로 전환하여 이미지 프로세싱을 통해 표현하는 것인데요. 

음... 글로만은 설명이 좀 어려울 수 있겠습니다.

 

말하자면 이런거죠.

 문자를 이용하여 사진을 표현한 모습

 

위의 그림을 보면 언뜻 사진처럼 보이지만 가까이서 보면 

문자(글자)를 이용하여 사진을 표현한 모습

이렇게 문자(알파벳, 숫자, 특수기호) 로 되어 있습니다.

 

신기하죠?

 

사실 사람이 이런 작업을 하는 것은 일정 사이즈를 넘어가는 순간 불가능 합니다. 하지만 스크립트를 이용하면 가능합니다.  이번에는 스크립트를 이용하여 위와 같은 그래픽을 자동으로 만드는 방법을 소개해 드릴 까 합니다. 

 

자 개발을 하려면 무엇을 어떻게 개발할 것인지 머리속에 잘 그려보는 것이 중요합니다.

한번 적어 볼까요?

 

  • 알파벳, 숫자, 특수기호를 이용하여 밝기 순으로 문자를 배열하는 작업을 한다. --> A
  • 도큐먼트를 사진을 분석이 가능한 최소 크기로 리사이즈 한다.
  • 분석작업이 용이하도록 흑백으로 전환 한다.
  • 각 픽셀의 밝기를 조사한다.
  • 각 픽셀의 밝기에 대응되는 A 의 문자열을 찾아 변수에 저장한다.
  • 다시 이미지 사이즈를 축소된 사이즈 * 글자크기 로 리사이즈 한다.
  • 이미지에 텍스트 레이어를 추가한다.
  • 텍스트 레이어에 아까 저장하였던 텍스트 변수의 값을 이용하여 글자를 표시한다.
  • 글자의 문자 간격과 줄간격을 설정한다.
  • 아! 글자는 모노타입 폰트를 설정한다. 폰트 간격이 pixel 처럼 일정해야 하므로.
    • 여기서 나는 Consolas 라는 모노타입 폰트를 10 pt 로 적용하였다.
  • 뒤에 이미지에 해당되는 배경을 숨겨주면 완료!

 

좀 장황하지만 위의 과정이 있어야만 표현이 가능하다는 것을 알 수 있습니다.

 

우선 문자열을 매번 이미지를 글자로 표현해 볼때 마다 분석을 하는 것은 불필요하므로 별도 스크립트를 이용하여 재배열을 해야 하는데요, 아래 포스트의 내용을 먼저 참고하시면 도움이 되겠습니다.

https://diy-dev-design.tistory.com/55

 

[포토샵스크립트] 글자들을 밝기 순으로 배열해 보기

좀 생뚱 맞을 수도 있는데 이번에 소개해드릴 강좌는 글자의 밝기를 알아보는 스크립트를 소개해 드릴까 합니다. 글짜에 무슨 밝기가 있다는 건가 하실수 있겠는데요. 바로 이런 표현을 하기 위하여 필요한 것이..

diy-dev-design.tistory.com

 

제가 사용한 글자는 

abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890[}±.:,/~';*-=+!@?>\#$%^&

인데요. 밝기 순으로 정렬을 해보면 아래와 같습니다.

.-':,;>^!~Lci/*1l?zC+±tsr2=JIT}[x75FvZ3eSYEfukjnayKoPXV9h6qdRp4bAG$8wDUO&%#Bg0mHQMWN@

순서가 뒤죽박죽이 되었죠? 제일 왼쪽이 가장 밝은 픽셀, 오른쪽이 어두운 픽셀에 매칭될 문자 입니다.

총 85개의 숫자인데요. 이미지의 픽섹의 밝기값을 0 ~ 100 사이의 밝기값으로 구한 뒤 x0.85 를 해주면 85 단계 정도로 리스케일이 됩니다. 그런 다음 각각의 리스케일 된 밝기를 저 글자의 해당 되는 위치의 글자로 표현해 주면 되는겁니다.

 

그럼 이미지를 준비해 볼까요? 

매트릭스 포스터

네. 유명한 영화 매트릭스의 주인공인 네오 포스터 입니다.

 

이제 코드를 짜보겠습니다. 주석을 달아 놓았으니 한줄 한줄 따라 적어 보시면서 읽어 보시면 됩니다.

코딩이 익숙치 않은 분은 좀 어려울 수도 있겠는데요. 기본적으로 for 를 이용한 반복 문이나 배열의 내용을 넣고 꺼내는 등의 기본적인 코딩이 가능하시면 크게 어려울 것은 없습니다.

var lset = ".-':,;>^!~Lci/*1l?zC+±tsr2=JIT}[x75FvZ3eSYEfukjnayKoPXV9h6qdRp4bAG$8wDUO&%#Bg0mHQMWN@@"

var cDoc = app.activeDocument

cDoc.colorSamplers.removeAll();


//현재 다큐먼트를 복제
dDoc = cDoc.duplicate();
var pointSample = dDoc.colorSamplers.add([1,1]);

// 이미지의 가로 사이즈를 정해준다.
var imageWidth = 24;
// 이미지의 세로사이즈는 가로사이즈에 맞추어 비율에 맞게 자동으로 구한다.
var imageHeight = Math.floor(dDoc.height * (imageWidth / dDoc.width));

// 이미지를 리사이즈 한다.
dDoc.resizeImage(imageWidth, imageHeight);
// 흑백으로 전환. 모드가 변경되는 것은 아니고 컬러만 흑백으로 변경하게 된다.
dDoc.layers[0].desaturate()

//밝기가 저장될 배열을 생성
var brightArray = [];

// 이미지의 모든 필셀의 밝기를 배열에 저장함
for (var yy = 0; yy < imageHeight ; yy++)
{
    for (var xx = 0; xx < imageWidth; xx ++)
    {
        pointSample.move([xx,yy]);
        brightArray.push(Math.floor(85 - pointSample.color.hsb.brightness * 0.85))
    }
}

// 글자를 10pt 로 표시할 것이므로 이미지의 가로 세로 픽셀 수 x 10 한 만큼의 크기로 리사이즈를 한다.
dDoc.resizeImage(imageWidth * 10, imageHeight * 10, 72, ResampleMethod.NEARESTNEIGHBOR);

//이전의 유닛 단위를 미리 저장해 놓는다.
var rulerUnits = app.preferences.rulerUnits;
// 유닛을 포인트로 변경한다.
app.preferences.rulerUnits = Units.POINTS;

// 레이어를 하나 만들어 준뒤 텍스트 레이어로 정해준다.
var aLyr = dDoc.artLayers.add();
aLyr.kind = LayerKind.TEXT;
aLyr.name = "myTxt";

var cTxtItem = dDoc.artLayers["myTxt"].textItem;
cTxtItem.font = "Consolas";
cTxtItem.useAutoLeading = false
cTxtItem.size = 10;
cTxtItem.leading = 10.0;
cTxtItem.tracking = 445; // 몇차례 테스트 후 얻어진 값
cTxtItem.position = [0,0];

var cid = 0;
var ct = "";

for (var yy = 0; yy < imageHeight ; yy++)
{
    for (var xx = 0; xx < imageWidth; xx ++)
    {
        ct += lset.charAt(brightArray[cid]); // 저장된 배열의 값에 해당되는 글자를 가져옴
        cid++;
    }
    ct += "\r"; // 가로행이 끝나면 리턴을 입력하여 줄바꿈을 해준다.
}
cTxtItem.contents = ct; // 텍스트 아이템의 내용을 수집한 문자열로 입력한다.
cTxtItem.leading = 10.0;

//저장해 두었던 유닛으로 설정을 되돌린다.
app.preferences.rulerUnits = rulerUnits;
pointSample.remove();

 

이렇게 하고 실행을 해보면 글자로 만들어진 그림이 표시됩니다.

이렇게요.

 

글자로 만들어진 그림 (가로 24px)

가로를 32px 로 하면 아래와 같이 됩니다.

글자로 만들어진 매트릭스 포스터 (가로 32px)

코드의 imageWidth 의 값을 변경하면 그에 해당하는 디테일의 이미지가 만들어 집니다. 24px 에 비하여 32px의 이미지가 좀더 디테일한 것을 알 수 있습니다. 다만 포토샵의 colorSampler 가 색상을 취득하는 과정이 매우 속도가 느려서 좀 큰 해상도로 하게 되면 상당히 오래 걸려야 표시가 되더군요. 

아무래도 포토샵이 실시간으로 이미지를 프로세싱하기에는 역부족인 듯 합니다만 포토샵 스크립트로도 이런 작업이 가능하구나 정도로 이해하시면 좋을 것 같습니다. 

참고로 이런류의 작업을 아주 빠르게 수행할 수 있는 툴도 있습니다. cycling74 라는 회사의 MAX 라는 툴이고요. JITTER 라는 툴이 MAX 와 함께 설치되면 영상 처리를 아주 빠른 속도로 할 수 있습니다. 실시간 영상도 위와 같이 표현이 가능할 정도로요. 포토샵에서도 이런게 되는구나 정도로 보시면 될 것 같습니다.

 

이렇게 만들어진 텍스트 이미지를 이용하여 제 휴대폰 배경화면을 하나 만들어 봤습니다.

Galaxy S10 Series (1080x2280) wallpaper MATRIX RELOADED - NEO

 

Galaxy S10 Series (1080x2280) wallpaper MATRIX RELOADED - TRINITY

 

 

좀 더 매트릭스의 텍스트 이펙트가 살아있는 배경화면은 아래 페이지에서 다운 로드 받으세요~

https://diy-dev-design.tistory.com/56

 

[wallpaper] Galaxy s10 series 배경화면 - MATRIX RELOADED

타이포 그래픽으로 제작한 갤럭시 S10 시리즈 배경화면 입니다. 문자의 이미지를 문자로 형상화 한 그래픽을 이용하여 배경화면을 만들어 보았는데요. 매트릭스의 경우 영화의 메인 컨셉 이미지와도 매칭되는 느낌..

diy-dev-design.tistory.com

존 윅 폰 배경화면 (간치 철철)

https://diy-dev-design.tistory.com/58

 

[wallpaper] Galaxy S10 배경화면 '존윅'

화끈함의 끝판왕 존윅 (JOHN WICK) 배경화면을 만들어 보았습니다. 아직 3편은 보지 못하였는데요. 빨리 보고 싶은 영화 1순위에 있다고해도 과언이 아닌 영화입니다. 존윅의 처참한 상황과 분위기를 폰 배경화면..

diy-dev-design.tistory.com

 

반응형
반응형

좀 생뚱 맞을 수도 있는데 이번에 소개해드릴 강좌는 글자의 밝기를 알아보는 스크립트를 소개해 드릴까 합니다. 

글짜에 무슨 밝기가 있다는 건가 하실수 있겠는데요. 

매트릭스 네오를 문자를 이용하여 표현한 모습

바로 이런 표현을 하기 위하여 필요한 것이죠.

각 단위 글자에 밝기를 분석하여 이미지의 픽셀에 매칭해보려는 것 입니다.

이렇게 하기 위하여 필요한 것이 글자의 밝기를 분석해서 어떤 글자가 가장 밝고 어떤 글자가 가장 어두운 글자인지 알아야 하는 것이죠.

정확히는 글자가 어둡다기 보다는 단위면적에 동일한 크기로 글자를 표시했을때 어두운 영역이 가장 많은 글자가 가장 어두운 글자가 되겠습니다.

제가 사용할 글자는 총 85 개로 알파벳 대소문자 및 특수기호들 입니다.

일단 생각나는데로 적은 글자는 abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890[}±.:,/~';*-=+!@?>\#$%^& 입니다.

이 글자들을 분석하여 어떤 글자가 가장 밝고 어떤 글자가 가장 어두운지 찾아내야 합니다.

먼저 아래와 같이 준비를 해놓겠습니다.

  • Photoshop 에 10 x 10 짜리 다큐먼트를 하나 만든 뒤 텍스트 메뉴로 글자를 하나 입력한다.
  • 폰트는 Consolas (무료), 사이즈는 10 pt 

그다음 스크립트를 이용하여 분석을 진행해보겠습니다.

다큐먼트의 텍스트 아이템의 글자를 위에 준비된 글자로 하나씩 바꿔가면서 전체 픽셀의 밝기를 모은 뒤 배열에 저장하고 저장된 배열의 값을 작은 수에서 큰수로 재배열을 해주면 되겠습니다. 

개념 적으론 별거 없죠?

코드를 보시죠. 주석을 잘 따라 읽어 보시면서 봐주세요.

var ltrSet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890[}±.:,/~';*-=+!@?>\#$%^&";
var finalLtrSet = ""
var cCount = ltrSet.length;

var letVals = [];

var cDoc = app.activeDocument;

// 컬러샘플러가 이미 있을 수 있으니 제거 해준다.
cDoc.colorSamplers.removeAll();

// pointSample 라는 컬러 샘플러를 하나 생성해 주자. 
// pointSample 라는 개체를 이용하여 컬러를 수집할 예정임.
var pointSample = cDoc.colorSamplers.add([1,1]);

// 미리 주어진 문자열을 하나씩 분석하여 밝기와 해당 글자를 배열에 저장해 주자.
for (var k=0; k < cCount; k++)
{
    cLtr = ltrSet.charAt(k);
    cDoc.layers[0].textItem.contents = cLtr;
    cBrt = getImageBrightness(); // 아래쪽에 글자의 밝기를 구하는 함수를 이용하여 밝기 분석
    letVals.push([cBrt, cLtr]);  // 구해진 밝기를 해당 문자와 함께 배열에 저장함
}

// 저장된 배열을 밝기 순으로 재정렬한다.
letVals.sort(arrayfn_chkBrt);

//finalLtrSet 라는 변수에 재배열된 글자를 순서대로 적어 준다.
for (var k=0; k < cCount; k++)
{
    finalLtrSet += letVals[k][1]
}

//밝기 순으로 재정렬 된 글자들 출력
$.writeln(finalLtrSet)

// 구해진 최종 결과 문자 셋 가장 좌측이 밝은색, 가장 우측이 어두운 색 되시겠습니다.
//var lset = ".-':,;>^!~Lci/*1l?zC+±tsr2=JIT}[x75FvZ3eSYEfukjnayKoPXV9h6qdRp4bAG$8wDUO&%#Bg0mHQMWN@"

pointSample.remove();

// 배열의 순서를 재정렬 하기 위한 함수. 배열의 첫번째 값을 비교하여 작은수를 앞으로 보낸다.
function arrayfn_chkBrt(a,b)
{
    if (a[0] > b[0])
    {
        return -1;
    }
    else if (a[0] < b[0])
    {
        return 1;
    }
    else
    {
        return 0;
    }
    
}

// 이미지의 모든 픽셀의 밝기를 더한뒤 전체 픽셀수로 나누어 평균 값을 구한다. 10 x 10 으로 고정함 
function getImageBrightness()
{
    var cDoc = app.activeDocument

    var brightAll = 0;

    for (var yy = 0; yy < 10; yy++)
    {
        for (var xx = 0; xx < 10; xx++)
        {
            pointSample.move([xx,yy]);
            brightAll += pointSample.color.hsb.brightness;            
        }
    }
    brightAll = brightAll / 100
    
    return brightAll;
}



 요렇게 하면 주어진 글자들을 이용하여 밝기 순으로 재정렬 된 문자열을 받을 수 있습니다. 

중간에 제가 주석으로 해놓은 부분이 최종적으로 $.writeln() 을 통해 출력해본 결과 입니다.

.-':,;>^!~Lci/*1l?zC+±tsr2=JIT}[x75FvZ3eSYEfukjnayKoPXV9h6qdRp4bAG$8wDUO&%#Bg0mHQMWN@

이렇게 구해진 문자열을 이용하여 실제이미지에 매칭하는 작업을 하면 됩니다.

 

이번 강좌에서는 조금 생소한 코드들이 좀 나왔습니다. 바로 colorSampler 와 배열을 재정렬할때 사용한 배열 함수 입니다. 

colorSampler 는 바로 포토샵의 스포이드 (color picker) 기능과 같습니다. 

바로 요녀석인데요. 특정 픽셀의 컬러를 가져오는 기능을 수행합니다. 

포토샵 컬러 피커 

우측에 보면 HSB , RGB, Lab, CMYK, 그리고 Hex 값으로 출력된 컬러 정보가 보여지는데요. colorSampler 역시 완전히 동일 합니다. 

레퍼런스에 보면 아래와 같이 나와 있고요

레퍼런스에 나와있는 컬러 샘플러에 대한 내용
레퍼런스에 나와있는 컬러 샘플러에 대한 내용

이 녀석의 프라퍼티 부분을 보면 SolidColor 라는 정보를 color 라는 프라퍼티를 통해 접근이 가능한 것을 알 수 있습니다. 한번 Solid Color 부분으로 가볼까요?

링크를 타고 들어가 보면 아래와 같이 Solod Color 에 대하여 나와있습니다.

레퍼런스에 나와있는 SolidColor 에 대한 내용

여기에 보면 위에 소개해 드렸던 cmyk, gray, hsb, lab, rgb 등의 프라퍼티를 이용할 수 있는 것을 알 수 있습니다. 제가 이번 스크립트에서 픽셀의 밝기를 받아온 것은 바로 hsb (hue, saturation, brightness) 를 이용한 것입니다. 

pointSample.move([xx,yy]);
pointSample.color.hsb.brightness;

이렇게 컬러샘플러의 위치를 필요한 곳으로 이동시키고 필요한 값을 얻어오는 것이죠.

 

다른 하나는 바로 배열을 재배열 하는 함수 입니다.

Array.sort ( sort function ) 인데요. 바로 sort function 에 해당하는 함수를 사용자가 만들 수 있다는게 특징입니다.

일반적으로 sort (정렬) 이라 하면 숫자가 낮은것에서 높은것으로 또는 높은 것에서 낮은 것으로 정렬 되는 것을 상상 할 수 있겠지만 별도의 정렬 함수를 이용하면 아주 새로운 정렬 규칙을 만들어 내는 것이 가능합니다.

저는 배열의 각 인자들이 두개의 값을 갖는 또다른 배열이기 때문에 배열 인자의 내부 값중 첫번재 (밝기) 를 이용하여 정렬을 한 것이죠. 첫번째 인자는 미리 계산해 두었던 글자들의 밝기 값이기 때문에 해당 값을 이용하여 정렬을 해주면 글자가 가장 밝은 글자부터 가장 어두운 글짜까지 순차적으로 정렬이 되는 것 입니다.

 

제가 만든 문제셋 말고 본인이 직접 문자셋을 준비하여 정렬된 순차적 문자열을 구해보시는것도 좋을 것 같습니다. 알파벳은 문자가 헐렁하여 아주 어두운 픽셀에 적용되었을 때 효과가 덜한 듯 합니다.

 

제가 구해보니 알파벳 중 W N @ 가 가장 어두운 글자였으나 한글이라면 "뚫" 이런 글자도 가능하지 않습니까? 또 한글이나 영문이 아니더라도 문자표에 가보시면 ᵺ ▓ ■ 이런 문자들도 있으니 더 어두운 색상 표현에 유리할 수 있습니다. 전 85 글자여서 0 ~ 255 인 밝기 값을 3으로 나누어 사용하였는데요. 이렇게 다양한 글자를 이용한다면 0~255 까지의 글자로 표현도 가능할 것입니다.

 

한번 도전해 보세요. 궁금하신 부분이나 잘 안되는 것은 질문해주시면 답변 드리겠습니다.

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

 

그럼 이만~

 

본 스크립트는 아래 포스트에서 실제 어떻게 적용되는지 확인할 수 있습니다.

https://diy-dev-design.tistory.com/57

 

[포토샵스크립트] 문자를 이용하여 사진 표현하기

미디어 아티스트를 꿈꾸는 디자이너라면 한번 쯤은 관심을 가져 봤을 법한 이미지 또는 영상이 있습니다. 바로 사진을 텍스트로 전환하여 이미지 프로세싱을 통해 표현하는 것인데요. 음... 글로만은 설명이 좀 어..

diy-dev-design.tistory.com

 

해당 스크립트를 이용하여 제작한 핸드폰 배경화면

https://diy-dev-design.tistory.com/56

 

[wallpaper] Galaxy s10 series 배경화면 - MATRIX RELOADED

타이포 그래픽으로 제작한 갤럭시 S10 시리즈 배경화면 입니다. 문자의 이미지를 문자로 형상화 한 그래픽을 이용하여 배경화면을 만들어 보았는데요. 매트릭스의 경우 영화의 메인 컨셉 이미지와도 매칭되는 느낌..

diy-dev-design.tistory.com

 

반응형
반응형

이번 강좌에서는 좀 재미있는 코드를 소개해 드릴까 합니다.

바로 엑셀 VBA 를 이용하여 포토샵 자동화 하기! 

오~~ 이게 되냐구요? 네 ! 됩니다.

사실 스크립트나 자동화 작업을 통하여 어떤 일을 할 것인가를 찾아내는 것이 실제 코드를 작성하는 것보다 훨씬 어려운 일이랍니다. 막상 어느 정도 개발을 할 수 있게 되면 생각보다 많은 것을 할 수 있다는 것을 알게되죠.

자 오늘은 그런 의미에서 새로운 문을 한번 열어 보겠습니다.

포토샵은 크게 세가지 스크립트 언어를 지원합니다. 바로 JavaScript, Apple Script (맥에서 만 가능), Visual Basic (윈도우에서만 가능) 요렇게 세가지 입니다. 엑셀은 기본적으로 비주얼 베이직 에디터를 포함하고 있기 때문에 포토샵 스크립트인 비주얼 베이직 버전의 개발이 가능한 것이죠. 

비주얼 베이직 버전의 포토샵 스크립트도 많은 기능을 지원합니다. 자바스크립트 버전과 거의 동일합니다. 오히려 코딩 관점에서는 더 간단하기도 합니다.

 재미없는 이야기는 집어 치우고 바로 코드로 실습을 해보시죠.

엑셀을 켜고 Alt + F11을 눌러 비주얼 베이직 에디터 창을 열어줍니다. 그리고 Sheet1 페이지를 더블클릭해서 코딩을 위한 창을 하나 만든다음 아래의 내용을 입력해주세요.

Sub usingPhotoshop()

    Dim psApp As Object
    
    Set psApp = CreateObject("Photoshop.Application")
    
    psApp.Documents.Add

End Sub

물론 컴퓨터에 당연히 포토샵이 설치가 된 상태여야 겠죠?

F5 키를 눌러보면 쨔짠~ 아래와 같이 포토샵이 자동으로 켜지고 곧이어 새창이 하나 만들어 집니다.

엑셀 VBA 로 실행시킨 포토샵과 엑셀에서 만든 포토샵 다큐먼트

신기 하신가요?

제가 제 블로그에서 포토샵 스크립트도 틈틈히 올리고 있는데요. 해당 카테고리에는 대부분 자바스크립트 기준의 스크립트를 올리고 있습니다. 사실 해당 카테고리에 올린 모든 내용은 VBA 로도 작성이 가능하답니다.

코드를 조금더 올려볼까요?

Sub usingPhotoshop()

    Dim psApp As Object
    Dim psdDoc
    
    Set psApp = CreateObject("Photoshop.Application")
    
    psApp.Documents.Add
    
    Cells(1, 1).Value = "Document Name"
    Cells(1, 2).Value = "가로"
    Cells(1, 3).Value = "세로"
    
    Set psdDoc = psApp.activeDocument
    
    Cells(2, 1).Value = psdDoc.Name
    Cells(2, 2).Value = psdDoc.Width
    Cells(2, 3).Value = psdDoc.Height
        
End Sub

 조금 길어졌지만 뭐 한줄 한줄 읽어 보면 어려울 것이 없습니다. 처음 짜시려면 막막하시겠지만 막상 짜놓은 코드를 읽어보면 간단합니다. 자꾸 이렇게 만들어진 코드를 보는 것이 중요합니다. 자꾸 보면서 따라 코딩을 하다보면 눈에 익게 되고 그 다음엔 손에 익게되죠. 일단 익숙해 지면 쉽게 자신만의 코드 작성이 되기 시작합니다.

내용을 보면 이렇습니다.

  • 포토샵 어플리케이션이 될 변수와 PSD 다큐먼트를 지정할 변수를 선언해준다.
  • photoshop.application 이라는 오브젝트를 생성한다 --> 이때 포토샵이 실행됨
  • 실행된 포토샵에 새로운 다큐먼트를 추가한다.
  • 엑셀 시트의 멘위 세줄에 각 항목의 이름을 기입한다.
  • 현재 포토샵에서 활성화된 창을 변수에 담아준다.
  • 활성화된 창의 이름과 가로 길이, 세로 길이를 두번째 줄에 차례로 입력해준다.

요런식이 되겠습니다. 간단하죠?

포토샵의 정보를 이용하여 엑셀에 값을 채운 모습

자 그럼 반대로 엑셀에서 지정한 이름과 크기로 포토샵 도큐먼트를 세팅해 볼까요? 아마 실제로는 이게 더 유용하겠죠?

제 블로그 이름과 별도의 크기를 지정해 보겠습니다.

코드는 이렇게 작성해 보겠습니다.

  • 포토샵으로 새로운 다큐먼트를 만들어 준다
  • 가로세로 크기를 지정한 크기로 Resize 한다
  • 지정한 이름의 PSD 파일로 저장한다.

간단하죠? 코드를 볼까요? 아까랑 별반 차이가 없습니다.

Sub usingPhotoshop()

    Dim psApp As Object
    Dim psdDoc
    
    Set psApp = CreateObject("Photoshop.Application")
    
    psApp.Documents.Add
    
    Cells(1, 1).Value = "Document Name"
    Cells(1, 2).Value = "가로"
    Cells(1, 3).Value = "세로"
    
    Set psdDoc = psApp.activeDocument
    
    psdDoc.ResizeImage CInt(Cells(2, 2).Value), CInt(Cells(2, 3).Value), 72, 4
      
    psdDoc.SaveAs ("d:\" & Cells(2, 1).Value & ".psd")
    
End Sub

윗쪽까지는 다 동일하고요. 아래 두줄이 다릅니다.

바로 ResizeImage 라는 명령이 들어갔고요. 그 아래에는 다큐먼트의 이름이 되는 PSD 파일을 저장해주는 코드 입니다.

VBA 에서는 문자열을 합칠때 + 기호가 아닌 & 를 사용하는 것 알고 계시죠??

요렇게 하면 아래와 같이 만들어 진답니다. 사이즈 확인을 위하여 이미지 리사이즈 창을 통해 정보를 띄워 놓았습니다.

엑셀에서 작성한 데로 DIY-DEV-DESIGN 이라는 이름의 다큐먼트를 만들었다. 사이즈도 엑셀에서 지정한 크기로 설정된 상태.

사실 이런 간단한 코드도 처음 작성하는 분에게는 막막하기만 합니다.

VBA 는 익숙치 JavaScript 나 C, C++, Java 와는 다른 좀 특이한 문장 형태를 갖고 있기 때문에 더 어렵게 느껴질 수 있습니다. 하지만 VBA 의 장점이라 할 수 있는 실시간 오류 리포팅 기능이 있지 않겠습니까? 코드 작성 중 잘못된 문법은 허용이 되지 않죠. 바로 경고창으로 알려 줍니다. 경고 창이 뜨지 않도록 잘 맞춰주면 코드가 완성이 됩니다.

그리고 ResizeImaze 뒤에 Cells(2,1).value 는 알겠는데 그 뒤에 오는 72 와 4 라는 숫자는 뭘까요?? 각각의 값은 위 이미지에서 볼 수있는데요. 바로 리사이즈시 사용하는 Resolution 정보와 아래 resample 옵션인 Bicubic 에 해당하는 옵션입니다. 

이런건 어떻게 알아내냐구요? 바로 레퍼런스죠. 

레퍼런스에서 필요한 개체를 찾는다. 클릭하면 해당 개체로 이동됨

먼저 다큐먼트 개체로 진입합니다. 그다음 리사이즈를 해야 하니 resize 라는 용어 근처를 찾아봐야겠죠? 

스크롤해서 내려가다 보면 ResizeImage 라는 명령을 찾을 수 있다.

자 ResizeImage 라는 명령을 찾았습니다. 바로 위에는 ResizeCanvas 라는 명령도 보이네요. 어쨌든 ResizeImage 아래에 어떤 옵션들을 적어야 하는지 설명이 되어 있습니다.

  • ResizeImage
    • Width (숫자, 더블형 - 소수)
    • Height (숫자, 더블형 - 소수)
    • Resoluton (숫자, 더블형 - 소수)
    • ResampleMethode (PsResampleMethod)

위에 3개의 옵션은 아시겠죠? 입력해야 하는 데이터의 자료형 입니다. 소수라고 정의 되어 있으니 12.5 이런 값으로 입력이 가능합니다. 그런데 맨 아래는 뭔지 잘 모르시겠죠? 파란색으로 링크 표시가 있으니 클릭해서 들어가 보겠습니다.

resample 방법으로 이동된 모습, 숫자별로 숫자가 어떤 옵션이 무엇인지 설명이 되어 있다.

이미지를 인터폴레이션 즉, 보간하기 위한방법이라고 나와있군요. 각 숫자별로 보간 방법이 나와 있구요. 일반적으로 포토샵에서 기본으로 설정되어 있는 옵션은 Bicubic 이며 4번에 해당됩니다. 제가 사용한 코드에 4 로 입력하였으니 Bicubic 으로 보간이 된 셈입니다. 

막간을 이용하여 간단하에 각 옵션을 설명 드리자면, (이번 기회에 알아두셔도 좋겠네요.)

  • psNoResampling - 보간하지 않음
  • psNearestNeighbor - 픽셀경계면의 색상을 섞지 않음 (지글지글거리게 됩니다. 안티 앨리어싱이 안먹은 느낌?)
  • psBilinear - 리니어하게 보간을 합니다. 선형보간이라 하는데 그냥 평범한 보간 법이라 보시면 됩니다.
  • psBicubic - 선형 보간에서 하나의 축을 더하여 보간을 한 것으로 좀더 자연스러운 보간이 됩니다. (추천)
  • psBicubicSharper - bicubic 을 기본으로 하며 좀더 선명한 이미지를 얻을 수 있습니다.(축소할 때 추천)
  • psBicubicSmoother - bicubic 을 기본으로 하며 좀더 부드러운 이미지를 얻을 수 있습니다. (확대할 때 추천)

요렇게 필요한 옵션으로 리사이즈를 하시면 됩니다. 보통 Bicubic 으로 하지만 저는 필요에 따라 옵션을 바꾸며 사용합니다. psNearestNeighbor 같은 경우는 어떨때 사용할까요? 3D 텍스처용 맵을 만들어 놓고 리사이즈가 필요할때 해당 옵션을 이용하여 alpha 채널을 리사이즈하면 알파채널 경계 영역이 흐릿해지는 현상을 막을 수 있습니다.

 

강좌가 좀 딴길로 샜습니다. ^^

 

끝으로 조금더 컨트롤 하는 예제를 보여드리고 마무리 하겠습니다.

  • 지정한 크기와 이름을 갖도록 설정하고 싶다.
  • 엑셀에서 배경 색상을 지정하고 싶다.
  • 텍스트 레이어를 만들어서 추가하고 싶다.

요정도만 해볼까요?

요런 내용으로 PSD 파일을 자동으로 생성해 보겠습니다.

 

코드를 작성해보면 아래와 같습니다.

Sub usingPhotoshop()

    Dim psApp As Object
    Dim psdDoc
    Dim bgColor
    Dim fontColor
    Dim cellColor
    Dim txtLayer
    
    Set psApp = CreateObject("Photoshop.Application")
    
    psApp.Documents.Add
    
    Set psdDoc = psApp.ActiveDocument
    
    psdDoc.ResizeImage CInt(Cells(2, 2).Value), CInt(Cells(2, 3).Value), 72, 4
    
    '셀 색상을 HEX 값으로 받아오기'
    cellColor = Right("000000" & Hex(Cells(2, 4).Interior.Color), 6)
    
    'bgColor 라는 SolidColor 개체를 만들어서 Hex -> DEC -> Doble 로 변환하여 적용하기'
    Set bgColor = CreateObject("Photoshop.SolidColor")
    bgColor.RGB.HexValue = cellColor
    
    bgColor.RGB.red = CDbl(WorksheetFunction.Hex2Dec(Right(cellColor, 2)))
    bgColor.RGB.green = CDbl(WorksheetFunction.Hex2Dec(Mid(cellColor, 3, 2)))
    bgColor.RGB.blue = CDbl(WorksheetFunction.Hex2Dec(Left(cellColor, 2)))
    
    '화면 전체 선택한 뒤 색상 칠하기'
    psdDoc.Selection.SelectAll
    psdDoc.Selection.Fill bgColor
    
    '폰트 색상용 색상 개체 만들어 색상 설정하기'
    cellColor = Right("000000" & Hex(Cells(2, 5).Interior.Color), 6)
    
    Set fontColor = CreateObject("Photoshop.SolidColor")
    fontColor.RGB.red = CDbl(WorksheetFunction.Hex2Dec(Right(cellColor, 2)))
    fontColor.RGB.green = CDbl(WorksheetFunction.Hex2Dec(Mid(cellColor, 3, 2)))
    fontColor.RGB.blue = CDbl(WorksheetFunction.Hex2Dec(Left(cellColor, 2)))
    
    '텍스트 레이어 추가해주기'
    Set txtLayer = psdDoc.artlayers.Add
    txtLayer.kind = 2
    txtLayer.Name = "my Text"
    
    '만들어진 텍스트 레이어에 텍스트 추가하기'
    Set txtItem = psdDoc.artlayers("my Text").textitem
    txtItem.Font = "MalgunGothicBold"
    txtItem.Size = 36
    txtItem.Color = fontColor
    txtItem.contents = Cells(2, 6).Value
    
    'PSD 파일로 저장하기'
    psdDoc.SaveAs ("d:\" & Cells(2, 1).Value & ".psd")
    
End Sub

와우 엄청 길어졌네요. 순서대로 주석을 읽어 보시면 내용은 이해가 되실텐데요. 새로운 명령어 들이 많이 나왔죠? 한번 실습한다 생각하시고 따라서 코딩을 해보신 다음 찬찬히 생각해보시면 이해가 되실거에요. 좀 생소한 코드도 있기는 하지만 어렵지는 않습니다. 실행해보면 아래와 같이 됩니다.

 

샘플 코드 만드는데 생각했던 것보다 오려걸렸네요. 꼭 필요하신 분에게 도움이 되었으면 합니다.

위에 저는 단순히 한줄만 제가 필요한 내용을 엑셀에 기재하여 PSD 파일을 만들었지만 저런 조건들이 이제 수백개가 되어도 자동으로 모두 만들 수 있는 여건이 되었습니다. 반복 문을 조금 응용하면 되겠죠?

이미지를 엑셀로 붙여넣은 포스트 기억나시나요? 해당 이미지를 열어서 셀 크기로 저장한뒤 다시 붙여 넣는 것도 가능하겠고, 여러 이미지를 하나의 포토샵에 레이어로 추가하는 것도 가능하겠으며 이미지에 파일명을 텍스트로 추가하는 것도 역시 쉽게 가능할 것 같습니다.

어렵다고 생각 마시고 바로 도전해 보시기 바랍니다.

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

 

엑셀로 포토샵 자동화 가능?

네. 쌉가능입니다. ㅋ

반응형
반응형

안녕하세요. 이번 강좌에서는 엑셀 시트에 있는 이미지 파일 경로를 이용하여 셀에 이미지를 붙여넣는 스크립트를 한번 알아 보겠습니다. 엑셀에 이미지를 몇장 붙여 넣는 거야 그림 삽입하기로 손쉽게 넣으면 되지만 붙여넣어야 할 그림이 몇백개 이상이 되면 답이 나오지 않는 상황이 옵니다. 절망 적이죠. 바로 야근 각입니다.

하지만 스크립트가 출동한다면 ?

칼퇴근 쌉가능

게다가 셀의 크기에 맞게 가지런히 딱 붙여줄수 있다면 말할 필요도 없이 선배님에게 쓰담쓰담 각 입니다.

어렵지 않으니 천천히 따라와 주시면 됩니다.

 

*** 개발에 관심 1g도 없고 그림만 자동으로 붙여 넣고 싶으시다면 아래 포스트를 참고해주세요

2020/01/08 - [DEV/c#] - Excel Automate, 엑셀 자동화 프로그램

 

Excel Automate, 엑셀 자동화 프로그램

필자의 블로그 명칭을 보고 이미 알고 계신분이 있을지 모르겠지만 사실 저는 디자이너 입니다. 하지만 블로그에 맨 개발 관련 된 이야기만 적고 있지요. 음... 그런데 실제로 회사에서도 저는 대부분의 시간을 코..

diy-dev-design.tistory.com

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

 

 

 

 

 

 

 

엑셀에 이미지를 붙여 넣는 방법중에 대표적으로 아래 두가지 방법이 있을 수 있겠습니다.

  • Worksheet.Pictures.Insert(pathName & bmpName)
  • Worksheet.Pictures.Insert.Shapes.AddPicture(Filename:=(pathName & bmpName), linktofile:=msoFalse, savewithdocument:=msoCTrue, Left:=imgPosX, Top:=imgPosY, width:=imgWidth, Height:=imgHeight)

요렇게 두가지 인데요. 

저는 아래의 방법을 선호 합니다. 위의 방법은 코드가 짧고 단순하여 작성이 편리하기는 하지만 엑셀 2007 이하의 버전에서 삽입한 이미지가 2010 버전에서 간혹 누락이 되는 경우가 있습니다. 정확히 원인을 알수는 없지만 두번째 방법은 그런 문제가 없어 현재 두번째로만 사용중입니다.

자 그럼 코드를 작성해 볼까요?

먼저 이미지 이름 (경로 포함 또는 경로는 별도로 설정) 이 있는 셀이 연속으로 있어야 겠습니다.

이미지 이름이 있는 엑세 리스트

요런식으로 말이죠.

그럼 코딩을 시작해 보겠습니다. 아래 코드를 봐주세요 전에 작성했던 코드에 비하면 조금 길지만 어렵지 않습니다.

Sub insertPicture()

    Dim aSht As Worksheet
    Dim rngA As Range
    Dim rng8 As Range
    
    Dim pathName As String  '이미지가 들어있는 경로'
    
    Dim imgPosX As Integer
    Dim imgPosY As Integer
    Dim imgWidth As Integer
    Dim imgHeight As Integer
    
    '이미지 정보 확인을 위한 개체를 만들겁니다.'
    Dim wia         As Object
    
    Dim m_Width As Integer
    Dim m_Height As Integer
    
    Dim pic As Shape
    
    Set aSht = ActiveSheet  ' 현재 선택된 시트에서 진행하겠습니다.'
    
    Set rngA = aSht.Range("B2")
    Set rngA = aSht.Range(rngA, rngA.End(xlDown)) ' 요렇게 하면 B2 부터 아래로 맨 끝까지가 설정이 되는거 아시죠?'
    
    Set wia = CreateObject("WIA.ImageFile")     ' 이미지 정보 확인을 위한 오브젝트를 설정함'
     
    pathName = "F:\test\unimog\" '이미지가 들어있는 경로'

    For Each aRng In rngA
    
        Set rng8 = aRng.Offset(0, 1) 'rng8 이라는 변수'
        bmpName = aRng.Value
                
        bmpName = bmpName
        
        ' 이미지가 경로상에 실제 존재하는지 파악하기 위하여 Dir 함수 사용'
        isBmpExist = Dir(pathName & bmpName)
        
        ' 이미지가 없으면 "" 가 리턴됨'
        If (isBmpExist <> "") Then
            
            ' 이미지를 열어서 사이즈를 확인함'
            wia.LoadFile (pathName & bmpName)
            
            m_Width = wia.Width
            m_Height = wia.Height
            
            '이미지의 세로크기가 셀 최대 높이 값을 넘는 경우 최대 높이값으로 설정함
            If (m_Height > 540) Then
                Dim scaleRatio As Double
                scaleRatio = 540 / m_Height
                m_Height = 540
                m_Width = CInt(m_Width * scaleRatio)
            End If
            
            '만약 이미지의 세로 크기가 현재 설정되어있는 셀보다 작다면 셀의 세로 길이를 늘여줌'
            If rng8.RowHeight < (m_Height * 0.75 + 4) Then
                rng8.RowHeight = m_Height * 0.75 + 4
            End If
            
            '이미지가 셀의 중앙에 위치하도록 위치와 크기를 계산하여줌.'
            '엑셀에서의 수치 단위가 px 이 아닌 point 이기 때문에 px 로 계산된 값에 각각 0.75 를 곱해주었다.
            imgPosX = rng8.Left + rng8.Width / 2 - (m_Width * 0.75) / 2
            imgPosY = rng8.Top + (rng8.RowHeight * 0.5 - (m_Height * 0.75 * 0.5))
            imgWidth = m_Width * 0.75
            imgHeight = m_Height * 0.75
            
            '최종 이미지를 위에서 설정한 값으로 삽입하는 과정'
            '복잡하게 계산할거 없이 다 동일한 크기에 동일한 위치라면 imgPosX, imgWidth, imgHeight 는 고정값을 적용해 주어도 된다.'
            Set pic = aSht.Shapes.AddPicture(Filename:=(pathName & bmpName), linktofile:=msoFalse, savewithdocument:=msoCTrue, Left:=imgPosX, Top:=imgPosY, Width:=imgWidth, Height:=imgHeight)
            
            
        End If
   
   Next
   
   Set wia = Nothing
   
End Sub

  좀 특별한 개체로 createObject 라는 함수가 호출이 되었고 그 개체에서 이미지 정보를 확인하는 부분이 들어있는데요. 이는 엑셀에서 COM(Component Object Model) 이라고 하는 오브젝트를 생성하여 기능을 수행하는 과정을 보여줍니다. vba 나 .net 기반의 개발 환경에서 아주 빠르고 손쉽게 여러가지 기능을 사용할 수 있도록 하기 위한 라이브러리 같은 개념이라고 보시면 됩니다. 다만 플랫폼이나 사용자별 환경에 따라 상당히 제약적인 부분이 있으니 남발하는 것은 좋지 않겠습니다.

F5 키를 눌러 실행을 하면 아래와 같이 이미지가 붙게 됩니다.

참고로 엑셀 시트의 확대 배율을 반드시 100% 로 해놓고 실행하셔야 정확하게 셀에 붙습니다. 축소된 상태면 이미지가 밀려 내려가는 경우가 발생할 수 있습니다.

제가 좋아하는 우니목 사진입니다. 자동으로 붙였기 때문에 가지런하기가 이를데 없습니다.

 

약 31개의 이미지가 붙었는데요. 1초만에 모두 삽입 되었습니다.

 

 

 

 

 

 

 

 

 

제가 작성한 코드를 복사해 가신 후 아래 내용에 경로만 수정해 주시면 바로 사용이 가능합니다.

pathName = "F:\test\unimog\" <-- 이미지가 들어있는 폴더 경로, 끝에 \ 를 붙여줘야 합니다.

물론 이미지 이름이 붙어 있는 range 의 시작 셀의 이름도 설정을 해주어야 겠지요.

Set rngA = aSht.Range("B2") <-- B2 부분에 시작 셀의 이름을 적어주면 됩니다. C3, F1 처럼 말이죠.

어디 메모장이나 노트에 붙여 넣어 두셨다가 필요하실 때 사용하시면 됩니다. 

 

이상으로 이미지를 한번에 붙여 넣는 자동스크립트를 알아 보았습니다.

 

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

 

2021/01/03 - [DEV/Adobe Script] - [포토샵스크립트] 코딩을 통하여 '모동숲 카드' 만들기

 

[포토샵스크립트] 코딩을 통하여 '모동숲 카드' 만들기

코로나로 인하여 아이들이 집밖에 나가지도 못하고 집안에서 게임만 하고 있는 것을 보고 아이들을 위해 놀이거리를 하나 만들어 주어야겠다고 생각하고 시작한 동물의 숲 카드 만들기 입니다.

diy-dev-design.tistory.com

2020/09/04 - [DEV/VBA] - [vba] 엑셀 이미지 리스트로 일괄 다운로드 받기

 

[vba] 엑셀 이미지 리스트로 일괄 다운로드 받기

안녕하세요. 오늘은 엑셀 리스트로 가지고 있는 웹 이미지 경로를 이용하여 일괄 다운로드 하는 방법을 소개해 드릴까 합니다. 인터넷에 찾아보면 이런저런 다운로더들이 있는데요. 입맛에 맞��

diy-dev-design.tistory.com

 

2020/01/08 - [DEV/c#] - Excel Automate, 엑셀 자동화 프로그램 (그림 자동으로 붙여주는 프로그램)

 

Excel Automate, 엑셀 자동화 프로그램

필자의 블로그 명칭을 보고 이미 알고 계신분이 있을지 모르겠지만 사실 저는 디자이너 입니다. 하지만 블로그에 맨 개발 관련 된 이야기만 적고 있지요. 음... 그런데 실제로 회사에서도 저는 대부분의 시간을 코..

diy-dev-design.tistory.com

2020/05/21 - [DEV/VBA] - [Excel] LCD 인치 정보로 가로 세로 길이 알아내는 방법

 

[Excel] LCD 인치 정보로 가로 세로 길이 알아내는 방법

가끔 모니터 가로세로 크기가 궁금할 때가 있습니다. 휴대폰 구입 전 화면 크기를 정확히 알고 싶은 경우도 있지요. 그런데 이상하게 화면의 가로세로 크기에 대하여 mm 로 설명이 나오지 않는 ��

diy-dev-design.tistory.com

 

셀의 크기, 테두리 등을 VBA 로 지정하는 방법

2020/01/30 - [분류 전체보기] - [vba] 셀 속성 조정하기 (넓이, 높이, 숨기기, 테두리 등)

 

[vba] 셀 속성 조정하기 (넓이, 높이, 숨기기, 테두리 등)

이번 포스트에서는 vba 를 이용하여 셀의 속성을 조정하는 방법을 설명 드리겠습니다. 엑셀은 단순한 표의 형식을 취하고 있지만 셀의 간격이나 테두리 등의 속성을 자유롭게 조정할 수 있어 다양한 서식에 사용하..

diy-dev-design.tistory.com

 

만약 사진을 잘못 붙여넣어서 한번에 다 지워야 한다면?

https://diy-dev-design.tistory.com/30

 

[VBA] 엑셀 시트에 있는 모든 그림 한번에 삭제하기

오늘은 엑셀 시트에 있는 모든 그림을 한번에 삭제하는 스크립트를 만들어 보겠습니다. 엑셀 시트에 첨부된 그림을 일일이 또는 어떤 조건에 맞는 모든 그림을 삭제 하는 것은 매우 귀찮은 일입니다. 일단 다중 선..

diy-dev-design.tistory.com

 

2020/08/27 - [DEV/VBA] - 재택근무 필수 엑셀 "자리안비움" - 윈도우 꺼짐 방지

 

재택근무 필수 엑셀 "자리안비움" - 윈도우 꺼짐 방지

안녕하세요. 코로나19 바이러스 이슈사 해결되는 듯 해결되지 않고 계속 지속되어 국민 모두가 힘든 시기입니다. 저와 같은 회사원들도 재택근무를 지속하느라 업무효율도 낮고 힘든 시기입니��

diy-dev-design.tistory.com

 

반응형
반응형

안녕하세요. 오늘은 자신이 작성하였거나 웹에서 다운로드 받은 스크립트를 간단하고 빠르게 실행하는 방법을 알려드리겠습니다. 

우선 스크립트를 실행하는 방법은 몇가지가 있는데 다음과 같습니다.

  1. Extend Script Toolkit 으로 열어서 실행하기
  2. Photoshop menu-> File -> Script -> Browse.. 로 jsx 파일 열어서 실행하기
  3. 프리셋 폴더에 넣어놓고 Photoshop menu-> File -> Script -> 선택하여 실행하기
  4. 2번의 과정을 액션으로 기록하여 액션 단축키로 실행하기
  5. 3번의 과정을 단축키로 등록하기

요렇게 다섯가지 정도가 대표적인 방법이라 볼 수 있겠습니다.

스크립트를 실행하기까지의 번거로움은 번호 순으로 점점 빠르고 편해진다고 볼 수 있겠습니다.

1번 Extend Script Toolkit 으로 열어서 실행하기 의 경우 스크립트를 직접 작성하는 분들은 매우 익숙한 방법일텐데요. target application 을 선택한뒤 F5 키 또는 실행 버튼을 이용하여 스크립트를 실행하는 방법 입니다. 스크립트 실행시 필요에 따라 코드를 수정해 가면서 실행할 수 있기 때문에 빠르지는 않지만 자주 사용하는 방법입니다.

2번 Photoshop menu-> File -> Script -> Browse.. 로 jsx 파일 열어서 실행하기의 경우 저는 잘 사용하지 않는데요. 코딩이 익숙치 않거나 extend script tool kit 을 아얘 접해보지 않은 분이라면 2번의 과정으로 실행이 가능합니다.

4번은 2번의 과정을 액션으로 기록하여 실행하는 방법으로 간단하게 반복해서 실행을 할 수 있는 방법입니다. 다만 스크립트파일의 위치가 변경되거나 의도치 않게 해당 파일이 수정되면 문제가 발생될 여지가 있습니다.

3번과정 부터는 이제 자세하게 설명을 드리겠습니다.

먼저 자주 사용하게 될 스크립트 파일 (jsx 파일)을 준비한뒤 아래의 폴더에 복사해서 넣어 주세요.

좌측은 원래 스크립트가 있던 폴더, 우측은 빠른 사용을 위하여 프리셋 폴더에 넣어둔 모습

스크립트 파일을 포토샵 설치 폴더 내 프리셋 폴더에 복사해 넣습니다. 경로는 다음과 같습니다.

C:\Program Files\Adobe\Adobe Photoshop CS6 (64 Bit)\Presets\Scripts

해당 폴더에 실행할 스크립트 (저는 이전 강좌에서 만들었던 moveToCenter.jsx) 파일을 복사해서 넣습니다.

만약 이때 포토샵이 켜져 있는 상태였다면 껏다가 다시켜주어야 하고 아니라면 포토샵을 실행해 봅시다.

포토샵을 실행한 뒤 File -> Script 메뉴에 가보면 해당 스크립트 파일명이 아래와 같이 보이게 됩니다.

Script 메뉴 안에 추가한 스크립트가 표시된다.

 

이제 해당 메뉴을 선택하게 되면 바로 스크립트가 실행이 되게 됩니다.

 

 

그럼 좀더 빠른 실행을 위하여 단축키로 등록하는 방법을 알아 보겠습니다.

아래와 같이 상단 메뉴바에서 Edit -> keyboard shortcut 메뉴로 진입합니다.

키보드 단축키 설정 메뉴

그러면 단축키 설정을 할 수 있는 창이 표시됩니다.

포토샵 단축키 설정 창

설정 방법은 간단 합니다. 단축키를 등록할 기능이 어디에 있었죠? 네. 바로 File -> script -> moveToCenter 였죠?

동일하게 찾아가봅니다. File 부분을 눌러 확장시켜서 아래로 드르륵드르륵 내리다보면 원하는 녀석이 보일겁니다. 

네. 찾았습니다.

추가한 스크립트의 단축키가 설정되어 있지 않은 상태

저는 Ctrl + Alt + / 로 단축키를 설정해 보겠습니다.

컨트롤키 + 알트키 + / 키로 단축키를 설정한 상태

이렇게 하고 OK 를 누르게 되면 다음부터는 "Ctrl + Alt + /" 키를 누르게 되면 현재 선택된 레이어가 화면의 중앙으로 이동이 되게 됩니다. 아주 빠르게 실행이 가능하죠. 

그런데 만약. 본인이 설정한 단축키가 기존에 이미 할당이 되어있는 경우가 있을 수 있습니다. 그런경우 아래와 같이 경로창이 표시됩니다.

Alt + Ctrl + C 를 등록하여 하였으나 기존에 다른 기능이 사용하는 단축키라는 경고가 표시되었다

아래쪽에 경고 마크와 표시된 내용을 읽어 보면 이런 내용입니다. "Alt + Ctrl + C' 는 이미 사용중인 단축키 라는 겁니다.  Canvas Size 를 조정하는 기능에 대한 단축키라는군요. 만약 Accept 를 누르게 되면 기존 단축키는 사라지고 현재 적용한 기능에서 해당 단축키가 동작을 하게 됩니다. 기존 기능이 자주 사용하는 기능이어서 변경되면 안된다면 다른키를 찾아 보면 됩니다. 저처럼 평소 사용하지 않던 키들 중에 Ctrl, Alt 키를 조합하며 찾다보면 경고창이 없는 비어있는 단축키 조합을 발견하게 되어 등록하여 사용하면 되고요. 기존에 사용하는 단축키이지만 내가 사용하지 않는 기능이라면 과감히 Accept 를 눌러 변경해주면 됩니다.

 

자 이제 유용한 스크립트를 빠르게 동작하는 방법을 알아 보았습니다.

업무 시간을 1초라도 줄일 수 있다면 도전해보는 것은 어떨까요?

 

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

2020/12/03 - [DEV/Adobe Script] - [illustrator script] 일러스트도 스크립트가 되나요?

 

[illustrator script] 일러스트도 스크립트가 되나요?

네! 당연히 됩니다. 일러스트레이터에서 스크립트를 사용할 수 있게 되면 진정 놀라운 결과들을 만들어 낼 수 있습니다. 사람이 손으로 하기에는 정말 귀찮은 작업들을 가능하게 만들어 줍니다.

diy-dev-design.tistory.com

 

반응형

+ Recent posts