|
| https://learning-python.com/trnpix/index-dynamic.html |
| changes | https://learning-python.com/thumbspage/UserGuide.html#Version History |
| learning-python.com | https://learning-python.com/ |
| thumbspage | https://learning-python.com/thumbspage.html#Download |
| Python 3.X | https://www.python.org/downloads/ |
| Pillow | https://pillow.readthedocs.io/en/stable/installation/index.html |
| web page | https://www.learning-python.com/thumbspage.html |
| live demo | https://learning-python.com/thumbspage/examples/3.0-upgrades/index.html |
| screenshots | https://learning-python.com/thumbspage/examples/3.0-screenshots/index.html |
| client | https://learning-python.com/trnpix/index-dynamic.html |
| caution | https://learning-python.com/thumbspage/UserGuide.html#Usage Caution |
| demo | https://learning-python.com/thumbspage.html#demos |
| examples | https://learning-python.com/thumbspage/examples/ |
| code | https://learning-python.com/thumbspage/ |
| case | http://learning-python.com/trnpix/index-dynamic.html |
| web page | https://learning-python.com/thumbspage.html |
| 3.0 Quick Start | https://learning-python.com/thumbspage/UserGuide.html#Quickstart30 |
| Overview | https://learning-python.com/thumbspage/UserGuide.html#Overview |
| Viewing Galleries | https://learning-python.com/thumbspage/UserGuide.html#Viewing Galleries |
| Index Pages | https://learning-python.com/thumbspage/UserGuide.html#Index Pages |
| Viewer Pages | https://learning-python.com/thumbspage/UserGuide.html#Viewer Pages |
| Viewing Tips | https://learning-python.com/thumbspage/UserGuide.html#Viewing Tips |
| Building Galleries | https://learning-python.com/thumbspage/UserGuide.html#Building Galleries |
| Installs and Platforms | https://learning-python.com/thumbspage/UserGuide.html#Installs and Platforms |
| Running thumbspage | https://learning-python.com/thumbspage/UserGuide.html#Running thumbspage |
| Customization | https://learning-python.com/thumbspage/UserGuide.html#Customization |
| Building Tips | https://learning-python.com/thumbspage/UserGuide.html#Building Tips |
| GUI Mode | https://learning-python.com/thumbspage/UserGuide.html#GUI Mode |
| Usage Caution | https://learning-python.com/thumbspage/UserGuide.html#Usage Caution |
| Version History | https://learning-python.com/thumbspage/UserGuide.html#Version History |
| 3.0.1: Android Chrome Fix | https://learning-python.com/thumbspage/UserGuide.html#3.0.1 |
| 3.0: Tags, Keys, Swipes | https://learning-python.com/thumbspage/UserGuide.html#3.0 |
| 2.3: Notes, Inputs | https://learning-python.com/thumbspage/UserGuide.html#2.3 |
| 2.2: Swipes, Configs | https://learning-python.com/thumbspage/UserGuide.html#2.2 |
| 2.1: Thumbs, Layout | https://learning-python.com/thumbspage/UserGuide.html#2.1 |
| 2.0: Auto, Top, Full | https://learning-python.com/thumbspage/UserGuide.html#2.0 |
| 1.7: Info, Exifs, Etc. | https://learning-python.com/thumbspage/UserGuide.html#1.7 |
| 1.6: Scaling, Rotation | https://learning-python.com/thumbspage/UserGuide.html#1.6 |
| 1.5: Viewer Pages | https://learning-python.com/thumbspage/UserGuide.html#1.5 |
| 1.4: Mobile | https://learning-python.com/thumbspage/UserGuide.html#1.4 |
| 1.3: Unicode | https://learning-python.com/thumbspage/UserGuide.html#1.3 |
| 1.2: Styling | https://learning-python.com/thumbspage/UserGuide.html#1.2 |
| 1.1: Subfolders | https://learning-python.com/thumbspage/UserGuide.html#1.1 |
| 1.0: The Basics | https://learning-python.com/thumbspage/UserGuide.html#1.0 |
| Development Notes | https://learning-python.com/thumbspage/UserGuide.html#Development Notes |
| More Resources | https://learning-python.com/thumbspage/UserGuide.html#More Resources |
| 3.0 | https://learning-python.com/thumbspage/UserGuide.html#3.0 |
| demo | https://learning-python.com/thumbspage/examples/3.0-upgrades/index.html |
| screenshot | https://learning-python.com/thumbspage/examples/3.0-screenshots/index.html |
| index page | https://learning-python.com/thumbspage/examples/3.0-upgrades/index.html |
| viewer page | https://learning-python.com/thumbspage/examples/3.0-upgrades/_thumbspage/z-explicitly-first.jpg.html |
| folder | https://learning-python.com/thumbspage.html#Download |
| Python 3.X | https://www.python.org/downloads |
| Pillow | https://pillow.readthedocs.io/en/stable/installation/index.html |
| user_configs.py | https://learning-python.com/thumbspage/user_configs.py |
| user_configs.py | https://learning-python.com/thumbspage/user_configs.py |
| ahead | https://learning-python.com/thumbspage/UserGuide.html#Customization |
| user_configs.py | https://learning-python.com/thumbspage/user_configs.py |
| build | https://learning-python.com/thumbspage/examples/3.0-upgrades/_generate.sh |
| publish | https://learning-python.com/thumbspage/examples/3.0-upgrades/_publish.sh |
| gallery | https://learning-python.com/trnpix/index-dynamic.html |
| customized | https://learning-python.com/site-mobile-screenshots/index.html |
| browser | https://learning-python.com/thumbspage/examples/2.0-upgrades/fullscreen-no-ios13-hidetoolbar2.jpeg |
| index page | https://learning-python.com/thumbspage/examples/unicode/images/index.html |
| flavors | https://learning-python.com/thumbspage/examples/dynamiclayout/index.html |
| display | https://learning-python.com/thumbspage/examples/unicode/images/%E7%9C%9F%E6%A3%92%E7%85%A7%E7%89%87.JPG |
| viewer pages | https://learning-python.com/thumbspage/examples/unicode/images/_thumbspage/%E7%9C%9F%E6%A3%92%E7%85%A7%E7%89%87.JPG.html |
| slideshows | https://learning-python.com/thumbspage/examples/2.1-upgrades/Q-auto-slideshow-on-indicator.png |
| fullscreen | https://learning-python.com/thumbspage/examples/2.1-upgrades/Z-2.1-viewer-pages-5-fullscreen.png |
| popups | https://learning-python.com/thumbspage/examples/2.3-upgrades/note-d4-info-on-top.png |
| popups | https://learning-python.com/thumbspage/examples/2.3-upgrades/note-d3-short.png |
| enabled | https://learning-python.com/thumbspage/examples/2.3-upgrades/btns-d4-all-on.png |
| too | https://learning-python.com/thumbspage/UserGuide.html#viewerswipes |
| desktop | https://learning-python.com/thumbspage/examples/2.0-upgrades/javascript-desktop-viewpage-on.png |
| mobile | https://learning-python.com/thumbspage/examples/2.0-upgrades/javascript-mobile-viewpage-on.jpg |
| ahead | https://learning-python.com/thumbspage/UserGuide.html#Building Galleries |
| subfolders | https://learning-python.com/thumbspage/examples/mixedtypes/index.html |
| page | https://learning-python.com/cgi/showcode.py?name=trnpix/index-dynamic.html |
| subfolder | https://learning-python.com/trnpix/_thumbspage/ |
| pages | https://learning-python.com/cgi/showcode.py?name=trnpix/_thumbspage/2023 Sync App.jpg.html |
| gallery | https://learning-python.com/trnpix/ |
| Zip | http://learning-python.com/ziptools.html |
| website | http://learning-python.com |
| demos | https://learning-python.com/thumbspage.html#demos |
| scripts | https://learning-python.com/thumbspage/build/ |
| interaction | https://learning-python.com/thumbspage/examples/console-logs/android.txt |
| lines | https://learning-python.com/thumbspage/UserGuide.html#Running thumbspage |
| links | https://learning-python.com/thumbspage/examples/__prior-version-items/__prior-screenshots/older/trnpix-1.1.png |
| extensions | https://learning-python.com/thumbspage/examples/3.0-screenshots/_thumbspage/index-light.png.html |
| pages | https://learning-python.com/thumbspage/examples/3.0-screenshots/_thumbspage/viewer-wraparound.png.html |
| notes | https://learning-python.com/thumbspage/examples/3.0-screenshots/_thumbspage/viewer-note-tags.png.html |
| messages | https://learning-python.com/thumbspage/examples/3.0-screenshots/_thumbspage/viewer-rawview.png.html |
| captions | https://learning-python.com/thumbspage/examples/3.0-screenshots/_thumbspage/viewer-captions.png.html |
| mode | https://learning-python.com/thumbspage/examples/3.0-screenshots/_thumbspage/index-page.png.html |
| button | https://learning-python.com/thumbspage/examples/2.3-upgrades/btns-d4-all-on.png |
| description | https://learning-python.com/thumbspage/examples/2.3-upgrades/note-d1-large.png |
| enabled | https://learning-python.com/thumbspage/UserGuide.html#viewerswipes |
| labels | https://learning-python.com/thumbspage/examples/2.3-upgrades/_thumbspage/xx-omit-labels-mobile-i.png.html |
| enabled | https://learning-python.com/thumbspage/examples/2.3-upgrades/tooltips4.png |
| inputs | https://learning-python.com/thumbspage/UserGuide.html#inputs23 |
| more | https://learning-python.com/thumbspage/UserGuide.html#2.3 |
| view | https://learning-python.com/thumbspage.html#demos |
| settings | https://learning-python.com/thumbspage/examples/2.2-upgrades/more-demos/config-args-demo.sh |
| pages | https://learning-python.com/thumbspage/examples/2.2-upgrades/tooltips-gallery/index.html |
| more | https://learning-python.com/thumbspage/UserGuide.html#2.2 |
| presets | https://learning-python.com/thumbspage/user_configs.py |
| blur | https://learning-python.com/thumbspage/examples/2.1-upgrades/_thumbspage/F-normzoom-2.0-vs-2.1-presets-2.png.html |
| mode | https://learning-python.com/thumbspage/examples/2.1-upgrades/_thumbspage/X-black-and-white-thumbs-mode.png.html |
| debuts | https://learning-python.com/thumbspage/examples/dynamiclayout/index.html |
| automated.
As of 2.0,
viewer pages gain an Auto button that toggles automatic
slideshows,
a Full that toggles one-page
fullscreen,
and custom dialogs and device lines for
info popups;
index pages sprout floating
Top buttons;
and all pages have improved styling for handling rare page
overflows.
As of 1.7,
viewer pages
open info popups on
filename taps
and browser-native views on
image taps,
avoid clipping for
large fonts,
and drop hover effects spotty on mobile;
and GIFs get better
thumbs,
rotations keep and update
Exif tags,
and iOS landscape images are
scaled.
As of 1.6,
JavaScript is used to
dynamically scale
viewer-page images without changing aspect ratio or overflowing pages,
and tilted images are
automatically rotated
to display right-side up.
Earlier releases added
formatted
image-viewer pages [1.5];
support for viewing galleries on
mobile devices [1.4];
support for filename and content
Unicode [1.3];
and more.
| https://learning-python.com/thumbspage/build |
| slideshows | https://learning-python.com/thumbspage/examples/2.0-upgrades/auto-slideshow-view-normalfont.png |
| fullscreen | https://learning-python.com/thumbspage/examples/2.0-upgrades/fullscreen-mobile-fson.jpg |
| info popups | https://learning-python.com/thumbspage/examples/2.0-upgrades/MORE-INFO-POPUP/info-custom-spacemonkey1.png |
| Top buttons | https://learning-python.com/thumbspage/examples/2.0-upgrades/floating-top-custom-midpage.png |
| overflows | https://learning-python.com/thumbspage/examples/2.0-upgrades/overflow-wrap-index-foldername.png |
| filename taps | https://learning-python.com/thumbspage/examples/1.7-upgrades/digitized-other-photo2.jpg |
| image taps | https://learning-python.com/thumbspage/examples/1.7-upgrades/image-tap-raw.png |
| large fonts | https://learning-python.com/thumbspage/examples/1.7-upgrades/largefont-clip-fixed-large.png |
| thumbs | https://learning-python.com/thumbspage/examples/1.7-upgrades/zz-gif-thumbs-after-rbga.png |
| Exif tags | https://learning-python.com/thumbspage/examples/reorientation/_thumbspage/galaxys8-3U.jpg.html |
| scaled | https://learning-python.com/thumbspage/examples/1.7-upgrades/ios13-safari-hid-landscape.PNG |
| dynamically scale | https://learning-python.com/thumbspage/examples/Screenshots/_thumbspage/scaling-portrait-tall.png.html |
| automatically rotated | https://learning-python.com/thumbspage/examples/reorientation/index.html |
| image-viewer pages | https://learning-python.com/thumbspage/examples/Screenshots/_thumbspage/colors-viewer.png.html |
| mobile devices | https://learning-python.com/thumbspage/examples/Screenshots/_thumbspage/trnpix-index-mobile.png.html |
| Unicode | https://learning-python.com/thumbspage/examples/unicode/images/_thumbspage/Марк Лутц.JPG.html |
| ahead | https://learning-python.com/thumbspage/UserGuide.html#Version History |
| builders' section | https://learning-python.com/thumbspage/UserGuide.html#Building Galleries |
| desktop | https://learning-python.com/thumbspage/examples/2.3-upgrades/note-d2-thin.png |
| mobile | https://learning-python.com/thumbspage/examples/2.3-upgrades/note-m1-portrait.png |
| online | https://learning-python.com/thumbspage/examples/2.0-upgrades/auto-slideshow-view-android6inch-1.jpg |
| offline | https://learning-python.com/thumbspage/examples/2.1-upgrades/Z-2.1-viewer-pages-1.png |
| ahead | https://learning-python.com/thumbspage/UserGuide.html#Viewing Tips |
| desktop | https://learning-python.com/thumbspage/examples/2.2-upgrades/misc-gallery/thumbs-border-2.2-a-fixed.png |
| mobile | https://learning-python.com/thumbspage/examples/2.2-upgrades/misc-gallery/thumbs-border-2.2-c-mobile.png |
| version | https://learning-python.com/trnpix/index-dynamic.html |
| basename | https://learning-python.com/thumbspage/examples/2.0-upgrades/xtra-other-unicode-index.png |
| subfolders | https://learning-python.com/thumbspage/examples/2.0-upgrades/xtra-other-subfolders.png |
| Top | https://learning-python.com/thumbspage/examples/2.0-upgrades/floating-top-custom-footer.png |
| subfolders | https://learning-python.com/thumbspage/examples/mixedtypes/index.html |
| ahead | https://learning-python.com/thumbspage/UserGuide.html#1.1 |
| mouseovers | https://learning-python.com/thumbspage/examples/2.2-upgrades/tooltips-gallery/firefox-index-thumb.png |
| fixed | https://learning-python.com/trnpix/index.html |
| dynamic | https://learning-python.com/trnpix/index-dynamic.html |
| demo | https://learning-python.com/thumbspage/examples/dynamiclayout/index.html |
| viewer pages | https://learning-python.com/thumbspage/examples/2.1-upgrades/Z-2.1-viewer-pages-1.png |
| desktop | https://learning-python.com/thumbspage/examples/2.0-upgrades/xtra-desktop.png |
| mobile | https://learning-python.com/thumbspage/examples/2.0-upgrades/xtra-mobile-android6inch-1.jpg |
| version | https://learning-python.com/trnpix/_thumbspage/2010 Sarasota 1.JPG.html |
| mouseovers | https://learning-python.com/thumbspage/examples/2.3-upgrades/tooltips4.png |
| info dialog | https://learning-python.com/thumbspage/examples/2.0-upgrades/xtra-mobile-android6inch-info.jpg |
| scan | https://learning-python.com/thumbspage/examples/2.0-upgrades/MORE-INFO-POPUP/info-custom-scanner2.png |
| raw display | https://learning-python.com/thumbspage/examples/2.0-upgrades/auto-slideshow-view-raw-imagetap.jpg |
| ahead | https://learning-python.com/thumbspage/UserGuide.html#viewerswipes |
| toolbar buttons | https://learning-python.com/thumbspage/examples/2.3-upgrades/btns-d4-all-on.png |
| index page | https://learning-python.com/thumbspage/examples/2.0-upgrades/floating-top-mobile-android6inch-prescroll.jpg |
| viewer pages | https://learning-python.com/thumbspage/examples/2.3-upgrades/note-d1-large.png |
| button | https://learning-python.com/thumbspage/examples/2.3-upgrades/btns-d4-all-on.png |
| line-through | https://learning-python.com/thumbspage/examples/2.3-upgrades/note-x1-none.png |
| screens | https://learning-python.com/thumbspage/examples/2.3-upgrades/note-m1-portrait.png |
| gallery | https://learning-python.com/thumbspage/examples/2.0-upgrades/auto-slideshow-view-android6inch-1.jpg |
| ahead | https://learning-python.com/thumbspage/UserGuide.html#moresafarijunk |
| 2.1 | https://learning-python.com/thumbspage/UserGuide.html#21autofull |
| is on | https://learning-python.com/thumbspage/examples/2.1-upgrades/Q-auto-slideshow-on-indicator.png |
| is off | https://learning-python.com/thumbspage/examples/2.1-upgrades/Q-auto-slideshow-off-indicator.png |
| toggle | https://learning-python.com/thumbspage/examples/2.0-upgrades/fullscreen-mobile-fson.jpg |
| before | https://learning-python.com/thumbspage/examples/2.0-upgrades/fullscreen-windows-fsoff.png |
| after | https://learning-python.com/thumbspage/examples/2.0-upgrades/fullscreen-windows-fson.png |
| tip | https://learning-python.com/thumbspage/UserGuide.html#fullscreenmanual |
| is on | https://learning-python.com/thumbspage/examples/2.1-upgrades/Z-2.1-viewer-pages-5-fullscreen.png |
| 2.2 | https://learning-python.com/thumbspage/UserGuide.html#2.2 |
| 3.0 | https://learning-python.com/thumbspage/UserGuide.html#3.0 |
| Quick Start | https://learning-python.com/thumbspage/UserGuide.html#aboutswipes |
| dialog | https://learning-python.com/thumbspage/examples/2.0-upgrades/xtra-mobile-android6inch-info.jpg |
| filename | https://learning-python.com/thumbspage/UserGuide.html#widgetactions |
| popup | https://learning-python.com/thumbspage/examples/2.3-upgrades/note-d1-large.png |
| above | https://learning-python.com/thumbspage/UserGuide.html#notebutton |
| raw view | https://learning-python.com/thumbspage/examples/2.0-upgrades/auto-slideshow-view-raw-imagetap.jpg |
| image | https://learning-python.com/thumbspage/UserGuide.html#widgetactions |
| popup | https://learning-python.com/thumbspage/examples/2.2-upgrades/misc-gallery/up-swipe-fail-chrome.jpg |
| ahead | https://learning-python.com/thumbspage/UserGuide.html#chromeupswipebug22 |
| gallery | https://learning-python.com/thumbspage/examples/2.0-upgrades/fullscreen-windows-fsoff.png |
| buttons | https://learning-python.com/thumbspage/UserGuide.html#toolbaractions |
| time | https://learning-python.com/thumbspage/UserGuide.html#swipegestures22 |
| here | https://learning-python.com/thumbspage.html#demos |
| above | https://learning-python.com/thumbspage/UserGuide.html#widgetactions |
| examples | https://learning-python.com/thumbspage/examples/ |
| live demos | https://learning-python.com/thumbspage.html#demos |
| JavaScript requirement | https://learning-python.com/thumbspage/UserGuide.html#_vt1 |
| Browser and device support | https://learning-python.com/thumbspage/UserGuide.html#_vt2 |
| Enable iOS 13's Hide Toolbar for Safari | https://learning-python.com/thumbspage/UserGuide.html#_vt3 |
| Fullscreen manual options | https://learning-python.com/thumbspage/UserGuide.html#_vt4 |
| iOS Chrome may stack navigation history | https://learning-python.com/thumbspage/UserGuide.html#_vt5 |
| Viewing galleries offline on PCs | https://learning-python.com/thumbspage/UserGuide.html#_vt9 |
| Viewing galleries offline on Android | https://learning-python.com/thumbspage/UserGuide.html#_vt7 |
| Viewing galleries offline on iOS? | https://learning-python.com/thumbspage/UserGuide.html#_vt8 |
| Beware browser settings and bugs | https://learning-python.com/thumbspage/UserGuide.html#_vt6 |
| desktop | https://learning-python.com/thumbspage/examples/2.0-upgrades/javascript-desktop-viewpage-off.png |
| mobile | https://learning-python.com/thumbspage/examples/2.0-upgrades/javascript-mobile-viewpage-off.jpg |
| experience | https://learning-python.com/thumbspage/examples/2.0-upgrades/javascript-desktop-viewpage-on.png |
| pages | https://learning-python.com/thumbspage/examples/2.3-upgrades/note-d2-thin.png |
| note | https://learning-python.com/thumbspage/UserGuide.html#tooltips23 |
| 4 inches | https://learning-python.com/thumbspage/examples/2.0-upgrades/xtra-mobile-ios4inch.PNG |
| window | https://learning-python.com/thumbspage/examples/1.7-upgrades/ios13-safari-hide-toolbars.PNG |
| better | https://learning-python.com/thumbspage/examples/2.0-upgrades/fullscreen-no-ios13-hidetoolbar.jpeg |
earlier,
the Full button on thumbspage viewer pages is optional,
because it lasts for just one page, and is supported unevenly across
browsers. By contrast, many browsers offer a manual, user-initiated
fullscreen mode that persists across page switches, including those of
thumbspage Auto slideshows. Where available, this can be a much
more useful alternative. The options for invoking a manual
fullscreen are too many to cover here, but here's a quick rundown:
On Windows, the F11 key (with fn if
needed) puts the browser in fullscreen mode, which persists for all
pages visited until explicitly disabled with another F11.
This works in Chrome, Firefox, Edge, Internet Explorer, and likely others,
and allows thumbspage Auto slideshows to run completely in fullscreen mode.
On Linux, the F11 key (with fn if
needed) switches browsers to and from persistent fullscreen mode, just
as it does on Windows. This works in Chromium, Firefox, and likely others,
and, as on Windows, allows thumbspage Auto slideshows to run completely
in fullscreen mode.
On macOS, you can toggle a similar persistent fullscreen
mode in Chrome, Safari, and Firefox, with the keys combination
control+command+f.
A shift+command+f
may additionally hide the toolbar in Chrome (but not Firefox, currently),
and you can also go fullscreen by clicking the upper-left-corner
green button or using menu fullscreen icons.
On iOS 13, Safari's Hide Toolbar option of the preceding
note
isn't fully fullscreen, but it's close enough to mention again here,
and lasts for all pages you visit (including those in Auto slideshows).
This alone makes it worth upgrading to iOS 13, if you already haven't.
On Android, numerous apps available from the Play Store promise
persistent fullscreen support. Judging from chatter on the web, though,
some may be better than others, so the usual due-diligence caution applies.
It may also be possible to force a browser app to use Android fullscreen
mode with a tethered ADB command or Settings option, but this may not
omit the browser's own UI baggage, and ADB seems well beyond most users'
patience.
See also the Opera update ahead for a new Android fullscreen option.
For additional tips and other platforms and browsers, try a web search,
or consult your browser; browsers change regularly, and new fullscreen
options may crop up over time.
Manual and persistent fullscreen isn't available everywhere today, but it
generally beats thumbspage's one-page Full where possible. You may still
find thumbspage's Full useful as a quick zoom, though, especially on
browsers that lack a manual option today. With any luck, those
browsers will make Full fully superfluous in the not-too-distant tomorrow.
Update: on Android, the Opera web browser
recently gained an amazing fullscreen mode for landscape that works much like
those in desktop browsers, and spans multiple pages. For details, see this
usage note
at thumbspage's host site. The Opera browser is largely the same as Chrome under
the hood,
and runs thumbspage galleries just as
well—and
arguably better with its landscape fullscreen.
Yet another reason to consider parting with the herd on Android.
(Defunct) iOS Chrome may stack navigation history
thumbspage image-viewer pages are not normally stacked (i.e., remembered)
in browser history as you—or a slideshow you started—navigate through
galleries. This by design, because it makes browser Back operations return
to the viewer pages' entry point immediately, instead of stepping back though each
image viewed. This may not work in some versions of Chrome on iOS, unfortunately,
due to a bug in that browser. That bug appears to have been fixed in Chrome 83
(or earlier), but was known to still be broken as of Chrome 75. If your Chrome
stacks pages, either retrace pages as needed for that browser's Back,
or use any other iOS browser to view thumbspage galleries.
Viewing galleries offline on PCs
thumbspage bills its galleries as viewable both online (at a website) and
offline (on your device). In more detail, online mode works universally on all
devices, and offline is trivial on PCs (which means Windows, Linux, and macOS here)—a click
in a file-explorer window (e.g., Finder or Explorer) normally suffices to open a gallery
in your default browser, and right-clicks, browser Open functions, and explicit
file:// URLs offer more options. On mobile devices, however,
offline viewing isn't always as seamless, but you'll have to move on to the next
two notes for the Android and iOS offline stories. macOS Safari users: see also the
caveat ahead for the rare use case of
browser Back returns to offline galleries.
Viewing galleries offline on Android
(TL;DR: jump to the latest
update for new file-explorer options.)
On some unrooted Androids, you may have trouble viewing a gallery stored
locally on the device: the index page may open in a file explorer, but its
thumbnails and viewer pages won't. This happens mostly in Chrome on newer
Androids, and seems related to that platform's push to tighter
permissions and
content://
URIs.
While these may be spun as security measures, that argument has been tiredly
used for many an Android
breakage.
thumbspage galleries are known to work offline on Androids Nougat,
Oreo, Pie, and 10, but its releases and devices vary too widely to give
universal advice here. If your offline gallery fails, try the following
work-arounds that have proved successful in some contexts:
Move it to internal storage instead of SD card (e.g., on Pie and earlier)
View it with a different browser (e.g., Firefox, Opera or Samsung instead of Chrome)
Open it with a different file explorer (e.g., Total Commander, and tap file://url if present)
Open it via a manually typed file URL (e.g., file:///sdcard/...)
Ditto, but try different pathnames in the URL (e.g., /storage/emulated/0; see the
primer)
Move it online if possible, and open with a web URL (e.g., https://...)
Especially on newer Androids, also make sure the browser has permission to access
your files in storage. Firefox, for example, may require this on Android 10.
Try Settings/Apps and navigate to storage permissions, or similar on your device.
This has grown more crucial as later Androids have moved to lock down storage to
app-specific
sandboxes.
If you're technically inclined, you might also try running a
web-server app
on your device and viewing your gallery on localhost or a
dedicated port number; this is wholly untested (but arguably awesome).
Caveat: the upcoming Android 11 will clamp permissions down further
(read the latest edicts
here),
but its impact on browser apps remains to be seen.
Update:
for recent findings on both local-file views and running web-server
apps on Android, see the off-page coverage
here,
which is part of an Android 11 review. In short, you can run a web server on Android,
but your functionality may be limited and your disconnections many. Android 11 has
also narrowed your options for local-file views in browsers, in the name of a
security rationale; inoperable phones may be secure, but they're also inoperable.
Update:
the thumbspage team recently discovered another route to offline viewing on Android.
On Android 11, simply copy your content into the browser's own sandboxed folder, using
a file explorer that has permission to do so (Solid Explorer and Cx File Explorer do
at this writing). Then, use that folder's local path in a file:// URL
in the browser to view offline. For example, copy content to these locations for
Chrome and Opera (alas, this won't work for Firefox on 11, because it strips
the file://):
file:///storage/emulated/0/Android/data/com.android.chrome/your-folder-and-file-here
file:///storage/emulated/0/Android/data/com.opera.browser/your-folder-and-file-here
This works for Chrome on Android 10 too, but isn't required for Opera or Firefox on 10,
where they have full access to arbitrary storage paths
(unlike both Chrome on 10, and all browsers on 11).
This isn't the same as arbitrary file access, of course; you're limited to files dropped
into a browser's folder. This is also an arguably terrible idea: your content
in the sandbox folder will be deleted if you uninstall the browser, and is prone to being
nuked if the browser ever resets its own folder. Hacker beware!
Update:
in late 2021, some Android file explorers now provide seemingly heroic work-arounds on
Android 11 that allow you to use a browser to view web pages stored locally on your
phone—including thumbspage galleries. For example, among file-explorer apps tested:
Cx now automatically
spawns an HTTP server to open local HTML files, and launches your browser to view
these files on the locally running server. This is not a full Apache web server (e.g.,
URL rewrites and auto-indexes won't work, and CGI scripts are displayed instead of run),
and local folder listings are explicitly disabled by the server. Still, this works well
for basic views of much client-side content, including galleries generated by thumbspage.
Solid, among others, now opens local HTML files in browsers with suitable
content:// URIs that implement Android's content-provider paradigm.
This scheme is not a substitute for a web server, opens some complex pages slowly, and
can break down for some nested website content (e.g., folder indexes may oddly invoke
a download that fails). But it also suffices for viewing basic content and thumbspage
galleries on your phone.
Thus, your first step when trying to view locally stored thumbspage galleries
on Android 11 and later today is to simply try opening them in a file-explorer
app to see if they are supported automatically. For more details on the
constantly evolving struggle between Android permissions and file explorers,
see also the updates
here,
here,
and
here.
Viewing galleries offline on iOS?
On unrooted Apple mobiles, iOS 13's enhanced Files app allows you to
open files both on USB drives and copied to internal storage. This lets
you view a gallery's pages, but doesn't open a browser. Instead, it runs
a stripped-down quick-view that lacks JavaScript and shows just the
top-level page's text, not any images it embeds. The net effect is
much like recent Android Chromes of the preceding note, and your most direct
recourse may be an online (or local network) upload.
While there may be additional iOS options
beyond thumbspage's testing budget, Apple has historically been
more closed than Android (and its appetite for control seems only to be
growing).
Beware browser settings and bugs
Some browser settings that may appear harmless can adversely
impact thumbspage galleries. The native (a.k.a. raw) image display
of some versions of Android Chrome, for example, may initially
render some images weirdly large in portrait orientation, but if and only
if the seemingly unrelated Force enable zoom is selected in
Accessibility Settings.
The image-tap raw displays of thumbspage viewer pages trigger this effect,
but do not cause it—it also happens when visiting images' URLs directly,
outside gallery pages.
There's more on this issue in
search
results, while they last; its impact is broad, but likely to be reversed soon.
Nor is this an isolated case.
As another example, the thumbspage team recently found and reported a
settings-related bug in 2020's Android Firefox—though not
thumbspage specific, this browser sometimes leaves an odd blank
strip at the bottom of thumbspage viewer pages if you enable its
"Scroll to hide toolbar" option (more details
here).
Thumbspage's host site also reported a bug in version 53
of Android Opera—though it does not impact thumbspage galleries (and was
fixed in version 60), this browser strangely truncated the remainder of a page at a
/* character sequence in text formatted with .
At the end of the day, thumbspage is completely dependent on browsers which
change frequently and arbitrarily, and have an unfortunate history of
fragility (indeed, at times it seems a website could be laid low by a good
sneeze). For best results, clear settings that cause issues on Android,
use similarly obscure browser behavioral switches with care, and try
other browsers as a last resort when browser bugs—and enhancements—break
your viewing experience.
| https://learning-python.com/thumbspage/UserGuide.html#fullscreenbutton |
| note | https://learning-python.com/thumbspage/UserGuide.html#_vt3 |
| patience | https://duckduckgo.com/?q=force+android+app+into+fullscreen |
| usage note | https://learning-python.com/about-this-site.html#androidbrowsernews_opera |
| hood | https://en.wikipedia.org/wiki/Browser_engine |
| well | https://en.wikipedia.org/wiki/Chromium_(web_browser) |
| ahead | https://learning-python.com/thumbspage/UserGuide.html#moresafarijunk |
| update | https://learning-python.com/thumbspage/UserGuide.html#androidbrowserlocalviews |
| permissions | https://duckduckgo.com/?q=android+scope+storage |
| URIs | https://duckduckgo.com/?q=android+content+uri+required |
| breakage | https://learning-python.com/mergeall-android-scripts/_README.html#thefutureisclosed |
| primer | https://learning-python.com/mergeall-android-scripts/_README.html#toc7 |
| sandboxes | https://learning-python.com/mergeall-android-scripts/_README.html#toc9 |
| web-server app | https://duckduckgo.com/?q=android+web+server+app |
| here | https://developer.android.com/preview/privacy/storage |
| here | https://learning-python.com/mergeall-android11-updates.html#asb6 |
| here | https://learning-python.com/mergeall-android11-updates.html#morefileexplorersupdate |
| here | https://learning-python.com/android-deltas-sync/_README.html#Android%20File%20Explorers |
| here | https://learning-python.com/pydroid3-loses-storage-access.html#s43 |
| growing | https://duckduckgo.com/?q=apple+mac+os+dropping+intel+chips |
| search | https://duckduckgo.com/?q=android+chrome+force+enable+zoom+displays+images+too+large |
| here | https://learning-python.com/about-this-site.html#androidbrowsernews |
| viewers' section | https://learning-python.com/thumbspage/UserGuide.html#Viewing Galleries |
| here | http://learning-python.com/site-mobile-screenshots/index.html |
| here | https://learning-python.com/thumbspage/examples/reorientation/index.html |
| defaults | https://learning-python.com/thumbspage/examples/subfolders/index.html |
| earlier | https://learning-python.com/thumbspage/UserGuide.html#Viewing Galleries |
| learning-python.com/thumbspage.html | https://learning-python.com/thumbspage.html#Download |
| www.python.org/downloads/ | https://www.python.org/downloads/ |
| pypi.python.org/pypi/Pillow | https://pypi.python.org/pypi/Pillow |
| this page | http://learning-python.com/tagpix/README-macapp.html |
| ahead | https://learning-python.com/thumbspage/UserGuide.html#rotateskeepexifs |
| piexif | https://pypi.org/project/piexif/ |
| itself | https://learning-python.com/thumbspage/piexif |
| Termux | https://termux.com/ |
| search | https://duckduckgo.com/?q=python+pillow+in+termux |
| here | https://pillow.readthedocs.io/en/stable/installation.html#building-on-android |
| Pydroid 3 | https://play.google.com/store/apps/details?id=ru.iiec.pydroid3 |
| here | https://learning-python.com/thumbspage/examples/1.7-upgrades/build-on-android-1.jpg |
| here | https://learning-python.com/thumbspage/examples/1.7-upgrades/build-on-android-2.jpg |
| here | https://learning-python.com/thumbspage/examples/1.7-upgrades/built-on-android-index.jpg |
| here | https://learning-python.com/thumbspage/examples/console-logs/android.txt |
| this doc | https://learning-python.com/mergeall-android-scripts/_README.html#toc9 |
| Pythonista | https://apps.apple.com/us/app/pythonista-3/id1085978097 |
| tighter | https://learning-python.com/post-release-updates.html#mergeallandroid |
| section | https://learning-python.com/thumbspage/UserGuide.html#Installs and Platforms |
| thumbspage.py | https://learning-python.com/thumbspage/thumbspage.py |
| PyEdit | http://learning-python.com/pyedit.html |
| IDLE | https://docs.python.org/3/library/idle.html |
| section | https://learning-python.com/thumbspage/UserGuide.html#otherusagemodes |
| ahead | https://learning-python.com/thumbspage/UserGuide.html#pathprimer |
| ahead | https://learning-python.com/thumbspage/UserGuide.html#Building Tips |
| folder | https://learning-python.com/thumbspage/UserGuide.html#other21 |
| ahead | https://learning-python.com/thumbspage/UserGuide.html#Customization |
| alternative | https://learning-python.com/thumbspage/UserGuide.html#dynamiclayout21 |
| section | https://learning-python.com/thumbspage/UserGuide.html#thumbsizeinputs |
| update | https://learning-python.com/thumbspage/UserGuide.html#thumbsize23 |
| ahead | https://learning-python.com/thumbspage/UserGuide.html#Building Tips |
| console log | https://learning-python.com/thumbspage/examples/console-logs/2.0-console-errors.txt |
| folder | https://learning-python.com/thumbspage/examples/console-logs/ |
| here | https://learning-python.com/thumbspage/UserGuide.html#inputs23 |
| here | https://learning-python.com/thumbspage/UserGuide.html#configcmdargs22 |
| stream | https://en.wikipedia.org/wiki/Standard_streams |
| open bug | https://bugs.python.org/issue25692 |
| tagpix | https://learning-python.com/tagpix.html |
| here | https://learning-python.com/thumbspage/examples/2.0-upgrades/_generate.sh |
| here | https://learning-python.com/thumbspage/examples/dynamiclayout/_generate.sh |
| here | https://learning-python.com/thumbspage/build/generate-examples.py |
| here | https://learning-python.com/thumbspage/build/ |
| above | https://learning-python.com/thumbspage/UserGuide.html#Running thumbspage |
| streams | https://en.wikipedia.org/wiki/Standard_streams |
| redirection | https://en.wikipedia.org/wiki/Redirection_(computing) |
| variables | https://duckduckgo.com/?q=shell+variables |
| here docs | https://duckduckgo.com/?q=here+documents |
| examples | https://learning-python.com/thumbspage/examples/ |
| Customization | https://learning-python.com/thumbspage/UserGuide.html#Customization |
| Building Tips | https://learning-python.com/thumbspage/UserGuide.html#Building Tips |
| argument | https://learning-python.com/thumbspage/UserGuide.html#_177 |
| reporting | https://learning-python.com/thumbspage/UserGuide.html#_20B |
| layout | https://learning-python.com/thumbspage/UserGuide.html#dynamiclayout21 |
| folders | https://learning-python.com/thumbspage/UserGuide.html#other21 |
| file | https://learning-python.com/thumbspage/UserGuide.html#Customization |
| release note | https://learning-python.com/thumbspage/UserGuide.html#configcmdargs22 |
| note | https://learning-python.com/thumbspage/UserGuide.html#inputs23 |
| examples | https://learning-python.com/thumbspage/UserGuide.html#inputconfigexamples |
| note | https://learning-python.com/thumbspage/UserGuide.html#thumbsize23 |
| prompt | https://learning-python.com/thumbspage/UserGuide.html#promptsandreplies |
| PyEdit | http://learning-python.com/pyedit.html |
| prompt | https://learning-python.com/thumbspage/UserGuide.html#promptsandreplies |
| Pillow | https://learning-python.com/thumbspage/UserGuide.html#Installs and Platforms |
| this script | https://learning-python.com/thumbspage/docetc/pillow-thumb-size-scaling.py |
| update | https://learning-python.com/thumbspage/UserGuide.html#thumbsize23 |
| section | https://learning-python.com/thumbspage/UserGuide.html#Running thumbspage |
| user_configs.py | https://learning-python.com/thumbspage/user_configs.py |
| images | https://learning-python.com/thumbspage/UserGuide.html#rotation |
| later | https://learning-python.com/thumbspage/UserGuide.html#Version History |
| file | https://learning-python.com/thumbspage/user_configs.py |
| release note | https://learning-python.com/thumbspage/UserGuide.html#configcmdargs22 |
| examples/ | https://learning-python.com/thumbspage/examples/ |
| this example | https://learning-python.com/thumbspage/examples/reorientation/index.html |
| this demo | https://learning-python.com/site-mobile-screenshots/index.html |
| narratives | https://learning-python.com/thumbspage/examples/2.0-upgrades/xtra-other-subfolders.png |
| Top | https://learning-python.com/thumbspage/UserGuide.html#_202 |
| subfolders | https://learning-python.com/thumbspage/UserGuide.html#1.1 |
| file | https://learning-python.com/thumbspage/user_configs.py |
| ahead | https://learning-python.com/thumbspage/UserGuide.html#1.3 |
| links | https://learning-python.com/trnpix/index-dynamic.html |
| text | https://learning-python.com/thumbspage/examples/unicode/images/index.html |
| ahead | https://learning-python.com/thumbspage/UserGuide.html#floatingtop20 |
| alternative | https://learning-python.com/thumbspage/UserGuide.html#dynamiclayout21 |
| here | http://learning-python.com/site-mobile-screenshots/ |
| this note | https://learning-python.com/thumbspage/UserGuide.html#_206 |
| this script | https://learning-python.com/thumbspage/build/insert-analytics.py |
| template-viewpage.html | https://learning-python.com/cgi/showcode.py?name=thumbspage/template-viewpage.html |
| here | https://learning-python.com/thumbspage/UserGuide.html#_206 |
| template-floatingtop.html | https://learning-python.com/cgi/showcode.py?name=thumbspage/template-floatingtop.html |
| note | https://learning-python.com/thumbspage/UserGuide.html#floatingtop20 |
| popup | https://learning-python.com/thumbspage/examples/2.3-upgrades/note-d1-large.png |
| button | https://learning-python.com/thumbspage/examples/2.3-upgrades/btns-d4-all-on.png |
| displays | https://learning-python.com/thumbspage/UserGuide.html#viewerswipes |
| gallery | https://learning-python.com/trnpix/index-dynamic.html |
| note | https://learning-python.com/thumbspage/UserGuide.html#notes23 |
| pages | https://learning-python.com/thumbspage/UserGuide.html#omitlabels23 |
| here | https://learning-python.com/cgi/showcode.py?name=trnpix/index-dynamic.html |
| here | https://learning-python.com/cgi/showcode.py?name=trnpix/_thumbspage/2010 Sarasota 1.JPG.html |
| here | https://learning-python.com/trnpix/_thumbspage-dynamic/ |
| here | https://learning-python.com/trnpix/index-dynamic.html |
| 3.0 | https://learning-python.com/thumbspage/UserGuide.html#3.0 |
| Quick Start | https://learning-python.com/thumbspage/UserGuide.html#configfiles30 |
| release notes | https://learning-python.com/thumbspage/UserGuide.html#3.0 |
| user_configs.py | https://learning-python.com/thumbspage/user_configs.py |
| Version History | https://learning-python.com/thumbspage/UserGuide.html#Version History |
| Viewer pages (or not) | https://learning-python.com/thumbspage/UserGuide.html#_un1 |
| Image filenames text and length | https://learning-python.com/thumbspage/UserGuide.html#_un2 |
| Supported image types | https://learning-python.com/thumbspage/UserGuide.html#_un3 |
| Other image-folder content | https://learning-python.com/thumbspage/UserGuide.html#_un4 |
| Subfolder bullet lists | https://learning-python.com/thumbspage/UserGuide.html#_un5 |
| Linking to results with URLs | https://learning-python.com/thumbspage/UserGuide.html#_un6 |
| Tilted-image rotation | https://learning-python.com/thumbspage/UserGuide.html#_un7 |
| Cleaning the thumbs folder | https://learning-python.com/thumbspage/UserGuide.html#_un8 |
| Thumbs-folder name | https://learning-python.com/thumbspage/UserGuide.html#_un9 |
| Extra-files overhead | https://learning-python.com/thumbspage/UserGuide.html#_unA |
| A word on image size and speed | https://learning-python.com/thumbspage/UserGuide.html#_unC |
| Running thumbspage | https://learning-python.com/thumbspage/UserGuide.html#Running thumbspage |
| pages | https://learning-python.com/thumbspage/examples/reorientation/_thumbspage/galaxys8-6R.jpg.html |
| release notes | https://learning-python.com/thumbspage/UserGuide.html#1.7 |
| notes | https://learning-python.com/thumbspage/UserGuide.html#2.0 |
| note | https://learning-python.com/thumbspage/UserGuide.html#_204 |
| type | https://en.wikipedia.org/wiki/Media_type |
| extension | https://en.wikipedia.org/wiki/Filename_extension |
| format | https://en.wikipedia.org/wiki/WebP |
| Safari | https://en.wikipedia.org/wiki/WebP#Support |
| this shot | https://learning-python.com/thumbspage/examples/mixedtypes/About-this-folder/chrome-firefox-safari-2020.png |
| examples/mixedtypes | https://learning-python.com/thumbspage/examples/mixedtypes/index.html |
| this page | https://en.wikipedia.org/wiki/Comparison_of_web_browsers#Image_format_support |
| this search | https://duckduckgo.com/?q=display+tiff+in+web+browser |
| popups | https://learning-python.com/thumbspage/examples/2.0-upgrades/MORE-INFO-POPUP/info-custom-camera-brand1-ff.png |
| solutions | https://duckduckgo.com/?q=pythin+pillow+heic |
| here | https://duckduckgo.com/?q=convert+heif+to+jpeg |
| here | https://duckduckgo.com/?q=iphone+share+images+as+jpeg+instead+of+heic |
| 2.3 coverage | https://learning-python.com/thumbspage/UserGuide.html#notes23 |
| special | https://learning-python.com/thumbspage/UserGuide.html#Customization |
| subfolder-links | https://learning-python.com/thumbspage/examples/Screenshots/subfolders-1.png |
| file | https://learning-python.com/thumbspage/user_configs.py |
| folder | https://learning-python.com/thumbspage/examples/mixedtypes/index.html |
| folders | https://learning-python.com/thumbspage/examples/subfolders/index.html |
| file | https://learning-python.com/thumbspage/UserGuide.html#Customization |
| ahead | https://learning-python.com/thumbspage/UserGuide.html#1.1 |
| too | https://learning-python.com/thumbspage/UserGuide.html#_178 |
| items | https://learning-python.com/thumbspage/UserGuide.html#other21 |
| tilted | https://learning-python.com/thumbspage/examples/Screenshots/reorient-prior-index.png |
| image | https://learning-python.com/thumbspage/examples/Screenshots/reorient-new-viewer.png |
| thumbnail | https://learning-python.com/thumbspage/examples/Screenshots/reorient-new-index.png |
| tags | https://en.wikipedia.org/wiki/Exif |
| standard | https://www.exif.org/Exif2-2.PDF |
| image | https://learning-python.com/thumbspage/UserGuide.html#rotateskeepexifs |
| user_configs.py | https://learning-python.com/thumbspage/user_configs.py |
| utility script | https://learning-python.com/thumbspage/docetc/restore-prerotate-originals.py |
| Version History | https://learning-python.com/thumbspage/UserGuide.html#rotation16 |
| Running thumbspage | https://learning-python.com/thumbspage/UserGuide.html#Running thumbspage |
| user_configs.py | https://learning-python.com/thumbspage/user_configs.py |
| learning-python.com | http://learning-python.com/programs.html |
| Mergeall | http://learning-python.com/mergeall.html |
| contexts | https://en.wikipedia.org/wiki/Bandwidth_throttling |
| Pillow | https://python-pillow.org/ |
| dimensions | https://duckduckgo.com/?q=python+pillow+image+scale+down |
| quality | https://duckduckgo.com/?q=python+pillow+image+reduce+file+size |
| shrinkpix | http://learning-python.com/shrinkpix.html |
| full package | http://learning-python.com/thumbspage.html#Download |
| shrinkpix | http://learning-python.com/shrinkpix.html |
| update note | https://learning-python.com/thumbspage/UserGuide.html#thumbnails17 |
| shrinkpix docs | http://learning-python.com/shrinkpix/shrinkpix.py |
| server | http://learning-python.com/about-this-site.html#vpssiterelo |
| mod_pagespeed | https://www.modpagespeed.com/ |
| book | http://learning-python.com/about-pp4e.html |
| app | https://learning-python.com/using-tkinter-programs-on-android.html |
| GUI | https://learning-python.com/thumbspage/examples/Screenshots/x-viewer_thumbs-gui-mode.png |
| as much | https://learning-python.com/thumbspage/examples/Screenshots/x-viewer_thumbs-links-popup.png |
| here | https://learning-python.com/thumbspage/examples/Screenshots/y-pyphoto-1.png |
| here | https://learning-python.com/thumbspage/examples/Screenshots/y-pyphoto-3.png |
| http://learning-python.com/pygadgets.html | http://learning-python.com/pygadgets.html |
| size | https://learning-python.com/thumbspage/UserGuide.html#packages21 |
| web page | http://learning-python.com/thumbspage.html#Download |
| file | https://learning-python.com/thumbspage/user_configs.py |
| here | https://learning-python.com/thumbspage/UserGuide.html#1.1 |
| adds | https://learning-python.com/thumbspage/UserGuide.html#subfolderslayout |
| rotates | https://learning-python.com/thumbspage/UserGuide.html#rotation16 |
| thumbnails | https://learning-python.com/thumbspage/UserGuide.html#21rotations |
| restore-prerotate-originals.py | https://learning-python.com/thumbspage/docetc/restore-prerotate-originals.py |
| user_configs.py | https://learning-python.com/thumbspage/user_configs.py |
| code files | https://learning-python.com/thumbspage/ |
| 3.0.1: Android Chrome Fix (2025) | https://learning-python.com/thumbspage/UserGuide.html#3.0.1 |
| 3.0: Tags, Keys, Swipes (2025) | https://learning-python.com/thumbspage/UserGuide.html#3.0 |
| 2.3: Notes, Inputs (2022+) | https://learning-python.com/thumbspage/UserGuide.html#2.3 |
| 2.2: Swipes, Configs (2021) | https://learning-python.com/thumbspage/UserGuide.html#2.2 |
| 2.1: Thumbs, Layout (2021) | https://learning-python.com/thumbspage/UserGuide.html#2.1 |
| 2.0: Auto, Top, Full (2020) | https://learning-python.com/thumbspage/UserGuide.html#2.0 |
| 1.7: Info, Exifs, Etc. (2020) | https://learning-python.com/thumbspage/UserGuide.html#1.7 |
| 1.6: Scaling, Rotation (2018) | https://learning-python.com/thumbspage/UserGuide.html#1.6 |
| 1.5: Viewer Pages (2018) | https://learning-python.com/thumbspage/UserGuide.html#1.5 |
| 1.4: Mobile (2018) | https://learning-python.com/thumbspage/UserGuide.html#1.4 |
| 1.3: Unicode (2016) | https://learning-python.com/thumbspage/UserGuide.html#1.3 |
| 1.2: Styling (2016) | https://learning-python.com/thumbspage/UserGuide.html#1.2 |
| 1.1: Subfolders (2016) | https://learning-python.com/thumbspage/UserGuide.html#1.1 |
| 1.0: The Basics (2016) | https://learning-python.com/thumbspage/UserGuide.html#1.0 |
| pages | https://learning-python.com/trnpix/_thumbspage-dynamic/2023%20Sync%20App.jpg.html |
| info | https://learning-python.com/thumbspage/examples/3.0-screenshots/_thumbspage/viewer-info.png.html |
| file | https://learning-python.com/cgi/showcode.py?name=thumbspage/template-viewpage.html |
| docs | https://developer.chrome.com/blog/overscroll-behavior/#disabling_pull-to-refresh |
| statcounter | https://gs.statcounter.com/browser-market-share/mobile/worldwide |
| statista | https://www.statista.com/statistics/263517/market-share-held-by-mobile-internet-browsers-worldwide/ |
| site | https://learning-python.com |
| live demo | https://learning-python.com/thumbspage/examples/3.0-upgrades/index.html |
| screenshots | https://learning-python.com/thumbspage/examples/3.0-screenshots/index.html |
| use case | https://learning-python.com/trnpix/index-dynamic.html |
| Omitted filename extensions | https://learning-python.com/thumbspage/UserGuide.html#30.1 |
| Gallery wraparound messages | https://learning-python.com/thumbspage/UserGuide.html#30.2 |
| Automatic end-of-gallery images | https://learning-python.com/thumbspage/UserGuide.html#30.3 |
| Raw-view messages on image taps | https://learning-python.com/thumbspage/UserGuide.html#30.4 |
| HTML tags and entities in notes | https://learning-python.com/thumbspage/UserGuide.html#30.5 |
| Explicit ordering with ORDER.txt | https://learning-python.com/thumbspage/UserGuide.html#30.6 |
| Alternative labels with CAPTIONS.py | https://learning-python.com/thumbspage/UserGuide.html#30.7 |
| Alternative notes with NOTES.py | https://learning-python.com/thumbspage/UserGuide.html#30.8 |
| Per-host or forced dark color theme | https://learning-python.com/thumbspage/UserGuide.html#30.9 |
| Configurable line spacing for text | https://learning-python.com/thumbspage/UserGuide.html#30.10 |
| Image filenames in info popups | https://learning-python.com/thumbspage/UserGuide.html#30.11 |
| Swipes on touchpads and mice too | https://learning-python.com/thumbspage/UserGuide.html#30.12 |
| Keypress shortcuts in viewer pages | https://learning-python.com/thumbspage/UserGuide.html#30.13 |
| Error checks for build filenames | https://learning-python.com/thumbspage/UserGuide.html#30.14 |
| Preset defaults and links color | https://learning-python.com/thumbspage/UserGuide.html#30.15 |
| configs | https://learning-python.com/thumbspage/user_configs.py |
| builds | https://learning-python.com/thumbspage/examples/3.0-upgrades/_generate.sh |
| config | https://learning-python.com/thumbspage/UserGuide.html#30.15 |
| counterpart | https://learning-python.com/thumbspage/UserGuide.html#30.9 |
| demo | https://learning-python.com/thumbspage/examples/3.0-upgrades/_viewable/ |
| demo | https://learning-python.com/thumbspage/examples/3.0-upgrades/_viewable/ |
| above | https://learning-python.com/thumbspage/UserGuide.html#fnlimits |
| demo | https://learning-python.com/thumbspage/examples/3.0-upgrades/_viewable/ |
| demo | https://learning-python.com/thumbspage/examples/3.0-upgrades/_viewable/ |
| user_configs.py | https://learning-python.com/thumbspage/user_configs.py |
| user_configs.py | https://learning-python.com/thumbspage/user_configs.py |
| below | https://learning-python.com/thumbspage/UserGuide.html#30presets |
| user_configs.py | https://learning-python.com/thumbspage/user_configs.py |
| omitted | https://learning-python.com/thumbspage/UserGuide.html#fnomit30 |
| captions | https://learning-python.com/thumbspage/UserGuide.html#captions30 |
| here | https://learning-python.com/thumbspage/examples/3.0-screenshots/_thumbspage/viewer-info.png.html |
| above | https://learning-python.com/thumbspage/UserGuide.html#30.9 |
| user_configs.py | https://learning-python.com/thumbspage/user_configs.py |
| image notes | https://learning-python.com/thumbspage/UserGuide.html#notes23 |
| overrides | https://learning-python.com/thumbspage/UserGuide.html#inputs23 |
| tooltips | https://learning-python.com/thumbspage/UserGuide.html#tooltips23 |
| changes | https://learning-python.com/thumbspage/UserGuide.html#other23 |
| folder | https://learning-python.com/thumbspage/examples/2.3-upgrades/index.html |
| colors | https://learning-python.com/thumbspage/UserGuide.html#popupcolors23 |
| opacity | https://learning-python.com/thumbspage/UserGuide.html#popupopacity23 |
| layout | https://learning-python.com/thumbspage/UserGuide.html#dynamiclayout23 |
| labels | https://learning-python.com/thumbspage/UserGuide.html#omitlabels23 |
| buglets | https://learning-python.com/thumbspage/UserGuide.html#buglets23 |
| enhancement | https://learning-python.com/thumbspage/UserGuide.html#thumbsize23 |
| popups | https://learning-python.com/thumbspage/examples/2.3-upgrades/note-d1-large.png |
| buttons | https://learning-python.com/thumbspage/examples/2.3-upgrades/btns-d4-all-on.png |
| example | https://learning-python.com/thumbspage/examples/2.3-upgrades/index.html |
| gallery | https://learning-python.com/trnpix/index-dynamic.html |
| here | https://learning-python.com/thumbspage/UserGuide.html#notebutton |
| here | https://learning-python.com/thumbspage/UserGuide.html#viewerswipes |
| section | https://learning-python.com/thumbspage/UserGuide.html#notefiles |
| file | https://learning-python.com/thumbspage/user_configs.py |
| 3.0 | https://learning-python.com/thumbspage/UserGuide.html#3.0 |
| setting | https://learning-python.com/thumbspage/user_configs.py |
| files | https://learning-python.com/thumbspage/UserGuide.html#Customization |
| demo | https://learning-python.com/cgi/showcode.py?name=thumbspage/examples/2.3-upgrades/x-nojavascript1-2.3.png.note |
| line-through | https://learning-python.com/thumbspage/examples/2.3-upgrades/note-x1-none.png |
| text | https://learning-python.com/thumbspage/examples/2.3-upgrades/note-x2-none.png |
| files | https://learning-python.com/thumbspage/examples/2.3-upgrades/btns-d3-full-only.png |
| emojis | https://learning-python.com/thumbspage/examples/2.3-upgrades/note-x4-long-unicode.png |
| here | https://learning-python.com/thumbspage/examples/2.3-upgrades/_thumbspage/z-escaped-note-text.png.html |
| 3.0 | https://learning-python.com/thumbspage/UserGuide.html#3.0 |
| setting | https://learning-python.com/thumbspage/user_configs.py |
| setting | https://learning-python.com/thumbspage/user_configs.py |
| ahead | https://learning-python.com/thumbspage/UserGuide.html#omitlabels23 |
| batchnotes.py | https://learning-python.com/thumbspage/docetc/batchnotes.py |
| example | https://learning-python.com/thumbspage/examples/2.3-upgrades/_batchnotes.txt |
| demo | https://learning-python.com/trnpix/_batchnotes.txt |
| info | https://learning-python.com/thumbspage/examples/2.3-upgrades/note-d4-info-on-top.png |
| Note | https://learning-python.com/thumbspage/examples/2.3-upgrades/note-d1-large.png |
| file | https://learning-python.com/thumbspage/user_configs.py |
| equivalents | https://learning-python.com/thumbspage/UserGuide.html#configcmdargs22 |
| info | https://learning-python.com/thumbspage/UserGuide.html#_20A |
| here | https://learning-python.com/thumbspage/examples/2.3-upgrades/_thumbspage/y-pcolors-1-prior-wb.png.html |
| gallery | https://learning-python.com/trnpix/index-dynamic.html |
| generate | https://learning-python.com/trnpix/_generate.sh |
| publish | https://learning-python.com/trnpix/_publish.sh |
| version 2.2 | https://learning-python.com/thumbspage/UserGuide.html#configcmdargs22 |
| file | https://learning-python.com/thumbspage/user_configs.py |
| 1.7 | https://learning-python.com/thumbspage/UserGuide.html#_177 |
| 2.1 | https://learning-python.com/thumbspage/UserGuide.html#dynamiclayout21 |
| 2.2 | https://learning-python.com/thumbspage/UserGuide.html#configcmdargs22 |
| earlier | https://learning-python.com/thumbspage/UserGuide.html#otherusagemodes |
| platforms | https://duckduckgo.com/?q=windows+line+coninuation |
| tooltips | https://learning-python.com/thumbspage/examples/2.3-upgrades/tooltips5.png |
| buttons | https://learning-python.com/thumbspage/examples/2.3-upgrades/tooltips2.png |
| message | https://learning-python.com/thumbspage/examples/2.3-upgrades/x-nojavascript1-2.3.png |
| style | https://learning-python.com/thumbspage/examples/2.3-upgrades/note-d4-info-on-top.png |
| suit | https://learning-python.com/thumbspage/examples/2.3-upgrades/note-d3-short.png |
| too | https://learning-python.com/thumbspage/examples/2.3-upgrades/_thumbspage/y-pcolors-2-preset-wb.png.html |
| above | https://learning-python.com/thumbspage/UserGuide.html#popupcolors23 |
| file | https://learning-python.com/thumbspage/user_configs.py |
| argument | https://learning-python.com/thumbspage/UserGuide.html#configcmdargs22 |
| here | https://learning-python.com/thumbspage/examples/2.3-upgrades/_thumbspage/yy-opacity1-image.png.html |
| arguments | https://learning-python.com/thumbspage/UserGuide.html#configcmdargs22 |
| overrides | https://learning-python.com/thumbspage/UserGuide.html#inputs23 |
| how | https://learning-python.com/thumbspage/examples/dynamiclayout/_generate.sh |
| does | https://learning-python.com/thumbspage/examples/2.3-upgrades/_generate.sh |
| generate | https://learning-python.com/trnpix/_generate.sh |
| publish | https://learning-python.com/trnpix/_publish.sh |
| file | https://learning-python.com/thumbspage/user_configs.py |
| equivalent | https://learning-python.com/thumbspage/UserGuide.html#inputs23 |
| case | https://learning-python.com/thumbspage/UserGuide.html#thumbsizereply |
| 2.1 | https://learning-python.com/thumbspage/UserGuide.html#dynamiclayout21 |
| note | https://learning-python.com/thumbspage/UserGuide.html#omitlabels23 |
| column | https://learning-python.com/thumbspage/examples/2.3-upgrades/_thumbspage/xx-mobile-dyn.png.html |
| thumbspage.py | https://learning-python.com/thumbspage/thumbspage.py |
| here | https://learning-python.com/thumbspage/examples/2.3-upgrades/_thumbspage/xx-desktop-dyn.png.html |
| file | https://learning-python.com/thumbspage/user_configs.py |
| example | https://learning-python.com/trnpix/_generate.sh |
| demo | https://learning-python.com/trnpix/index.html |
| flavor | https://learning-python.com/trnpix/index-dynamic.html |
| pages | https://learning-python.com/thumbspage/examples/2.3-upgrades/xx-desktop-dyn.png |
| here | https://learning-python.com/thumbspage/examples/2.3-upgrades/_thumbspage/xx-omit-index-labels-dyn.png.html |
| demo | https://learning-python.com/trnpix/index-thumbsonly.html |
| docs | https://learning-python.com/thumbspage/user_configs.py |
| pages | https://learning-python.com/thumbspage/examples/2.3-upgrades/btns-d4-all-on.png |
| mobile | https://learning-python.com/thumbspage/examples/2.3-upgrades/_thumbspage/xx-omit-labels-mobile-i.png.html |
| notes | https://learning-python.com/thumbspage/UserGuide.html#notes23 |
| example | https://learning-python.com/thumbspage/examples/2.3-upgrades/_thumbspage/y-pcolors-5-ccc-18.png.html |
| demo | https://learning-python.com/thumbspage/examples/2.3-upgrades/_thumbspage/z-escaped-note-text.png.html |
| gallery | https://learning-python.com/trnpix/index.html |
| dynamic layout | https://learning-python.com/trnpix/index-dynamic.html |
| name | https://learning-python.com/thumbspage/examples/reorientation/_thumbspage/galaxys8-1N.jpg.html |
| version 3.0 | https://learning-python.com/thumbspage/UserGuide.html#3.0 |
| swipe gestures | https://learning-python.com/thumbspage/UserGuide.html#swipegestures22 |
| config arguments | https://learning-python.com/thumbspage/UserGuide.html#configcmdargs22 |
| tooltips | https://learning-python.com/thumbspage/UserGuide.html#tooltips22 |
| changes | https://learning-python.com/thumbspage/UserGuide.html#other22 |
| folder | https://learning-python.com/thumbspage/examples/2.2-upgrades/index.html |
| section | https://learning-python.com/thumbspage/UserGuide.html#viewerswipes |
| section | https://learning-python.com/thumbspage/UserGuide.html#configcmdargs22 |
| template | https://learning-python.com/cgi/showcode.py?name=thumbspage/template-viewpage.html |
| here | https://learning-python.com/thumbspage.html#demos |
| note | https://learning-python.com/thumbspage/UserGuide.html#notes23 |
| notes | https://learning-python.com/thumbspage/UserGuide.html#3.0 |
| message | https://learning-python.com/thumbspage/examples/2.2-upgrades/misc-gallery/up-swipe-fail-chrome.jpg |
| code | https://learning-python.com/cgi/showcode.py?name=thumbspage/template-viewpage.html |
| message | https://learning-python.com/thumbspage/examples/2.2-upgrades/misc-gallery/up-swipe-message-samsung.jpg |
| file | https://learning-python.com/thumbspage/user_configs.py |
| file | https://learning-python.com/thumbspage/user_configs.py |
| file | https://learning-python.com/thumbspage/user_configs.py |
| differ | https://duckduckgo.com/?q=windows+command+line+escapes |
| subsystem | https://duckduckgo.com/?q=windows+linux+subsystem |
| example | https://learning-python.com/thumbspage/examples/dynamiclayout/_generate.sh |
| layout | https://learning-python.com/thumbspage/UserGuide.html#dynamiclayout21 |
| tooltips | https://learning-python.com/thumbspage/UserGuide.html#tooltips22 |
| theme | https://learning-python.com/thumbspage/UserGuide.html#indexcolor22 |
| swipes | https://learning-python.com/thumbspage/UserGuide.html#swipegestures22 |
| tools | https://duckduckgo.com/?q=windows+line+coninuation |
| usual | https://learning-python.com/thumbspage/UserGuide.html#Running thumbspage |
| file | https://learning-python.com/thumbspage/user_configs.py |
| usage | https://learning-python.com/android-deltas-sync/_etc/screenshots/index.html |
| here | https://learning-python.com/thumbspage/examples/2.2-upgrades/more-demos/config-args-demo.sh |
| note | https://learning-python.com/thumbspage/UserGuide.html#inputs23 |
| examples | https://learning-python.com/thumbspage/UserGuide.html#inputconfigexamples |
| file | https://learning-python.com/thumbspage/user_configs.py |
| arguments | https://learning-python.com/thumbspage/UserGuide.html#configcmdargs22 |
| nonstarters | https://learning-python.com/thumbspage/UserGuide.html#moresafarijunk |
| here | https://learning-python.com/thumbspage/examples/2.2-upgrades/tooltips-gallery/index.html |
| note | https://learning-python.com/thumbspage/UserGuide.html#tooltips23 |
| popup | https://learning-python.com/thumbspage/UserGuide.html#_20A |
| earlier | https://learning-python.com/thumbspage/UserGuide.html#tooltips22 |
| configs | https://learning-python.com/thumbspage/UserGuide.html#Customization |
| above | https://learning-python.com/thumbspage/UserGuide.html#configcmdargs22 |
| example | https://learning-python.com/thumbspage/examples/2.2-upgrades/misc-gallery/index.html |
| true | https://learning-python.com/thumbspage/examples/2.2-upgrades/tooltips-gallery/index.html |
| layout | https://learning-python.com/thumbspage/UserGuide.html#dynamiclayout21 |
| config | https://learning-python.com/thumbspage/user_configs.py |
| tables | https://learning-python.com/thumbspage/UserGuide.html#dynamiclayout21 |
| config | https://learning-python.com/thumbspage/user_configs.py |
| 2.1 | https://learning-python.com/thumbspage/UserGuide.html#other21 |
| this | https://learning-python.com/thumbspage/examples/2.2-upgrades/misc-gallery/index.html |
| this | https://learning-python.com/thumbspage/examples/2.2-upgrades/index.html |
| file | https://learning-python.com/thumbspage/UserGuide.html#Customization |
| here | https://learning-python.com/thumbspage/examples/2.2-upgrades/misc-gallery/_thumbspage/tagline-off-sans-top.png.html |
| Android | https://learning-python.com/thumbspage/UserGuide.html#androidbrowserlocalviews |
| images | https://learning-python.com/thumbspage/UserGuide.html#enhancedthumbs21 |
| layout | https://learning-python.com/thumbspage/UserGuide.html#dynamiclayout21 |
| changes | https://learning-python.com/thumbspage/UserGuide.html#other21 |
| here | https://learning-python.com/thumbspage/examples/2.1-upgrades/index.html |
| here | https://learning-python.com/thumbspage/examples/dynamiclayout/index.html |
| download | https://learning-python.com/thumbspage.html#Download |
| file | https://learning-python.com/thumbspage/user_configs.py |
| noise | https://learning-python.com/thumbspage/examples/2.1-upgrades/H-highzoom-2.0-noise-and-blurry.png |
| blur | https://learning-python.com/thumbspage/examples/2.1-upgrades/E-normzoom-2.0-vs-2.1-presets-1.png |
| galleries | https://learning-python.com/thumbspage/examples/2.1-upgrades/Z-2.1-index-pages-1.png |
| displays | https://learning-python.com/thumbspage/examples/2.1-upgrades/Y-mobile-2.1-notblurry.jpg |
| generated | https://learning-python.com/thumbspage/examples/2.1-upgrades/_HOW-MADE.txt |
| black-and-white | https://learning-python.com/thumbspage/examples/2.1-upgrades/X-black-and-white-thumbs-mode.png |
| effects | https://learning-python.com/thumbspage/examples/2.1-upgrades/X-way-too-much-tweaking.png |
| gallery | https://learning-python.com/thumbspage/examples/2.1-upgrades/index.html |
| user_configs.py | https://learning-python.com/thumbspage/user_configs.py |
| viewer_thumbs.py | https://learning-python.com/thumbspage/viewer_thumbs.py |
| columns | https://learning-python.com/thumbspage/examples/2.1-upgrades/P-resized-dynamic-layout-narrow.png |
| single column | https://learning-python.com/thumbspage/examples/2.1-upgrades/P-mobile-dynamic-layout-wide-p.jpg |
| landscape | https://learning-python.com/thumbspage/examples/2.1-upgrades/P-mobile-dynamic-layout-wide-l.jpg |
| content | https://learning-python.com/thumbspage/examples/2.1-upgrades/P-mobile-dynamic-layout-narrow-p.jpg |
| tested | https://learning-python.com/thumbspage/examples/dynamiclayout/index.html |
| tables | https://learning-python.com/thumbspage/examples/2.1-upgrades/Z-2.1-index-pages-1.png |
| user_configs.py | https://learning-python.com/thumbspage/user_configs.py |
| size | https://duckduckgo.com/?q=css+units |
| file | https://learning-python.com/thumbspage/user_configs.py |
| space | https://learning-python.com/thumbspage/examples/2.1-upgrades/P-zero-padding-dynamic-layout.png |
| gallery | https://learning-python.com/thumbspage/examples/dynamiclayout/index.html |
| screenshots | https://learning-python.com/thumbspage/examples/2.1-upgrades/_thumbspage/P-desktop-dynamic-layout-narrow.png.html |
| page | https://learning-python.com/thumbspage/examples/dynamiclayout/Demo-Wide-Filename-Labels/index.html |
| thumbspage.py | https://learning-python.com/thumbspage/thumbspage.py |
| inputs | https://learning-python.com/thumbspage/UserGuide.html#Running thumbspage |
| release notes | https://learning-python.com/thumbspage/UserGuide.html#configcmdargs22 |
| note | https://learning-python.com/thumbspage/UserGuide.html#dynamiclayout23 |
| 3.0 | https://learning-python.com/thumbspage/UserGuide.html#3.0 |
| message | https://learning-python.com/thumbspage/examples/2.1-upgrades/_HOW-MADE.txt |
| ahead | https://learning-python.com/thumbspage/UserGuide.html#builds21 |
| links | https://learning-python.com/thumbspage/UserGuide.html#1.1 |
| file | https://learning-python.com/thumbspage/user_configs.py |
| value | https://duckduckgo.com/?q=css+units |
| screenshot | https://learning-python.com/thumbspage/examples/2.1-upgrades/N-subfolder-links-2.0-vs-2-1.png |
| demo | https://learning-python.com/thumbspage/examples/subfolders/index.html |
| tagline | https://learning-python.com/thumbspage/examples/2.1-upgrades/N-subfolder-links-2.0-vs-2-1.png |
| footer | https://learning-python.com/thumbspage/UserGuide.html#Customization |
| Image | https://learning-python.com/thumbspage/examples/subfolders/index.html |
| titles | https://learning-python.com/thumbspage/examples/2.1-upgrades/O-imageless-folder-pages-default.png |
| tagline | https://learning-python.com/thumbspage/examples/2.1-upgrades/O-imageless-folder-pages-custom.png |
| gallery | https://learning-python.com/thumbspage/examples/2.1-upgrades/_thumbspage/N-subfolder-links-2.0-vs-2-1.png.html |
| queries | https://learning-python.com/thumbspage/UserGuide.html#Running thumbspage |
| imageless | https://learning-python.com/thumbspage/examples/console-logs/android.txt |
| gallery | https://learning-python.com/thumbspage/examples/dynamiclayout/index.html |
| on | https://learning-python.com/thumbspage/examples/2.1-upgrades/Q-auto-slideshow-on-indicator.png |
| off | https://learning-python.com/thumbspage/examples/2.1-upgrades/Q-auto-slideshow-off-indicator.png |
| mode | https://learning-python.com/thumbspage/examples/2.1-upgrades/Z-2.1-viewer-pages-5-fullscreen.png |
| rotated | https://learning-python.com/thumbspage/UserGuide.html#rotation16 |
| console log | https://learning-python.com/thumbspage/examples/console-logs/2.1-embedded-thumbs-removal.txt |
| demo | https://learning-python.com/thumbspage/examples/reorientation/index.html |
| before | https://learning-python.com/thumbspage/examples/2.1-upgrades/R-embedded-thumbs-kept2.0.png |
| after | https://learning-python.com/thumbspage/examples/2.1-upgrades/R-embedded-thumbs-removed2.1.png |
| file | https://learning-python.com/thumbspage/user_configs.py |
| backups | https://learning-python.com/thumbspage/docetc/restore-prerotate-originals.py |
| code | https://learning-python.com/thumbspage/viewer_thumbs.py |
| viewer_thumbs.py | https://learning-python.com/thumbspage/viewer_thumbs.py |
| here | https://learning-python.com/thumbspage/UserGuide.html#GUI Mode |
| examples | https://learning-python.com/thumbspage/examples/ |
| downloads | https://learning-python.com/thumbspage.html#Download |
| web page | https://learning-python.com/thumbspage.html#Download |
| this script | https://learning-python.com/thumbspage/build/userguide-online-links.py |
| this | https://learning-python.com/thumbspage/build/_PUBLISH.sh |
| this | https://learning-python.com/thumbspage/build/generate-examples.py |
| this | https://learning-python.com/thumbspage/build/insert-analytics.py |
| this | https://learning-python.com/thumbspage/examples/2.0-upgrades/_generate.sh |
| this | https://learning-python.com/thumbspage/examples/dynamiclayout/_generate.sh |
| build | https://learning-python.com/thumbspage/build |
| change | https://learning-python.com/thumbspage/build/x-publish-external-demos.sh |
| generate | https://learning-python.com/trnpix/_generate.sh |
| publish | https://learning-python.com/trnpix/_publish.sh |
| demo | https://learning-python.com/trnpix/index.html |
| package | https://learning-python.com/thumbspage/ |
| slideshow | https://learning-python.com/thumbspage/examples/2.0-upgrades/auto-slideshow-view-normalfont.png |
| fullscreen | https://learning-python.com/thumbspage/examples/2.0-upgrades/fullscreen-mobile-fson.jpg |
| Top button | https://learning-python.com/thumbspage/examples/2.0-upgrades/floating-top-custom-midpage.png |
| custom dialog | https://learning-python.com/thumbspage/examples/2.0-upgrades/MORE-INFO-POPUP/info-custom-camera-brand2-ch.png |
| device line | https://learning-python.com/thumbspage/examples/2.0-upgrades/xtra-mobile-android6inch-info2.jpg |
| styling | https://learning-python.com/thumbspage/examples/2.0-upgrades/overflow-wrap-index-foldername.png |
| live demos | https://learning-python.com/thumbspage.html#demos |
| screenshots | https://learning-python.com/thumbspage/examples/2.0-upgrades/index.html |
| Automatic slideshows for viewer pages | https://learning-python.com/thumbspage/UserGuide.html#_201 |
| Optional floating Top button for large index pages | https://learning-python.com/thumbspage/UserGuide.html#_202 |
| Optional one-page fullscreen display for viewer pages | https://learning-python.com/thumbspage/UserGuide.html#_203 |
| Improved horizontal-overflow styling for border cases | https://learning-python.com/thumbspage/UserGuide.html#_204 |
| The iOS Chrome history-stacking bug is no more | https://learning-python.com/thumbspage/UserGuide.html#_205 |
| Replacement-target comment in the head | https://learning-python.com/thumbspage/UserGuide.html#_206 |
| Show user-friendly messages on console-input errors | https://learning-python.com/thumbspage/UserGuide.html#_20B |
| Info-popup: use a custom dialog instead of alert() | https://learning-python.com/thumbspage/UserGuide.html#_20A |
| Info-popup: add Device (or Software) line if present | https://learning-python.com/thumbspage/UserGuide.html#_207 |
| Info-popup: Taken=>Created if origin date unknown | https://learning-python.com/thumbspage/UserGuide.html#_208 |
| Info-popup: display dimensions as "Nw x Mh" | https://learning-python.com/thumbspage/UserGuide.html#_209 |
| Safari work-around: use HTML5 session storage for Auto | https://learning-python.com/thumbspage/UserGuide.html#_20C |
| Safari punt: Auto may stop (or crash) on Back to gallery | https://learning-python.com/thumbspage/UserGuide.html#_20D |
| Silence a pointless and confusing Pillow DOS warning | https://learning-python.com/thumbspage/UserGuide.html#_20E |
| Image auto-rotations are not optional in thumbspage | https://learning-python.com/thumbspage/UserGuide.html#_20F |
| Auto button | https://learning-python.com/thumbspage/examples/2.0-upgrades/auto-slideshow-view-android6inch-1.jpg |
| here | https://learning-python.com/thumbspage/examples/2.0-upgrades/auto-slideshow-view-normalfont.png |
| demo | https://learning-python.com/thumbspage.html#demos |
| configs file | https://learning-python.com/thumbspage/user_configs.py |
| Raw button | https://learning-python.com/thumbspage/examples/1.7-upgrades/ios13-safari-hid-landscape.PNG |
| 1.7 | https://learning-python.com/thumbspage/UserGuide.html#_174 |
| browser | https://duckduckgo.com/?q=Throttling+Javascript+Timers |
| Safari | https://learning-python.com/thumbspage/UserGuide.html#moresafarijunk |
| coverage | https://learning-python.com/thumbspage/UserGuide.html#slideshowbutton |
| proposal | https://learning-python.com/thumbspage/UserGuide.html#_dnH |
| template | https://learning-python.com/cgi/showcode.py?name=thumbspage/template-viewpage.html |
| here | https://learning-python.com/thumbspage/examples/2.0-upgrades/demo-pagestate-basics/ |
| here | https://learning-python.com/thumbspage/examples/2.0-upgrades/demo-timerloop-basics/ |
| indicator | https://learning-python.com/thumbspage/examples/2.1-upgrades/Q-auto-slideshow-on-indicator.png |
| note | https://learning-python.com/thumbspage/UserGuide.html#21autofull |
| warning | https://learning-python.com/thumbspage/examples/2.0-upgrades/javascript-desktop-viewpage-off.png |
| experience | https://learning-python.com/thumbspage/examples/2.0-upgrades/javascript-desktop-viewpage-on.png |
| note | https://learning-python.com/thumbspage/UserGuide.html#_vt1 |
| Top button | https://learning-python.com/thumbspage/examples/2.0-upgrades/floating-top-default-footer.png |
| here | https://learning-python.com/thumbspage/examples/2.0-upgrades/_thumbspage/floating-top-custom-footer.png.html |
| here | https://learning-python.com/trnpix/index.html |
| configs file | https://learning-python.com/thumbspage/user_configs.py |
| template-floatingtop.html | https://learning-python.com/cgi/showcode.py?name=thumbspage/template-floatingtop.html |
| file | https://learning-python.com/thumbspage/UserGuide.html#Customization |
| here | https://learning-python.com/thumbspage/examples/2.0-upgrades/floating-top-default-footer.png |
| similar | https://learning-python.com/thumbspage/examples/2.0-upgrades/floating-top-custom-footer.png |
| displays | https://learning-python.com/thumbspage/examples/2.0-upgrades/floating-top-mobile-ios4inch.PNG |
| Full button | https://learning-python.com/thumbspage/examples/2.0-upgrades/fullscreen-mobile-fsoff.jpg |
| user_configs.py | https://learning-python.com/thumbspage/user_configs.py |
| here | https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API |
| note | https://learning-python.com/thumbspage/UserGuide.html#fullscreenmanual |
| code | https://learning-python.com/cgi/showcode.py?name=thumbspage/template-viewpage.html |
| activated | https://learning-python.com/thumbspage/examples/2.1-upgrades/Z-2.1-viewer-pages-5-fullscreen.png |
| note | https://learning-python.com/thumbspage/UserGuide.html#21autofull |
| file | https://learning-python.com/thumbspage/user_configs.py |
| warning | https://learning-python.com/thumbspage/examples/2.0-upgrades/javascript-mobile-viewpage-off.jpg |
| platforms | https://learning-python.com/thumbspage/UserGuide.html#fullscreenmanual |
| this | https://learning-python.com/thumbspage/examples/2.0-upgrades/overflow-wrap-index-foldername.png |
| before | https://learning-python.com/thumbspage/examples/2.0-upgrades/overflow-wrap-viewer-fileandtoolbar1.png |
| after | https://learning-python.com/thumbspage/examples/2.0-upgrades/overflow-wrap-viewer-fileandtoolbar2.png |
| files | https://learning-python.com/thumbspage/UserGuide.html#Customization |
| generator | https://learning-python.com/thumbspage/thumbspage.py |
| template.
| https://learning-python.com/cgi/showcode.py?name=thumbspage/template-viewpage.html |
| release notes | https://learning-python.com/thumbspage/UserGuide.html#destacking16 |
| config-file | https://learning-python.com/thumbspage/user_configs.py |
| files | https://learning-python.com/thumbspage/UserGuide.html#Customization |
| this script | https://learning-python.com/thumbspage/build/insert-analytics.py |
| build | https://learning-python.com/thumbspage/build |
| console log | https://learning-python.com/thumbspage/examples/console-logs/2.0-console-errors.txt |
| script | https://learning-python.com/thumbspage/thumbspage.py |
| dialog | https://learning-python.com/thumbspage/examples/1.7-upgrades/info-dialog-chrome-mobile.png |
| dialog | https://learning-python.com/thumbspage/examples/2.0-upgrades/xtra-mobile-android6inch-info2.jpg |
| template file | https://learning-python.com/cgi/showcode.py?name=thumbspage/template-viewpage.html |
| captures | https://learning-python.com/thumbspage/examples/2.0-upgrades/index.html |
| gallery | https://learning-python.com/thumbspage/examples/2.0-upgrades/MORE-INFO-POPUP/index.html |
| usage | https://developers.google.com/web/updates/2017/03/dialogs-policy |
| silence | https://duckduckgo.com/?q=Prevent+this+page+from+creating+additional+dialogs |
| needed | https://learning-python.com/thumbspage/examples/2.0-upgrades/MORE-INFO-POPUP/info-x-ios4inch-hide-port.PNG |
| settings | https://learning-python.com/thumbspage/user_configs.py |
| appearance | https://learning-python.com/thumbspage/examples/2.0-upgrades/MORE-INFO-POPUP/info-xx-color-configs2.png |
| here | https://learning-python.com/thumbspage/UserGuide.html#popupcolors23 |
| here | https://learning-python.com/thumbspage/UserGuide.html#popupopacity23 |
| standard | https://www.exif.org/Exif2-2.PDF |
| escapes | https://learning-python.com/thumbspage/UserGuide.html#buglets23 |
| device | https://learning-python.com/thumbspage/examples/2.0-upgrades/MORE-INFO-POPUP/info-custom-camera-only1.png |
| brand | https://learning-python.com/thumbspage/examples/2.0-upgrades/MORE-INFO-POPUP/info-custom-camera-brand2-ch.png |
| software | https://learning-python.com/thumbspage/examples/2.0-upgrades/MORE-INFO-POPUP/info-custom-software2.png |
| tag | https://learning-python.com/thumbspage/examples/2.0-upgrades/MORE-INFO-POPUP/info-custom-none1.png |
| gallery | https://learning-python.com/thumbspage/examples/2.0-upgrades/MORE-INFO-POPUP/index.html |
| live demo | http://learning-python.com/trnpix/ |
| open ended | https://learning-python.com/thumbspage/UserGuide.html#_dnI |
| photo | https://learning-python.com/thumbspage/examples/2.0-upgrades/MORE-INFO-POPUP/info-custom-camera-brand1-ff.png |
| scan | https://learning-python.com/thumbspage/examples/2.0-upgrades/MORE-INFO-POPUP/info-custom-scanner2.png |
| drawn | https://learning-python.com/thumbspage/examples/2.0-upgrades/MORE-INFO-POPUP/info-custom-software2.png |
| filesystem | https://en.wikipedia.org/wiki/Comparison_of_file_systems#Metadata |
| os.path.getctime() | https://docs.python.org/3/library/os.path.html#os.path.getctime |
| searches | https://duckduckgo.com/?q=filesystem+creation+date |
| views | https://learning-python.com/thumbspage/UserGuide.html#_vt8 |
| in full | https://learning-python.com/thumbspage/UserGuide.html#msjepilogue |
| another | https://learning-python.com/thumbspage/UserGuide.html#egokillscode17 |
| file's source | https://learning-python.com/cgi/showcode.py?name=thumbspage/template-viewpage.html |
| here | https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage |
| here | https://www.w3schools.com/html/html5_webstorage.asp |
| ahead | https://learning-python.com/thumbspage/UserGuide.html#msjepilogue |
| falsy | https://developer.mozilla.org/en-US/docs/Glossary/Falsy |
| notorious | https://duckduckgo.com/?q=%22The+operation+couldn%27t+be+completed.+Operation+not+permitted%22+(NSPOSIXErrorDomain%3A1) |
| dialog | https://learning-python.com/thumbspage/examples/2.0-upgrades/_etc/bogus-safari-local-gallery-error-dialog.png |
| galleries on mobile altogether (but watch for later clues
in the epilogue).
In the possibly related department, it's worth noting that, both with and
without the change to use session storage, Safari also produces an uncatchable
exception on Auto image switch, which leaves the following suspicious
error message in the JavaScript console:
Not allowed to load local resource: file:///favicon.ico
This happens only for local-file views just like the initial Auto-slideshow
failures, but there appears to be no cause-and-effect relationship between the two:
the exception also occurs on Next and Prev taps, and isn't remedied by disabling
local-file restrictions in the Develop menu or pasting a valid favicon into the folder.
Just as strangely, a Back in Safari, only, does not run (or properly run)
resize handlers in remote galleries: if the window is resized while away, the gallery
doesn't catch up until the next page in the show or a forced reload. By contrast,
a Safari Back does resize local-file galleries, but also kills their shows
by clearing storage (and sometimes crashing). No other tested browser has these issues.
thumbspage tried multiple work-arounds to address the Safari failures—including
moving timer rescheduling from top-level code to pageshow event handler;
forcibly cancelling timers on page unloads; and forcibly reloading the
page when reshown. Some of these were meant to address the theory (really,
wild guess) that failures stemmed from the browser's
back-forward cache.
For example, the first of these used top-level JavaScript code of this form:
function autoContinue(event) {
// former top-level reschedule code of prior note
}
try {
trace('run timer-reschedule code deferred');
window.addEventListener('pageshow', autoContinue);
}
catch (err) {
trace('run timer-reschedule code immediately');
autoContinue(null); // run now in older browsers (or: window.onpageshow)
}
None of these attempts helped as coded.
Whether overzealous security constraints, cache optimization schemes gone bad,
or outright bugs, something is clearly amiss in Safari local-file views that
use session storage and timers.
As a more radical alternative,
HTML5 localStorage, unlike sessionStorage, might
not be erroneously cleared by Safari on Back, but this may not fix the crashes,
and is too broad and persistent to be used in any event: a site's slideshow toggle
would then be machine
global,
enduring to apply to later shows in ways users seem unlikely to expect—or
appreciate. Downgrading user experience this way for every browser
is not a valid fix for the foibles of one.
The upside here is that slideshows do work well in all other browsers, and work
well in Safari most of the time too, after moving to session storage. They're
currently known to fail only on switching from and to local galleries in specific
Safaris; this is a rare—and even unlikely—use case.
Nevertheless, given that this Safari
glitch has all the hallmarks of a browser-vendor bug, and has stubbornly defied all
work-around heroics to date,
it will have to remain an out-of-scope caveat for thumbspage 2.0.
If this Safari quirk crops up in your thumbspage adventures, your best recourses are
to tap Auto again to restart the show when possible; use an alternative browser that's
less broken; or lobby Apple to fix its junk.
Epilogue:
after the above was written, further usage revealed that a Back in Safari sometimes
stops Auto slideshows for all-remote (i.e., online) navigation too, if users leave to another
domain (i.e., site) and return to the slideshow page.
That is, Safari's Back glitch may also be triggered by a domain switch. Just as
importantly, all-remote stops appear to happen only in the desktop Safari browser—not
in mobile Safari on iOS 13, and not in a dozen other browsers tested among Windows, macOS, Linux,
and Android.
In more detail, Safari, only, is now also known to stop an Auto slideshow running
in an https:// page, after navigating to another https:// page
at a different domain, and returning to the https:// slideshow page with
Back. This does not happen for all such remote switches, however. Curiously—and
perhaps entertainingly—a slideshow running at https://learning-python.com
rarely stops when switching to and from https://apple.com, but reliably
does when the navigation target is https://google.com.
HTML5 session storage should endure for all like-kind pages visited in a browser tab (or window).
It's specific to page protocol and domain by definition
(see
here,
here, and
here),
so it's expected to start fresh when navigating from a file:// page to https://,
or to a new site in https://.
But a prior page's session storage should also be restored and/or intact when a Back returns
in both of these contexts, and neither a protocol- nor domain-switching Back should ever
crash the browser. Only Safari bears these warts.
There's certainly more to this story, but forensics sans code is guesswork, and we'll
have to leave this bug tale here. Whatever the underlying cause, this is clearly
an issue for Apple to resolve;
until it does, the work-around for thumbspage users remains an Auto-press restart,
or an alternative-browser install.
Today's desktop Safari seems far too prone to toss its cookies
(or at least its session storage...).
Silence a pointless and confusing Pillow DOS warning
thumbspage 2.0 was patched and rereleased in September 2020 to silence
a bogus DecompressionBombWarning message now issued
senselessly by the underlying
Pillow library for all large
images.
Because the fix does not in any way alter the galleries which thumbspage builds,
none need be regenerated; this mutes one build-time message only.
Specifically, when building galleries with images larger than 89MP,
the Pillow library by default prints a single DOS (denial of service)
warning message in program output that looks like this (with line-breaks
added here for marginal readability):
/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/PIL/Image.py:2797:
DecompressionBombWarning: Image size (108000000 pixels) exceeds limit of 89478485 pixels,
could be decompression bomb DOS attack.
warnings.warn(
This baseless warning is completely harmless, and does not impact thumbspage results;
large images work fine in thumbspage galleries whether this message appears or not.
But it's also stupidly excessive, and needlessly confuses users of
this and many other Pillow-based
programs.
The message's over-strong language may even scare some users over a threat
that doesn't exist.
The warning was first seen for valid 108MP images shot on a
Galaxy Note20 Ultra smartphone in 2020, and will crop up for all
the increasingly common large images created by newer devices and
tools. While the fix to silence the spurious warning
may be trivial for program developers, program users have no recourse,
and are left wondering if programs are buggy—or worse!
To see the fix's code for yourself, search for Sep-2020 in the
source.
Though simple, a "fix" is often far easier than a release.
At thumbspage's host site, multiple programs were impacted—including
thumbspage,
tagpix,
shrinkpix, and
PyPhoto—and each
required time-consuming retesting, repackaging, and redistribution.
This warning might be useful in some contexts, but it clearly should have
required an enable, not a disable.
Unfortunately, opt out is a regular by-product of opinion on overdrive.
Lesson: open-source agendas have consequences for others,
and "batteries included" development entails substantial trade-offs.
While this program could not easily exist without libraries like
Pillow, it's also woefully dependent on them—even when
they serve as platforms for personal preferences and subjective
changes that stomp on the work of others.
So don't be rude out there.
Postscript:
though scantly documented, it turns out that Pillow later turned the
warning described here into a full error for images larger
than twice the warning's size limit. Though unlikely, this error takes
the form of an exception that will cause client programs to fail or terminate.
Despite this, its only mention seems to be in an obscure
release note;
whose details contradict an earlier obscure
release note;
and require studying Pillow's
source code
for full fidelity.
To avoid large-image Pillow errors, thumbspage's warning-silencing code has been
updated to use a new and broader fix
that sets Image.MAX_IMAGE_PIXELS to None—which will,
of course, suffice only until Pillow tightens the screws again. Large images are not
all attacks, and their creators are hardly ever criminals; unless it really
means to anger programmers and insult users, Pillow should really think
about making this check both opt in and better documented.
Image auto-rotations are not optional in thumbspage
Short story:
version 2.0 explored the idea of dropping rotations (a.k.a. reorientations)
of tilted images in thumbspage, by propagating sources' Exif orientation
tags to their thumbnails and relying on browsers to rotate. This was rejected
because browsers still don't support rotations universally in fall 2020.
Browsers widely straighten images displayed alone,
but not images displayed as in-page elements—like those in thumbspage
index and
viewer pages.
To be inclusive of all users, thumbspage must rotate images itself,
because some browsers still
don't,
and even some that do today did not
rotate in versions released just a year or two
ago.
This note discusses the alternative
proposal and its later
rejection, as developer-oriented
information only; no changes were made, but the story is typical of
browser-dependent UI development.
The Proposal
Summary:
although thumbspage image rotations work well and as designed,
recent findings suggest that it may be possible to implement thumbspage without
rotations altogether, by propagating tags from sources to thumbnails. This hasn't
yet been fully verified and no thumbspage changes have been implemented—mostly
because programs that work don't generally need to be fixed—but this section
provides background on non-rotation alternatives.
Details:
to get started, we first need to understand the current rotation policy.
Given a tilted source image coded with a non-"normal" Exif orientation tag (of the
sort commonly had from smartphones held vertically), thumbspage today follows an
evolved procedure to reorient images for in-page display that works like this:
Rotate the source in memory to be right-side up
Back up the source's file to a .original copy
Save the rotated source to its file, with updated orientation,
width, and height Exif tags
Make and save a thumbnail from the rotated source
The first three of these steps can be turned off on a per-build-run basis
by a user configuration; if so disabled,
thumbnails aren't rotated either, just because they're built from unrotated sources.
This scheme arose in phases over multiple versions and releases.
thumbspage 1.5 displayed images too naively to count; 1.6 added
auto-rotation of tilted sources, and their thumbnails by proxy;
and 1.7 added Exif orientation-tag update and propagation for
rotated source images (thumbs are simply built from already-straightened sources). The
combination of these yields the procedure above, which is harmless for builders
and viewers, and ensures that both sources and thumbs display right-side up in all
contexts, regardless of their original orientation, and despite the vagaries of
web-browser support.
Like much in computing, though, there may be alternative ways to do this.
Per later research, it now appears that thumbspage may be able to skip
rotations for both source images and their thumbnails altogether, as long
as sources' orientation tags are propagated to their thumbnails.
A non-rotation option is too involved to cover in full
here, and is outside the scope of version 2.0. But the facts behind
this alternative merit a few words.
In short, the JavaScript DOM seems to account for image orientation automatically
in both its image properties and display. Specifically, the standard's doc
here
says this on the subject:
The IDL attributes naturalWidth and naturalHeight must return the
density-corrected intrinsic width and height of the image, in CSS pixels,
if the image has intrinsic dimensions and is available, or else 0.
...
Since the intrinsic dimensions of an image take into account any orientation
specified in its metadata, naturalWidth and naturalHeight reflect the dimensions
after applying any rotation needed to correctly orient the image, regardless
of the value of the 'image-orientation' property.
In other words, the DOM's "natural" sizes in JavaScript are already corrected
for right-side-up display. The doc doesn't explicitly state that images
themselves will be displayed this way when rendered as in-page elements,
but this seems the case for a handful of major browsers in recent tests so far.
Because thumbspage has used the DOM's natural width and height in its dynamic
image scaling since 1.6, it sizes the image for display in a viewer page
with orientation already "baked in." By contrast, version 1.5 used the Pillow
library's build-time width and height, which are not corrected for
orientation the way that the DOM properties are; the result is an unscaled
image auto-rotated by the same browsers, but stretched into pre-rotation dimensions.
Given the DOM's definition—and assuming every browser of interest implements an
arguably implicit reorientation for in-page display—thumbspage's own reorientation
of the source image is not required. Reorientation of thumbnails may
similarly be unnecessary, but only as long as the source's orientation tag
is propagated unchanged to the thumb to force the browser's adjustment.
In sum, the alternative non-rotating procedure would:
Make a thumbnail from the source in memory
Copy the source's Exif orientation tag to the thumbnail
Save the thumbnail to a file
And hope that every browser on the planet does the right thing for in-page
display of unstraightened images, both source and thumb
This seems simpler, and may be, but it still must propagate updated tags using the
piexif library (and fix tags known to make that library fail);
requires the image-info
popup
to get dimensions from the JavaScript DOM instead of build-time Pillow (else they
may appear swapped); and adds a browser-support dependency that the current scheme
evades (and these are almost always
best
evaded).
On the other hand, the source image would remain unchanged.
The required tag propagation of step 2 in the alternative scheme wasn't considered
in 1.6 because it wasn't implemented until thumbspage 1.7. Prior to that, thumbnails
made from unrotated sources were
askew
just because they had no orientation tag (and rotated source images were
askew if their tags were copied but not
updated).
Rotating the source solved the issue in 1.6, but may now seem overkill.
All of which sounds simpler in hindsight, but thumbspage's scheme arose
in piecemeal fashion over years, and cannot easily be modified today.
While it's possible to disable thumbspage's auto-rotations process by setting
autoRotateImages to False in
user_configs.py, this leaves thumbs
tilted: because they're currently built from source images without copying the
source's orientation tag, they will display askew. Hence, either the source
must be rotated first (as done currently), or code must be changed to skip rotations
and propagate source tags to thumbs. And any change must also be predicated on
universal browser support for reorientations.
For now, thumbspage's reorientation scheme works as intended, has been used
successfully for years, and incurs no penalties apart from the minor overhead
of .original backups.
While rotations might be rendered superfluous with redesign and recoding,
it's difficult to justify fixing a program with such a positive marketing story.
In its role as example for learners, however, thumbspage follows a
full-disclosure policy—even when that means pointing out its own rooms
for possible improvement.
The Rejection
Stop the presses:
the non-rotating alternative proposed in the preceding section proved to be
unusable after testing revealed that browser support for reorientation
of images displayed as in-page elements is still coming online, and nowhere
near the universal level required even on the latest platforms. Hence, in
the name of inclusiveness, thumbspage will continue to rotate source and
thumbnail images itself, because some browsers don't.
Details:
although Exif orientation support has appeared in some browsers
by fall 2020, a more complete analysis reveals that this is a very recent feature
that has been appearing slowly. Along the way, its course included a
CSS property
that aimed to force the issue, but had weak support and was
deprecated in favor of automatic adjustment. While automatic
reorientation seems on track to becoming the norm in years
ahead, it won't be present in versions of some browsers released
just one or two years ago, and may never be adopted by others.
As a sample of where this support lies today, the following table
summarizes auto-rotation findings for desktop and mobile browsers,
as compiled empirically by thumbspage's testing department in October 2020;
a "No" in the leftmost column means the browser doesn't adjust
for orientation when displaying images as in-page elements:
Rotates Device OS Browser Version Released
No Desktop macOS 10.15 Firefox 70 Oct-2019
No Desktop macOS 10.15 Safari 13 Sep-2019
Yes Desktop macOS 10.15 Firefox 78 Jul-2020
Yes Desktop macOS 10.15 Chrome 85 Aug-2020
No Desktop Windows 7 Chrome 77 Sep-2019
No Desktop Windows 7 Firefox 56 Sep-2017
No Desktop Windows 7 IE 9 (unknown)
No Desktop Windows 10 IE 11 (unknown)
Yes Desktop Windows 10 Firefox 78 Jun-2020
Yes Desktop Windows 10 Chrome 85 Aug-2020
Yes Desktop Windows 10 Edge 85 2020
No Mobile Android 7 Firefox 65 Jan-2019
Yes Mobile Android 7 Chrome 81 Apr-2020
No Mobile Android 10 Samsung 12 Jun-2020
Yes Mobile Android 10 Chrome 85 Aug-2020
Yes Mobile Android 10 Firefox 81 Oct-2020
Yes Mobile iOS 13 Safari 13 Sep-2019
Yes Mobile iOS 13 Chrome 84 Jul-2019
For a more graphical look at these results, open the examples' thumbspage-screenshots
gallery.
As you can see, auto-rotation has come to some browsers in just the last
year, and others still don't support it at all in fall 2020.
On both desktop and mobile devices, current and recent versions of
widely used web browsers still show orientation-coded images askew.
Which nicely captures a dilemma constantly facing engineers who work in a
field as dynamic as software. Dropping its own reorientation might make
sense if thumbspage could restrict its scope to just the latest-and-greatest
browsers and versions.
As a program designed to build galleries inclusive of all viewers,
though, this is not an option. Even for browsers that have added
the required support recently, versions just a few years old will still
be common for years to come (despite the best efforts of their vendors).
Because we don't live in a world that restarts afresh each release
cycle, thumbspage cannot be changed to rely on browsers to reorient
tilted images any time soon. While this might trim some program
complexity, it wouldn't work for many thumbspage-gallery viewers
today, and requiring browser updates or replacements just to view
thumbspage galleries would both be too extreme, and almost certainly
qualify as rude (see the prior note).
For hard-core readers: the following Python session demos one way to do
the source-to-thumb tag propagation which was tested but ruled out;
Pillow also has some support for reading tags and processing them as
a bytes blob (see reorientImage in
viewer_thumbs.py), but
little to match
piexif
when it comes to updating tags:
>>> from PIL import Image
>>> import piexif
>>> it = Image.open('2020-09-17__180904.jpg') # unreoriented thumb
>>> es = piexif.load('../2020-09-17__180904.jpg') # source tags (unreoriented)
>>> et = piexif.load('2020-09-17__180904.jpg') # thumb tags (none yet)
>>> es['0th'][piexif.ImageIFD.Orientation]
6
>>> et
{'0th': {}, 'Exif': {}, 'GPS': {}, 'Interop': {}, '1st': {}, 'thumbnail': None}
>>>
>>> et['0th'][piexif.ImageIFD.Orientation] = es['0th'][piexif.ImageIFD.Orientation]
>>> et['0th'][piexif.ImageIFD.Orientation]
6
>>> saveexifs = piexif.dump(et)
>>> saveexifs[:20]
b'Exif\x00\x00MM\x00*\x00\x00\x00\x08\x00\x01\x01\x12\x00\x03'
>>> it.save('2020-09-17__180904.jpg', exif=saveexifs)
It's also worth noting that Pillow's ImageOps module
has a call exif_transpose(image) that straightens images
and simply deletes their Exif orientation tags, but this call
also discards all other Exif tags if its result is saved directly;
per warnings, seems to have even more issues parsing tags than
piexif;
and wouldn't make logistics any easier here in any event—regardless
of how rotation is coded, Exif tags must be propagated to sources for display,
and thumbs and sources must be saved to files in reoriented form because
both are displayed in thumbspage galleries as in-page elements that
aren't automatically righted by many browsers:
>>> from PIL import ImageOps
>>> it = Image.open('../2020-09-17__180904.jpg') # unreoriented source
>>> ir = ImageOps.exif_transpose(it)
/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/PIL/TiffImagePlugin.py:588: UserWarning: Metadata Warning, tag 282 had too many entries: 2, expected 1
warnings.warn(
/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/PIL/TiffImagePlugin.py:588: UserWarning: Metadata Warning, tag 283 had too many entries: 2, expected 1
warnings.warn(
/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/PIL/TiffImagePlugin.py:588: UserWarning: Metadata Warning, tag 34853 had too many entries: 6, expected 1
warnings.warn(
>>> ir.save('rotated.jpg') # simple saves drop Exif tags
>>> piexif.load('rotated.jpg')
{'0th': {}, 'Exif': {}, 'GPS': {}, 'Interop': {}, '1st': {}, 'thumbnail': None}
>>> piexif.load('../2020-09-17__180904.jpg')
{'0th': {256: 4000, 257: 3000, 271: b'samsung', 272: b'SM-N986U1'... # and a lot more
In the end—and with all the evidence in—thumbspage
did the right rotations thing in 2018
and still does in
2020.
Its universally portable image reorientation still beats the partial
support among browsers today (even if readers 10 years down the pike may not think so).
| https://learning-python.com/thumbspage/UserGuide.html#_vt8 |
| epilogue | https://learning-python.com/thumbspage/UserGuide.html#msjepilogue |
| back-forward cache | https://duckduckgo.com/?q=safari+back-forward+cache |
| global | https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage |
| here | https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage |
| here | https://www.w3schools.com/html/html5_webstorage.asp |
| here | https://html.spec.whatwg.org/multipage/webstorage.html#webstorage |
| Pillow | https://pypi.org/project/Pillow/ |
| images | https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.open |
| programs | https://duckduckgo.com/?q=Pillow+DecompressionBombWarning |
| source | https://learning-python.com/thumbspage/viewer_thumbs.py |
| thumbspage | https://learning-python.com/thumbspage.html |
| tagpix | https://learning-python.com/tagpix.html |
| shrinkpix | https://learning-python.com/shrinkpix.html |
| PyPhoto | https://learning-python.com/pygadgets.html |
| release note | https://pillow.readthedocs.io/en/stable/releasenotes/5.0.0.html |
| release note | https://pillow.readthedocs.io/en/stable/releasenotes/4.2.0.html |
| source code | https://pillow.readthedocs.io/en/stable/_modules/PIL/Image.html?highlight=MAX_IMAGE_PIXELS |
| broader fix | https://learning-python.com/thumbspage/viewer_thumbs.py |
| index | https://learning-python.com/thumbspage/examples/reorientation/index.html |
| viewer | https://learning-python.com/thumbspage/examples/reorientation/_thumbspage/galaxys8-6R.jpg.html |
| don't | https://learning-python.com/thumbspage/examples/reorientation/Unrotated-images-in-browsers/_thumbspage/m-android10-NO-samsung-12-source.jpg.html |
| ago | https://learning-python.com/thumbspage/examples/reorientation/Unrotated-images-in-browsers/index.html |
| proposal | https://learning-python.com/thumbspage/UserGuide.html#tpsansrotates_proposal |
| rejection | https://learning-python.com/thumbspage/UserGuide.html#tpsansrotates_rejection |
| configuration | https://learning-python.com/thumbspage/user_configs.py |
| auto-rotation | https://learning-python.com/thumbspage/UserGuide.html#rotation16 |
| propagation | https://learning-python.com/thumbspage/UserGuide.html#_17C |
| here | https://html.spec.whatwg.org/multipage/embedded-content.html#dom-img-naturalwidth |
| fail | https://learning-python.com/thumbspage/UserGuide.html#_17G |
| popup | https://learning-python.com/thumbspage/examples/2.0-upgrades/MORE-INFO-POPUP/info-custom-camera-brand1-ff.png |
| best | https://learning-python.com/thumbspage/UserGuide.html#_205 |
| evaded | https://learning-python.com/thumbspage/UserGuide.html#_17F |
| askew | https://learning-python.com/thumbspage/examples/Screenshots/reorient-prior-index.png |
| updated | https://learning-python.com/thumbspage/examples/Screenshots/reorient-prior-viewer.png |
| user_configs.py | https://learning-python.com/thumbspage/user_configs.py |
| CSS property | https://developer.mozilla.org/en-US/docs/Web/CSS/image-orientation |
| gallery | https://learning-python.com/thumbspage/examples/reorientation/Unrotated-images-in-browsers/index.html |
| note | https://learning-python.com/thumbspage/UserGuide.html#pillowdoswarning |
| viewer_thumbs.py | https://learning-python.com/thumbspage/viewer_thumbs.py |
| piexif | https://pypi.org/project/piexif/ |
| piexif | https://learning-python.com/thumbspage/UserGuide.html#piexifworkaround |
| 2018 | https://learning-python.com/thumbspage/UserGuide.html#1.6 |
| 2020 | https://learning-python.com/thumbspage/examples/reorientation/Unrotated-images-in-browsers/index.html |
| popup | https://learning-python.com/thumbspage/examples/1.7-upgrades/info-dialog-chrome-mobile.png |
| display | https://learning-python.com/thumbspage/examples/Screenshots/scaling-android-raw-landscape.png |
| together | https://learning-python.com/thumbspage/examples/1.7-upgrades/largefont-buttons-fixed.png |
| displays | https://learning-python.com/thumbspage/examples/1.7-upgrades/image-larger-desktop-1.7.png |
| browsers | https://learning-python.com/thumbspage/UserGuide.html#drophover17 |
| popups | https://learning-python.com/thumbspage/examples/1.7-upgrades/info-dialog-chrome-desktop.png |
| GIFs | https://learning-python.com/thumbspage/UserGuide.html#thumbnails17 |
| images | https://learning-python.com/thumbspage/UserGuide.html#rotateskeepexifs |
| folder name | https://learning-python.com/thumbspage/UserGuide.html#otherusagemodes |
| galleries | https://learning-python.com/thumbspage/UserGuide.html#imagesizeandspeed |
| for you | http://learning-python.com/shrinkpix.html |
| popups | https://learning-python.com/thumbspage/UserGuide.html#digitzedscanlabel17 |
| browsers | https://learning-python.com/thumbspage/UserGuide.html#iosscale17 |
| pages | https://learning-python.com/thumbspage/UserGuide.html#iostextupscale17 |
| library | https://learning-python.com/thumbspage/UserGuide.html#Installs and Platforms |
| June patch | https://learning-python.com/thumbspage/UserGuide.html#piexifworkaround |
| code files | https://learning-python.com/thumbspage/ |
| screenshots page | https://learning-python.com/thumbspage/examples/1.7-upgrades/index.html |
| Avoid image clipping at large font settings | https://learning-python.com/thumbspage/UserGuide.html#_171 |
| Avoid button run-together at very large font settings | https://learning-python.com/thumbspage/UserGuide.html#_172 |
| Open a new info popup dialog on filename click/tap | https://learning-python.com/thumbspage/UserGuide.html#_173 |
| Open the full image on image click/tap, just like Raw | https://learning-python.com/thumbspage/UserGuide.html#_174 |
| Note version number and generation date in all pages | https://learning-python.com/thumbspage/UserGuide.html#_175 |
| Viewer-pages and clean-thumbs default to yes in console prompts | https://learning-python.com/thumbspage/UserGuide.html#_176 |
| Allow folder name to be passed in as a command-line argument | https://learning-python.com/thumbspage/UserGuide.html#_177 |
| Skip Unix .* hidden names in subfolders bullet lists | https://learning-python.com/thumbspage/UserGuide.html#_178 |
| Remove tkinter dependency for building on Android | https://learning-python.com/thumbspage/UserGuide.html#_179 |
| Drop hover italics/underline effects for toolbar buttons | https://learning-python.com/thumbspage/UserGuide.html#_17A |
| Improve thumbnail quality for shrunken images and GIFs (Mar) | https://learning-python.com/thumbspage/UserGuide.html#_17B |
| Retain—and update—Exif tags in rotated JPEG images (Mar) | https://learning-python.com/thumbspage/UserGuide.html#_17C |
| Index pages: avoid text upscaling in iOS Safari landscape (May) | https://learning-python.com/thumbspage/UserGuide.html#_17D |
| Info popup: label scans as "Digitized" instead of "Taken" (May) | https://learning-python.com/thumbspage/UserGuide.html#_17E |
| iOS landscape: use JavaScript image scaling in all browsers (May) | https://learning-python.com/thumbspage/UserGuide.html#_17F |
| piexif work-around: fix rare failures on some rotated images (Jun) | https://learning-python.com/thumbspage/UserGuide.html#_17G |
| border | https://learning-python.com/thumbspage/examples/1.7-upgrades/largefont-clip-prefix-border.png |
| content | https://learning-python.com/thumbspage/examples/1.7-upgrades/largefont-clip-prefix-content.png |
| desktop | https://learning-python.com/thumbspage/examples/1.7-upgrades/largefont-clip-desktop-prefix.png |
| here | https://learning-python.com/thumbspage/examples/1.7-upgrades/largefont-clip-fixed-large.png |
| here | https://learning-python.com/thumbspage/examples/1.7-upgrades/largefont-clip-fixed-normal.png |
| here | https://learning-python.com/thumbspage/examples/1.7-upgrades/largefont-clip-desktop-fixed.png |
| run together | https://learning-python.com/thumbspage/examples/1.7-upgrades/largefont-buttons-prefix.png |
| here | https://learning-python.com/thumbspage/examples/1.7-upgrades/largefont-buttons-fixed.png |
| here | https://learning-python.com/thumbspage/examples/1.7-upgrades/_thumbspage/image-larger-desktop-1.6.png.html |
| examples | https://learning-python.com/thumbspage/examples/ |
| demos | http://learning-python.com/thumbspage.html#demos |
| note | https://learning-python.com/thumbspage/UserGuide.html#_204 |
| template file | https://learning-python.com/cgi/showcode.py?name=thumbspage/template-viewpage.html |
| desktop | https://learning-python.com/thumbspage/examples/1.7-upgrades/info-dialog-chrome-desktop.png |
| mobile | https://learning-python.com/thumbspage/examples/1.7-upgrades/info-dialog-chrome-mobile.png |
| Exif | https://en.wikipedia.org/wiki/Exif |
| standard | https://www.exif.org/Exif2-2.PDF |
| ahead | https://learning-python.com/thumbspage/UserGuide.html#_17E |
| custom dialog | https://learning-python.com/thumbspage/examples/2.0-upgrades/MORE-INFO-POPUP/info-custom-camera-brand1-ff.png |
| release note | https://learning-python.com/thumbspage/UserGuide.html#infocustom20 |
| maker line | https://learning-python.com/thumbspage/UserGuide.html#_207 |
| images | https://learning-python.com/thumbspage/UserGuide.html#_208 |
| 2.2 | https://learning-python.com/thumbspage/UserGuide.html#2.2 |
| 2.3 | https://learning-python.com/thumbspage/UserGuide.html#2.3 |
| browser | https://learning-python.com/thumbspage/examples/Screenshots/scaling-norm-raw.png |
| normal | https://learning-python.com/thumbspage/examples/Screenshots/scaling-android-landscape.png |
| tapped | https://learning-python.com/thumbspage/examples/Screenshots/scaling-android-raw-landscape.png |
| slideshows | https://learning-python.com/thumbspage/UserGuide.html#slideshow20 |
| utility script | https://learning-python.com/thumbspage/docetc/cmp-thumbspage-results.py |
| reply | https://learning-python.com/thumbspage/UserGuide.html#Running thumbspage |
| examples | https://learning-python.com/thumbspage/examples/console-logs/ |
| earlier | https://learning-python.com/thumbspage/UserGuide.html#otherusagemodes |
| examples | https://learning-python.com/thumbspage/examples/console-logs/ |
| 2.2 | https://learning-python.com/thumbspage/UserGuide.html#2.2 |
| 2.3 | https://learning-python.com/thumbspage/UserGuide.html#2.3 |
| this module | https://learning-python.com/thumbspage/viewer_thumbs.py |
| mode | https://learning-python.com/thumbspage/UserGuide.html#GUI Mode |
| Termux | https://termux.com/ |
| Pydroid 3 | https://play.google.com/store/apps/details?id=ru.iiec.pydroid3 |
| notebox | https://learning-python.com/thumbspage/UserGuide.html#androidnote |
| two | https://learning-python.com/thumbspage/examples/1.7-upgrades/note10-samsung-stylus-cursor.jpg |
| formerly | https://learning-python.com/thumbspage/examples/1.7-upgrades/x-hover-effects-before-1.6.png |
| above | https://learning-python.com/thumbspage/UserGuide.html#filenametap |
| as of 1.7 | https://learning-python.com/thumbspage/examples/1.7-upgrades/x-hover-effects-after-1.7.png |
| this MDN page | https://developer.mozilla.org/en-US/docs/Web/CSS/:hover |
| this search | https://duckduckgo.com/?q=ios+hover+double+tap&ia=web |
| Samsung's browser | https://learning-python.com/thumbspage/examples/1.7-upgrades/note10-samsung-stylus-cursor.jpg |
| improved | https://learning-python.com/thumbspage/examples/1.7-upgrades/zz-gif-thumbs-after-rbga.png |
| above | https://learning-python.com/thumbspage/UserGuide.html#imagesizeandspeed |
| shrinkpix | http://learning-python.com/shrinkpix.html |
| before | https://learning-python.com/thumbspage/examples/1.7-upgrades/zz-gif-thumbs-before-rbga.png |
| after | https://learning-python.com/thumbspage/examples/1.7-upgrades/zz-gif-thumbs-after-rbga.png |
| viewer-thumbs.py | https://learning-python.com/thumbspage/viewer_thumbs.py |
| note | https://learning-python.com/thumbspage/UserGuide.html#enhancedthumbs21 |
| popups | https://learning-python.com/thumbspage/examples/1.7-upgrades/rotate-exifs1-info-taken.png |
| auto-rotation | https://learning-python.com/thumbspage/UserGuide.html#rotation16 |
| Exif | https://en.wikipedia.org/wiki/Exif |
| standard | https://www.exif.org/Exif2-2.PDF |
| above | https://learning-python.com/thumbspage/UserGuide.html#filenametap |
| this page | https://learning-python.com/thumbspage/examples/reorientation/_thumbspage/galaxys8-3U.jpg.html |
| Raw mode | https://learning-python.com/thumbspage/examples/1.7-upgrades/rotate-exifs3-raw-SANSupdates.png |
| date taken | https://learning-python.com/thumbspage/examples/1.7-upgrades/rotate-exifs1-info-taken.png |
| the Raw apes | https://learning-python.com/thumbspage/examples/1.7-upgrades/rotate-exifs2-raw.png |
| piexif library | https://pypi.org/project/piexif/ |
| package | https://learning-python.com/thumbspage/piexif/ |
| ahead | https://learning-python.com/thumbspage/UserGuide.html#piexifworkaround |
| here | https://learning-python.com/thumbspage/UserGuide.html#tpsansrotates |
| update | https://learning-python.com/thumbspage/UserGuide.html#21rotations |
| file | https://learning-python.com/thumbspage/user_configs.py |
| file | https://learning-python.com/thumbspage/UserGuide.html#Customization |
| this | https://learning-python.com/thumbspage/examples/1.7-upgrades/digitized-fix-scan-after.jpg |
| standard | https://www.exif.org/Exif2-2.PDF |
| tagpix | http://learning-python.com/tagpix.html |
| scan | https://learning-python.com/thumbspage/examples/1.7-upgrades/digitized-fix-scan-before.jpg |
| camera | https://learning-python.com/thumbspage/examples/1.7-upgrades/digitized-other-photo.jpg |
| scanned | https://learning-python.com/thumbspage/examples/1.7-upgrades/digitized-fix-scan-after.jpg |
| screenshot | https://learning-python.com/thumbspage/examples/1.7-upgrades/digitized-other-shot.jpg |
| try this | https://en.wikipedia.org/wiki/Exif#Problems |
| tested | https://learning-python.com/thumbspage/examples/1.7-upgrades/ios-scaled-landscape-ch.png |
| behavior | https://learning-python.com/thumbspage/examples/1.7-upgrades/image-larger-mobile-1.7.jpg |
| once | https://learning-python.com/thumbspage/examples/1.7-upgrades/ios11-safari-landscape-new-1t.png |
| image | https://learning-python.com/thumbspage/examples/1.7-upgrades/ios11-safari-landscape-new-2b.png |
| before | https://learning-python.com/thumbspage/examples/1.7-upgrades/ios11-safari-landscape-old-2b.PNG |
| ideally | https://learning-python.com/thumbspage/examples/1.7-upgrades/ios13-safari-hid-landscape.PNG |
| menu | https://learning-python.com/thumbspage/examples/1.7-upgrades/ios13-safari-hide-toolbars.PNG |
| views | https://learning-python.com/thumbspage/examples/1.7-upgrades/ios11-safari-landscape-old-1t.PNG |
| file | https://learning-python.com/thumbspage/user_configs.py |
| here | https://learning-python.com/thumbspage/UserGuide.html#scaling16 |
| here | https://learning-python.com/thumbspage/UserGuide.html#_dn9 |
| scrolled scaling | https://learning-python.com/thumbspage/examples/1.7-upgrades/ios11-safari-landscape-old-1t.PNG |
| here | https://learning-python.com/thumbspage/UserGuide.html#destacking16 |
| here | https://gs.statcounter.com/browser-market-share |
| toolbars | https://learning-python.com/thumbspage/examples/1.7-upgrades/ios11-safari-landscape-new-1t.png |
| Chrome | https://learning-python.com/thumbspage/examples/1.7-upgrades/ios-scaled-landscape-ch.png |
| Firefox | https://learning-python.com/thumbspage/examples/1.7-upgrades/ios-scaled-landscape-ff.png |
| Edge | https://learning-python.com/thumbspage/examples/1.7-upgrades/ios-scaled-landscape-eg.png |
| UC Browser | https://learning-python.com/thumbspage/examples/1.7-upgrades/ios-scaled-landscape-uc.png |
| Android | https://learning-python.com/thumbspage/examples/Screenshots/scaling-android-landscape.png |
| window | https://learning-python.com/thumbspage/examples/1.7-upgrades/ios13-safari-hide-toolbars.PNG |
| web search | https://duckduckgo.com/?&q=safari+ios+13+hide+toolbar |
| like this | https://learning-python.com/thumbspage/examples/1.7-upgrades/ios13-safari-hid-landscape.PNG |
| display | https://learning-python.com/thumbspage/examples/1.7-upgrades/ios13-safari-hid-portrait.PNG |
| broken | https://learning-python.com/thumbspage/examples/1.7-upgrades/ios-portrait-safari.png |
| widgets | https://duckduckgo.com/?q=ioS+Safari+toolbar+double+taps+hide+toolbar |
| host | https://learning-python.com/about-this-site.html#safariios13toolbars |
| top | https://learning-python.com/thumbspage/examples/1.7-upgrades/ios11-safari-landscape-new-1t.png |
| bottom | https://learning-python.com/thumbspage/examples/1.7-upgrades/ios11-safari-landscape-new-2b.png |
| down-scroll) | https://learning-python.com/thumbspage/examples/1.7-upgrades/ios11-safari-landscape-old-2b.PNG |
| disabled | https://learning-python.com/thumbspage/examples/Screenshots/scaling-nojavascript-warn.png |
| displays | https://learning-python.com/thumbspage/examples/1.7-upgrades/ios11-safari-landscape-old-1t.PNG |
| file | https://learning-python.com/thumbspage/user_configs.py |
| defect | https://learning-python.com/edge41-hover-left.png |
| page | https://learning-python.com/edge-links-bug.html |
| duet | https://learning-python.com/about-this-site.html#chromeduet |
| display | https://learning-python.com/android-chrome-duet-lp5e-land.jpg |
| agendas | https://duckduckgo.com/?q=android+chrome+duet |
| piexif | https://learning-python.com/thumbspage/UserGuide.html#Installs and Platforms |
| earlier | https://learning-python.com/thumbspage/UserGuide.html#rotateskeepexifs |
| piexif | https://pypi.org/project/piexif/ |
| Pillow | https://pypi.python.org/pypi/Pillow |
| GitHub | https://github.com/hMatoba/Piexif/issues/95 |
| standard | https://www.exif.org/Exif2-2.PDF |
| tagpix | https://learning-python.com/tagpix.html |
| report | https://github.com/hMatoba/Piexif/issues/83 |
| viewer_thumbs.py | https://learning-python.com/thumbspage/viewer_thumbs.py |
| worse | https://learning-python.com/thumbspage/UserGuide.html#rotateskeepexifs |
| 1.6 note | https://learning-python.com/thumbspage/UserGuide.html#rotation16 |
| GUI viewer | https://learning-python.com/thumbspage/UserGuide.html#GUI Mode |
| version 1.7 | https://learning-python.com/thumbspage/UserGuide.html#android |
| JavaScript | https://learning-python.com/cgi/showcode.py?name=thumbspage/template-viewpage.html |
| images | https://learning-python.com/thumbspage/examples/2.0-upgrades/xtra-desktop.png |
| Chrome | https://learning-python.com/thumbspage/examples/Screenshots/trnpix-view-desktop1.png |
| Firefox | https://learning-python.com/thumbspage/examples/Screenshots/unicode-images-view1-firefox.png |
| Windows | https://learning-python.com/thumbspage/examples/Screenshots/trnpix-x-windows-view.png |
| Linux | https://learning-python.com/thumbspage/examples/Screenshots/trnpix-x-linux-view.png |
| Chrome | https://learning-python.com/thumbspage/examples/Screenshots/scaling-android-portrait.png |
| Safari | https://learning-python.com/thumbspage/examples/Screenshots/scaling-ios-portrait.jpeg |
| space | https://learning-python.com/thumbspage/examples/Screenshots/trnpix-view-mobile2.png |
| mode | https://learning-python.com/thumbspage/examples/Screenshots/scaling-ios-landscape.jpeg |
| images | https://learning-python.com/thumbspage/examples/Screenshots/scaling-android-landscape.png |
| solve | https://learning-python.com/thumbspage/examples/1.7-upgrades/ios13-safari-hid-landscape.PNG |
| problems | https://learning-python.com/thumbspage/examples/1.7-upgrades/ios11-safari-landscape-new-2b.png |
| Android | https://learning-python.com/thumbspage/examples/1.7-upgrades/image-larger-mobile-1.7.jpg |
| iOS | https://learning-python.com/thumbspage/examples/1.7-upgrades/ios-scaled-landscape-ch.png |
| here | https://learning-python.com/thumbspage/UserGuide.html#iosscale17 |
| message | https://learning-python.com/thumbspage/examples/Screenshots/scaling-loading-1.png |
| indicator | https://learning-python.com/thumbspage/examples/Screenshots/scaling-loading-mobile-1.png |
| note | https://learning-python.com/thumbspage/examples/Screenshots/scaling-nojavascript-warn.png |
| results | https://learning-python.com/thumbspage/examples/Screenshots/scaling-nojavascript-mobile.png |
| the code | https://learning-python.com/cgi/showcode.py?name=thumbspage/template-viewpage.html |
| tilted | https://learning-python.com/thumbspage/examples/Screenshots/reorient-prior-index.png |
| right-side | https://learning-python.com/thumbspage/examples/Screenshots/reorient-new-index.png |
| tags | https://en.wikipedia.org/wiki/Exif |
| standard | https://www.exif.org/Exif2-2.PDF |
| website | http://learning-python.com/pygadgets.html |
| user_configs.py | https://learning-python.com/thumbspage/user_configs.py |
| examples/reorientation | https://learning-python.com/thumbspage/examples/reorientation |
| restore-prerotate-originals.py | https://learning-python.com/thumbspage/docetc/restore-prerotate-originals.py |
| viewer_thumbs.py | https://learning-python.com/thumbspage/viewer_thumbs.py |
| details | https://learning-python.com/thumbspage/UserGuide.html#rotateskeepexifs |
| dialogs | https://learning-python.com/thumbspage/examples/1.7-upgrades/info-dialog-chrome-desktop.png |
| this 1.7 note | https://learning-python.com/thumbspage/UserGuide.html#piexifworkaround |
| note | https://learning-python.com/thumbspage/UserGuide.html#tpsansrotates |
| demo | https://learning-python.com/thumbspage/examples/reorientation/Unrotated-images-in-browsers/index.html |
| note | https://learning-python.com/thumbspage/UserGuide.html#21rotations |
| Customization | https://learning-python.com/thumbspage/UserGuide.html#Customization |
| user_configs.py | https://learning-python.com/thumbspage/user_configs.py |
| user_configs.py | https://learning-python.com/thumbspage/user_configs.py |
| note | https://learning-python.com/thumbspage/UserGuide.html#floatingtop20 |
| user_configs.py | https://learning-python.com/thumbspage/user_configs.py |
| template file | https://learning-python.com/cgi/showcode.py?name=thumbspage/template-viewpage.html |
| user_configs.py | https://learning-python.com/thumbspage/user_configs.py |
| this page | http://learning-python.com/site-traffic-half1-2018.txt |
| 2.0 note | https://learning-python.com/thumbspage/UserGuide.html#_205 |
| viewer_thumbs.py | https://learning-python.com/thumbspage/viewer_thumbs.py |
| this site | https://developer.mozilla.org/en-US/docs/Web/CSS/border-width |
| ahead | https://learning-python.com/thumbspage/UserGuide.html#chromehrfix15 |
| notes | https://learning-python.com/thumbspage/UserGuide.html#1.6 |
| viewer page | https://learning-python.com/thumbspage/examples/Screenshots/trnpix-view-desktop1.png |
| display | https://learning-python.com/thumbspage/examples/Screenshots/trnpix-view-desktop4-raw.png |
| clicks | https://learning-python.com/thumbspage/examples/Screenshots/trnpix-index-desktop.png |
| thumbs folder | https://learning-python.com/thumbspage/examples/Screenshots/_thumbspage |
| this site | http://learning-python.com/trnpix/ |
| CSS alone | https://learning-python.com/thumbspage/examples/Screenshots/trnpix-x-ios-mobile4-landscape.jpeg |
| above | https://learning-python.com/thumbspage/UserGuide.html#scaling16 |
| user_configs.py | https://learning-python.com/thumbspage/user_configs.py |
| thumbspage.py | https://learning-python.com/thumbspage/thumbspage.py |
| thumbspage.py | https://learning-python.com/thumbspage/thumbspage.py |
| file | https://learning-python.com/thumbspage/UserGuide.html#Customization |
| configuration | https://learning-python.com/thumbspage/user_configs.py |
| borders | https://learning-python.com/thumbspage/UserGuide.html#imgborderfix16 |
| user_configs.py | https://learning-python.com/thumbspage/user_configs.py |
| HEADER.html | https://learning-python.com/thumbspage/UserGuide.html#Customization |
| smaller screens | https://learning-python.com/thumbspage/examples/Screenshots/trnpix-index-mobile.png |
| user_configs.py | https://learning-python.com/thumbspage/user_configs.py |
| HEADER.html | https://learning-python.com/thumbspage/UserGuide.html#Customization |
| live demo | https://learning-python.com/thumbspage/examples/unicode/images/index.html |
| user_configs.py | https://learning-python.com/thumbspage/user_configs.py |
| user_configs.py | https://learning-python.com/thumbspage/user_configs.py |
| examples/unicode/images | https://learning-python.com/thumbspage/examples/unicode/images |
| file | https://learning-python.com/thumbspage/UserGuide.html#Customization |
| byte values | https://learning-python.com/thumbspage/UserGuide.html#urlescape15 |
| templateEncoding | https://learning-python.com/thumbspage/UserGuide.html#templateencoding16 |
| user_configs.py | https://learning-python.com/thumbspage/user_configs.py |
| fix | https://learning-python.com/thumbspage/UserGuide.html#chromehrfix15 |
| auto-scrolls | https://learning-python.com/thumbspage/UserGuide.html#1.4 |
| subfolder-links list | https://learning-python.com/thumbspage/examples/subfolders/index.html |
| user_configs.py | https://learning-python.com/thumbspage/user_configs.py |
| file | https://learning-python.com/thumbspage/UserGuide.html#Customization |
| subfolder | https://learning-python.com/thumbspage/examples/mixedtypes/index.html |
| machine | https://duckduckgo.com/?q=run+web+server+locally |
| configs | https://learning-python.com/thumbspage/user_configs.py |
| release note.
| https://learning-python.com/thumbspage/UserGuide.html#other21 |
| page | https://learning-python.com/thumbspage/examples/__prior-version-items/__prior-screenshots/older/trnpix-1.1.png |
| results | https://learning-python.com/thumbspage/examples/__prior-version-items/__prior-screenshots/older/frigcal-thumbs-1.1.png |
| pages | https://learning-python.com/thumbspage/examples/__prior-version-items/__prior-screenshots/older/frigcal-before-1.1.png |
| releases | https://learning-python.com/thumbspage/examples/2.1-upgrades/index.html |
| code files | https://learning-python.com/thumbspage/ |
| Version History | https://learning-python.com/thumbspage/UserGuide.html#Version History |
| Info popups display a subset of Exif tags
Embedded thumbnails are ignored
Image types are not universally supported
Rotations drop Exif tags (closed)
Android Chrome scrollbar oddment
Extra-files overhead
Parent-folder links
Index-file location
Meta tags for custom headers
More code clean up
Mobile landscape scaling (closed)
Chrome history destacking bug (closed)
More user customizations
Dynamic index-page columns
Image information display (closed)
Browser fullscreen-mode options (closed)
Automatic slideshows (closed)
A floating "Top" for index pages (closed)
Can reorientation be dropped? (closed)
Per-image notes?
How about a GUI?
| https://learning-python.com/thumbspage/UserGuide.html#_dnI |
| Embedded thumbnails are ignored
Image types are not universally supported
Rotations drop Exif tags (closed)
Android Chrome scrollbar oddment
Extra-files overhead
Parent-folder links
Index-file location
Meta tags for custom headers
More code clean up
Mobile landscape scaling (closed)
Chrome history destacking bug (closed)
More user customizations
Dynamic index-page columns
Image information display (closed)
Browser fullscreen-mode options (closed)
Automatic slideshows (closed)
A floating "Top" for index pages (closed)
Can reorientation be dropped? (closed)
Per-image notes?
How about a GUI?
| https://learning-python.com/thumbspage/UserGuide.html#_dnK |
| Image types are not universally supported
Rotations drop Exif tags (closed)
Android Chrome scrollbar oddment
Extra-files overhead
Parent-folder links
Index-file location
Meta tags for custom headers
More code clean up
Mobile landscape scaling (closed)
Chrome history destacking bug (closed)
More user customizations
Dynamic index-page columns
Image information display (closed)
Browser fullscreen-mode options (closed)
Automatic slideshows (closed)
A floating "Top" for index pages (closed)
Can reorientation be dropped? (closed)
Per-image notes?
How about a GUI?
| https://learning-python.com/thumbspage/UserGuide.html#_dn1 |
| Rotations drop Exif tags (closed)
Android Chrome scrollbar oddment
Extra-files overhead
Parent-folder links
Index-file location
Meta tags for custom headers
More code clean up
Mobile landscape scaling (closed)
Chrome history destacking bug (closed)
More user customizations
Dynamic index-page columns
Image information display (closed)
Browser fullscreen-mode options (closed)
Automatic slideshows (closed)
A floating "Top" for index pages (closed)
Can reorientation be dropped? (closed)
Per-image notes?
How about a GUI?
| https://learning-python.com/thumbspage/UserGuide.html#_dn2 |
| Android Chrome scrollbar oddment
Extra-files overhead
Parent-folder links
Index-file location
Meta tags for custom headers
More code clean up
Mobile landscape scaling (closed)
Chrome history destacking bug (closed)
More user customizations
Dynamic index-page columns
Image information display (closed)
Browser fullscreen-mode options (closed)
Automatic slideshows (closed)
A floating "Top" for index pages (closed)
Can reorientation be dropped? (closed)
Per-image notes?
How about a GUI?
| https://learning-python.com/thumbspage/UserGuide.html#_dn3 |
| Extra-files overhead
Parent-folder links
Index-file location
Meta tags for custom headers
More code clean up
Mobile landscape scaling (closed)
Chrome history destacking bug (closed)
More user customizations
Dynamic index-page columns
Image information display (closed)
Browser fullscreen-mode options (closed)
Automatic slideshows (closed)
A floating "Top" for index pages (closed)
Can reorientation be dropped? (closed)
Per-image notes?
How about a GUI?
| https://learning-python.com/thumbspage/UserGuide.html#_dn4 |
| Parent-folder links
Index-file location
Meta tags for custom headers
More code clean up
Mobile landscape scaling (closed)
Chrome history destacking bug (closed)
More user customizations
Dynamic index-page columns
Image information display (closed)
Browser fullscreen-mode options (closed)
Automatic slideshows (closed)
A floating "Top" for index pages (closed)
Can reorientation be dropped? (closed)
Per-image notes?
How about a GUI?
| https://learning-python.com/thumbspage/UserGuide.html#_dn5 |
| Index-file location
Meta tags for custom headers
More code clean up
Mobile landscape scaling (closed)
Chrome history destacking bug (closed)
More user customizations
Dynamic index-page columns
Image information display (closed)
Browser fullscreen-mode options (closed)
Automatic slideshows (closed)
A floating "Top" for index pages (closed)
Can reorientation be dropped? (closed)
Per-image notes?
How about a GUI?
| https://learning-python.com/thumbspage/UserGuide.html#_dn6 |
| Meta tags for custom headers
More code clean up
Mobile landscape scaling (closed)
Chrome history destacking bug (closed)
More user customizations
Dynamic index-page columns
Image information display (closed)
Browser fullscreen-mode options (closed)
Automatic slideshows (closed)
A floating "Top" for index pages (closed)
Can reorientation be dropped? (closed)
Per-image notes?
How about a GUI?
| https://learning-python.com/thumbspage/UserGuide.html#_dn7 |
| More code clean up
Mobile landscape scaling (closed)
Chrome history destacking bug (closed)
More user customizations
Dynamic index-page columns
Image information display (closed)
Browser fullscreen-mode options (closed)
Automatic slideshows (closed)
A floating "Top" for index pages (closed)
Can reorientation be dropped? (closed)
Per-image notes?
How about a GUI?
| https://learning-python.com/thumbspage/UserGuide.html#_dn8 |
| Mobile landscape scaling (closed)
Chrome history destacking bug (closed)
More user customizations
Dynamic index-page columns
Image information display (closed)
Browser fullscreen-mode options (closed)
Automatic slideshows (closed)
A floating "Top" for index pages (closed)
Can reorientation be dropped? (closed)
Per-image notes?
How about a GUI?
| https://learning-python.com/thumbspage/UserGuide.html#_dn9 |
| Chrome history destacking bug (closed)
More user customizations
Dynamic index-page columns
Image information display (closed)
Browser fullscreen-mode options (closed)
Automatic slideshows (closed)
A floating "Top" for index pages (closed)
Can reorientation be dropped? (closed)
Per-image notes?
How about a GUI?
| https://learning-python.com/thumbspage/UserGuide.html#_dnA |
| More user customizations
Dynamic index-page columns
Image information display (closed)
Browser fullscreen-mode options (closed)
Automatic slideshows (closed)
A floating "Top" for index pages (closed)
Can reorientation be dropped? (closed)
Per-image notes?
How about a GUI?
| https://learning-python.com/thumbspage/UserGuide.html#_dnB |
| Dynamic index-page columns
Image information display (closed)
Browser fullscreen-mode options (closed)
Automatic slideshows (closed)
A floating "Top" for index pages (closed)
Can reorientation be dropped? (closed)
Per-image notes?
How about a GUI?
| https://learning-python.com/thumbspage/UserGuide.html#_dnC |
| Image information display (closed)
Browser fullscreen-mode options (closed)
Automatic slideshows (closed)
A floating "Top" for index pages (closed)
Can reorientation be dropped? (closed)
Per-image notes?
How about a GUI?
| https://learning-python.com/thumbspage/UserGuide.html#_dnD |
| Browser fullscreen-mode options (closed)
Automatic slideshows (closed)
A floating "Top" for index pages (closed)
Can reorientation be dropped? (closed)
Per-image notes?
How about a GUI?
| https://learning-python.com/thumbspage/UserGuide.html#_dnG |
| Automatic slideshows (closed)
A floating "Top" for index pages (closed)
Can reorientation be dropped? (closed)
Per-image notes?
How about a GUI?
| https://learning-python.com/thumbspage/UserGuide.html#_dnH |
| A floating "Top" for index pages (closed)
Can reorientation be dropped? (closed)
Per-image notes?
How about a GUI?
| https://learning-python.com/thumbspage/UserGuide.html#_dnE |
| Can reorientation be dropped? (closed)
Per-image notes?
How about a GUI?
| https://learning-python.com/thumbspage/UserGuide.html#_dnL |
| Per-image notes?
How about a GUI?
| https://learning-python.com/thumbspage/UserGuide.html#_dnM |
| How about a GUI?
| https://learning-python.com/thumbspage/UserGuide.html#_dnF |
| info popups | https://learning-python.com/thumbspage/examples/2.0-upgrades/xtra-mobile-android6inch-info.jpg |
| earlier | https://learning-python.com/thumbspage/UserGuide.html#_207 |
| data items | https://www.exiv2.org/tags.html |
| Exif standard | https://www.exif.org/Exif2-2.PDF |
| rotates | https://learning-python.com/thumbspage/UserGuide.html#rotation16 |
| note | https://learning-python.com/thumbspage/UserGuide.html#21rotations |
| earlier | https://learning-python.com/thumbspage/UserGuide.html#tiffs |
| search | https://duckduckgo.com/?q=display+tiff+in+web+browser |
| earlier | https://learning-python.com/thumbspage/UserGuide.html#rotation16 |
| tags | https://en.wikipedia.org/wiki/Exif |
| details | https://learning-python.com/thumbspage/UserGuide.html#rotateskeepexifs |
| dialogs | https://learning-python.com/thumbspage/examples/1.7-upgrades/info-dialog-chrome-desktop.png |
| earlier | https://learning-python.com/thumbspage/UserGuide.html#chromescroll16 |
| earlier | https://learning-python.com/thumbspage/UserGuide.html#extrafiles |
| PyPhoto | https://learning-python.com/pygadgets.html |
| scheme | https://learning-python.com/cgi/showcode.py?name=pygadgets-products/unzipped/_PyPhoto/PIL/viewer_thumbs.py |
| lists | https://learning-python.com/thumbspage/UserGuide.html#1.1 |
| trnpix | https://learning-python.com/thumbspage/examples/trnpix |
| custom headers | https://learning-python.com/thumbspage/UserGuide.html#Customization |
| 1.5 | https://learning-python.com/thumbspage/UserGuide.html#1.5 |
| images scaling | https://learning-python.com/thumbspage/UserGuide.html#scaling16 |
| scrollable | https://learning-python.com/thumbspage/examples/Screenshots/scaling-ios-landscape.jpeg |
| shrunken | https://learning-python.com/thumbspage/examples/Screenshots/scaling-android-landscape.png |
| here | https://learning-python.com/thumbspage/UserGuide.html#_174 |
| Android | https://learning-python.com/thumbspage/examples/1.7-upgrades/image-larger-mobile-1.7.jpg |
| iOS | https://learning-python.com/thumbspage/examples/1.7-upgrades/ios-scaled-landscape-ch.png |
| here | https://learning-python.com/thumbspage/UserGuide.html#iosscale17 |
| above | https://learning-python.com/thumbspage/UserGuide.html#destacking16 |
| configuration | https://learning-python.com/thumbspage/user_configs.py |
| above | https://learning-python.com/thumbspage/UserGuide.html#destacking16 |
| 2.0 | https://learning-python.com/thumbspage/UserGuide.html#_205 |
| earlier | https://learning-python.com/thumbspage/UserGuide.html#Customization |
| user_configs.py | https://learning-python.com/thumbspage/user_configs.py |
| note | https://learning-python.com/thumbspage/UserGuide.html#dynamiclayout21 |
| dialog | https://learning-python.com/thumbspage/UserGuide.html#filenametap |
| release note | https://learning-python.com/thumbspage/UserGuide.html#infocustom20 |
| fullscreen display | https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API |
| browsers | https://learning-python.com/thumbspage/UserGuide.html#fullscreenmanual |
| disabled | https://learning-python.com/thumbspage/user_configs.py |
| note | https://learning-python.com/thumbspage/UserGuide.html#fullscreen20 |
| available | https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API |
| mobile | https://learning-python.com/thumbspage/examples/1.7-upgrades/ios-portrait-safari.png |
| here | https://learning-python.com/thumbspage/UserGuide.html#slideshow20 |
| here | https://learning-python.com/thumbspage/UserGuide.html#_vt1 |
| above | https://learning-python.com/thumbspage/UserGuide.html#_20C |
| story | https://learning-python.com/thumbspage/UserGuide.html#moresafarijunk |
| tables of links | http://learning-python.com/trnpix/index.html |
| file | https://learning-python.com/thumbspage/user_configs.py |
| note | https://learning-python.com/thumbspage/UserGuide.html#floatingtop20 |
| 2.0 note | https://learning-python.com/thumbspage/UserGuide.html#tpsansrotates |
| note | https://learning-python.com/thumbspage/UserGuide.html#tpsansrotates |
| here | https://learning-python.com/thumbspage/UserGuide.html#notes23 |
| prompts | https://learning-python.com/thumbspage/UserGuide.html#Running thumbspage |
| module | https://learning-python.com/thumbspage/user_configs.py |
| inserts | https://learning-python.com/thumbspage/UserGuide.html#Customization |
| think | http://learning-python.com/programs.html#complete |
| docetc/more-docs-trimmed | https://learning-python.com/thumbspage/docetc/more-docs-trimmed.txt |
| web page | http://learning-python.com/thumbspage.html#Resources |
| tagpix | http://learning-python.com/tagpix.html |
| PyPhoto | http://learning-python.com/pygadgets.html |
| learning-python.com | http://learning-python.com/programs.html |
| up | https://learning-python.com/thumbspage/examples/reorientation/_thumbspage/galaxys8-3U.jpg.html |
|
| http://learning-python.com/index.html |
| Top | https://learning-python.com/thumbspage/UserGuide.html |
| Code | http://learning-python.com/thumbspage/ |
| Page | http://learning-python.com/thumbspage.html |
| Demo | http://learning-python.com/thumbspage.html#demos |
| News | http://learning-python.com/post-release-updates.html |
| Blog | http://learning-python.com/posts.html |
| Apps | http://learning-python.com/programs.html |