Skip to content

Instantly share code, notes, and snippets.

@mieki256
Last active July 17, 2018 11:25
Show Gist options
  • Save mieki256/4bfa3c696f0e2029e812 to your computer and use it in GitHub Desktop.
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 で動作確認。
#!/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