mpetroff / pannellum

Pannellum is a lightweight, free, and open source panorama viewer for the web.
https://pannellum.org/
MIT License
4.29k stars 726 forks source link

Resolutions/Compatibility Question #199

Open Amadeus- opened 8 years ago

Amadeus- commented 8 years ago

I've been testing Pannellum using the simple example: http://www.amcmahan.com/calpoly/216Update-1.html Although it works fine in most displays, it won't work in others (such as the iphone 5-6s, etc.)

Is there a trick for using Pannellum in such a way that it works for all types of display resolutions? Or, do I need to reduce the resolution on my photo for it to be usable on all devices? (If it's the latter, does anyone have an example of a page using Pannellum in which the choice of photo resolution is dictated by the resolution of the current display being used?)

Thanks!

MmmDee commented 8 years ago

I ended up reducing resolution of most of my pics to 4096 specifically to accommodate my iPhone 5. In one image, I elected to use multires tiles (if you want to call that a "trick") to maintain resolution during zooming. The website is compatible with my iPhone, but it's not the best experience given the small display.

Edit: I just looked, the images started out as 5376 by 2688 (output of a Ricoh Theta S camera), I then made them all 2048x1024. The multires tiles are 512x512.

Amadeus- commented 8 years ago

Yea, I recall the error message on the iphone 5/6s being that the max resolution is 4096, and I'm sure there's nothing that can be done with any software to get around that. I guess my question was whether there is an easy way to provide multiple resolutions of the same photo and then use script or code to have Pannellum (or the browser) pick the one best to display given the maximum resolution allowed by the current display. Perhaps multires is what I'm looking for?

Anyway, if you know of any simple examples of websites using Pannellum to display high resolution images in a way that is viewable by all displays, I'd love to take a look.

Thanks!!

MmmDee commented 8 years ago

Until Matthew comes along with a better idea, your script could always assess the proper dimensions for your device, then do a loadScene (available in the development branch) of the appropriate image. Meaning, you could have scenes with the same image at various resolutions, and simply loadScene the right one.

Perhaps as an enhancement, Matthew will add a getMaxWidth() function to reveal a device's maximum texture width.

Something like this:

viewer = pannellum.viewer('panorama', {...});

function updateDisplay() {
    var rn = viewer.getRenderer();
    var cn = rn.getCanvas();
    var gl = cn.getContext("webgl");
    var maxWidth = gl.getParameter(gl.MAX_TEXTURE_SIZE);

    switch (maxWidth) {
        case 2048:
           loadScene(image2048...);
           break;
        case 8192:
           loadScene(image8192...);
           break;
        case 16384:
           loadScene(image16384...);
           break;
        default:
           loadScene(image4096...);
    }
};
mpetroff commented 8 years ago

The built-in method is to use the multires mode. This tiles the panorama, allowing for arbitrarily large images. It does take a bit more work, as the tiles need to be created first using the generate.py script. See example.

If you want to use multiple sizes of equirectangular images, you'll need to check the maximum texture size first by doing something like this:

<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Example</title>
    <link rel="stylesheet" href="https://cdn.pannellum.org/2.2/pannellum.css"/>
    <script type="text/javascript" src="https://cdn.pannellum.org/2.2/pannellum.js"></script>
    <style>
    #panorama {
        width: 600px;
        height: 400px;
    }
    </style>
</head>
<body>

<div id="panorama"></div>
<div style="display:none;"><canvas id="test"></canvas></div>

<script>
function checkTextureSize() {
    var canvas = document.getElementById("test");
    var gl = canvas.getContext("experimental-webgl");
    return gl.getParameter(gl.MAX_TEXTURE_SIZE);
}
textureSize = checkTextureSize();
panorama = 'large.jpg';
if (textureSize <= 8192)
    panorama = 'medium.jpg'
if (textureSize <= 4096)
    panorama = 'small.jpg'

pannellum.viewer('panorama', {
    "type": "equirectangular",
    "panorama": panorama
});
</script>

</body>
</html>
Amadeus- commented 8 years ago

Thanks for the response -- it's perfect. I'll try both methods, just so I have them both as reference.

Thanks!

dannythomas13 commented 8 years ago

@mpetroff @Amadeus- Can you tell me the difference in the two approaches? I'm, guessing multires will load the high quality image quicker?

mpetroff commented 8 years ago

Using multires will allow the highest resolution image to be displayed on all devices, will load faster, and will use less bandwidth (the highest resolution image is only loaded in the areas where the user zooms in).

dannythomas13 commented 8 years ago

@mpetroff multires works great I was worried I would not be able to work with large images but it's almost instant :) One quick question regarding it though. I am loading images from azure blob storage and in order to have tight access a SAS (Shared Access Signature) is required to access the images, this is done by appending something such as ?st=2016-11-21T14%3A34%3A00Z&se=2016-11-22T14%3A34%3A00Z&sp=rl&sv=2015-12-11&sr=c&sig=0FH1OA4pW%2FUJowUR%2BrpSuyDzW%2BII3d99%2F%2BayCL0M%2BkE%3C to the filename and all I set is a basepath, can you advise what would be the best way to tackle this please?

mpetroff commented 8 years ago

Add it to the extension parameter in the multires configuration, e.g. jpg?st=....

dannythomas13 commented 8 years ago

I had thought that may do it but without looking through all of the source I wasn't sure what side effects it may have, thanks for your continued support on this great library!

veggigit commented 7 years ago

@mpetroff Great solution for multiple device whit equirectangular image. One question, that method is replicable for each scene?

Thanks!

hanshansen commented 5 years ago

@dannythomas13 @mpetroff

Hello. We are trying something similar with pannellum and SAS Tokens and facing a similar issue. I think the issue is caused by encodeURI, which is used here and the SAS Token then gets malformed.

Is there a reason why the image path is encoded in the URI on this line?

faceImg.src = encodeURI(path.replace('%s', sides[s]) + '.' + image.extension);

We tried working around this issue by predecoding the sas token before passing it to pannellum, but since encodeURI is used instead of encodeURIComponent, nothing happens.

Would you be willing to accept a pull request removing this encoding or encoding the parts individually with encodeURIComponent, or would it break something else?

hanshansen commented 5 years ago

I see that this was changed in this commit, due to an DOM XSS vulnerability, so removing it would reintroduce this. Would it be possible to use encodeURICompoent instead then?

mpetroff commented 5 years ago

That commit was a bit over-zealous. While escaping the HTML is important, encodeURI isn't necessary, so I removed the calls in 15ddea01bdda109277ebcfe26af22e8ea9ac00ed.

joglr commented 5 years ago

@mpetroff Is this going in a new release then?

mpetroff commented 5 years ago

Yes