Last active
July 17, 2018 11:25
-
-
Save mieki256/4bfa3c696f0e2029e812 to your computer and use it in GitHub Desktop.
Night Building Texture : GIMPで夜景のビルのテクスチャっぽい画像を生成するPython-fuスクリプト。GIMP (2.8.10|2.10.2) Portbale + Windows(7|10) x64 で動作確認。
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 | |
# -*- coding: utf-8 -*- | |
# -*- mode: python; Encoding: utf8n -*- | |
# Last updated: <2018/07/17 20:20:07 +0900> | |
""" | |
Make night building texture | |
Author ; mieki256 | |
License : CC0 / Public Domain | |
System Requirements : | |
* GIMP 2.8.10 Portable + Windows7 x64 | |
* GIMP 2.10.2 Portable + Windows10 x64 | |
usage: | |
1. make new image (ex. 512 x 512) | |
2. Filter -> Render -> Night Building Texture | |
""" | |
from gimpfu import * | |
from array import array | |
import random | |
def _get_lights(w, h, ratio, line_enable): | |
n = w * h | |
lights = [0] * n | |
vlist = [0, 32, 64, 96, 192, 255] | |
if line_enable: | |
for y in range(h): | |
v = random.random() | |
xbuf = [0] * w | |
if v < ratio: | |
for i, x in enumerate(range(w * 2 / 3)): | |
xbuf[i] = vlist[random.randint(0, len(vlist) - 1)] | |
random.shuffle(xbuf) | |
else: | |
xbuf = [0] * w | |
for x, v in enumerate(xbuf): | |
lights[y * w + x] = v | |
else: | |
cnt = int(n * ratio) / len(vlist) | |
for v in vlist: | |
for i in range(cnt): | |
x = random.randint(0, w - 1) | |
y = random.randint(0, h - 1) | |
lights[y * w + x] = v | |
return lights | |
def _get_one_block(w, h, light, p_size): | |
pixels = [] | |
if light <= 128: | |
for py in range(h): | |
cw = random.randint(0, 96 * py / h) | |
for px in range(w): | |
r = light + random.randint(0, cw) | |
if r < 0: | |
r = 0 | |
pixels.append((r, r, r)) | |
else: | |
for py in range(h): | |
cw = light * py / h | |
for px in range(w): | |
vv = light - random.randint(0, cw) | |
r = vv - random.randint(0, vv / 4) | |
g = vv - random.randint(0, vv / 4) | |
b = vv - random.randint(0, vv / 4) | |
pixels.append((r, g, b)) | |
return pixels | |
def python_night_building_texture(image, drawable, | |
gw = 64, gh = 64, | |
sw = 8, sh = 8, | |
ratio = 0.2, linefg = False, | |
newimage = True, newlayer = True, | |
glowlayer = False, glow_hue = 40, | |
margelayer = False): | |
width = gw * sw | |
height = gh * sh | |
# gimp.message("image size = %d x %d" % (width, height)) | |
if newimage == True or image == None: | |
# make new image | |
image = gimp.Image(width, height, RGB) | |
gimp.Display(image) | |
newlayer = True | |
if newlayer == False: | |
# get layer width and height | |
if drawable.width != width or drawable.height != height: | |
newlayer = True | |
if newlayer == True: | |
# make new layer | |
layer = gimp.Layer(image, "layer0", width, height, | |
RGBA_IMAGE, 100, NORMAL_MODE) | |
image.add_layer(layer, 0) | |
else: | |
layer = drawable | |
# gimp.message("layer size = %d x %d" % (layer.width, layer.height)) | |
# init prgress bar | |
gimp.progress_init("Make night building texture...") | |
# start undo push | |
pdb.gimp_undo_push_group_start(image) | |
# fill layer | |
gimp.set_foreground(0, 0, 0) # r, g, b | |
pdb.gimp_edit_fill(layer, FOREGROUND_FILL) | |
# get layer pixel data | |
src = layer.get_pixel_rgn(0, 0, width, height, False, False) | |
src_pixels = array("B", src[0:width, 0:height]) | |
dst = layer.get_pixel_rgn(0, 0, width, height, True, True) | |
p_size = len(src[0, 0]) | |
dst_pixels = array("B", "\x00" * (width * height * p_size)) | |
# copy src to dst | |
for y in range(height): | |
for x in range(width): | |
src_pos = (x + width * y) * p_size | |
dst_pos = src_pos | |
nv = src_pixels[src_pos : src_pos + p_size] | |
dst_pixels[dst_pos : dst_pos + p_size] = nv | |
gimp.progress_update(0.2 * y / height) | |
# get light list | |
lights = _get_lights(gw, gh, ratio, linefg) | |
# make block pattern | |
cnt = 0 | |
for gy in range(gh): | |
for gx in range(gw): | |
light_value = lights[cnt] # light : 0 - 255 | |
block_width = sw - 2 | |
block_height = sh - 2 | |
pixels = _get_one_block(block_width, block_height, light_value, p_size) | |
idx = 0 | |
for sy in range(block_height): | |
for sx in range(block_width): | |
r, g, b = pixels[idx] | |
idx += 1 | |
dx = gx * sw + 1 + sx | |
dy = gy * sh + 1 + sy | |
dst_pos = (dx + width * dy) * p_size | |
if p_size == 3: | |
# RGB | |
dst_pixels[dst_pos : dst_pos + p_size] = array("B", [r, g, b]) | |
elif p_size == 4: | |
# RGBA | |
dst_pixels[dst_pos : dst_pos + p_size] = array("B", [r, g, b, 255]) | |
else: | |
# GRAY | |
dst_pixels[dst_pos : dst_pos + p_size] = array("B", [r]) | |
cnt += 1 | |
gimp.progress_update(0.2 + (0.8 * gy / gh)) | |
dst[0:width, 0:height] = dst_pixels.tostring() | |
# layer update | |
layer.flush() | |
layer.merge_shadow(True) | |
layer.update(0, 0, width, height) | |
# end progress bar | |
pdb.gimp_progress_end() | |
# add glow layer | |
if glowlayer == True: | |
glow_layer = layer.copy() | |
image.add_layer(glow_layer, 0) | |
# gauss filter | |
pdb.plug_in_gauss(image, glow_layer, 20, 20, 0) | |
glow_layer.mode = ADDITION_MODE | |
# Brightness-Contrast ... drawable, brightness, contrast | |
pdb.gimp_brightness_contrast(layer, 30, 20) | |
# Colorize ... drawable, hue, saturation, lightness | |
pdb.gimp_colorize(glow_layer, glow_hue, 75, 0) | |
# merge down layer | |
if margelayer == True: | |
pdb.gimp_image_merge_down(image, glow_layer, EXPAND_AS_NECESSARY) | |
# end undo push | |
pdb.gimp_undo_push_group_end(image) | |
gimp.displays_flush() | |
return | |
register( | |
"python_fu_night_building_texture", | |
"Night Building Texture", | |
"Make Night Building Texture", | |
"mieki256", | |
"CC0 / Public domain", | |
"2018/07, 2015/06", | |
"Night Building Texture", | |
"RGB*", | |
[ | |
(PF_IMAGE, "image", "Input image", None), | |
(PF_DRAWABLE, "drawable", "Input drawable", None), | |
(PF_INT, "gw", "Grid count x", 64), | |
(PF_INT, "gh", "Grid count y", 64), | |
(PF_INT, "sw", "Grid size x", 8), | |
(PF_INT, "sh", "Grid size y", 8), | |
(PF_SLIDER, "ratio", "Ratio", 0.2, (0.01, 1.0, 0.01)), | |
(PF_TOGGLE, "linefg", "Line", False), | |
(PF_TOGGLE, "newimage", "New Image", True), | |
(PF_TOGGLE, "newlayer", "New Layer", True), | |
(PF_TOGGLE, "glowlayer", "Glow Layer", False), | |
(PF_SLIDER, "glowhue", "Glow Hue", 40, (0, 360, 1)), | |
(PF_TOGGLE, "margelayer", "Marge Layer", False), | |
], | |
[], | |
python_night_building_texture, | |
menu="<Image>/Filters/Render" | |
) | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment