Created
November 10, 2015 11:34
-
-
Save mieki256/bdbfc754f846e85828b7 to your computer and use it in GitHub Desktop.
fakeantijaggies2.py - アンチジャギのテスト
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- mode: python; Encoding: utf-8; coding: utf-8 -*- | |
# Last updated: <2015/11/10 02:24:47 +0900> | |
""" | |
fakeantijaggies2 | |
アンチジャギ、ジャギ消しの実験。 | |
layman, lrevise.c を移植。 | |
たぶん移植時に失敗して動作がバグってる予感。 | |
original 佐藤 正春 | |
移植 mieki256 | |
usage: | |
python fakeantijaggies2.py -i INPUT.png -o OUT.png | |
use: Python 2.7.10 + Pillow | |
""" | |
__version__ = '0.0.1' | |
from optparse import OptionParser, OptionValueError | |
from PIL import Image | |
import sys | |
import os | |
def c_set(img, x1, y1, x2, y2, f, dbgimg, dbgcol): | |
u""" | |
ドットを打つ。 | |
x1, y1 参照座標 | |
x2, y2 描画座標 | |
f 参照色割合 ( / 128) | |
dbgcol デバッグ用指定職 | |
""" | |
if not dbgimg is None: | |
dbgimg.putpixel((x2, y2), dbgcol) | |
# 割合が0以下なら何もしない | |
if f <= 0: | |
return | |
r0, g0, b0, a0 = img.getpixel((x1, y1)) | |
r1, g1, b1, a1 = img.getpixel((x2, y2)) | |
# 参照座標と描画座標が同じ色なら何もしない | |
if r0 == r1 and g0 == g1 and b0 == b1: | |
return | |
if f < 256: | |
# 割合が256未満なら描画すべきRGB値を求める | |
# 256以上なら参照座標のRGB値をそのまま使って描画 | |
r0 = ((r0 * f) + (r1 * (256 - f)) + 128) >> 8 | |
g0 = ((g0 * f) + (g1 * (256 - f)) + 128) >> 8 | |
b0 = ((b0 * f) + (b1 * (256 - f)) + 128) >> 8 | |
img.putpixel((x2, y2), (r0, g0, b0, a1)) | |
def set_pixels(img, x, y, up, left, down, right, sw, fuz, dbgimg): | |
u"""指定された座標から上下左右にグラデーションを描画""" | |
if not dbgimg is None: | |
print "x,y=(%d,%d) up,left,down,right=(%d,%d,%d,%d) sw=%d" % \ | |
(x, y, up, left, down, right, sw) | |
w, h = img.size | |
adj = 128 | |
# x0, y0 : 描画座標 dst | |
# x1, y1 : 参照座標 src | |
# 上方向に描画 | |
# O x -> S D x O -> D S | |
# x O x x O x x x | |
if not dbgimg is None: | |
dbgcol = (0, 0, 255, 255) | |
else: | |
dbgcol = None | |
if sw == 0: | |
x0, y0, x1, y1 = x + 1, y, x, y | |
else: | |
x0, y0, x1, y1 = x, y, x + 1, y | |
if up > 0: | |
# 複数のドットを打つ場合 | |
l1 = (up + 1) / 2 | |
if (y - l1 + 1) < 0: | |
l1 = y + 1 | |
if l1 < 4: | |
adj_tmp = adj - 16 # 式に根拠なし、と書いてあった | |
else: | |
adj_tmp = adj | |
i = 0 | |
while i <= l1: | |
f1 = adj_tmp - (adj_tmp * i / l1) | |
c_set(img, x1, y1, x0, y0, f1, dbgimg, dbgcol) | |
y0 -= 1 | |
i += 1 | |
elif up == 0: | |
# 1ドットだけ打つ場合 | |
c_set(img, x1, y1, x0, y0, adj / 2, dbgimg, dbgcol) | |
# 下方向に描画 | |
# O x -> x x x O -> x x | |
# x O D S O x S D | |
if not dbgimg is None: | |
dbgcol = (0, 255, 255, 255) | |
else: | |
dbgcol = None | |
if sw == 0: | |
x0, y0, x1, y1 = x, y + 1, x + 1, y + 1 | |
else: | |
x0, y0, x1, y1 = x + 1, y + 1, x, y + 1 | |
if down > 0: | |
l1 = (down + 1) / 2 | |
if (y + l1) > (h - 1): | |
l1 = (h - 1) - y | |
if l1 < 4: | |
adj_tmp = adj - 16 | |
else: | |
adj_tmp = adj | |
i = 0 | |
while i <= l1: | |
f1 = adj_tmp - (adj_tmp * i / l1) | |
c_set(img, x1, y1, x0, y0, f1, dbgimg, dbgcol) | |
y0 += 1 | |
i += 1 | |
elif down == 0: | |
c_set(img, x1, y1, x0, y0, adj / 2, dbgimg, dbgcol) | |
# 左方向に描画 | |
# O x -> S x x O -> D x | |
# x O D x O x S x | |
if not dbgimg is None: | |
dbgcol = (0, 255, 0, 255) | |
else: | |
dbgcol = None | |
if sw == 0: | |
x0, y0, x1, y1 = x, y + 1, x, y | |
else: | |
x0, y0, x1, y1 = x, y, x, y + 1 | |
if left > 0: | |
l1 = (left + 1) / 2 | |
if (x - l1 + 1) < 0: | |
l1 = x + 1 | |
if l1 < 4: | |
adj_tmp = adj - 16 | |
else: | |
adj_tmp = adj | |
i = 0 | |
while i <= l1: | |
f1 = adj_tmp - (adj_tmp * i / l1) | |
c_set(img, x1, y1, x0, y0, f1, dbgimg, dbgcol) | |
x0 -= 1 | |
i += 1 | |
elif left == 0: | |
# 上下描画ですでにドットが打たれてるはずなのでここでは何もしない | |
pass | |
# c_set(img, x1, y1, x0, y0, adj / 4, dbgimg, dbgcol) | |
# 右方向に描画 | |
# O x -> x D x O -> x S | |
# x O x S O x x D | |
if not dbgimg is None: | |
dbgcol = (255, 0, 255, 255) | |
else: | |
dbgcol = None | |
if sw == 0: | |
x0, y0, x1, y1 = x + 1, y, x + 1, y + 1 | |
else: | |
x0, y0, x1, y1 = x + 1, y + 1, x + 1, y | |
if right > 0: | |
l1 = (right + 1) / 2 | |
if (x + l1) > (w - 1): | |
l1 = (w - 1) - x | |
if l1 < 4: | |
adj_tmp = adj - 16 | |
else: | |
adj_tmp = adj | |
i = 0 | |
while i <= l1: | |
f1 = adj_tmp - (adj_tmp * i / l1) | |
c_set(img, x1, y1, x0, y0, f1, dbgimg, dbgcol) | |
x0 += 1 | |
i += 1 | |
elif right == 0: | |
pass | |
# c_set(img, x1, y1, x0, y0, adj / 4, dbgimg, dbgcol) | |
def judge(img, x, y, sw, fuz, dbgimg): | |
u"""上下左右に連続部分がないか調べる。 | |
sw = 0 なら右肩下がり | |
sw = 1 なら右肩上がり | |
""" | |
up, down, left, right = -1, -1, -1, -1 | |
w, h = img.size | |
# 上方向に境界がどれだけ伸びているか調べる | |
if sw == 0: | |
x0, y0, x1, y1 = x, y, x + 1, y | |
else: | |
x0, y0, x1, y1 = x + 1, y, x, y | |
if not pix_equal(img, x0, y0, x1, y1, fuz): | |
# 隣の色が違うので境界部分 | |
up = 0 | |
m = 0 | |
i = y - 1 | |
while i >= 0: | |
m += 1 | |
if pix_equal(img, x0, y0, x0, y0 - m, fuz) \ | |
and not pix_equal(img, x0, y0, x1, y1 - m, fuz): | |
# 境界が続いている | |
up += 1 | |
else: | |
break | |
i -= 1 | |
# 左方向に境界がどれだけ伸びているか調べる | |
if sw == 0: | |
x0, y0, x1, y1 = x, y, x, y + 1 | |
else: | |
x0, y0, x1, y1 = x, y + 1, x, y | |
if not pix_equal(img, x0, y0, x1, y1, fuz): | |
# 上下の色が違うので境界部分 | |
left = 0 | |
m = 0 | |
i = x - 1 | |
while i >= 0: | |
m += 1 | |
if pix_equal(img, x0, y0, x0 - m, y0, fuz) \ | |
and not pix_equal(img, x0, y0, x1 - m, y1, fuz): | |
left += 1 | |
else: | |
break | |
i -= 1 | |
# 下方向に境界がどれだけ伸びているか調べる | |
if sw == 0: | |
x0, y0, x1, y1 = x + 1, y + 1, x, y + 1 | |
else: | |
x0, y0, x1, y1 = x, y + 1, x + 1, y + 1 | |
if not pix_equal(img, x0, y0, x1, y1, fuz): | |
# 隣の色が違うので境界部分 | |
down = 0 | |
m = 0 | |
i = y + 2 | |
while i <= h - 1: | |
m += 1 | |
if pix_equal(img, x0, y0, x0, y0 + m, fuz) \ | |
and not pix_equal(img, x0, y0, x1, y1 + m, fuz): | |
# 境界が続いている | |
down += 1 | |
else: | |
break | |
i += 1 | |
# 右方向に境界がどれだけ伸びているか調べる | |
if sw == 0: | |
x0, y0, x1, y1 = x + 1, y + 1, x + 1, y | |
else: | |
x0, y0, x1, y1 = x + 1, y, x + 1, y + 1 | |
if not pix_equal(img, x0, y0, x1, y1, fuz): | |
# 上下の色が違うので境界部分 | |
right = 0 | |
m = 0 | |
i = x + 2 | |
while i <= w - 1: | |
m += 1 | |
if pix_equal(img, x0, y0, x0 + m, y0, fuz) \ | |
and not pix_equal(img, x0, y0, x1 + m, y1, fuz): | |
right += 1 | |
else: | |
break | |
i += 1 | |
# グラデーションで塗る | |
if up >= 0 or left >= 0 or down >= 0 or right >= 0: | |
set_pixels(img, x, y, up, left, down, right, sw, fuz, dbgimg) | |
def pix_equal(img, x0, y0, x1, y1, fuz): | |
u"""指定座標の色を比較して結果をTrue/Falseで返す""" | |
r0, g0, b0, a0 = img.getpixel((x0, y0)) | |
r1, g1, b1, a1 = img.getpixel((x1, y1)) | |
if int(r0 / fuz) != int(r1 / fuz) \ | |
or int(g0 / fuz) != int(g1 / fuz) \ | |
or int(b0 / fuz) != int(b1 / fuz): | |
return False | |
return True | |
def main(imgfile, outfile, count, tcolor, fuz, debug): | |
# 画像を開く | |
img = Image.open(imgfile) | |
if img.mode != "RGBA": | |
img = img.convert("RGBA") | |
w, h = img.size | |
if debug: | |
dbgimg = Image.new("RGBA", (w, h)) | |
else: | |
dbgimg = None | |
# 指定色で透明化 | |
if tcolor is not None: | |
ttr, ttg, ttb = tcolor # transparent color | |
for y in xrange(h): | |
for x in xrange(w): | |
r, g, b, a = img.getpixel((x, y)) | |
if r == ttr and g == ttg and b == ttb: | |
img.putpixel((x, y), (0, 0, 0, 0)) | |
# ジャギ消し | |
for i in xrange(count): | |
for y in xrange(h - 1): | |
for x in xrange(w - 1): | |
# 2x2ドットが同色なら何もしない | |
if pix_equal(img, x, y, x + 1, y + 1, fuz) \ | |
and pix_equal(img, x + 1, y, x, y + 1, fuz) \ | |
and pix_equal(img, x, y, x, y + 1, fuz): | |
continue | |
# 右肩下がりで同色か | |
if pix_equal(img, x, y, x + 1, y + 1, fuz): | |
judge(img, x, y, 0, fuz, dbgimg) | |
# 右肩上がりで同色か | |
if pix_equal(img, x + 1, y, x, y + 1, fuz): | |
judge(img, x, y, 1, fuz, dbgimg) | |
img.save(outfile) | |
if debug: | |
root, ext = os.path.splitext(outfile) | |
dbgfile = "%s_dbg%s" % (root, ext) | |
dbgimg.save(dbgfile) | |
if __name__ == '__main__': | |
# コマンドラインオプションを判別 | |
p = OptionParser(version=__version__) | |
p.add_option( | |
"-i", "--input", dest="imgfile", default=None, help="Input image file") | |
p.add_option( | |
"-o", "--output", dest="outfile", default=None, help="Output image file") | |
p.add_option( | |
"-c", "--count", type="int", dest="count", default=1, help="Count") | |
p.add_option( | |
"-f", type="int", dest="factor", default=4, help="Factor [4]") | |
p.add_option("-n", "--nottransparent", action="store_false", | |
dest="tp_fg", help="disable transparent") | |
p.add_option("-t", "--transparentcolor", dest="tcolor", | |
default="255,255,255", help="transparent color [255,255,255]") | |
p.add_option("--debug", action="store_true", default=False, help="debug") | |
opts, args = p.parse_args() | |
if opts.imgfile is None: | |
# 画像ファイルが指定されてないので、ヘルプを表示して終了 | |
p.error("require Input image file") | |
p.print_help() | |
sys.exit | |
elif opts.outfile is None: | |
# 出力ファイルが指定されてないので生成 | |
root, ext = os.path.splitext(opts.imgfile) | |
opts.outfile = "%s_new%s" % (root, ext) | |
if opts.tp_fg is False: | |
# 透明化をしない | |
tcol = None | |
else: | |
# 透明化したい指定色を取り出す | |
a = opts.tcolor.split(",") | |
tcol = (int(a[0]), int(a[1]), int(a[2])) | |
main(opts.imgfile, opts.outfile, opts.count, tcol, opts.factor, opts.debug) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment