Significant updates.
This commit is contained in:
parent
e053713e4f
commit
d649be2de5
1 changed files with 179 additions and 136 deletions
311
pixelcanvas.py
311
pixelcanvas.py
|
@ -69,100 +69,25 @@ BIGCHUNK_SIZE_BYTES = int(BIGCHUNK_SIZE_PIX * (BIGCHUNK_SIZE_PIX / 2))
|
||||||
ORIGIN_OFFSET_X = 448
|
ORIGIN_OFFSET_X = 448
|
||||||
ORIGIN_OFFSET_Y = 448
|
ORIGIN_OFFSET_Y = 448
|
||||||
|
|
||||||
|
DB_INIT = '''
|
||||||
|
BEGIN;
|
||||||
|
CREATE TABLE IF NOT EXISTS chunks (x INT, y INT, data BLOB, updated_at REAL);
|
||||||
|
CREATE INDEX IF NOT EXISTS chunks_x_y ON chunks(x, y);
|
||||||
|
COMMIT;
|
||||||
|
'''
|
||||||
|
|
||||||
sql = sqlite3.connect('pixelcanvas.db')
|
sql = sqlite3.connect('pixelcanvas.db')
|
||||||
cur = sql.cursor()
|
cur = sql.cursor()
|
||||||
cur.execute('CREATE TABLE IF NOT EXISTS chunks (x INT, y INT, data BLOB, updated_at REAL)')
|
cur.executescript(DB_INIT)
|
||||||
cur.execute('CREATE INDEX IF NOT EXISTS chunks_x_y ON chunks(x, y)')
|
|
||||||
|
|
||||||
|
|
||||||
DOCSTRING = '''
|
|
||||||
This tool is run from the command line, where you provide the coordinates you
|
|
||||||
want to download and render.
|
|
||||||
|
|
||||||
The format for typing coordinates is `UPPERLEFT--LOWERRIGHT`. The format for
|
|
||||||
each of those pieces is `X.Y`.
|
|
||||||
|
|
||||||
Sometimes, argparse gets confused by negative coordinates because it thinks
|
|
||||||
you're trying to provide another argument. Sorry.
|
|
||||||
If this happens, use a tilde `~` as the negative sign instead.
|
|
||||||
|
|
||||||
Remember, because this is an image, up and left are negative;
|
|
||||||
down and right are positive.
|
|
||||||
|
|
||||||
Commands:
|
|
||||||
{update}
|
|
||||||
{render}
|
|
||||||
|
|
||||||
So, for example:
|
|
||||||
|
|
||||||
> pixelcanvas.py update 0.0--100.100
|
|
||||||
> pixelcanvas.py update ~100.~100--100.100
|
|
||||||
> pixelcanvas.py update ~1200.300--~900.600
|
|
||||||
|
|
||||||
> pixelcanvas.py render 0.0--100.100
|
|
||||||
> pixelcanvas.py render ~100.~100--100.100 --update
|
|
||||||
> pixelcanvas.py render ~1200.300--~900.600 --show
|
|
||||||
'''
|
|
||||||
|
|
||||||
MODULE_DOCSTRINGS = {
|
|
||||||
'update': '''
|
|
||||||
update:
|
|
||||||
Download chunks into the database.
|
|
||||||
|
|
||||||
> pixelcanvas.py update ~100.~100--100.100
|
|
||||||
''',
|
|
||||||
|
|
||||||
'render': '''
|
|
||||||
render:
|
|
||||||
Export an image as PNG.
|
|
||||||
|
|
||||||
> pixelcanvas.py render 0.0--100.100 <flags>
|
|
||||||
|
|
||||||
flags:
|
|
||||||
--scale <float>:
|
|
||||||
Render the image at a different scale.
|
|
||||||
For best results, use powers of 2 like 0.5, 0.25, etc.
|
|
||||||
This will disable the autocropping.
|
|
||||||
|
|
||||||
--show:
|
|
||||||
Instead of saving the image, display it on the screen.
|
|
||||||
https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.show
|
|
||||||
|
|
||||||
--update:
|
|
||||||
Update the chunks before exporting them.
|
|
||||||
'''
|
|
||||||
}
|
|
||||||
|
|
||||||
def docstring_preview(text):
|
|
||||||
'''
|
|
||||||
Return the brief description at the top of the text.
|
|
||||||
User can get full text by looking at each specifically.
|
|
||||||
'''
|
|
||||||
return text.split('\n\n')[0]
|
|
||||||
|
|
||||||
def listget(li, index, fallback=None):
|
|
||||||
try:
|
|
||||||
return li[index]
|
|
||||||
except IndexError:
|
|
||||||
return fallback
|
|
||||||
|
|
||||||
def indent(text, spaces=4):
|
|
||||||
spaces = ' ' * spaces
|
|
||||||
return '\n'.join(spaces + line if line.strip() != '' else line for line in text.split('\n'))
|
|
||||||
|
|
||||||
docstring_headers = {
|
|
||||||
key: indent(docstring_preview(value))
|
|
||||||
for (key, value) in MODULE_DOCSTRINGS.items()
|
|
||||||
}
|
|
||||||
|
|
||||||
DOCSTRING = DOCSTRING.format(**docstring_headers)
|
|
||||||
|
|
||||||
|
|
||||||
####################################################################################################
|
|
||||||
##================================================================================================##
|
|
||||||
####################################################################################################
|
|
||||||
|
|
||||||
|
# HELPER FUNCTIONS
|
||||||
|
################################################################################
|
||||||
|
def now():
|
||||||
|
n = datetime.datetime.now(datetime.timezone.utc)
|
||||||
|
return n.timestamp()
|
||||||
|
|
||||||
|
# DB FUNCTIONS
|
||||||
|
################################################################################
|
||||||
def get_chunk_from_db(chunk_x, chunk_y):
|
def get_chunk_from_db(chunk_x, chunk_y):
|
||||||
'''
|
'''
|
||||||
Get the chunk from the database, and raise IndexError if it doesn't exist.
|
Get the chunk from the database, and raise IndexError if it doesn't exist.
|
||||||
|
@ -177,7 +102,7 @@ def get_chunk_from_db(chunk_x, chunk_y):
|
||||||
cur.execute(query, bindings)
|
cur.execute(query, bindings)
|
||||||
fetch = cur.fetchone()
|
fetch = cur.fetchone()
|
||||||
if fetch is None:
|
if fetch is None:
|
||||||
raise IndexError
|
raise IndexError(f'{chunk_x}, {chunk_y}')
|
||||||
(x, y, data) = fetch
|
(x, y, data) = fetch
|
||||||
data = gzip.decompress(data)
|
data = gzip.decompress(data)
|
||||||
return (x, y, data)
|
return (x, y, data)
|
||||||
|
@ -207,14 +132,23 @@ def insert_chunk(chunk_x, chunk_y, data, commit=True):
|
||||||
if commit:
|
if commit:
|
||||||
sql.commit()
|
sql.commit()
|
||||||
|
|
||||||
|
# API FUNCTIONS
|
||||||
|
################################################################################
|
||||||
|
def url_for_bigchunk(bigchunk_x, bigchunk_y):
|
||||||
|
return f'http://api.pixelcanvas.io/api/bigchunk/{bigchunk_x}.{bigchunk_y}.bmp'
|
||||||
|
|
||||||
|
def request(url):
|
||||||
|
response = requests.get(url)
|
||||||
|
response.raise_for_status()
|
||||||
|
return response
|
||||||
|
|
||||||
def download_bigchunk(bigchunk_x, bigchunk_y):
|
def download_bigchunk(bigchunk_x, bigchunk_y):
|
||||||
'''
|
'''
|
||||||
Download a bigchunk into the database, and return the list of chunks.
|
Download a bigchunk into the database, and return the list of chunks.
|
||||||
'''
|
'''
|
||||||
url = url_for_bigchunk(bigchunk_x, bigchunk_y)
|
url = url_for_bigchunk(bigchunk_x, bigchunk_y)
|
||||||
logging.info('Downloading %s', url)
|
logging.info('Downloading %s', url)
|
||||||
response = requests.get(url)
|
response = request(url)
|
||||||
response.raise_for_status()
|
|
||||||
bigchunk_data = response.content
|
bigchunk_data = response.content
|
||||||
if len(bigchunk_data) != BIGCHUNK_SIZE_BYTES:
|
if len(bigchunk_data) != BIGCHUNK_SIZE_BYTES:
|
||||||
message = 'Received bigchunk does not matched the expected byte size!\n'
|
message = 'Received bigchunk does not matched the expected byte size!\n'
|
||||||
|
@ -228,7 +162,8 @@ def download_bigchunk(bigchunk_x, bigchunk_y):
|
||||||
|
|
||||||
def download_bigchunk_range(bigchunk_xy1, bigchunk_xy2):
|
def download_bigchunk_range(bigchunk_xy1, bigchunk_xy2):
|
||||||
'''
|
'''
|
||||||
Download multiple bigchunks, and return the total list of chunks.
|
Given (UPPERLEFT_X, UPPERLEFT_Y), (LOWERRIGHT_X, LOWERRIGHT_Y),
|
||||||
|
download multiple bigchunks, and return the total list of small chunks.
|
||||||
'''
|
'''
|
||||||
chunks = []
|
chunks = []
|
||||||
for (x, y) in bigchunk_range_iterator(bigchunk_xy1, bigchunk_xy2):
|
for (x, y) in bigchunk_range_iterator(bigchunk_xy1, bigchunk_xy2):
|
||||||
|
@ -236,16 +171,12 @@ def download_bigchunk_range(bigchunk_xy1, bigchunk_xy2):
|
||||||
chunks.extend(bigchunk)
|
chunks.extend(bigchunk)
|
||||||
return chunks
|
return chunks
|
||||||
|
|
||||||
def url_for_bigchunk(bigchunk_x, bigchunk_y):
|
# CHUNK FUNCTIONS
|
||||||
return f'http://pixelcanvas.io/api/bigchunk/{bigchunk_x}.{bigchunk_y}.bmp'
|
################################################################################
|
||||||
|
|
||||||
def now():
|
|
||||||
n = datetime.datetime.now(datetime.timezone.utc)
|
|
||||||
return n.timestamp()
|
|
||||||
|
|
||||||
def chunk_range_iterator(chunk_xy1, chunk_xy2):
|
def chunk_range_iterator(chunk_xy1, chunk_xy2):
|
||||||
'''
|
'''
|
||||||
Yield (x, y) pairs for chunks in this range, inclusive.
|
Given (UPPERLEFT_X, UPPERLEFT_Y), (LOWERRIGHT_X, LOWERRIGHT_Y),
|
||||||
|
yield (x, y) pairs for chunks in this range, inclusive.
|
||||||
'''
|
'''
|
||||||
for x in range(chunk_xy1[0], chunk_xy2[0] + 1):
|
for x in range(chunk_xy1[0], chunk_xy2[0] + 1):
|
||||||
for y in range(chunk_xy1[1], chunk_xy2[1] + 1):
|
for y in range(chunk_xy1[1], chunk_xy2[1] + 1):
|
||||||
|
@ -253,7 +184,8 @@ def chunk_range_iterator(chunk_xy1, chunk_xy2):
|
||||||
|
|
||||||
def bigchunk_range_iterator(bigchunk_xy1, bigchunk_xy2):
|
def bigchunk_range_iterator(bigchunk_xy1, bigchunk_xy2):
|
||||||
'''
|
'''
|
||||||
Yield (x, y) pairs for bigchunks in this range, inclusive.
|
Given (UPPERLEFT_X, UPPERLEFT_Y), (LOWERRIGHT_X, LOWERRIGHT_Y),
|
||||||
|
yield (x, y) pairs for bigchunks in this range, inclusive.
|
||||||
'''
|
'''
|
||||||
for x in range(bigchunk_xy1[0], bigchunk_xy2[0] + BIGCHUNK_SIZE_CHUNKS, BIGCHUNK_SIZE_CHUNKS):
|
for x in range(bigchunk_xy1[0], bigchunk_xy2[0] + BIGCHUNK_SIZE_CHUNKS, BIGCHUNK_SIZE_CHUNKS):
|
||||||
for y in range(bigchunk_xy1[1], bigchunk_xy2[1] + BIGCHUNK_SIZE_CHUNKS, BIGCHUNK_SIZE_CHUNKS):
|
for y in range(bigchunk_xy1[1], bigchunk_xy2[1] + BIGCHUNK_SIZE_CHUNKS, BIGCHUNK_SIZE_CHUNKS):
|
||||||
|
@ -265,12 +197,20 @@ def chunk_to_bigchunk(chunk_x, chunk_y):
|
||||||
# log.debug('Converted chunk %s, %s to bigchunk %s, %s', chunk_x, chunk_y, bigchunk_x, bigchunk_y)
|
# log.debug('Converted chunk %s, %s to bigchunk %s, %s', chunk_x, chunk_y, bigchunk_x, bigchunk_y)
|
||||||
return (bigchunk_x, bigchunk_y)
|
return (bigchunk_x, bigchunk_y)
|
||||||
|
|
||||||
|
def chunk_range_to_bigchunk_range(chunk_xy1, chunk_xy2):
|
||||||
|
bigchunk_range = (chunk_to_bigchunk(*chunk_xy1), chunk_to_bigchunk(*chunk_xy2))
|
||||||
|
return bigchunk_range
|
||||||
|
|
||||||
def chunk_to_pixel(chunk_x, chunk_y):
|
def chunk_to_pixel(chunk_x, chunk_y):
|
||||||
pixel_x = chunk_x * CHUNK_SIZE_PIX - ORIGIN_OFFSET_X
|
pixel_x = chunk_x * CHUNK_SIZE_PIX - ORIGIN_OFFSET_X
|
||||||
pixel_y = chunk_y * CHUNK_SIZE_PIX - ORIGIN_OFFSET_Y
|
pixel_y = chunk_y * CHUNK_SIZE_PIX - ORIGIN_OFFSET_Y
|
||||||
# log.debug('Converted chunk %s, %s to pixel %s, %s', chunk_x, chunk_y, pixel_x, pixel_y)
|
# log.debug('Converted chunk %s, %s to pixel %s, %s', chunk_x, chunk_y, pixel_x, pixel_y)
|
||||||
return (pixel_x, pixel_y)
|
return (pixel_x, pixel_y)
|
||||||
|
|
||||||
|
def chunk_range_to_pixel_range(chunk_xy1, chunk_xy2):
|
||||||
|
pixel_range = (chunk_to_pixel(*chunk_xy1), chunk_to_pixel(*chunk_xy2))
|
||||||
|
return pixel_range
|
||||||
|
|
||||||
def pixel_to_chunk(pixel_x, pixel_y):
|
def pixel_to_chunk(pixel_x, pixel_y):
|
||||||
chunk_x = (pixel_x + ORIGIN_OFFSET_X) // CHUNK_SIZE_PIX
|
chunk_x = (pixel_x + ORIGIN_OFFSET_X) // CHUNK_SIZE_PIX
|
||||||
chunk_y = (pixel_y + ORIGIN_OFFSET_Y) // CHUNK_SIZE_PIX
|
chunk_y = (pixel_y + ORIGIN_OFFSET_Y) // CHUNK_SIZE_PIX
|
||||||
|
@ -279,7 +219,7 @@ def pixel_to_chunk(pixel_x, pixel_y):
|
||||||
|
|
||||||
def pixel_range_to_chunk_range(pixel_xy1, pixel_xy2):
|
def pixel_range_to_chunk_range(pixel_xy1, pixel_xy2):
|
||||||
chunk_range = (pixel_to_chunk(*pixel_xy1), pixel_to_chunk(*pixel_xy2))
|
chunk_range = (pixel_to_chunk(*pixel_xy1), pixel_to_chunk(*pixel_xy2))
|
||||||
log.debug('Converted pixel range %s, %s to chunk range %s, %s', pixel_xy1, pixel_xy2, *chunk_range)
|
# log.debug('Converted pixel range %s, %s to chunk range %s, %s', pixel_xy1, pixel_xy2, *chunk_range)
|
||||||
return chunk_range
|
return chunk_range
|
||||||
|
|
||||||
def pixel_to_bigchunk(pixel_x, pixel_y):
|
def pixel_to_bigchunk(pixel_x, pixel_y):
|
||||||
|
@ -290,7 +230,7 @@ def pixel_to_bigchunk(pixel_x, pixel_y):
|
||||||
|
|
||||||
def pixel_range_to_bigchunk_range(pixel_xy1, pixel_xy2):
|
def pixel_range_to_bigchunk_range(pixel_xy1, pixel_xy2):
|
||||||
bigchunk_range = (pixel_to_bigchunk(*pixel_xy1), pixel_to_bigchunk(*pixel_xy2))
|
bigchunk_range = (pixel_to_bigchunk(*pixel_xy1), pixel_to_bigchunk(*pixel_xy2))
|
||||||
log.debug('Converted pixel range %s, %s to bigchunk range %s, %s', pixel_xy1, pixel_xy2, *bigchunk_range)
|
# log.debug('Converted pixel range %s, %s to bigchunk range %s, %s', pixel_xy1, pixel_xy2, *bigchunk_range)
|
||||||
return bigchunk_range
|
return bigchunk_range
|
||||||
|
|
||||||
def split_bigchunk(bigchunk_x, bigchunk_y, bigchunk_data):
|
def split_bigchunk(bigchunk_x, bigchunk_y, bigchunk_data):
|
||||||
|
@ -320,6 +260,8 @@ def split_bigchunk(bigchunk_x, bigchunk_y, bigchunk_data):
|
||||||
chunks.append(chunk)
|
chunks.append(chunk)
|
||||||
return chunks
|
return chunks
|
||||||
|
|
||||||
|
# IMAGE FUNCTIONS
|
||||||
|
################################################################################
|
||||||
def chunk_to_rgb(chunk_data):
|
def chunk_to_rgb(chunk_data):
|
||||||
'''
|
'''
|
||||||
Convert the data chunk into RGB tuples.
|
Convert the data chunk into RGB tuples.
|
||||||
|
@ -395,11 +337,85 @@ def crop_image(image, pixel_xy1, pixel_xy2):
|
||||||
image = image.crop(bbox)
|
image = image.crop(bbox)
|
||||||
return image
|
return image
|
||||||
|
|
||||||
|
# COMMAND LINE
|
||||||
|
################################################################################
|
||||||
|
from voussoirkit import betterhelp
|
||||||
|
|
||||||
####################################################################################################
|
DOCSTRING = '''
|
||||||
##================================================================================================##
|
This tool is run from the command line, where you provide the coordinates you
|
||||||
####################################################################################################
|
want to download and render.
|
||||||
|
|
||||||
|
The format for typing coordinates is `UPPERLEFT--LOWERRIGHT`. The format for
|
||||||
|
each of those pieces is `X.Y`.
|
||||||
|
|
||||||
|
Sometimes, argparse gets confused by negative coordinates because it thinks
|
||||||
|
you're trying to provide another argument. Sorry.
|
||||||
|
If this happens, use a tilde `~` as the negative sign instead.
|
||||||
|
|
||||||
|
Remember, because this is an image, up and left are negative;
|
||||||
|
down and right are positive.
|
||||||
|
|
||||||
|
Commands:
|
||||||
|
|
||||||
|
{update}
|
||||||
|
|
||||||
|
{render}
|
||||||
|
|
||||||
|
So, for example:
|
||||||
|
|
||||||
|
> pixelcanvas.py update 0.0--100.100
|
||||||
|
> pixelcanvas.py update ~100.~100--100.100
|
||||||
|
> pixelcanvas.py update ~1200.300--~900.600
|
||||||
|
|
||||||
|
> pixelcanvas.py render 0.0--100.100
|
||||||
|
> pixelcanvas.py render ~100.~100--100.100 --update
|
||||||
|
> pixelcanvas.py render ~1200.300--~900.600 --show
|
||||||
|
'''
|
||||||
|
|
||||||
|
SUB_DOCSTRINGS = dict(
|
||||||
|
overview='''
|
||||||
|
overview:
|
||||||
|
Draw an ascii map representing the owned chunks.
|
||||||
|
'''.strip(),
|
||||||
|
|
||||||
|
update='''
|
||||||
|
update:
|
||||||
|
Download chunks into the database.
|
||||||
|
|
||||||
|
> pixelcanvas.py update ~100.~100--100.100
|
||||||
|
|
||||||
|
flags:
|
||||||
|
--chunks:
|
||||||
|
The coordinates which you provided are chunk coordinates instead of
|
||||||
|
pixel coordinates.
|
||||||
|
'''.strip(),
|
||||||
|
|
||||||
|
render='''
|
||||||
|
render:
|
||||||
|
Export an image as PNG.
|
||||||
|
|
||||||
|
> pixelcanvas.py render 0.0--100.100 <flags>
|
||||||
|
|
||||||
|
flags:
|
||||||
|
--chunks:
|
||||||
|
The coordinates which you provided are chunk coordinates instead of
|
||||||
|
pixel coordinates.
|
||||||
|
|
||||||
|
--scale <float>:
|
||||||
|
Render the image at a different scale.
|
||||||
|
For best results, use powers of 2 like 0.5, 0.25, etc.
|
||||||
|
This will disable the autocropping.
|
||||||
|
|
||||||
|
--show:
|
||||||
|
Instead of saving the image, display it on the screen.
|
||||||
|
https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.show
|
||||||
|
|
||||||
|
--update:
|
||||||
|
Update the chunks before exporting them.
|
||||||
|
'''.strip(),
|
||||||
|
)
|
||||||
|
|
||||||
|
DOCSTRING = betterhelp.add_previews(DOCSTRING, SUB_DOCSTRINGS)
|
||||||
|
|
||||||
def parse_coordinate_string(coordinates):
|
def parse_coordinate_string(coordinates):
|
||||||
'''
|
'''
|
||||||
|
@ -409,6 +425,7 @@ def parse_coordinate_string(coordinates):
|
||||||
if '--' in coordinates:
|
if '--' in coordinates:
|
||||||
(xy1, xy2) = coordinates.split('--', 1)
|
(xy1, xy2) = coordinates.split('--', 1)
|
||||||
else:
|
else:
|
||||||
|
# If you are only updating a single chunk.
|
||||||
xy1 = coordinates
|
xy1 = coordinates
|
||||||
xy2 = coordinates
|
xy2 = coordinates
|
||||||
|
|
||||||
|
@ -419,25 +436,63 @@ def parse_coordinate_string(coordinates):
|
||||||
return (int(x), int(y))
|
return (int(x), int(y))
|
||||||
|
|
||||||
(xy1, xy2) = (split_xy(xy1), split_xy(xy2))
|
(xy1, xy2) = (split_xy(xy1), split_xy(xy2))
|
||||||
# log.debug('Parsed coordinates %s into %s %s', coordinates, xy1, xy2)
|
log.debug('Parsed coordinates %s into %s %s', coordinates, xy1, xy2)
|
||||||
return (xy1, xy2)
|
return (xy1, xy2)
|
||||||
|
|
||||||
|
def overview_argparse(args):
|
||||||
|
cur.execute('SELECT x, y, updated_at FROM chunks GROUP BY x, y ORDER BY updated_at DESC')
|
||||||
|
chunks = cur.fetchall()
|
||||||
|
min_x = min(chunk[0] for chunk in chunks)
|
||||||
|
max_x = max(chunk[0] for chunk in chunks)
|
||||||
|
min_y = min(chunk[1] for chunk in chunks)
|
||||||
|
max_y = max(chunk[1] for chunk in chunks)
|
||||||
|
width = max_x - min_x + 1
|
||||||
|
height = max_y - min_y + 1
|
||||||
|
x_offset = abs(min(min_x, 0))
|
||||||
|
y_offset = abs(min(min_y, 0))
|
||||||
|
|
||||||
|
matrix = [[' ' for x in range(width)] for y in range(height)]
|
||||||
|
for (x, y, updated_at) in chunks:
|
||||||
|
x += x_offset
|
||||||
|
y += y_offset
|
||||||
|
matrix[y][x] = '.'
|
||||||
|
|
||||||
|
for (x, y, updated_at) in chunks:
|
||||||
|
if (x % 15 == 0) and (y % 15 == 0):
|
||||||
|
text = f'{x},{y}'
|
||||||
|
x += x_offset
|
||||||
|
y += y_offset
|
||||||
|
for c in text:
|
||||||
|
matrix[y][x] = c
|
||||||
|
x+=1
|
||||||
|
|
||||||
|
for row in matrix:
|
||||||
|
for column in row:
|
||||||
|
print(column, end='')
|
||||||
|
print()
|
||||||
|
|
||||||
def render_argparse(args):
|
def render_argparse(args):
|
||||||
if args.do_update:
|
if args.do_update:
|
||||||
update_argparse(args)
|
update_argparse(args)
|
||||||
|
|
||||||
coordinates = parse_coordinate_string(args.coordinates)
|
coordinates = parse_coordinate_string(args.coordinates)
|
||||||
|
if args.is_chunks:
|
||||||
|
chunk_range = coordinates
|
||||||
|
coordinates = chunk_range_to_pixel_range(*coordinates)
|
||||||
|
else:
|
||||||
chunk_range = pixel_range_to_chunk_range(*coordinates)
|
chunk_range = pixel_range_to_chunk_range(*coordinates)
|
||||||
|
|
||||||
chunks = [get_chunk(*chunk_xy) for chunk_xy in chunk_range_iterator(*chunk_range)]
|
chunks = [get_chunk(*chunk_xy) for chunk_xy in chunk_range_iterator(*chunk_range)]
|
||||||
scale = float(args.scale)
|
scale = float(args.scale)
|
||||||
image = chunks_to_image(chunks, scale=scale)
|
image = chunks_to_image(chunks, scale=scale)
|
||||||
|
|
||||||
if scale == 1:
|
if scale == 1:
|
||||||
image = crop_image(image, *coordinates)
|
image = crop_image(image, *coordinates)
|
||||||
|
|
||||||
if args.do_show:
|
if args.do_show:
|
||||||
image.show()
|
image.show()
|
||||||
else:
|
else:
|
||||||
(p1, p2) = coordinates
|
((p1x, p1y), (p2x, p2y)) = coordinates
|
||||||
(p1x, p1y) = p1
|
|
||||||
(p2x, p2y) = p2
|
|
||||||
scale_s = f'_{scale}' if scale != 1 else ''
|
scale_s = f'_{scale}' if scale != 1 else ''
|
||||||
filename = f'{p1x}.{p1y}--{p2x}.{p2y}{scale_s}.png'
|
filename = f'{p1x}.{p1y}--{p2x}.{p2y}{scale_s}.png'
|
||||||
image.save(filename)
|
image.save(filename)
|
||||||
|
@ -445,47 +500,35 @@ def render_argparse(args):
|
||||||
|
|
||||||
def update_argparse(args):
|
def update_argparse(args):
|
||||||
coordinates = parse_coordinate_string(args.coordinates)
|
coordinates = parse_coordinate_string(args.coordinates)
|
||||||
|
if args.is_chunks:
|
||||||
|
bigchunk_range = chunk_range_to_bigchunk_range(*coordinates)
|
||||||
|
else:
|
||||||
bigchunk_range = pixel_range_to_bigchunk_range(*coordinates)
|
bigchunk_range = pixel_range_to_bigchunk_range(*coordinates)
|
||||||
download_bigchunk_range(*bigchunk_range)
|
download_bigchunk_range(*bigchunk_range)
|
||||||
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
subparsers = parser.add_subparsers()
|
subparsers = parser.add_subparsers()
|
||||||
|
|
||||||
p_update = subparsers.add_parser('update')
|
p_update = subparsers.add_parser('update')
|
||||||
p_update.add_argument('coordinates')
|
p_update.add_argument('coordinates')
|
||||||
|
p_update.add_argument('--chunks', dest='is_chunks', action='store_true')
|
||||||
p_update.set_defaults(func=update_argparse)
|
p_update.set_defaults(func=update_argparse)
|
||||||
|
|
||||||
p_render = subparsers.add_parser('render')
|
p_render = subparsers.add_parser('render')
|
||||||
p_render.add_argument('coordinates')
|
p_render.add_argument('coordinates')
|
||||||
|
p_render.add_argument('--chunks', dest='is_chunks', action='store_true')
|
||||||
p_render.add_argument('--update', dest='do_update', action='store_true')
|
p_render.add_argument('--update', dest='do_update', action='store_true')
|
||||||
p_render.add_argument('--show', dest='do_show', action='store_true')
|
p_render.add_argument('--show', dest='do_show', action='store_true')
|
||||||
p_render.add_argument('--scale', dest='scale', default=1)
|
p_render.add_argument('--scale', dest='scale', default=1)
|
||||||
p_render.set_defaults(func=render_argparse)
|
p_render.set_defaults(func=render_argparse)
|
||||||
|
|
||||||
|
p_overview = subparsers.add_parser('overview')
|
||||||
|
p_overview.set_defaults(func=overview_argparse)
|
||||||
|
|
||||||
|
@betterhelp.subparser_betterhelp(parser, main_docstring=DOCSTRING, sub_docstrings=SUB_DOCSTRINGS)
|
||||||
def main(argv):
|
def main(argv):
|
||||||
helpstrings = {'', 'help', '-h', '--help'}
|
|
||||||
|
|
||||||
command = listget(argv, 0, '').lower()
|
|
||||||
|
|
||||||
# The user did not enter a command, or entered something unrecognized.
|
|
||||||
if command not in MODULE_DOCSTRINGS:
|
|
||||||
print(DOCSTRING)
|
|
||||||
if command == '':
|
|
||||||
print('You are seeing the default help text because you did not choose a command.')
|
|
||||||
elif command not in helpstrings:
|
|
||||||
print('You are seeing the default help text because "%s" was not recognized' % command)
|
|
||||||
return 1
|
|
||||||
|
|
||||||
# The user entered a command, but no further arguments, or just help.
|
|
||||||
argument = listget(argv, 1, '').lower()
|
|
||||||
if argument in helpstrings:
|
|
||||||
print(MODULE_DOCSTRINGS[command])
|
|
||||||
return 1
|
|
||||||
|
|
||||||
args = parser.parse_args(argv)
|
args = parser.parse_args(argv)
|
||||||
args.func(args)
|
return args.func(args)
|
||||||
return 0
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
raise SystemExit(main(sys.argv[1:]))
|
raise SystemExit(main(sys.argv[1:]))
|
||||||
|
|
Loading…
Reference in a new issue