Commit c132fea6 authored by Muhamad's avatar Muhamad

Tiles Downloader

parent 621871b3
{
"cells": [
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"import json\n",
"import psycopg2\n",
"from config import config\n",
"from downtiles import *\n",
"\n",
"def get_tiles(provinsi='', tabel=''):\n",
" try:\n",
" filedownload = f\"{provinsi}/download/\"\n",
" fileresult = f\"{provinsi}/result/\"\n",
" fileoutput = f\"{provinsi}/output/\"\n",
" os.makedirs(os.path.dirname(filedownload), exist_ok=True)\n",
" os.makedirs(os.path.dirname(fileresult), exist_ok=True)\n",
" os.makedirs(os.path.dirname(fileoutput), exist_ok=True)\n",
" params = config()\n",
" conn = psycopg2.connect(**params)\n",
" cur = conn.cursor()\n",
" cur.execute(\"select ST_AsGeoJSON(geom :: geometry) from %s where name_1 ILIKE '%s'\" % (tabel, provinsi))\n",
" poly_prov = cur.fetchall()\n",
" poly = json.loads(poly_prov[0][0])\n",
" latlat = []\n",
" lnglng = []\n",
" for x in poly['coordinates']:\n",
" for lng, lat in x[0]:\n",
" latlat.append(lat)\n",
" lnglng.append(lng)\n",
" lat_max = max(float(sub) for sub in latlat)\n",
" lat_min = min(float(sub) for sub in latlat)\n",
" lng_max = max(float(sub) for sub in lnglng)\n",
" lng_min = min(float(sub) for sub in lnglng)\n",
"\n",
"\n",
" down_tiles(provinsi, lng_min, lng_max, lat_min, lat_max)\n",
" \n",
" # close communication with the PostgreSQL database server\n",
" cur.close()\n",
" # commit the changes\n",
" conn.commit()\n",
" except (Exception, psycopg2.DatabaseError) as error:\n",
" print(error)\n",
" finally:\n",
" if conn is not None:\n",
" conn.close()"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"206506,135568\n",
"206506,135569\n",
"206506,135570\n",
"206506,135571\n",
"206506,135572\n",
"206507,135568\n"
]
},
{
"ename": "KeyboardInterrupt",
"evalue": "",
"output_type": "error",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)",
"\u001b[1;32m<ipython-input-8-4e5b095ba0ae>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mget_tiles\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mprovinsi\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34m'lampung'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtabel\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34m'geo_kota1'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[1;32m<ipython-input-7-d3bf7565b051>\u001b[0m in \u001b[0;36mget_tiles\u001b[1;34m(provinsi, tabel)\u001b[0m\n\u001b[0;32m 31\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 32\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 33\u001b[1;33m \u001b[0mdown_tiles\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mprovinsi\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mlng_min\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mlng_max\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mlat_min\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mlat_max\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 34\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 35\u001b[0m \u001b[1;31m# close communication with the PostgreSQL database server\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;32mE:\\data NA\\downloader_tiles\\downtiles.py\u001b[0m in \u001b[0;36mdown_tiles\u001b[1;34m(nama_dir, long_min, long_max, lat_min, lat_max)\u001b[0m\n\u001b[0;32m 138\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0my\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mfloor\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0my_min\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m(\u001b[0m\u001b[0mfloor\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0my_max\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m+\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 139\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34mf\"{x},{y}\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 140\u001b[1;33m \u001b[0mpng_path\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mdownload_tile\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mx\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0my\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mzoom\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtile_server\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 141\u001b[0m \u001b[0mgeoreference_raster_tile\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mx\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0my\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mzoom\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mpng_path\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 142\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;32mE:\\data NA\\downloader_tiles\\downtiles.py\u001b[0m in \u001b[0;36mdownload_tile\u001b[1;34m(x, y, z, tile_server)\u001b[0m\n\u001b[0;32m 80\u001b[0m \"{z}\", str(z))\n\u001b[0;32m 81\u001b[0m \u001b[0mpath\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;34mf'{temp_dir}/{x}_{y}_{z}.png'\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 82\u001b[1;33m \u001b[0murllib\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mrequest\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0murlretrieve\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0murl\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mpath\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 83\u001b[0m \u001b[1;32mreturn\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mpath\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 84\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;32mc:\\users\\owi-khansia\\appdata\\local\\programs\\python\\python37\\lib\\urllib\\request.py\u001b[0m in \u001b[0;36murlretrieve\u001b[1;34m(url, filename, reporthook, data)\u001b[0m\n\u001b[0;32m 255\u001b[0m \u001b[1;31m# Handle temporary file setup.\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 256\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mfilename\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 257\u001b[1;33m \u001b[0mtfp\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mopen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mfilename\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'wb'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 258\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 259\u001b[0m \u001b[0mtfp\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mtempfile\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mNamedTemporaryFile\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mdelete\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mFalse\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;31mKeyboardInterrupt\u001b[0m: "
]
}
],
"source": [
"get_tiles(provinsi='lampung', tabel='geo_kota1')"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"^C\n"
]
}
],
"source": [
"!python download.py --provinsi=jawa_barat --db=NationalAdd --host=localhost --user=admin --password=admin123 --namatabel=geo_kota1"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.8"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
import psycopg2
from configparser import ConfigParser
def config(filename='database.ini', section='postgresql'):
# create a parser
parser = ConfigParser()
# read config file
parser.read(filename)
# get section, default to postgresql
db = {}
if parser.has_section(section):
params = parser.items(section)
for param in params:
db[param[0]] = param[1]
else:
raise Exception('Section {0} not found in the {1} file'.format(section, filename))
return db
def connect():
""" Connect to the PostgreSQL database server """
conn = None
try:
# read connection parameters
params = config()
# connect to the PostgreSQL server
print('Connecting to the PostgreSQL database...')
conn = psycopg2.connect(**params)
# create a cursor
cur = conn.cursor()
# execute a statement
print('PostgreSQL database version:')
cur.execute('SELECT version()')
# display the PostgreSQL database server version
db_version = cur.fetchone()
print(db_version)
# close the communication with the PostgreSQL
cur.close()
except (Exception, psycopg2.DatabaseError) as error:
print(error)
finally:
if conn is not None:
conn.close()
print('Database connection closed.')
if __name__ == '__main__':
connect()
\ No newline at end of file
Aceh
Bali
Bangka-Belitung
Banten
Bengkulu
Gorontalo
Irian_Jaya Barat
Jakarta_Raya
Jambi
Jawa_Barat
Jawa_Tengah
Jawa_Timur
Kalimantan_Barat
Kalimantan_Selatan
Kalimantan_Tengah
Kalimantan_Timur
Kalimantan_Utara
Kepulauan_Riau
Lampung
Maluku_Utara
Maluku
Nusa_Tenggara_Barat
Nusa_Tenggara_Timur
Papua
Riau
Sulawesi_Barat
Sulawesi_Selatan
Sulawesi_Tengah
Sulawesi_Tenggara
Sulawesi_Utara
Sumatera_Barat
Sumatera_Selatan
Sumatera_Utara
Yogyakarta
\ No newline at end of file
This diff is collapsed.
[postgresql]
host=localhost
database=NationalAdd
user=admin
password=admin123
\ No newline at end of file
import sys
import argparse
from argparse import RawTextHelpFormatter
from math import *
from urllib.request import Request, urlopen
from downtiles import *
import os
import json
import psycopg2
parser=argparse.ArgumentParser(prog="Download tiles CUK??", description="contoh : python download.py --provinsi=jawa_barat --db=nama_DB_mu --host=localhost --user=postgres --password=postgres", formatter_class=RawTextHelpFormatter)
required_named = parser.add_argument_group('required named arguments')
optional_named = parser.add_argument_group('optional named arguments')
required_named.add_argument('--provinsi', type=str, required=True, help='nama provinsi')
required_named.add_argument('--db', type=str, required=True, help='nama database kang')
required_named.add_argument('--user', type=str, required=True, help='user')
required_named.add_argument('--password', type=str, required=True, help='password')
required_named.add_argument('--host', type=str, required=True, help='host')
required_named.add_argument('--namatabel', type=str, required=True, help='nama tabel provinsi')
args=parser.parse_args()
conn = psycopg2.connect(database=args.db, user=args.user, password=args.password, host=args.host)
def main():
nama_prov = args.provinsi
try:
filedownload = f"{nama_prov}/download/"
fileresult = f"{nama_prov}/result/"
fileoutput = f"{nama_prov}/output/"
os.makedirs(os.path.dirname(filedownload), exist_ok=True)
os.makedirs(os.path.dirname(fileresult), exist_ok=True)
os.makedirs(os.path.dirname(fileoutput), exist_ok=True)
cur = conn.cursor()
nama_tabel = args.namatabel
cur.execute("select ST_AsGeoJSON(geom :: geometry) from %s where name_1 ILIKE '%s'" % (nama_tabel, nama_prov))
poly_prov = cur.fetchall()
poly = json.loads(poly_prov[0][0])
latlat = []
lnglng = []
for x in poly['coordinates']:
for lng, lat in x[0]:
latlat.append(lat)
lnglng.append(lng)
lat_max = max(float(sub) for sub in latlat)
lat_min = min(float(sub) for sub in latlat)
lng_max = max(float(sub) for sub in lnglng)
lng_min = min(float(sub) for sub in lnglng)
down_tiles(nama_prov, lng_min, lng_max, lat_min, lat_max)
# close communication with the PostgreSQL database server
cur.close()
# commit the changes
conn.commit()
except (Exception, psycopg2.DatabaseError) as error:
print(error)
finally:
if conn is not None:
conn.close()
if __name__ == '__main__':
main()
\ No newline at end of file
import math
import numpy as np
import urllib.request
import os
import glob
import subprocess
import shutil
# from tile_convert import bbox_to_xyz, tile_edges
from osgeo import gdal
from math import log, tan, radians, cos, pi, floor, degrees, atan, sinh
def down_tiles(nama_dir, long_min, long_max, lat_min, lat_max):
nama_desa = nama_dir
temp_dir = (f'{nama_desa}/download')
output_dir = (f'{nama_desa}/output')
zoom = 18
# [105.996093,-5.965754][106.083985,-6.053163]
lo_min = long_min
lo_max = long_max
la_min = lat_min
la_max = lat_max
for ln_min, ln_max in zip(np.arange(lo_min, lo_max,0.005493), np.arange(lo_min+0.005493, lo_max+0.005493, 0.005493)):
for lt_min, lt_max in zip(np.arange(la_min, la_max,0.005449), np.arange(la_min+0.005449, la_max+0.005449, 0.005449)):
lon_min = ln_min
lon_max = ln_max
lat_min = lt_min
lat_max = lt_max
tile_server = "https://api.mapbox.com/v4/mapbox.satellite/{z}/{x}/{y}.png?access_token=pk.eyJ1Ijoib3dlbCIsImEiOiJja2VsNjNxY3AwNng1MzNvOWs0N2U5aXA3In0.kobQj6R5JdlgV78glqjL2Q"
def sec(x):
return(1/cos(x))
def latlon_to_xyz(lat, lon, z):
tile_count = pow(2, z)
x = (lon + 180) / 360
y = (1 - log(tan(radians(lat)) + sec(radians(lat))) / pi) / 2
return(tile_count*x, tile_count*y)
def bbox_to_xyz(lon_min, lon_max, lat_min, lat_max, z):
x_min, y_max = latlon_to_xyz(lat_min, lon_min, z)
x_max, y_min = latlon_to_xyz(lat_max, lon_max, z)
return(floor(x_min), floor(x_max),
floor(y_min), floor(y_max))
def mercatorToLat(mercatorY):
return(degrees(atan(sinh(mercatorY))))
def y_to_lat_edges(y, z):
tile_count = pow(2, z)
unit = 1 / tile_count
relative_y1 = y * unit
relative_y2 = relative_y1 + unit
lat1 = mercatorToLat(pi * (1 - 2 * relative_y1))
lat2 = mercatorToLat(pi * (1 - 2 * relative_y2))
return(lat1, lat2)
def x_to_lon_edges(x, z):
tile_count = pow(2, z)
unit = 360 / tile_count
lon1 = -180 + x * unit
lon2 = lon1 + unit
return(lon1, lon2)
def tile_edges(x, y, z):
lat1, lat2 = y_to_lat_edges(y, z)
lon1, lon2 = x_to_lon_edges(x, z)
return[lon1, lat1, lon2, lat2]
def download_tile(x, y, z, tile_server):
url = tile_server.replace(
"{x}", str(x)).replace(
"{y}", str(y)).replace(
"{z}", str(z))
path = f'{temp_dir}/{x}_{y}_{z}.png'
urllib.request.urlretrieve(url, path)
return(path)
def merge_tiles(input_pattern, output_path):
merge_command = ['python.exe','gdal_merge.py', '-o', output_path]
for name in glob.glob(input_pattern):
merge_command.append(name)
subprocess.call(merge_command)
def georeference_raster_tile(x, y, z, path):
bounds = tile_edges(x, y, z)
filename, extension = os.path.splitext(path)
gdal.Translate(filename + '.png',
path,
outputSRS='EPSG:4326',
outputBounds=bounds)
def generateImage(self, **kwargs):
start_x = kwargs.get('start_x', None)
start_y = kwargs.get('start_y', None)
tile_width = kwargs.get('tile_width', 5)
tile_height = kwargs.get('tile_height', 5)
# Check that we have x and y tile coordinates
if start_x == None or start_y == None :
start_x, start_y = self.getXY()
# Determine the size of the image
width, height = 256 * tile_width, 256 * tile_height
#Create a new image of the size require
map_img = Image.new('RGB', (width,height))
for x in range(0, tile_width):
for y in range(0, tile_height) :
url = "https://api.mapbox.com/v4/mapbox.satellite/{z}/{x}/{y}.png?access_token=pk.eyJ1Ijoib3dlbCIsImEiOiJja2VsNjNxY3AwNng1MzNvOWs0N2U5aXA3In0.kobQj6R5JdlgV78glqjL2Q"
current_tile = str(x)+'-'+str(y)
urllib.request.urlretrieve(url, current_tile)
im = Image.open(current_tile)
map_img.paste(im, (x*256, y*256))
os.remove(current_tile)
return map_img
x_min, x_max, y_min, y_max = bbox_to_xyz(
lon_min, lon_max, lat_min, lat_max, zoom)
# print((floor(x_max)+1)-floor(x_min))
for x in range((floor(x_min)), (floor(x_max)) + 1):
for y in range((floor(y_min)), (floor(y_max)) + 1):
print(f"{x},{y}")
png_path = download_tile(x, y, zoom, tile_server)
georeference_raster_tile(x, y, zoom, png_path)
print("Download complete")
print("All Complete")
import math
def latlon2px(z,lat,lon):
x = 2**z*(lon+180)/360*256
y = -(.5*math.log((1+math.sin(math.radians(lat)))/(1-math.sin(math.radians(lat))))/math.pi-1)*256*2**(z-1)
return x,y
def latlon2xy(z,lat,lon):
x,y = latlon2px(z,lat,lon)
x = int(x/256)#,int(x%256)
y = int(y/256)#,int(y%256)
return x,y
from PIL import Image
import sys, os
def merge_down(nama_dir, lon_start, lon_stop, lat_stop, lat_start, satellite=True):
# merge_down(zoom, lat_max, lat_min, lon_min, lon_max, satellite=False)
# def merge_down(zoom, lat_start, lat_stop, lon_start, lon_stop, satellite=True):
nama_desa = nama_dir
zoom = 18
TYPE, ext = 'r', 'png'
if satellite:
TYPE, ext = 's', 'jpg'
x_start, y_start = latlon2xy(zoom, lat_start, lon_start)
x_stop, y_stop = latlon2xy(zoom, lat_stop, lon_stop)
w = (x_stop - x_start) * 256
h = (y_stop - y_start) * 256
print("width:", w)
print("height:", h)
result = Image.new("RGBA", (w, h))
for x in range(x_start, x_stop +1):
for y in range(y_start, y_stop +1):
filename = f"{nama_desa}/download/%d_%d_%d.png" % (x, y, zoom)
if not os.path.exists(filename):
continue
x_paste = (x - x_start) * 256
y_paste = h - (y_stop - y) * 256
try:
i = Image.open(filename)
except Exception as e:
print ("-- %s, removing %s" % (e, filename))
trash_dst = os.path.expanduser("~/.Trash/%s" % filename)
os.rename(filename, trash_dst)
continue
result.paste(i, (x_paste, y_paste))
del i
result.save(f"{nama_desa}/output/{nama_desa}.PNG")
def merge_res(wil, lon_start, lon_stop, lat_stop, lat_start, satellite=True):
nama_desa = wil
zoom = 18
TYPE, ext = 'r', 'png'
if satellite:
TYPE, ext = 's', 'jpg'
x_start, y_start = latlon2xy(zoom, lat_start, lon_start)
x_stop, y_stop = latlon2xy(zoom, lat_stop, lon_stop)
w = (x_stop - x_start) * 256
h = (y_stop - y_start) * 256
print("width:", w)
print("height:", h)
result = Image.new("RGBA", (w, h))
for x in range(x_start, x_stop +1):
for y in range(y_start, y_stop +1):
filename = f"{nama_desa}/result/%d_%d_%d.png" % (x, y, zoom)
if not os.path.exists(filename):
continue
x_paste = (x - x_start) * 256
y_paste = h - (y_stop - y) * 256
try:
i = Image.open(filename)
except Exception as e:
print ("-- %s, removing %s" % (e, filename))
trash_dst = os.path.expanduser("~/.Trash/%s" % filename)
os.rename(filename, trash_dst)
continue
result.paste(i, (x_paste, y_paste))
del i
result.save(f"{nama_desa}/output/result.PNG")
\ No newline at end of file
GDAL==3.1.3
glob2==0.7
jsonfield==3.1.0
jsonschema==3.2.0
psycopg2==2.8.5
urllib3==1.25.9
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment