136 lines
3.4 KiB
Python
136 lines
3.4 KiB
Python
import PIL.Image
|
||
import urllib.request
|
||
import io
|
||
import math
|
||
import subprocess
|
||
import tempfile
|
||
import pathlib
|
||
import os
|
||
from stitching import tiles_to_equirectangular_blender, multistitch
|
||
|
||
def pindora_normalize(url):
|
||
'''
|
||
Takes the URL of any image in a pindora panorama and returns a string
|
||
with substitutable variables for image IDs.
|
||
|
||
:param url: URL of an image contained in a pindora panorama
|
||
:return: string with substitutable variables or False if URL invalid
|
||
'''
|
||
|
||
try:
|
||
with urllib.request.urlopen(url) as res:
|
||
assert res.getcode() == 200
|
||
|
||
parts = url.split("/")
|
||
|
||
assert "_" in parts[-1]
|
||
parts[-1] = "c%i_l%i_%i_%i.jpg"
|
||
|
||
return "/".join(parts)
|
||
|
||
except:
|
||
return False
|
||
|
||
def pindora_getmaxzoom(schema):
|
||
'''
|
||
Takes a normalized string from pindora_normalize() and returns the maximum
|
||
zoom level available.
|
||
|
||
:param schema: normalized URL format output by pindora_normalize()
|
||
:return: int value of largest available zoom level
|
||
'''
|
||
|
||
l = 0
|
||
|
||
while True:
|
||
try:
|
||
url = schema % (0, l+1, 0, 0)
|
||
with urllib.request.urlopen(url) as res:
|
||
assert res.getcode() == 200
|
||
l += 1
|
||
except:
|
||
return l
|
||
|
||
def pindora_export(schema):
|
||
'''
|
||
Takes a normalized string from pindora_normalize() and returns a list of
|
||
lists of lists containing all images fit for passing into stitch().
|
||
|
||
:param schema: normalized URL format output by pindora_normalize()
|
||
:return: list of lists of lists of PIL.Image() objects for multistitch()
|
||
'''
|
||
|
||
maxzoom = 0 # ? – pindora_getmaxzoom(schema)
|
||
|
||
# c{cube}_l{z}_{y}_{x}.jpg
|
||
|
||
output = []
|
||
|
||
for tile in range(6):
|
||
t_array = []
|
||
y = 0
|
||
|
||
while True:
|
||
r_array = []
|
||
x = 0
|
||
|
||
while True:
|
||
try:
|
||
res = urllib.request.urlopen(schema % (tile, maxzoom, y, x))
|
||
assert res.getcode() == 200
|
||
fo = io.BytesIO(res.read())
|
||
img = PIL.Image.open(fo)
|
||
r_array.append(img)
|
||
x += 1
|
||
except Exception as e:
|
||
break
|
||
|
||
if not r_array:
|
||
break
|
||
|
||
t_array.append(r_array)
|
||
y += 1
|
||
|
||
output.append(t_array)
|
||
|
||
return output
|
||
|
||
def pindora_make_tiles(url):
|
||
'''
|
||
Determines the type of processing needed to build the six tiles, then
|
||
creates and returns them.
|
||
|
||
:param urL: URL of any image in a pindora panorama
|
||
:return: list of stitched PIL.Image objects (back, right, front, left, top,
|
||
bottom)
|
||
'''
|
||
|
||
parts = url.split("/")
|
||
|
||
try:
|
||
schema = pindora_normalize(url)
|
||
images = pindora_export(schema)
|
||
return multistitch(images)
|
||
|
||
except:
|
||
raise
|
||
raise ValueError("%s does not seem to be a valid pindora URL." % url)
|
||
|
||
|
||
def pindora_to_equirectangular(url, rotation=[0,0,0], resolution=[3840,1920]):
|
||
'''
|
||
Takes the URL of any image in a pindora panorama and returns a finished
|
||
stitched image.
|
||
|
||
:param url: Image URL
|
||
:return: PIL.Image object containing the final image
|
||
'''
|
||
|
||
stitched = pindora_make_tiles(url)
|
||
function = tiles_to_equirectangular_blender
|
||
|
||
rx, ry, rz = rotation
|
||
width, height = resolution
|
||
return function(*stitched, rx=rx, ry=ry, rz=rz, width=width, height=height)
|
||
|
||
process_url = pindora_to_equirectangular
|