게시판 즐겨찾기
편집
드래그 앤 드롭으로
즐겨찾기 아이콘 위치 수정이 가능합니다.
[루아 이야기] 7. 그림속에 비밀 메시지를 담아 보아요..
게시물ID : programmer_1465짧은주소 복사하기
작성자 : 달빛연구자
추천 : 6
조회수 : 595회
댓글수 : 4개
등록시간 : 2014/02/26 21:47:38
안녕하세요.
달빛연구자 입니다.

이번 화에서는 그림 파일에 비밀 메시지를 숨겨 넣는 프로그램을 만들어 보도록 할께요.

프로그램의 원리는 다음과 같습니다.
메시지를 숨기는 프로그램
 1. 그림파일을 연다. 텍스트 파일도 연다.
 2. 그림의 색깔을 미묘~하게 조절해서 비밀 메시지를 숨겨 넣는다.
 3. 그림파일을 닫는다. 텍스트 파일도 닫는다.
 4. 인터넷에 올린다. 끝~

메시지를 꺼내는 프로그램
 1. 인터넷에서 그림파일을 받는다.
 2. 그림파일을 연다.
 3. 그림의 미묘~한 색상 변화를 읽어서 비밀메시지를 복원한다.
 4. 복원한 비밀메시지를 텍스트파일로 출력한다.
 5. 그림파일을 닫는다.

단순하죠? :)
소스코드는 가장 아랫쪽에 첨부해 두었습니다. 

프로그램의 동작은 다음과 같아요...

1. hide_messge.wlua
 프로그램을 동작시키면, 첫번째 열기창이 나오는데요. 여러분이 메시지를 담을 이미지 파일을 선택해 줍니다.
비밀메시지동작1.png

그림파일의 선택을 하고나면, 두번째 열기 창이 나오는데요. 여기서 담고자 하는 메시지가 들어있는 텍스트 파일을 선택해 줍니다.
이때 주의할 점은 텍스트 파일의 크기인데요. 대략 픽셀 3개당 1byte 씩 넣을 수 있고 텍스트파일이 너무 크면 중간에 잘릴 수 있으니,
픽셀 개수의 1/3 byte 크기의 파일을 선택해 주어야 합니다. (그래도 꽤 많이 들어가요 ㄷㄷ)
비밀메시지동작2.png

두 파일을 선택한 뒤 아래와 같이 out.png파일이 생성되고 Complete 라는 창이 나오면 메세지 삽입이 완료된 것 입니다.
비밀메시지동작3.png

out.png라는 출력파일이 생성됩니다.


2. get_message.wlua

두둥!!!!! 망했습니다. ㅜㅠ
본래 만들어지는  out.png는 250kb 의 크기를 가지고 있는데요. 
오유 게시판에 올리고나서 받으니, 그림크기가 50kb가 되어 있네요.. 오유게시판 내부적으로 png를 jpg로 압축해서 올리는 로직이 있는 듯 합니다..
아아.. 운영자님이시여 저에게 어찌하여 이런 시련을 내리시나이까... ㅠㅠ

 쓰읍... 뭐.. 안되는건 어쩔 수 없으니...  여기 가서 이미지를 받아옵니다.
http://www.etorrent.co.kr/bbs/board.php?bo_table=any&wr_id=56653&page=0&sca=&sfl=&stx=&sst=&sod=&spt=0&page=0

스파이복호화1.png


 두번째 스크립트를 get_message.wlua 로 저장하고 실행하면 다음과 같은 열기창이 나옵니다.
 방금 받은 png파일을 선택해 줍니다.

복호화2.png

역시 Complete 가 나오면 끝입니다. Out.txt 파일이 생성됩니다.

스파이복호화3.png

생성된 out.txt 를 열어보면 아까 이미지에 넣엇던 메시지가 복원되었음을 알 수 있습니다.
스파이복호화4.png

자... 여기까지 따라오신 분들이 계시다면 아마 묻겠지요...
이거 어디에 쓰냐고 (...)

네.. 쓸데 없습니다;;
루아이야기 6편 쓰다가 갑자기 아이디어가 떠올라서 작성한 코드인데요..
딱히 쓸모는 없는데, 동작하기는 하지;; 버리기는 아깝고.. ㅜㅜ;;

