2013/12/30(月) [n年前の日記]
#2 [ruby][python] 画像を難読化してみる
画像に変な難読化をかけてみる実験。
とりあえず、Python 2.6.6 + PIL(Pillow)を使って、読み込んだ画像を難読化。
_imgcrypt.py
以下のような画像になった。とりあえず、コレを見てどんな画像か理解できる人は、まず居ないだろうと。
image0_out.png
image1_out.png
これを Ruby + DXRuby で読み込んで元に戻して表示する。
_imgdecrypt.rb
以下のような結果に。
ちゃんと元の画像に戻せましたな。アルファチャンネルも有効になってる。(ポスト画像がアルファチャンネルを使用。)
もっとも、LLのソースを眺めることができる=どんな難読化をしてるのか容易に分かってしまうので、この手のソレをする意味なんてどの程度あるのか、という気もしますが。まあ、非プログラマーの方に御褒美画像をそのまま見せない、ということぐらいなら、使えるのかもと。
とりあえず、Python 2.6.6 + PIL(Pillow)を使って、読み込んだ画像を難読化。
_imgcrypt.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
u"""
画像に変な暗号化をかけてみるPythonスクリプト
PIL(Pillow)を使用。
Usage:
python imgcrypt.py IN_IMAGE OUT_IMAGE
"""
import sys
import os
from PIL import Image
next = 1
def rand():
u"""乱数生成器(C言語のソレ)"""
global next
next = (next * 1103515245 + 12345) & 0xffffffff
return int((next / 65536) % 32768)
def srand(seed):
u"""乱数初期化。種を渡す。"""
global next
next = seed
def encrypt_image(img):
u"""画像を難読化。Imageを渡す。"""
outimg = img.copy()
w, h = img.size
srand(0)
for y in range(h):
rx = rand()
for x in range(w):
c = img.getpixel(((x + rx) % w, y))
outimg.putpixel((x, y), c)
return outimg
def decrypt_image(img):
u"""画像の難読化の解除。Imageを渡す。"""
outimg = img.copy()
w, h = img.size
srand(0)
for y in range(h):
rx = rand()
for x in range(w):
c = img.getpixel(((x - rx) % w, y))
outimg.putpixel((x, y), c)
return outimg
def main():
if len(sys.argv) < 3:
print "Usage: python %s IN_IMAGE OUT_IMAGE" % \
os.path.basename( __file__ )
sys.exit()
inimgfn = sys.argv[1]
if not os.path.isfile(inimgfn):
print "Not Found %s" % inimgfn
sys.exit()
outimgfn = sys.argv[2]
img = Image.open(inimgfn, "r")
outimg = encrypt_image(img)
if True:
# 画像を保存
outimg.save(outimgfn)
print "Output %s" % outimgfn
else:
# 画像を表示して確認
outimg.show()
decrypt_image(outimg).show()
if __name__ == '__main__':
main()
python imgcrypt.py image0.png image0_out.png python imgcrypt.py image1.png image1_out.png画像の難読化も Ruby でやらなかったのは、Ruby でアルファチャンネルつきのpngが出力できるかどうか不明だったので…。Python + PIL(Pillow)ならできることは知ってたので、そちらを使ってみた次第。
以下のような画像になった。とりあえず、コレを見てどんな画像か理解できる人は、まず居ないだろうと。
image0_out.png

image1_out.png
これを Ruby + DXRuby で読み込んで元に戻して表示する。
_imgdecrypt.rb
# 画像の難読化を解除して表示するRubyスクリプト
#
# DXRuby を使用
require 'dxruby'
$next = 1
# 乱数生成器(C言語のソレを再現)
def c_rand
$next = ($next * 1103515245 + 12345) & 0xffffffff
return (($next / 65536) % 32768).to_i
end
# 乱数初期化。種を渡す
def c_srand(seed)
$next = seed
end
# 画像の難読化を解除
def decrypt_image(img)
w, h = img.width, img.height
outimg = Image.new(w, h)
c_srand(0)
h.times do |y|
rx = c_rand()
w.times do |x|
outimg[x, y] = img[(x - rx) % w, y]
end
end
return outimg
end
img0 = Image.load("image0_out.png")
img1 = Image.load("image1_out.png")
img0 = decrypt_image(img0)
img1 = decrypt_image(img1)
Window.loop do
break if Input.keyPush?(K_ESCAPE)
Window.draw(0,0, img1)
Window.draw(0,0, img0)
end
ruby imgdecrypt.rb
以下のような結果に。
ちゃんと元の画像に戻せましたな。アルファチャンネルも有効になってる。(ポスト画像がアルファチャンネルを使用。)
もっとも、LLのソースを眺めることができる=どんな難読化をしてるのか容易に分かってしまうので、この手のソレをする意味なんてどの程度あるのか、という気もしますが。まあ、非プログラマーの方に御褒美画像をそのまま見せない、ということぐらいなら、使えるのかもと。
◎ 参考ページ。 :
乱数生成器(線形合同法)は、以下の記事をそのまま使わせてもらいました。
_Algorithms with Python / 乱数
周期性がある疑似乱数らしいけど、とりあえず Python と Ruby で同じ結果が出てくる簡素な疑似乱数が欲しかったので…。もっとも、Python の乱数(Random)もMT法らしいので、書き方次第で前述のソース内の乱数生成器部分は丸々削除できるかもしれませんが。
_Algorithms with Python / 乱数
周期性がある疑似乱数らしいけど、とりあえず Python と Ruby で同じ結果が出てくる簡素な疑似乱数が欲しかったので…。もっとも、Python の乱数(Random)もMT法らしいので、書き方次第で前述のソース内の乱数生成器部分は丸々削除できるかもしれませんが。
[ ツッコむ ]
以上です。

