]> marstr Code Repo - marstr/orthographic.git/commitdiff
Added resource generator class
authorMarcus Str. <marcus@marstr.online>
Tue, 17 Dec 2024 16:21:55 +0000 (17:21 +0100)
committerMarcus Str. <marcus@marstr.online>
Tue, 17 Dec 2024 16:21:55 +0000 (17:21 +0100)
layergen.py
resourcegen.py [new file with mode: 0644]

index ff3dd651b6ae75bde300db5a2ffbe939239374b4..9a34beebdfd8d3fcf3244dd2d5dc29c610ec87f7 100644 (file)
@@ -292,15 +292,6 @@ class mstr_layergen:
             # Patch and border sources. There can only be one for each.\r
             brd_src = None\r
             ptc_src = []\r
-            \r
-            # Find out if the generated image already exists.\r
-            # If not, both border and patch need to be generated first.\r
-            gensrc_ptc = mstr_datafolder + "_cache/_pool/ptc_" + self._tag + "_" + self._value + "_"\r
-            for s in range(len(src)):\r
-                gensrc_ptc = gensrc_ptc + str(src[s])\r
-                if s < len(src) - 1:\r
-                    gensrc_ptc = gensrc_ptc + "_"\r
-            gensrc_ptc = gensrc_ptc + ".png"\r
 \r
             # Find this layer's predetermined contrast\r
             lyr_contrast = self.findLayerContrast()\r
diff --git a/resourcegen.py b/resourcegen.py
new file mode 100644 (file)
index 0000000..41cd315
--- /dev/null
@@ -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
+