{"id":17209171,"url":"https://github.com/rswinkle/sdl_img","last_synced_at":"2025-04-13T22:32:19.230Z","repository":{"id":146964916,"uuid":"114594884","full_name":"rswinkle/sdl_img","owner":"rswinkle","description":"A simple image viewer based on SDL2 and stb_image","archived":false,"fork":false,"pushed_at":"2025-04-13T06:33:38.000Z","size":5998,"stargazers_count":17,"open_issues_count":0,"forks_count":4,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-13T07:34:46.550Z","etag":null,"topics":["c","gif","image-viewer","linux-app","nuklear","sdl","stb-image","vim","windows-app"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rswinkle.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"rswinkle","liberapay":"rswinkle","custom":"http://www.robertwinkler.com/donations.html"}},"created_at":"2017-12-18T04:10:46.000Z","updated_at":"2025-04-13T06:33:42.000Z","dependencies_parsed_at":"2023-05-05T23:48:04.127Z","dependency_job_id":"761cc2b7-02ca-4da3-8557-e8c437c84eb9","html_url":"https://github.com/rswinkle/sdl_img","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rswinkle%2Fsdl_img","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rswinkle%2Fsdl_img/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rswinkle%2Fsdl_img/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rswinkle%2Fsdl_img/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rswinkle","download_url":"https://codeload.github.com/rswinkle/sdl_img/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248790698,"owners_count":21162073,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c","gif","image-viewer","linux-app","nuklear","sdl","stb-image","vim","windows-app"],"created_at":"2024-10-15T02:50:57.632Z","updated_at":"2025-04-13T22:32:19.190Z","avatar_url":"https://github.com/rswinkle.png","language":"C","funding_links":["https://github.com/sponsors/rswinkle","https://liberapay.com/rswinkle","http://www.robertwinkler.com/donations.html"],"categories":[],"sub_categories":[],"readme":"sdl_img\n=======\n\n[![Coverity Scan Build Status](https://scan.coverity.com/projects/15740/badge.svg)](https://scan.coverity.com/projects/rswinkle-sdl_img)\n\nA \"simple\" image viewer based on [stb_image.h](https://github.com/nothings/stb/blob/master/stb_image.h) (with the suggested animated GIF API extension).\n\nIt's \"simple\" in that it would work fine as a drop in replacement for most people since all the normal/expected behavior is there,\nbut it has tons of extra and unique features for power users, especially on Linux/Unix and if you're comfortable with the terminal.\n\nDownload\n========\nGet the latest [source](https://github.com/rswinkle/sdl_img) or the latest\n[release](https://github.com/rswinkle/sdl_img/releases) from Github\n\nGoals / Focus\n=============\n* Implement features I've always wanted in an image viewer\n* Relatively simple, short, readable code\n* Learn/Practice/Fun\n* Not really focused on speed but keep it reasonably fast and light weight\n\nControls/Basic Usage\n====================\n    ./sdl_img\n    ./sdl_img image_name.jpg\n    ./sdl_img -f image_name.jpg  (to start in full screen mode)\n\nThe first will open in \"File Selection\" mode since you didn't provide it any\nimages. The second will open image_name.jpg and all files with recognized image\nextensions in the same directory. On Windows that would be `sdl_img.exe`, but\nbetter to just right click on an image of each type and change the default\napplication to be sdl_img.exe and then double clicking any image of that type\nwill open it with sdl_img.  Left and right will go through images in the same\ndirectory in [alphabetical](http://stereopsis.com/strcmp4humans.html)\n[order](https://github.com/rswinkle/sdl_img/blob/master/src/string_compare.c).\n\n| Basic Controls      | Description |\n| --------------------|-------------|\n| Left (or Up)        | Previous image(s) or pan if appropriate |\n| Right (or Down)     | Next image(s) or pan if appropriate |\n| Space               | Next image(s) |\n| CTRL + Space        | Previous image(s) |\n| CTRL + Direction    | Next or previous image(s) even when zoomed in |\n| +/-                 | Zoom in/out |\n| Mouse Wheel         | Zoom in/out |\n| Left click + drag   | Pan around a zoomed in image |\n| A                   | Actual size |\n| F                   | Toggle fill screen mode |\n| Home                | Go to first image in the list |\n| End                 | Go to last image in the list |\n| M                   | Shuffle (Mix) the images (only in single mode) |\n| N                   | Sort the images by file name (only in single mode) |\n| CTRL+N              | Sort the images by file path (only in single mode) |\n| Z                   | Sort the images by size (only in single mode) |\n| T                   | Sort the images by last modified (only in single mode) |\n| CTRL + F or F11     | Toggle Fullscreen |\n| ESC                 | Exit or \"Back\" similar to Android |\n| L/R                 | Rotate the current image 90 degrees left/right |\n| CTRL + L/R          | Rotate the current image arbitrary degrees (popup GUI) |\n| H/V                 | Flip the current image horizontally/vertically |\n| S                   | Save current image(s) to current playlist |\n| CTRL + S            | Remove current image(s) from current playlist |\n| Delete              | Delete the current image and move to the next (only in single mode) |\n| Backspace           | Remove the current image and move to the next (only in single mode) |\n| CTRL + 1            | Single image mode |\n| CTRL + 2            | Double image mode |\n| CTRL + 4            | Quad image mode   |\n| CTRL + 8            | 8 image mode      |\n| CTRL + U            | Thumbnail mode    |\n| CTRL + I            | List mode    |\n| F1 - F10            | Start a slideshow with 1 - 10 second delay |\n\nFor GIFS there are extra controls, though the progress bar is only\ndisplayed if you are viewing a GIF in single image mode:\n\n| GIF Controls            | Description |\n| --------------------    |-------------|\n| CTRL + +/-              | Speed up or slow down an animated gif |\n| CTRL + Mouse Wheel      | Speed up or slow down an animated gif |\n| P                       | Pause/Unpause gif |\n| Mouse over progress bar | Pause |\n| Wheel over progress bar | Scroll through frames |\n| click/drag progress bar | select/scroll frames |\n\nThe most obvious unique features are the multi-image modes but others include the\nextra GIF features, the vim inspired thumbnail mode, the list mode, shuffle/sort etc.\n\nWithin each image mode the basic controls work on all images simultaneously\nunless a specific image is selected by hitting 1-n and then they operate only\non that image, ie cycling, zooming, fit will only effect that image.\nTo return to \"all at once\" mode, hit 0.\n\nBy default, when you hit next/prev in n-image mode, it will display the n sequential\nimages immediately after the nth image or before the 1st image.  This is annoying if\nyou're trying to compare a sequence of tuples that aren't interleaved when sorted.  For\nexample if you have files abc01.jpg, abc02.jpg,... and xyz01.jpg, xyz02.jpg..., all of\nthe former would sort first.  If you wanted to compare abcX with xyzX in 2-image mode\nevery time you hit next, you'd go from [abcX,xyzX] to [xyzX+1,xyzX+2].  To solve this\nyou can go to preferences and select the toggle \"Preserve relative offsets in multimode\nmovement\" which would lead to [abcX,xyzX] to [abcX+1,xyzX+1] behavior.  I'm open to\na better name/description (\"Independent movement mode\"?) and to making that the default\nbehavior.\n\nSwitching from a lower to a higher mode will load images to the right of the last image\ncurrently viewed.  Switching from a higher to a lower will show the first n images\nof the higher mode where n is the lower number.  An exception is if you have an\nimage selected and go to single mode, that is the image that will be used.\n\nThe slideshow feature is smart enough to wait long enough to finish any gif being\ndisplayed even if that takes longer than the specificed delay.  ESC ends the slideshow.\nAll other controls work while in slideshow mode, meaning starting a slideshow does not\nautomatically toggle to fullscreen, it will run in double, quad or oct-image mode, or\neven on a single image selected within those modes.\n\nSomething to note about the rotation functionality is that while it will rotate any\nimage, it will only ask whether you're sure you want to save single frame images because\nstb_image_write does not support gifs at all, let alone animated gifs.  It will try to\ndetect the type from the extension and output that type if possible, otherwise jpg is\nthe default.\n\nAdvanced Usage\n==============\n    ./sdl_img -l list_of_images (urls or local paths or mixed, doesn't matter)\n    ./sdl_img --list list_of_images\n    ./sdl_img dir (scan dir for images)\n    ./sdl_img -r dir (scan dir recursively for images)\n    ./sdl_img dir1 -r dir2 dir3 (scan dir1, dir2 recursively, dir3 )\n    ./sdl_img dir1 -R dir2 dir3 (scan dir1, then dir2 and dir3 recursively)\n    ./sdl_img image1.jpg image2.png\n    ./sdl_img image1.jpg -s 4\n    ./sdl_img -l list_of_urls -c ./custom_cache_dir\n\nOr any combination of those options, ie\n\n    ./sdl_img image.jpg -l list1 -s 8 ~/some/dir example.com/image.jpg -l list3 image4.gif -f\n\nThe option -s [delay] means start in slideshow mode with the given delay in seconds.\nIf delay is not 1-10 or is missing, delay will be set to 3 seconds.\n\nWhen using any of these modes, all the images will be collected in a list in the\norder they're given (not sorted like basic usage).  For now, if you have multiple\nurl images with the same name, downloaded on the same day, the one downloaded last\nwill simply overwrite the earlier ones in the cache.  This is because the cache does\ncreate subdirectories by date of the form YYYY-MM-DD for easy browsing/cleaning.\n\nThere is also the -c/--cache option which allows you to specify a custom cache\nlocation (only for this instance) which can be useful if you know you want to\nsave these images and don't want to bother copying them from the normal cache later.\n\nVim Inspired Thumb Mode\n=======================\nSwitch with CTRL+U to viewing all your current images as thumbnails on a vertically\nscrolling plane.  Animated GIF thumbnails are generated from the first frame.\nYou can use the arrows and mouse and scrollwheel to move around\nand select an image but if you're a vim user you'll feel right at home.\nNote the basic controls above are based on scancode (ie what you see on the\nphysical key, what the hardware actually sends, not any custom layout you have in\nsoftware) while the Thumbmode controls are based on keycode and do respect your\nlayout (otherwise you lose all that vim muscle memory).  This is irrelevant\nto most people but for people like myself who use Dvorak and *don't* change\nthe default Vim keybinds, HJKL, are JCVP physically.\n\n| Thumbmode Controls      | Description |\n| --------------------    |-------------|\n| Arrow Keys or HJKL      | Move around |\n| Mouse Wheel             | Move up and down |\n| g or Home               | Move to first image |\n| G or End                | Move to last image |\n| Click                   | Move to that image |\n| CTRL + Click            | Select multiple arbitrary images |\n| SHIFT + Click           | Select a contiguous range of images |\n| Enter or Double Click   | Change to normal mode on current image |\n| CTRL + HJKL             | Adjust the number of rows and columns shown |\n| V                       | Enter Visual Selection Mode |\n| SHIFT + V               | Enter Visual Line Selection Mode |\n| Backspace or R          | Removes current selection from the list |\n| X                       | Removes and possibly Deletes current selection |\n| CTRL + Backspace/R/X    | Invert action (remove/delete unselected items) |\n| S                       | Save current image(s) to current playlist |\n| CTRL + S                | Remove current image(s) from current playlist |\n| /                       | Start typing a search |\n| /pattern + ENTER        | Enter \"Results mode\" (cycle with n/N) |\n| CTRL + ENTER            | (in results mode) View results |\n| ESC                     | Exit or \"Back\" similar to Android |\n| CTRL + C                | Same as Vim, almost the same as ESC but can't exit thumbmode |\n\nThe number of rows and columns can also be set in Preferences, as well as whether X deletes\ninstead of just removing the selection.\n\nList Mode\n=========\nSwitch with CTRL+I to view a list of all your current images with columns showing the\nname, size, and last modified time.  You can select the column headings to sort by that,\nascending or descending.  You can scroll through the list or use up and down.  Hitting\nEnter or double clicking will go back to normal mode on that image.\n\nType something in the search bar at the top and hit enter to show a list of files that match.\nSame controls as normal list mode, but if you hit enter or double click you will be in \"View\nResults\" mode, which is normal mode but only viewing the results (same as from thumb search).\nESC to backs out of View Results, Results, and list mode entirely.\n\nBuilding\n========\nThere's a Makefile which is not great but gets the job done.\n\nOn Linux just running `make` will create a debug build,\nwhile `make config=release` (after a `make clean`) will create an optimized build.\n\nFor Windows builds I use the cross compiling environment\n[quasi-msys2](https://github.com/HolyBlackCat/quasi-msys2). I'm using the default setup\nwhich is native clang with a UCRT environment.  Do `make PLAT=cross_win` for that.\n\nOn Windows you can use the equivalent UCRT environment of\n[MSYS2](https://github.com/msys2/msys2/wiki/MSYS2-installation) (none of the other\nenvironments work curently) with `make PLAT=msys2` or just change the default\nat the top of the makefile so you don't have to specify it every time. Unfortunately it\nis broken for other MSYS2 environments (ie mingw64, clang64).  I think it's a\nplatform mismatch issue with SDL2 but UCRT is the recommended environment so even\nif I figured it out I'd probably keep using UCRT.\n\nThere are other targets for creating packages (ie installers) for each platform.\n\nPackaging\n=========\nI'll expand this section later, once I get to 1.0 and have packages and\nmore finalized packaging processes but I'm using\n[NSIS](http://nsis.sourceforge.net/Main_Page) to create my windows installer and\n[fpm](https://github.com/jordansissel/fpm) on linux to create linux packages.  Maybe\nI'll even try something like AppImage or Flatpak long term just for fun.\n\nNaming Issues\n=============\nSo I know there are some issues with the name.\n\nOriginally sdl_img only used SDL2 and stb_image; [stb_image](https://github.com/nothings/stb)\nand [stb_imv](https://github.com/nothings/stb-imv) already exist,\nso I chose sdl_img rather than stb_img.  Unfortunately, SDL_image and SDL2_image\n(libsdl-image1.2 and libsdl2-image in repos) also exist so there's a minor clash there too.\n\nNow I'm using the following libraries:\n[SDL2](https://www.libsdl.org), stb_image, stb_image_write, stb_image_resize2\n[libcurl](https://curl.haxx.se/libcurl/)\n[nuklear](https://github.com/vurtun/nuklear) (immediate mode GUI library)\n[WjCryptLibMd5](https://github.com/WaterJuice/WjCryptLib)\n[Lua](https://lua.org/) in the form of [minilua](https://github.com/edubart/minilua)\n\nSo potential names are stb_img, sdl_img, sdl2_img, sdl_imv, nuklear_img, or\nsome cool original name that I'm not creative enough to think of.  I'm open to\nsuggestions.\n\n\nTODO/IDEAS\n==========\n- [ ] Add window icon (either static or based on current image(s))\n- [x] Install icon in deb package\n- [ ] WebM support with mbew?\n- [ ] Clean up code a bit (ongoing)\n- [ ] Save memory by having the main thread update images as they're loaded\n- [x] AppImage and/or Flatpak (needs more work/testing)\n- [ ] Automatic updating\n- [ ] Travis-CI or Github Actions\n- [x] Coverity (Really out of date, need to run again)\n- [x] Figure out why certain rare animated gifs don't load all the frames\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frswinkle%2Fsdl_img","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frswinkle%2Fsdl_img","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frswinkle%2Fsdl_img/lists"}