@@ -61,6 +61,14 @@ try:
except:
sys.stderr.write("Unable to import pyshtools. Not generating SHT preview.\n")
b83chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~"
def b83encode(vals, length):
result = ""
for val in vals:
for i in range(1, length + 1):
result += b83chars[int(val // (83 ** (length - i))) % 83]
return result
def img2shtHash(img, lmax=5):
'''
Create spherical harmonic transform (SHT) hash preview.
@@ -74,15 +82,6 @@ def img2shtHash(img, lmax=5):
quantB = encodeFloat(b / maxVal, 9)
return quantR * 19 ** 2 + quantG * 19 + quantB
b83chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~"
def b83encode(vals, length):
result = ""
for val in vals:
for i in range(1, length + 1):
result += b83chars[int(val // (83 ** (length - i))) % 83]
return result
# Calculate SHT coefficients
r = pysh.expand.SHExpandDH(img[..., 0], sampling=2, lmax_calc=lmax)
g = pysh.expand.SHExpandDH(img[..., 1], sampling=2, lmax_calc=lmax)
@@ -210,6 +209,10 @@ partialPano = True if args.haov != -1 and args.vaov != -1 else False
colorList = ast.literal_eval(args.backgroundColor)
colorTuple = (int(colorList[0]*255), int(colorList[1]*255), int(colorList[2]*255))
# Don't generate preview for partial panoramas
if haov < 360 or vaov < 180:
genPreview = False
if args.debug:
print('maxLevel: '+ str(levels))
print('tileResolution: '+ str(tileSize))
@@ -243,6 +246,7 @@ faces = ['face0000.tif', 'face0001.tif', 'face0002.tif', 'face0003.tif', 'face00
# Generate tiles
print('Generating tiles...')
missingTiles = []
for f in range(0, 6):
size = cubeSize
faceExists = os.path.exists(os.path.join(args.output, faces[f]))
@@ -271,8 +275,45 @@ for f in range(0, 6):
background = Image.new(tile.mode[:-1], tile.size, colorTuple)
background.paste(tile, tile.split()[-1])
tile = background
tile.save(os.path.join(args.output, str(level), faceLetters[f] + str(i) + '_' + str(j) + extension), quality=args.quality)
colors = tile.getcolors(1)
if not genPreview and colors is not None and colors[0][1] == colorTuple:
missingTiles.append((f, level, j, i))
else:
tile.save(os.path.join(args.output, str(level), faceLetters[f] + str(i) + '_' + str(j) + extension), quality=args.quality)
else:
missingTiles.append((f, level, j, i))
size = int(size / 2)
else:
missingTiles.append((f, level, 0, 0))
# Tell viewer not to load missing tiles
if len(missingTiles) > 0:
# Remove children of missing tiles, since they won't be loaded anyway
tilesToRemove = []
for t in missingTiles:
tilesToRemove.append((t[0], t[1] + 1, t[2] * 2, t[3] * 2))
tilesToRemove.append((t[0], t[1] + 1, t[2] * 2, t[3] * 2 + 1))
tilesToRemove.append((t[0], t[1] + 1, t[2] * 2 + 1, t[3] * 2))
tilesToRemove.append((t[0], t[1] + 1, t[2] * 2 + 1, t[3] * 2 + 1))
for t in tilesToRemove:
if t in missingTiles:
missingTiles.pop(missingTiles.index(t))
# Encode missing tile list as string
missingTilesStr = ''
prevFace = prevLevel = None
for missingTile in sorted(missingTiles):
face = missingTile[0]
level = missingTile[1]
if face != prevFace:
missingTilesStr += '!' + faceLetters[face]
#prevLevel = None
if level != prevLevel:
missingTilesStr += '>' + b83encode([level], 1)
maxTileNum = math.ceil(cubeSize / 2**(levels - level) / tileSize) - 1
numTileDigits = math.ceil(math.log(maxTileNum + 1, 83))
missingTilesStr += b83encode(missingTile[2:], numTileDigits)
prevFace = face
prevLevel = level
# Generate fallback tiles
if args.fallbackSize > 0:
@@ -297,8 +338,6 @@ if not args.debug:
os.remove(os.path.join(args.output, face))
# Generate preview (but not for partial panoramas)
if haov < 360 or vaov < 180:
genPreview = False
if genPreview:
# Generate SHT-hash preview
shtHash = img2shtHash(np.array(Image.open(args.inputFile).resize((1024, 512))))
@@ -328,7 +367,7 @@ if vaov < 180:
text.append(' "pitch": ' + str( args.vOffset)+ ',')
text.append(' "maxPitch": ' + str(+vaov/2+args.vOffset)+ ',')
if colorTuple != (0, 0, 0):
text.append(' "backgroundColor": " ' + args.backgroundColor+ '" ,')
text.append(' "backgroundColor": ' + args.backgroundColor+ ',')
if args.avoidbackground and (haov < 360 or vaov < 180):
text.append(' "avoidShowingBackground": true,')
if args.autoload:
@@ -339,6 +378,8 @@ if genPreview:
text.append(' "shtHash": "' + shtHash + '",')
if args.thumbnailSize > 0:
text.append(' "equirectangularThumbnail": "' + equiPreview + '",')
if len(missingTiles) > 0:
text.append(' "missingTiles": "' + missingTilesStr + '",')
text.append(' "path": "/%l/%s%y_%x",')
if args.fallbackSize > 0:
text.append(' "fallbackPath": "/fallback/%s",')