Why QuickImageViewer?
Built for Speed
Unlike modern web-based Electron wrappers, qIV is a pure native application. It uses a GPU bitmap cache to keep decoded images in VRAM, preloading in both directions on a background thread pool. The UI thread never blocks — switching between images is instant.
Hardware Accelerated
Built directly on top of Direct2D, D3D11 and the Windows Imaging Component (WIC). Zero-flicker rendering with per-panel DXGI swap chains, full per-monitor DPI awareness for crisp 4K rendering, and a GDI software fallback when needed.
Genuinely Portable
One
sub-10
MB
EXE.
No
installer,
no
background
services,
no
telemetry,
no
ads.
Hide
it
to
the
system
tray
with
Esc
and
the
process
stays
resident
in
RAM
—
the
next
image
opens
instantly.
More Than a Viewer
Thumbnail strips double as a lightweight file manager: drag & drop files between folders, right-click Copy / Cut / Paste / Delete with full Windows clipboard and Recycle Bin integration, plus offline EXIF GPS geocoding.
Format Support
Open HEIC, AVIF, JPEG XL, WebP, SVG, OpenEXR and Radiance HDR on Windows — plus every classic format. Native OS formats are handled by the zero-dependency Windows Imaging Component, while complex formats use optimized custom and static-library decoders.
| Format | Extensions | Decoder | Notes |
|---|---|---|---|
| JPEG |
.jpg
.jpeg
.jpe
|
WIC | Full EXIF / GPS metadata |
| PNG |
.png
.apng
|
WIC | 16-bit, alpha |
| BMP |
.bmp
|
WIC | |
| TIFF |
.tif
.tiff
|
WIC | Multi-page (first frame) |
| GIF |
.gif
|
WIC | Animated — plays with per-frame delays |
| WebP |
.webp
|
WIC | Windows 10+ native codec |
| HEIF / HEIC |
.heif
.heic
.hif
.heics
.heifs
|
WIC | Requires MS HEIF Extensions |
| AVIF |
.avif
.avci
.avcs
.avifs
|
WIC | Windows 11 native codec |
| JPEG XL |
.jxl
|
WIC | Windows 11 24H2+ native codec |
| JPEG XR |
.jxr
.wdp
.hdp
|
WIC | OS native |
| DDS |
.dds
|
WIC | OS native |
| Camera RAW |
.dng
.cr2
.cr3
.nef
.arw
|
WIC | Requires MS Raw Image Extension |
| JPEG 2000 |
.jp2
.j2k
.j2c
.jpf
.jpx
|
OpenJPEG | Static lib |
| SVG |
.svg
|
resvg | Rust static lib, async IO thread |
| OpenEXR |
.exr
|
tinyexr | Reinhard tone-map + γ2.2 |
| Radiance HDR |
.hdr
|
Inline | RGBE adaptive RLE, Reinhard tone-map |
| Targa |
.tga
|
Inline | RLE and colour-mapped, 8/15/16/24/32-bit |
| PNM |
.ppm
.pgm
.pbm
|
Inline | P1–P6, up to 16-bit maxval |
| QOI |
.qoi
|
Inline | Lossless fast format |
| ICO / CUR |
.ico
.cur
|
WIC |
Core Features
Performance
- GPU bitmap cache — decoded images live in VRAM, preloaded in both directions
- Background decode — worker thread pool; the UI thread never blocks on IO
-
Instant
startup
—
process
stays
resident
in
RAM
after
first
launch
(hide
to
tray
with
Esc, recall instantly) - Software fallback — GDI renderer for edge cases where Direct2D is unavailable
- Per-monitor DPI awareness V2 — pixel-perfect rendering on 4K and mixed-DPI setups
File Management
-
Drag
&
Drop
between
folders:
Drag
a
thumbnail
from
one
directory
strip
onto
another
to
move
the
file;
hold
Ctrlto copy. The cursor shows the active operation and both panels refresh instantly. - Clipboard integration: Right-click any thumbnail for Copy / Cut / Paste / Delete. Works both ways with Windows Explorer; cut files are shown dimmed; deletes go to the Recycle Bin.
Offline Reverse Geocoding
GPS coordinates in EXIF data are resolved to full location details with zero network calls. All data is compressed (zlib) and embedded directly in the EXE.
| Data | Source | Entries | Shows |
|---|---|---|---|
| Cities | GeoNames cities1000 | 170,387 | City name, timezone |
| Admin1 | admin1CodesASCII | 3,865 | State / Province |
| Admin2 | admin2Codes | 47,549 | District / County |
| Country | countryInfo | 252 | Country, Capital, Continent, Currency, Phone prefix |
Complete Shortcut Reference
Every
shortcut
in
qIV,
grouped
exactly
like
the
built-in
help
window
(F1).
Navigation
| Shortcut | Action |
|---|---|
→
/
←
or
Wheel
|
Next / previous image |
Space
/
Shift+Space
|
Next / previous image |
Backspace
|
Smart jump between first and last image (goes to whichever is further) |
Shift+Backspace
|
Return to the image before the first/last jump |
E
|
Toggle between current and previously viewed image |
Q
|
Toggle between current and previously opened folder |
J
/
Ctrl+G
|
Jump
to
image
by
number
(type
@
to
switch
to
Find
mode)
|
Ctrl+F
|
Find
by
filename
—
wildcards
*
and
?;
type
#
to
switch
to
Jump
mode
|
L
|
Reveal current file in Windows Explorer |
PageUp / PageDown
|
Previous / next folder in your history — walks only the non-starred rows |
Insert / Delete
|
Next / previous favourite folder — walks only the starred rows |
| Horizontal Wheel | Cycle through navigation history folders |
F2
|
Open-file dialog |
| Drag & Drop | Drop a file or folder onto the window to open it |
Zoom, Pan & View Modes
| Shortcut | Action |
|---|---|
Up
/
Down
or
Num
+
/
Num
−
|
Zoom in / out |
Num
*
|
Reset zoom and pan to the active view mode's default fit |
Ctrl+Wheel
|
Zoom in / out centered on the mouse cursor |
W
/
A
/
S
/
D
|
Pan the viewport when the image is larger than the window |
1
–
5
|
View modes: 1 Fit to view • 2 Fit to width • 3 Fit to height • 4 Fill window • 5 Original 1:1 pixels |
0
|
Open the Zoom panel and type an exact percentage |
Y
|
Lock Viewport — carry zoom and pan to the next image instead of resetting, so flipping through same-framed shots holds the same detail at the same magnification. Rotation and flips still reset, because each file's EXIF orientation tag owns those |
UI Panels
| Panel | Shortcut | Description |
|---|---|---|
| Help |
F1
|
Full
shortcut
&
CLI
reference
—
Ctrl+E
exports
it
to
Desktop
as
UTF-8
text
|
| EXIF / Info |
M
|
Full metadata: camera, exposure, GPS with offline geocoding, embedded preview thumbnail |
| Statistics |
K
|
Decode time, codec, file details and cache info for the current image |
| Directory |
F6
(or
Right
Shift)
/
F7
|
All images in current folder; syncs selection with viewer / moves panel to next screen edge |
| Cache |
F3
/
F4
|
Live GPU cache occupancy with thumbnails / moves panel |
| Clear cache |
Ctrl+F3
|
Empty the VRAM cache — images are re-decoded on demand afterwards |
| History |
Tab
|
Recent
folders
with
favorites
—
Shift+Enter
spawns
a
directory
strip
|
| Reload |
F5
|
Refresh / reload the current directory from disk |
| Close panel |
Esc
/
Ctrl+W
|
Close the focused panel — works in every panel window |
Thumbnail Strips
| Input | Action |
|---|---|
| Mouse Wheel |
Scroll
the
strip;
hold
Shift
for
3×
speed
|
B
|
Toggle wheel wrap-around (past last thumbnail jumps to first and vice-versa) |
U
|
Toggle the strip's visual effects — rounded corners, the accent glow on the selected thumbnail and the hover-scale enlarge |
| Left Click | Open the clicked thumbnail in the main viewer |
| Click + drag | Grab the strip and drag to scroll freely |
| Scrollbar edge | Thin scrollbar on the inner edge — click-drag for quick scrubbing |
| Drag thumbnail → other strip |
Move
the
file
to
that
folder;
hold
Ctrl
to
copy
—
cursor
shows
the
operation
|
| Right Click | Context menu: Copy, Cut, Delete (Recycle Bin), Paste — full Explorer clipboard interop |
History Panel
| Shortcut | Action |
|---|---|
Tab
|
Toggle History panel |
Ctrl+Tab
|
Toggle full (uncapped) view and refresh the folder snapshot |
Enter
|
Open hovered folder in main viewer |
Shift+Enter
|
Spawn a floating directory strip for the hovered folder (up to 4) |
| type anything |
Filter
the
list
—
fuzzy
by
default,
wildcards
(*,
?)
when
the
query
contains
one.
Matched
characters
are
highlighted
in
the
row
|
Esc
/
✕
|
Clear
the
filter
(Esc
closes
the
panel
when
the
filter
is
already
empty)
|
Space
|
Toggle favorite on hovered entry (types a space once the filter has text) |
Ctrl+Delete
|
Delete
hovered
entry
(Ctrl+Z
restores
last
deleted)
|
Ctrl+Shift+Delete
|
Clear all history, keep favorites |
Ctrl+Alt+Shift+Delete
|
Clear all favorites, keep history |
Slideshow
| Shortcut | Action |
|---|---|
Ctrl+F1
|
Start / stop slideshow |
Space
(while
running)
|
Pause / resume |
R
(while
running)
|
Toggle loop |
S
(while
running)
|
Toggle shuffle |
T
(while
running)
|
Cycle transition: Cut → Fade → Dissolve → Ripple → Push → Zoom |
Color Effects
All
effects
are
non-destructive
and
GPU-accelerated
via
the
Direct2D
effect
graph
—
the
file
on
disk
is
never
touched.
Ctrl+S
saves
the
result
to
disk.
Every
colour
effect
requires
Ctrl.
The
plain
presses
of
the
same
keys
belong
to
navigation
—
Home
/
End
jump
to
the
first
/
last
image,
Page Up
/
Page Down
walk
the
history
folders
and
Insert
/
Delete
walk
the
favourites.
| Effect | Key |
|---|---|
| Rotate CW / CCW |
R
/
Shift+R
|
| Flip horizontal / vertical |
H
/
V
|
| Grayscale |
Ctrl+Delete
|
| Invert |
Ctrl+Insert
|
| Sepia |
Ctrl+Home
|
| Solarize (>50% brightness inverted) |
Ctrl+End
|
| Outline (GPU edge detection) |
Ctrl+Page
Up
|
| Threshold (black & white at 50%) |
Ctrl+Page
Down
|
| Brightness ± |
Ctrl+\
/
Ctrl+'
|
| Contrast ± |
Ctrl+/
/
Ctrl+.
|
| Saturation ± |
Ctrl+]
/
Ctrl+[
|
| Gamma ± |
Ctrl+=
/
Ctrl+-
|
| Toggle all effects (bypass) |
`
(backtick)
|
| Reset all effects |
Num
0
|
| Save with effects baked in |
Ctrl+S
|
Overlay System
9 independently configurable data slots rendered on the image canvas in a 3×3 grid.
| Shortcut | Action |
|---|---|
N
/
I
/
Ctrl+0
|
Master toggle — show / hide all slots |
Ctrl+1
–
Ctrl+9
|
Walk
one
slot
through
Compact
→
Full
→
Off
—
compact
is
one
line
instead
of
two.
Ctrl+5
(center
messages)
has
no
compact
form,
so
it
cycles
On
→
Off.
Slots:
1
index+filename
•
3
zoom
%
•
5
center
messages
•
7
active
effects
+
folder
name
•
9
dimensions+size.
Slots
2,
4,
6,
8
show
the
thumbnail-strip
selection
count
for
the
panel
on
that
edge
|
O
|
Cycle overlay layout: Grid → Stacked → Summary |
P
|
Toggle semi-transparent background behind overlay text |
Appearance
is
set
from
the
tray
menu's
Overlays
submenu
rather
than
by
shortcut:
Layout
(the
same
Grid
/
Stacked
/
Summary
that
O
cycles),
Font
and
Font
Size
and
Font
Color
for
every
slot,
and
Message
Duration
in
milliseconds.
The
nine
slots
are
listed
there
too,
each
named
for
what
it
carries,
and
each
opens
a
three-state
radio
group
—
Compact
/
Full
/
Off,
the
same
cycle
its
Ctrl+N
key
walks.
Mid
Center
is
always
single-line,
so
it
offers
only
On
/
Off.
Bot
Left
carries
two
extra
toggles
above
its
radio
group,
because
they
decide
whether
there
is
anything
to
format:
Effects
(the
active
colour-effect
list)
and
Folder
Name
(the
containing
folder
beside
the
file
name).
Sorting
| Shortcut | Order |
|---|---|
Ctrl+Alt+Shift+0
|
By name (natural / Explorer order) — press again to reverse |
Ctrl+Alt+Shift+9
|
By date modified — press again to flip newest ↔ oldest |
Ctrl+Alt+Shift+8
|
By file size — press again to flip largest ↔ smallest |
Ctrl+Alt+Shift+7
|
By extension — press again to reverse |
Ctrl+Alt+Shift+6
|
By physical disk order (fastest for HDDs) |
Window & Chrome
| Shortcut | Action |
|---|---|
F
/
Enter
/
Ctrl+Shift+T
|
Toggle
borderless
fullscreen
(F11 is now the mirroring toggle)
|
Ctrl+Enter
/
Alt+Enter
/
Ctrl+Alt+Enter
|
Send this position / stream this image / fetch the image another instance is showing — see Remote Control & Mirroring |
Ctrl+Shift+Enter
|
Send this position to every connected instance, not only the
ones ticked under Control in Ctrl+F11
|
Ctrl+T
/
Ctrl+A
|
Toggle always-on-top (main window + all panels) |
Ctrl+M
|
Move the window to the next monitor, wrapping at the last. Screens are ordered left to right by their desktop position, and the window keeps its relative size and place — so a window sized for a 4K screen does not land half off a 1080p one. The overlay names the monitor it moved to |
Shift+W/A/S/D
|
Nudge window 20 px up / left / down / right |
Alt+W/A/S/D
|
Snap to top / left / bottom / right half of work area |
Alt+Q/E/Z/C
|
Snap to top-left / top-right / bottom-left / bottom-right quarter |
Alt+X
|
Reset window size, position and all effects |
Shift+Num
+/−
or
Shift+=/−
|
Grow / shrink window by 20 px per side |
| Drag near screen edge | Snap to that edge (within 24 px) |
Ctrl+Space
|
Toggle: fit viewer to work area (avoiding visible panels) ↔ restore default size centered on monitor |
Ctrl+Alt+Num
+/−
|
Step all panel colors lighter / darker at runtime |
Ctrl+Alt+Num
0
|
Reset theme brightness to compiled default |
Ctrl+Shift+Num
*
|
Toggle window corners: rounded ↔ square |
Ctrl+Shift+Num
/
|
Cycle backdrop material: None → Mica → Acrylic → MicaAlt |
Mouse Controls
| Input | Action |
|---|---|
| Wheel | Previous / next image |
Ctrl+Wheel
|
Zoom in / out centered on cursor |
Shift+Wheel
|
Adjust window opacity in 10% steps |
| Horizontal Wheel | Cycle navigation history folders |
| LMB hold | Quick zoom 3× centered on cursor |
| LMB drag (while zoomed) | Pan; reverts on release |
| LMB double-click | Toggle fullscreen |
| RMB drag | Move window |
| RMB + LMB | Reveal current file in Explorer |
| RMB + Wheel | Zoom in / out |
| RMB + Horizontal Wheel | Live-resize window from center (20 px per notch) |
| MMB click | Full visual reset: zoom, pan, opacity; center and resize window |
| MMB drag | Live-resize window from top-left |
Application Lifecycle
| Shortcut | Action |
|---|---|
Esc
/
Ctrl+W
|
Hide to system tray — process stays resident for instant recall |
Ctrl+Q
|
Hard quit — fully removes the process from memory |
Ctrl+N
|
Open a new independent qIV window |
Shift+Delete
|
Reset everything — window layout and all effects return to defaults |
Ctrl+C
|
Copy the current image to the clipboard |
System Tray
When qIV is hidden or running in the background, its icon lives in the system tray. Right-click it for the full settings menu — no config files to edit. Double-click to restore the window.
Settings submenu — toggles
| Setting | Effect |
|---|---|
| Keep in Background | Esc / Ctrl+W hides to tray instead of exiting; process stays resident for instant re-open |
| Run on Startup | Write / remove a Windows startup registry entry so qIV launches with Windows. Dedicated instances use a separate entry |
| Thumbnail Effects | Master switch for glow borders, rounded corners and hover-scale on thumbnail strips |
| History: Open Full List | Tab opens the full uncapped history view when enabled |
| Info Overlays | Show / hide all nine overlay text slots |
| Open Thumbnail Strip on Start | Auto-open the directory strip on every launch |
| Overlay Background | Semi-transparent background panel behind overlay text |
| Swap Mouse Buttons | Exchange left/right roles: hold-to-zoom ↔ drag-to-move-window |
| Invert Scroll Direction | Reverse vertical wheel for image navigation |
| Invert Horizontal Scroll | Reverse horizontal wheel for folder history navigation |
| Start in Fullscreen | Open fullscreen on every launch |
Settings submenu — numeric values
Click any numeric label to open an input dialog. Current value is shown in the menu item itself.
| Setting | Range | Effect |
|---|---|---|
| VRAM Cache Size | 0 – 999 | Images to keep decoded in GPU memory |
| Window Width / Height | 240 – 16000 px | Default dimensions used by Ctrl+Space and window reset |
| History Max Dirs / Favs | 0 – 999 | Items shown in the History panel |
| Dir Thumb Cache | 100 – 64000 MB | Memory budget for directory thumbnail bitmaps |
| Preload Lookaside | 1 – 99 | Images to pre-decode ahead and behind the current one |
| Overlay Message Duration | 250 – 10000 ms | How long center overlay messages stay visible |
| History Save Limit | 1 – 99999 | Folders persisted to disk between sessions |
Settings file operations
| Item | Effect |
|---|---|
| Export Settings |
Save
all
settings
to
a
UTF-8
.ini
file
(filename
includes
today's
date)
|
| Import Settings |
Load
a
previously
exported
.ini
—
confirmation
required;
all
settings
applied
immediately
|
| Restore Defaults | Reset every setting to its compiled-in default — confirmation required; history and favorites are not affected |
Other submenus
| Submenu | What you can change |
|---|---|
| View Mode | Default fit mode: Fit to view · Fit to width · Fit to height · Stretch · Original size |
| Slideshow | Interval (100 – 60000 ms), Loop, Shuffle, transition type (Cut / Fade / Dissolve / Ripple / Push / Zoom) |
| Sort | Sort order (Name / Date / Size / Type / Disk) and Reverse Order toggle — takes effect immediately |
| Backup |
Backup
history
&
favorites
to
a
.zip
archive,
or
restore
from
a
previous
backup
|
| Logging |
General
Log
—
what
qIV
itself
did:
started,
closed,
and
whether
the
previous
run
ended
abnormally
(with
the
crash
dump's
filename
when
there
is
one).
TCP/IP
Log
—
every
line
exchanged
with
a
remote
client,
the
same
traffic
the
Server
Log
panel
shows
(Ctrl+F12),
written
to
disk
as
well.
Open
Log
Folder
opens
logs\
in
Explorer
|
Both logs are off by default and survive a restart once switched on — which is the point of them. A screen that misbehaves at four in the morning is exactly the one nobody was watching, so the setting is persisted rather than something you must remember to enable first.
Files
land
in
logs\general\
and
logs\network\
beside
the
EXE,
named
QuickImageViewer_General_<timestamp>.log
and
QuickImageViewer_Tcp_IP_<timestamp>.log,
rotating
every
5000
lines.
Switching
a
log
off
and
on
again
continues
the
newest
file
rather
than
starting
a
fresh
one.
The
format
is
the
standard
time [thread] LEVEL message
layout,
so
LogViewPlus,
lnav
and
similar
tools
parse
it
with
no
configuration
—
and
a
rotated
TCP/IP
file
opens
straight
back
in
the
Server
Log
panel
with
Ctrl+O.
Writing
happens
on
a
thread
of
its
own:
a
slow
disk
cannot
stall
the
viewer,
and
with
a
log
switched
off
the
cost
at
each
record
point
is
a
single
atomic
read.
Dedicated Screens
Press F8 for the Dedicated panel. A dedicated screen is a separate copy of qIV with its own settings file beside it — normally parked fullscreen on one monitor running a slideshow. Any number can run at once, alongside the main app, sharing nothing.
How a copy is identified
Everything derives from the executable's own path, so two screens can never resolve to the same settings, mutex or window class — two files cannot share a name in one folder.
D:\Screens\qIV_dedicated_Lobby.exe the copy
D:\Screens\qIV_dedicated_Lobby.ini its settings
D:\Screens\imageLists_qIV_dedicated_Lobby.qim image folders
D:\Screens\promotionList_qIV_dedicated_Lobby.qpr promotion folders
Startup decision
Made from the filesystem before any setting is read:
| Condition | Result |
|---|---|
An
.ini
sits
beside
the
exe
|
Settings come from it; the registry is never touched |
Exe
name
contains
dedicated,
no
.ini
|
A
default
.ini
is
generated
and
the
F8
panel
opens
|
| Neither | Normal registry-backed launch |
Inside
the
.ini,
[Instance]Dedicated
decides
behaviour
—
1/true/on/yes
or
any
non-zero
number.
Set
it
to
0
and
you
get
a
portable
ordinary
viewer:
settings
in
a
file,
history
and
favorites
intact,
nothing
in
the
registry.
Panel buttons
| Button | Action |
|---|---|
| Generate App |
Copy
this
executable
to
a
chosen
folder
as
qIV_dedicated_<name>.exe
|
| Generate Config |
Write
that
copy's
.ini,
holding
every
setting
shown
in
the
panel
|
| Add Images / Add Promotions |
Append
a
folder
to
the
.qim
/
.qpr
list
—
duplicates
reported
and
skipped
|
| Add Startup / Remove Startup |
Create
or
delete
a
shell:startup
shortcut
pointing
at
the
copy
|
| Test Config / Test Images / Test Promos | Check one thing at a time |
The panel edits the config only — it never changes the app you are using, and every value starts from the compiled defaults rather than your current settings, so a screen never inherits the authoring machine's preferences.
Test
Images
/
Test
Promos
count
the
images
actually
found
per
folder
and
flag
folders
that
are
missing
or
empty.
A
folder
that
exists
but
holds
nothing
decodable
looks
identical
to
a
working
one
until
the
screen
goes
blank.
Kiosk lock
Tick
Kiosk
lock
in
the
panel
and
the
screen
ignores
every
key
and
every
click
—
nobody
walking
past
can
pause
the
slideshow
or
open
a
panel.
The
tray
icon
keeps
working
(its
menu
runs
its
own
message
loop,
so
the
locked
window
never
sees
those
messages),
and
Settings
›
Kiosk
Lock
there
is
the
only
way
back
in.
The
main
app
has
the
same
toggle
in
its
tray
menu,
and
-lock
forces
it
on
for
a
single
launch
without
changing
the
stored
setting.
Always on top
Keeps the screen above every other window so nothing that pops up can cover it. Ctrl+T toggles it live and the setting persists; the panel sets it for a generated screen.
Keep display awake
Blocks the screensaver and display sleep while the window is on screen. Leave it off and Windows eventually blanks the display with nobody there to wake it — and with the kiosk lock on, nobody could. The hold is released automatically when the window hides to the tray, so a viewer sitting in the tray never keeps a machine up.
Isolation
A
dedicated
screen
writes
nothing
to
the
registry,
keeps
no
history
or
favorites,
and
has
its
own
mutex
and
window
class
—
so
a
file
opened
from
Explorer
can
never
land
on
a
slideshow
instead
of
the
main
window.
It
auto-starts
from
a
shortcut
rather
than
the
Run
key.
Promotions
A dedicated screen can interleave a second playlist with its images — never merged into them, and invisible to the image counter and arrow keys.
| Setting | Meaning |
|---|---|
| Pick |
Sequential
(folder
order)
or
Weighted
by
priority
|
| Priority |
From
a
#N
suffix
on
the
filename
—
sale#500.jpg
is
500×
likelier
than
a
file
with
no
suffix.
Range
1–65535
|
| Every N images | Gap counted in pictures |
| Every N seconds | Gap counted in wall-clock time |
| Shown for | Promotion dwell time, independent of the slide interval |
Both
triggers
are
(from,
to)
pairs
and
run
independently
—
set
either,
or
both,
and
whichever
comes
due
first
shows
a
promotion:
-
(0, 0)— off -
(5, 0)— exactly every 5 -
(5, 15)— re-rolled between 5 and 15 each time, so it never looks mechanical
Remote Control & Mirroring
One qIV can drive others — a wall of screens from the copy on your desk, or a
single display in another room. It is a plain UTF-8 line protocol over TCP, so a
script, netcat, a home-automation system or a phone app are all
first-class clients.
The phone app has its own section — qIV Remote for Android, which speaks exactly the protocol described here.
| Shortcut | Panel / Action |
|---|---|
| F9 | Local Server — the listener this instance runs. Off unless switched on; needs a name and a port |
| Ctrl+F9 | My Clients — who is connected to your listener right now: address, the name and platform each gave, whether it is encrypted, how long it has been on, and whether it is watching. Kick, kick-for-N-minutes, or ban from here |
| F10 | Remote Servers — the instances this copy can drive. Connect, start / stop, watch, sync |
| Ctrl+F10 | Send Command — pick any wire command from the list, give it a value, send it |
| F11 | Mirroring on / off — forward every mirrorable command to the connected targets |
| Ctrl+F11 | Mirroring — which connected servers receive what this instance does, plus Identify and Watch |
| F12 | While mirroring, also execute here (off = this viewer is a pure remote control) |
| Ctrl+F12 | RemoteLog — every line that crossed the wire, both directions, with round trips — plus a line each time a client arrives, leaves, drops or is refused, naming its address and port and how long it stayed |
F11 and F12 are session-only and always start off — a viewer that came back from a restart already driving machines you had forgotten about would be the worst kind of surprise.
Announce (beacon)
First item in the TCP/IP menu, off by default. The server publishes itself
over mDNS as _qiv._tcp, so a phone or another qIV finds it
in a list instead of being told an address to type. That one step
— read your PC's LAN address, type it without a typo on a phone keyboard,
know what a port is — is where most people give up.
It announces only the instance name and the port. Never a password, never a path, never a file. And discovery is not access: the AllowList, the password challenge and TLS are untouched by it, so someone who finds this instance and is not allowed in gets exactly as far as someone who guessed the address.
Off by default on purpose — this app's whole posture is that nothing
leaves your network unasked, and a machine that started advertising itself the
moment you enabled the server would be a change to that made on your behalf. It
also only announces while the server is actually running and
reachable: with the listener stopped, or bound to
127.0.0.1, the menu says will announce rather than
claiming it did.
Putting one picture on another screen
Four keys, one question at four depths.
| Key | What travels | Across machines | The far end |
|---|---|---|---|
| Ctrl+Enter | a position — folder, sort order, image number | ❌ same machine only | goes there and stays |
| Alt+Enter | the image bytes, outbound | ✅ | shows it once, unchanged otherwise |
| Ctrl+Alt+Enter | the image bytes, inbound | ✅ | is only read from — you see what it shows |
| Ctrl+Shift+Enter | the same position, to every connected instance | ❌ same machine only | the whole wall goes there and stays |
Ctrl+Shift+Enter is Ctrl+Enter widened: it ignores the Control ticks in Ctrl+F11 and pushes to everything connected, for lining a whole wall up at once without first ticking rows you are about to untick again.
Ctrl+Enter asks before it sends. It queries the target: already in the same folder in the same order? Then just the image number — one round trip, no rescan, no flicker, so you can walk a folder and push each picture as you reach it. In a different folder? Then the folder, then the sort order, then — after waiting for that instance's own scan to finish — the number. Sending a position before the scan lands is the race this avoids.
Alt+Enter and Ctrl+Alt+Enter carry the picture's own file bytes, base64 across several protocol lines, and the far end decodes them with its own decoder. That is why they work to a machine that cannot read your disk. The received image is shown once and changes nothing else: no folder, no sort order, no playlist position. A target running a fullscreen slideshow keeps running it and simply continues from the pushed image — the picture never enters its playlist, and both the received file and its cache entry are thrown away afterwards. An advert dropped between two slides is the case it was built for.
The Send Command panel
Every command has one wire name, spelled exactly like its internal enumerator, and the panel's list is built from the same table the parser accepts — so a name shown there cannot come back “unknown command”.
- Browse, don't remember — the list is permanent and filterable; names are shown in two blues, the second marking a command that takes a value
- Descriptions where they belong — what the highlighted command does sits over the list, what its value means sits over the Value box, with units, limits and an example
- Send to — its own box of connected instances with a checkbox each, so an arbitrary command reaches an arbitrary subset without disturbing what F11 drives
- Session log — every line sent and every answer, numbered, newest first, with the instance that answered and its round trip
The protocol describes itself
$ nc 127.0.0.1 7777
OK qIV 2.190.0.235 remote v6 [Monitor2]
OK
help
qIV remote protocol v6
FORMAT CMD <name>|<takesValue 0|1>|<description>|<value description>
CMD NextImage|0|next image in the playlist|
CMD JumpToImage|1|go to a numbered image in the current playlist|image NUMBER, 1-based …
…
help lists everything this build accepts with its descriptions, so a
client builds its own command list from one call instead of carrying a copy that goes
stale. ping checks liveness, version reports the app and
protocol version.
Since protocol v5 exactly one line always follows the banner, so a
client never has to guess: AUTH <iterations> <salt> <nonce>
when the server wants a password, or a bare OK when it does not —
which is the OK on the second line above. A successful AUTH
is answered OK as well. Nothing is signalled by silence, so no client
needs a timeout to discover what kind of server it reached.
Security
Encryption is decided by the address, and never negotiated. A peer on
the same machine (127.0.0.0/8, ::1, localhost)
gets plaintext; every other peer — your own LAN included — gets
TLS 1.2 / 1.3 from the first byte, before the banner. One listener on
0.0.0.0 serves both. Each end decides from the address independently, so
there is no offer on the wire for an attacker to strip and no plaintext fallback to
force.
The certificate is self-signed and the client pins it by SHA-256 fingerprint — no CA chain, which is the right answer for a machine no public CA would ever issue for. The fingerprint is shown at the bottom of the F9 panel; read it there and enter it in the client. A client with no pin stored refuses to connect rather than trusting whatever it is handed.
A password is compulsory off loopback — the listener refuses to start without one. It never crosses the wire: the server stores a PBKDF2-HMAC-SHA256 digest (210,000 iterations) and the client answers an HMAC over a fresh per-connection nonce, so every guess costs the guesser a full derivation and the server one HMAC. Five failures from one address within ten minutes blacklist it, each failure is answered a second late, and a peer that connects and then goes quiet is dropped after ten seconds.
AllowList and BlackList take addresses, never domain names — a rule is matched against the address a connection actually arrived from, so DNS never enters the access decision. An empty AllowList denies everyone, by design. Both lists accept:
| Form | Example | Notes |
|---|---|---|
| everything |
*
|
|
| text prefix |
192.168.1.*
|
compares characters — see the warning below |
| CIDR |
192.168.0.0/24, 2001:db8::/32
|
either family, any prefix length |
| range |
192.168.0.10-50
|
shorthand — the upper bound is the last octet |
| range, full |
192.168.0.10-192.168.1.5
|
crosses octet boundaries |
| one host |
192.168.0.5, 2001:db8::1
|
compared numerically, so IPv6 spelling does not matter |
⚠ The star is a string prefix, not an octet boundary.
192.168.1.* is what it looks like, but 192.168.1* — no
trailing dot — also matches 192.168.10.x and
192.168.100.x, and 1* matches most of the internet. Use
/24 when the boundary matters. Entries that could never match an address
are dropped when you save, and the panel names what it dropped.
File-altering commands — delete, move, paste, save — are structurally unreachable over the wire: a compile-time assertion proves none of them has a row in the command table, and the executor refuses them again at run time.
Exposing it to the internet. Authentication is the only boundary
— behind it, a peer can do what someone sitting at the viewer can, including
opening a local path and pulling the displayed image back. The AllowList is
address-based, so a client on a dynamic IP pushes you toward * and leaves
the password as the sole gate. Prefer a VPN (WireGuard, Tailscale) over
port-forwarding: every protection above still applies, the AllowList becomes
meaningful again with stable addresses, and the listener stops being reachable by
anyone who scans the port.
qIV Remote — the Android app
Your phone becomes the viewer's remote, a second screen, and a photo frame your PC drives.
Point it at your PC over your own network and drive qIV from the sofa, the far side
of a meeting room, or anywhere the keyboard is not. It is a real client of the
protocol above, not screen sharing: it speaks the same verbs netcat
does, so it stays in step with the desktop instead of streaming pixels at it.
It collects nothing. No accounts, no analytics, no advertising, and nothing sent to the developer — pictures and commands travel only between your phone and the server you point it at. Read the privacy policy.
Photos travel both ways
This is the part a remote control usually cannot do at all.
| Direction | What travels | Why it is built that way |
|---|---|---|
| Desktop → phone live preview |
The current picture, scaled and re-encoded as JPEG before it leaves the PC | 25–40× fewer bytes than the original, and a far smaller decode on the phone |
| Desktop → phone Save |
The original file, byte for byte, into
Pictures/qIVRemote in your gallery |
Save asks for the original separately rather than keeping the preview — a re-encoded JPEG is not the file you meant to keep |
| Phone → desktop push |
Your photo's own bytes, base64 in chunks | Works to a PC that has never seen the photo and cannot read your phone's storage |
A pushed photo appears on the desktop once, over whatever is up. It changes no folder, no sort order, no playlist position, and a running slideshow keeps running with it occupying a single slide. Nothing has to be paused first, and nothing is left behind.
Saving to the gallery needs no storage permission — the app publishes through MediaStore, and the entry stays invisible until the transfer finishes, so a gallery scanning mid-transfer can never show you a half-written thumbnail.
Turn any spare screen into a photo frame
The same connection runs the other way round. Instead of using the phone to drive the PC, put it on a stand and let the PC drive it.
Open the Fullscreen screen and the device shows whatever the viewer is showing — nothing else. No toolbar, no buttons, no chrome. Start a slideshow on the PC and the tablet on the shelf follows it, picture for picture, for as long as you leave it there.
| An old tablet becomes a photo frame | The one in a drawer with a cracked case is a perfectly good display. Prop it up, point it at the PC, start a slideshow. |
| A phone becomes a second screen for photos | Cull on the big screen, review at arm's length, hand it to someone across the table. |
| The PC stays the library | Your folders, your sort order, your filters, your drives. The screen is a window onto the machine that already has all of it. |
It keeps up without being asked. The viewer announces every picture change — including the ones a slideshow makes on its own, where no key was pressed and no command was sent — and the screen fetches the new image the moment it hears. Nothing polls, nothing lags a frame behind.
It sends nothing back. The Fullscreen screen has no Next, no Previous and no toolbar, and that is deliberate rather than unfinished: a control that could nudge a running presentation from a phone in somebody's pocket is a hazard, not a feature. It asks for two read-only things and nothing else. Tap anywhere to leave.
What crosses the network is a preview — scaled to that screen's size and re-encoded as JPEG on the PC before it is sent, not the original file. A 6 MB photo shown on a tablet moves as a few hundred kilobytes. That is what makes it comfortable over Wi-Fi, and what keeps a frame refreshing all evening from being a bandwidth decision.
As many screens as you have devices. Every connected device watches independently, so one PC can feed the tablet in the kitchen, the phone in the hallway and the spare monitor on the desk at the same time — all following the same library, all updating together. There is no per-screen licence, because there is nobody to license it from.
That also makes it signage and advertising that costs nothing to run: a shop window, a waiting room, a menu board, a studio wall. One PC you already own, screens you already have, your own network. No subscription, no cloud account, no per-display fee, and no service that can raise its price or shut down and take the wall with it.
And it runs unattended, which is the part that decides whether a display is a product or a chore. The viewer already has every piece:
| Starts with the machine | -runOnStartup, or the tray toggle. Power comes back after
a cut and the wall comes back with it — nobody drives to the
shop to click anything. |
| Ignores everybody | Kiosk lock (-lock) makes the screen ignore every key and
every click, so a passer-by cannot pause your loop or open a panel.
The tray is the only way back in. |
| Stays awake | Keep display awake blocks the screensaver and display sleep, and releases the hold the moment the window hides — a viewer sitting in the tray never keeps a machine up. |
| Loops by itself | Slideshow with interval, loop and shuffle, and 21 GPU transitions. Point it at a folder and drop new artwork in — no playlist to rebuild, no re-upload, no publish step. |
Changing what a wall shows is copying a file into a folder. That is the whole workflow.
No cloud account, no subscription, no photos uploaded anywhere. The pictures go from your PC to your screen across your own network, and stop there.
What else it does
Drive the viewer. Next / previous, first / last. Slideshow with its interval, pause, loop and shuffle. Zoom, rotate, flip. All five view modes. Colour effects. Fullscreen, always-on-top, panels and the on-image overlay.
Jump anywhere. The viewer's folder history comes down to the phone — tap a folder and the desktop goes there.
Presentation mode. The current picture and two large next/previous buttons, sized to press without looking. Built for talking to a room rather than staring at a phone.
Follow the desktop. Bind the connection and the preview keeps itself up to date — when someone changes the picture at the PC, your phone shows it.
As many PCs as you like. Each saved machine keeps its own address, port and optional password. Tap one to connect.
Demo mode. Every screen runs against a viewer that does not exist, so you can see the whole app before installing anything or opening a port.
A private network, and nothing else
The app talks only to the computer whose address you type. There is no account, no cloud, no analytics, no advertising, and nothing is ever sent to the developer — there is no back end to send it to.
When your PC requires a password it is verified by challenge–response, so the password itself never crosses the network. Off the loopback the connection is TLS with a pinned certificate, and qIV's own AllowList (F9) still decides who may connect at all. Passwords you choose to save stay in app-private storage on the phone.
Requirements. It is a companion app and does nothing on its own — the same way a TV remote does nothing without the TV. You need QuickImageViewer running on a Windows PC with its Local Server enabled (F9), and the phone on the same network. The app's About screen walks through the setup.
Coming to Google Play. Until then, the desktop side is ready and waiting on F9.
Command-Line & Kiosk Mode
qIV supports extensive CLI arguments for automation, digital signage, slideshows and locked-down kiosk environments.
QuickImageViewer.exe [image_path] [options]
| Argument | Description |
|---|---|
"path\to\image.jpg"
|
Open this image at startup and browse its folder |
-startFolder
<path>
|
Open this folder as the browse / slideshow source |
-background
|
Start hidden in the system tray (service mode) |
-fullscreen
|
Start in fullscreen |
-windowedView
|
Start windowed (explicit override) |
-alwaysOnTop
|
Keep window above all others from launch |
-monitorNum#N
|
Open
centered
on
monitor
N
(1-based,
e.g.
-monitorNum#2)
|
-slideshow
|
Auto-start slideshow after content loads |
-slideshowInterval
N
|
Seconds
between
slides
(e.g.
-slideshowInterval
8)
|
-repeat
|
Loop the slideshow when it reaches the end |
-shuffle
|
Play slideshow in random order |
-slideshowTransition=<type>
|
Transition by name — 21 available
(Fade, Iris, SlideLeft,
ZoomIn, Spin, …)
|
-slideshowTransitions=<list>
|
Custom set, by name or by the numbers shown in the menu
(Fade,Iris,Spin or 6,8,1)
|
-slideshowTransitionSource=<none|all|list>
|
Which transitions are in play |
-slideshowTransitionOrder=<sequential|random>
|
How the next one is drawn from that set |
-slideshowTransitionShuffle
|
Pick a random transition per slide |
-hideMouse
|
Hide the mouse cursor at startup |
-lock
|
KIOSK mode — all keyboard and mouse input is ignored; unlock from the tray |
-keepDisplayAwake
|
Block the screensaver and display sleep while the window is on screen |
-dedicated
|
Run as a dedicated screen — no registry writes, no history, own icon, mutex and window class |
-config
<path>
|
Use
this
.ini
instead
of
the
one
named
after
the
exe
|
-instance=<name>
|
Name this instance — settings, lists, mutex and window class derive from it |
-instanceDesc=<text>
|
Free-text description, shown on the generated shortcut |
-promoOrder=<sequential|weighted>
|
How the next promotion is chosen |
-promoEveryImages=<from>-<to>
|
Promotion
every
N
images
—
0
off,
5-0
exact,
5-15
random
|
-promoEverySeconds=<from>-<to>
|
Same, counted in seconds — independent of the image counter |
-RestoreDefaults
|
Wipe all saved settings from the registry, show a confirmation dialog, and exit — recovery fallback if the app misbehaves after a config change |
-runOnStartup
|
Write / refresh the Windows startup registry entry so QIV launches automatically with Windows — equivalent to "Run on startup" in the tray menu. Dedicated instances write their own separate entry |
Kiosk example:
QuickImageViewer.exe -dedicated -lock -fullscreen -slideshow -shuffle -slideshowInterval 8 -startFolder "D:\Ads"
A
dedicated
screen
—
the
form
the
F8
panel
writes
into
a
startup
shortcut.
Folders
and
every
setting
come
from
the
.ini
and
its
.qim
/
.qpr
lists:
qIV_dedicated_Lobby.exe -dedicated -config "D:\Screens\qIV_dedicated_Lobby.ini"
Runs an isolated instance, loops a shuffled slideshow every 8 seconds, and ignores all user mouse/keyboard input — ideal for unattended public displays.
How qIV Compares to Other Windows Image Viewers
Searching for the best free image viewer for Windows 10 or 11? Here is how QuickImageViewer stacks up against the most common alternatives.
| Feature | qIV | Windows Photos | IrfanView |
|---|---|---|---|
| Speed & footprint | |||
| GPU VRAM bitmap cache | ✅ Direct2D | ❌ | ❌ |
| Instant image switching | ✅ pre-decoded neighbours | ⚠️ visible load delay | ⚠️ visible load delay |
| Portable — no installer | ✅ sub-10 MB single EXE | ❌ UWP / Store | ✅ |
| No background services | ✅ process exits cleanly | ❌ always-on UWP runtime | ✅ |
| Formats | |||
| HEIC / AVIF / JPEG XL | ✅ native + codec | ✅ | ⚠️ plugin required |
| SVG / OpenEXR / HDR | ✅ built-in | ❌ | ⚠️ plugin required |
| Batch convert & rename | ❌ | ❌ | ✅ |
| Plugin ecosystem | ❌ codecs built in instead | ❌ | ✅ |
| Viewing & editing | |||
| Non-destructive GPU effects | ✅ full D2D effect graph | ⚠️ basic adjustments | ⚠️ CPU, applied to the buffer |
| Crop / paint / resize editing | ❌ effects only, Ctrl+S bakes |
✅ | ✅ |
| Configurable info overlays | ✅ 9 independent slots | ❌ | ⚠️ slideshow captions |
| Slideshow transitions | ✅ 21, GPU | ⚠️ basic | ✅ |
| Floating thumbnail panels | ✅ up to 6 simultaneous | ❌ | ⚠️ separate browser window |
| Thumbnail strips as file manager | ✅ drag between folders, shell ops | ❌ | ⚠️ in the browser window |
| Offline GPS geocoding | ✅ embedded, zero network | ❌ | ❌ |
| Remote & multi-screen | |||
| Android companion app | ✅ qIV Remote — control, live preview, photo frame | ❌ | ❌ |
| Phone ↔ desktop photo transfer | ✅ both ways, originals not re-encodes | ❌ | ❌ |
| Drive other copies over TCP | ✅ plain-text protocol, self-describing | ❌ | ❌ |
| Mirror one screen to many | ✅ F11, per-target selection | ❌ | ❌ |
| Send an image across machines | ✅ Alt+Enter, file bytes on the wire |
❌ | ❌ |
| Scriptable from anything | ✅ netcat, shell, home automation |
❌ | ⚠️ local command line only |
| Kiosk / locked display mode | ✅ CLI flag, ignores every key and click | ❌ | ⚠️ limited |
| Starts with Windows, unattended | ✅ -runOnStartup + kiosk + keep-awake |
❌ | ⚠️ manual |
| Digital signage / ad loop | ✅ folder in, wall out — no publish step | ❌ | ⚠️ slideshow only |
| Phones, tablets & TVs as extra screens | ✅ as many as you own, no per-screen fee | ❌ | ❌ |
| Trust | |||
| No telemetry / tracking | ✅ zero | ❌ Microsoft telemetry | ✅ |
| No ads | ✅ | ❌ promoted content | ✅ |
| Open source | ✅ AGPLv3 | ❌ | ❌ |
| Per-monitor DPI V2 | ✅ | ✅ | ⚠️ partial |
✅ built in · ⚠️ partial, or needs a plugin or a separate window · ❌ not available. IrfanView wins the rows it wins — batch work and real editing are what it is for, and qIV does not try to replace them.
Frequently Asked Questions
Can qIV control another PC's image viewer, or a screen in another room?
Yes. Each copy can run a small TCP listener (F9) and any other copy
can drive it (F10). F11 mirrors what you do to every
selected screen; Ctrl+F10 sends a single typed command to whichever
instances you tick. Because the protocol is plain UTF-8 text and describes
itself — send help and it lists every command with its
description — a script, netcat, a home-automation system or a
phone app can drive it just as well. Sending one picture to a screen on a
different machine works too: Alt+Enter streams the image's own bytes,
so nothing depends on the far end being able to read your disk. See
Remote Control & Mirroring.
qIV crashed. What do I do?
qIV writes a crash report next to its own executable, named
QuickImageViewer_crash_<date>_<time>_<pid>.dmp, and
tells you where it put it.
Nothing is sent anywhere. qIV has no telemetry and makes no network call of its own, so that file is written to your disk and stays there. Attaching it to an issue is entirely your choice — but it is the difference between a bug that gets fixed and one that stays a mystery, because it records the exact point the program failed.
The file contains a snapshot of qIV's internal state, including open file paths and window titles. It does not contain your images. If a path in it is sensitive, describe the problem in the issue rather than attaching the file.
Is QuickImageViewer free?
Yes. QuickImageViewer is completely free and open source under the AGPLv3 license. No ads, no telemetry, no paid version.
Can it open HEIC, AVIF and JPEG XL files on Windows?
Yes. AVIF works natively on Windows 11, JPEG XL on Windows 11 24H2+, and HEIC/HEIF via the free Microsoft HEIF Extensions from the Microsoft Store. WebP, SVG, OpenEXR, Radiance HDR, JPEG 2000, QOI and all classic formats are supported too — 17 formats in total.
Does it need to be installed?
No. It is a single portable 7 MB executable — download and run. No installer, no registry pollution, no background services.
Why is it so fast?
Native C++23 on the raw Win32 API with Direct2D GPU rendering. Decoded images live in a VRAM cache, neighbours are pre-decoded on background threads, and the process can stay resident in the tray for instant recall.
Can it manage files — copy, move or delete images?
Yes. Directory thumbnail strips support drag & drop between folders (move, or Ctrl+drag to copy) plus right-click Copy, Cut, Paste and Delete with full Windows clipboard and Recycle Bin integration.
Can QuickImageViewer open RAW camera files?
QuickImageViewer uses the Windows Imaging Component (WIC) for decoding. If you install the appropriate Windows Camera Codec Pack or a manufacturer codec (Canon, Nikon, Sony, etc.), WIC will decode those RAW files and qIV will open them automatically — no extra configuration needed.
How do I set QuickImageViewer as my default image viewer?
Right-click any image file in Windows Explorer, choose Open with → Choose another app, browse to QuickImageViewer.exe and tick Always use this app. You can also set defaults per file type in Windows Settings → Apps → Default apps.
Does QuickImageViewer use a lot of memory or CPU?
No. Working set is typically under 100 MB when browsing standard JPEG folders. Decoded images are cached in VRAM (GPU memory) rather than system RAM. Background decode threads run at below-normal CPU priority so they never compete with foreground work.
Is QuickImageViewer available for Mac or Linux?
No. qIV is a native Windows application built on Direct2D, D3D11, Win32 APIs and the Windows Imaging Component — technologies specific to Windows 10 and 11. There are no plans for a Mac or Linux port.
Found a bug? Want something added?
Small requests count — a missing keyboard shortcut is as valid a request as a whole panel. The forms ask for a few details up front, because "it crashed" and "it crashed opening a 400 MB TIFF from a network drive" are different amounts of work to act on.
Report a bug Request a feature
Issues for the Android app belong here too
qIV Remote is developed separately, but its issues live alongside the viewer it talks to — almost every question about one involves the other. There is a form for it, and it starts with the three things that cause nearly every connection problem: Local Server switched off, the phone missing from the AllowList, or the two devices being on different networks.
Security issues get a private channel. qIV can listen on a network port, so anything touching authentication, TLS or the AllowList belongs in a security advisory rather than a public issue.
If it crashed, there is a .dmp file next to
QuickImageViewer.exe. Attaching it turns a mystery into a stack
trace. It holds open file paths and window titles — not the contents of your
images — and nothing is ever sent anywhere on its own.
Architecture & Building
- Renderer — Direct2D + D3D11 with GPU bitmap cache. GDI software fallback. Full ID2D1Effect graph for color operations.
- Decoding — WIC pipeline for OS-native formats. Custom decoders for EXR, HDR, PNM, QOI. SVG via resvg on a background IO thread.
- Threading — Worker thread pool for background decode and preload. Atomic indices prevent stale frames; window messages synchronize back to the UI thread.
- Caching — GPU bitmap cache with configurable size, preloading adjacent images in both directions. Live cache inspector panel.
- DPI — Per-monitor DPI aware V2; pixel-perfect on 4K and mixed-DPI setups.
- Persistence — Registry-backed settings, folder history manager, favorites system.
Third-Party Libraries
| Library | Purpose |
|---|---|
| resvg | SVG rasterizer (Rust static lib) |
| OpenJPEG | JPEG 2000 decoder |
| tinyexr | OpenEXR decoder |
| miniz | zlib compression for embedded GeoNames data |
Building from Source
Written in C++23. Requires CMake and MSVC (Visual Studio 2022 or CLion).
git clone https://github.com/icyhoty2k/QuickImageViewer.git
cd QuickImageViewer
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
cmake --build . --config Release
For
offline
geocoding,
generate
the
GeoNames
binary
resources
before
building
—
download
cities1000.txt,
admin1CodesASCII.txt,
admin2Codes.txt
and
countryInfo.txt
from
geonames.org
into
resources/geoData/,
then
run
python
tools/preprocess_cities.py.