From 70e895692c67f8ba7144ee26315694bc98bd707e Mon Sep 17 00:00:00 2001 From: "Marcus Str." Date: Tue, 17 Dec 2024 17:21:55 +0100 Subject: [PATCH] Added resource generator class --- layergen.py | 9 --- resourcegen.py | 173 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 173 insertions(+), 9 deletions(-) create mode 100644 resourcegen.py diff --git a/layergen.py b/layergen.py index ff3dd65..9a34bee 100644 --- a/layergen.py +++ b/layergen.py @@ -292,15 +292,6 @@ class mstr_layergen: # Patch and border sources. There can only be one for each. brd_src = None ptc_src = [] - - # Find out if the generated image already exists. - # If not, both border and patch need to be generated first. - gensrc_ptc = mstr_datafolder + "_cache/_pool/ptc_" + self._tag + "_" + self._value + "_" - for s in range(len(src)): - gensrc_ptc = gensrc_ptc + str(src[s]) - if s < len(src) - 1: - gensrc_ptc = gensrc_ptc + "_" - gensrc_ptc = gensrc_ptc + ".png" # Find this layer's predetermined contrast lyr_contrast = self.findLayerContrast() diff --git a/resourcegen.py b/resourcegen.py new file mode 100644 index 0000000..41cd315 --- /dev/null +++ b/resourcegen.py @@ -0,0 +1,173 @@ + +# ------------------------------------------------------------------- +# ORTHOGRAPHIC +# Your personal aerial satellite. Always on. At any altitude.* +# Developed by MarStrMind +# License: Open Software License 3.0 +# Up to date version always on marstr.online +# ------------------------------------------------------------------- +# resourcegen.py +# Generates resources from existing material to provide much more +# variety than the fixed patch sources. +# +# We usually pass in 5 numbers, out of 15 possible images. This +# gives us a total of 3000+ possible combinations of images, per +# OSM tag. +# ------------------------------------------------------------------- + +import glob +import os +from random import randrange +import random +from PIL import Image, ImageFilter, ImageDraw, ImageChops, ImageEnhance +from defines import * +from log import * + +class mstr_resourcegen: + + def __init__(self, tag, value, sources): + self._sources = sources + self._tag = tag + self._value = value + self._contrast = 0 + + + # Sets the contrast from layergen + def setLayerContrast(self, contrast): + self._contrast = contrast + + + # This generates a resource from the given sources + # ResourceGen(tm) technology. Only in Orthographic. + def gensource(self): + + # The images to return + resources = [] + + # The array for the sources + sources = self._sources + + num_string = "" + for s in range(0, len(sources)): + num_string = num_string + str(sources[s]) + if s < len(sources) - 1: + num_string = num_string + "_" + + # File name + gensrc_fn = mstr_datafolder + "_cache/_pool/ptc_" + self._tag + "_" + self._value + "_" + num_string + ".png" + + # For equalizing + smlsize = 0 + + # Load the sources + src_img = [] + for s in range(0, len(sources)): + imgfn = mstr_datafolder + "textures/" + self._tag + "/" + self._value + "/" + str(sources[s]) + ".png" + img = Image.open(imgfn) + if smlsize == 0 or smlsize > img.width: + smlsize = img.width + src_img.append(img) + + # Generate a resource image + gensrc = Image.new("RGBA", (smlsize, smlsize)) + + # Pixel access + gensrc_p = gensrc.load() + + # Pixel access for the sources + src_pix = [] + for p in range(0, len(sources)): + src_pix.append(src_img[p].load()) + + # Generate the source + for y in range(0, gensrc.height): + for x in range(0, gensrc.width): + pdata = [] + for p in range(0, len(sources)): + pdata.append(src_pix[p][x,y]) + + # Calculate a pixel average + avg_r = 0 + avg_g = 0 + avg_b = 0 + avg_a = 0 + + for p in range(0, len(sources)): + avg_r = avg_r + pdata[p][0] + avg_g = avg_g + pdata[p][1] + avg_b = avg_b + pdata[p][2] + avg_a = avg_a + pdata[p][3] + + avg_r = int( (avg_r / len(sources)) * random.uniform(0.85, 1.01) ) + avg_g = int( (avg_g / len(sources)) * random.uniform(0.85, 1.01) ) + avg_b = int( (avg_b / len(sources)) * random.uniform(0.85, 1.01) ) + #avg_a = 255 + avg_a = int( (avg_a / len(sources)) * random.uniform(0.85, 1.01) ) + + pxcolor = (avg_r, avg_g, avg_b, avg_a) + + gensrc_p[x,y] = pxcolor + + + # Some features need a bit of contrast to make details visible + if ( + (self._tag == "landuse" and self._value == "forest") or + (self._tag == "landuse" and self._value == "meadow") or + (self._tag == "landuse" and self._value == "grass") or + (self._tag == "leisure" and self._value == "nature_reserve") or + (self._tag == "natural" and self._value == "grassland") or + (self._tag == "landuse" and self._value == "greenfield") or + (self._tag == "natural" and self._value == "heath") or + (self._tag == "natural" and self._value == "wetland") or + (self._tag == "leisure" and self._value == "park") or + (self._tag == "building") + ): + gensrc = ImageEnhance.Contrast(gensrc).enhance(self._contrast) + + + #gensrc.save(gensrc_fn) + resources.append(gensrc) + + + # We also need to generate a border for the source. For this to work, + # we first need to generate an image as we do in layergen + border = Image.new("RGBA", (mstr_photores, mstr_photores)) + + # Generate the source image + for p in range(1, 201): + rx = randrange(0-int(gensrc.width/2), border.width - int(gensrc.width/2)) + ry = randrange(0-int(gensrc.height/2), border.height - int(gensrc.height/2)) + border.alpha_composite(gensrc, dest=(rx, ry)) + + # Make it seamless + half_width = int(mstr_photores / 2) + half_height = int(mstr_photores / 2) + + img_shifted_x = ImageChops.offset(border, half_width, 0) # Shift horizontally + img_shifted_y = ImageChops.offset(border, 0, half_height) # Shift vertically + img_shifted_xy = ImageChops.offset(border, half_width, half_height) # Shift diagonally + + img_blend_x = Image.blend(border, img_shifted_x, alpha=0.5) + img_blend_y = Image.blend(img_blend_x, img_shifted_y, alpha=0.5) + img_blend = Image.blend(img_blend_y, img_shifted_xy, alpha=0.5) + + # Apply the mask + brdmsk = Image.open(mstr_datafolder + "textures/brdmsk.png") + smlpix = img_blend.load() + mskpix = brdmsk.load() + for y in range(0, img_blend.height): + for x in range(0, img_blend.width): + msk = mskpix[x,y] + sml = smlpix[x,y] + c = (sml[0], sml[1], sml[2], msk[3]) + smlpix[x,y] = c + + + # Save the border + resources.append(img_blend) + #img_blend.save(mstr_datafolder + "_cache/_pool/brd_" + self._tag + "_" + self._value + "_" + num_string + ".png") + + + # Provide the images + return resources +