자.. 이 프로그램 과연 어디에 쓰면 좋을까요? ㄷㄷㄷ

소스코드 입니다.

1. hide_message.wlua
require("iuplua")
require("imlua")

--image file open
iup.Message("Message","메세지를 넣고자 하는 png 파일을 선택해 주세요.")
filename = iup.GetFile("*.png")
local image = im.FileImageLoad(filename)

--txt file open
iup.Message("Message","메시지가 들어있는 txt 파일을 선택해 주세요.")
filename = iup.GetFile("*.txt")
msfile = io.open(filename)
local message = msfile:read("*all")
msfile:close()

bytechar = {}
bitfield ={}
local bitidx = 1
--message break to bit
for idx = 1,string.len(message) do
bytechar[idx] = string.byte(message,idx)
for tx = 1,8 do
bitfield[bitidx] = (bytechar[idx] % (2^tx))/2^(tx-1)
bytechar[idx] = bytechar[idx] - (bytechar[idx] % (2^tx))
bitidx = bitidx + 1

end
end

local r = image[0]
local g = image[1]
local b = image[2]
bitidx = 1
--break pixel just 1 bit
for row = 0, image:Height() - 1, 1 do
for column = 0, image:Width() - 1, 1 do
r[row][column] = r[row][column] - (r[row][column] % 2)
g[row][column] = g[row][column] - (g[row][column] % 2)
b[row][column] = b[row][column] - (b[row][column] % 2)

--insert message
if(bitfield[bitidx] ~= nil) then
r[row][column] = r[row][column] + bitfield[bitidx]
bitidx = bitidx + 1
end

if(bitfield[bitidx] ~= nil) then
g[row][column] = g[row][column] + bitfield[bitidx]
bitidx = bitidx + 1
end

if(bitfield[bitidx] ~= nil) then
b[row][column] = b[row][column] + bitfield[bitidx]
bitidx = bitidx + 1
end

end
end
print (bitidx-1)
image:Save("out.png", "PNG")
iup.Message("Message","Complete.")
-----------------------------------------------------------------

2. get_message.wlua
require("iuplua")
require("imlua")

iup.Message("Message","메세지를 꺼내고자 하는 png 파일을 선택해 주세요.")
local filename = iup.GetFile("*.*")
local image = im.FileImageLoad(filename)

local r = image[0]
local g = image[1]
local b = image[2]

bitidx = 1
local bitfield ={}
--get message bit from image
for row = 0, image:Height() - 1, 1 do
for column = 0, image:Width() - 1, 1 do
bitfield[bitidx] = r[row][column] % 2
bitidx = bitidx + 1
bitfield[bitidx] = g[row][column] % 2
bitidx = bitidx + 1
bitfield[bitidx] = b[row][column] % 2
bitidx = bitidx + 1
end
end

--recover message
local asciibox = {}
local asciiidx = 1
local strbox = {}
local stridx = 1
for idx = 1, #bitfield do
asciibox[asciiidx] = bitfield[idx]
if asciiidx == 8 then
asciiidx = 0
strbox[stridx] = asciibox[1] + asciibox[2] * 2 +asciibox[3] * 4 +asciibox[4] * 8
+asciibox[5]* 16 +asciibox[6] * 32 +asciibox[7] * 64 +asciibox[8] * 128
if strbox[stridx] == 0 then
break;
end
stridx = stridx + 1
end
asciiidx = asciiidx + 1;
end

local outfilename = "out.txt"
local outfile = io.open(outfilename,"w")
local iidx = 1
for iidx = 1 , #strbox -1 do
outfile:write(string.char(strbox[iidx]))
end
outfile:close()
iup.Message("Message","Complete")
-----------------------------------------------------------------

네.. 각각 60라인 , 50라인 밖에 안되는(?) 간단한 소스 코드 입니다. (퍽!)
전체 추천리스트 보기
새로운 댓글이 없습니다.
새로운 댓글 확인하기
글쓰기
◀뒤로가기
PC버전
맨위로▲
공지 운영 자료창고 청소년보호