exec64 / imv Goto Github PK
View Code? Open in Web Editor NEWImage viewer for X11/Wayland
License: MIT License
Image viewer for X11/Wayland
License: MIT License
At the moment, image decoding and processing is done in the UI thread, which makes imv unresponsive when loading large images. This should be done in the background.
Image viewing is done in two implicit modes, locked, and unlocked. Images start as unlocked, but when the user pans/zooms they are locked. Changing image or resetting the view unlocks it again.
When the window resizes, such as when changing fullscreen mode we should be resizing if unlocked.
With webm getting more and more common, it would be awesome to support it. It might be a bit close to video for an image viewer, but since people often use webm like gifs(see Gfycat and Imgur's gifv), it seems like it might fit.
FreeImage being licensed under the GPL makes the legal state of imv a bit complex. For our sanity let's just switch from MIT to GPL and avoid the mess.
I'll need consent from all contributors thus far, which is myself, @jdiez, and @guiniol.
Please post a comment confirming your approval. Failure to do so will result in your contributions having to be removed.
Here's an example:
I was going through some holiday pictures with my family when I noticed:
I made some successful changes, but I'm not at all familiar with SDL.
Hides cursor when drawing/redrawing the window.
Shows cursor when moving mouse.
diff --git a/src/main.c b/src/main.c
index 5a9c54c..bcbebd8 100644
--- a/src/main.c
+++ b/src/main.c
@@ -338,6 +338,7 @@ int main(int argc, char** argv)
imv_viewport_zoom(&view, &ldr, IMV_ZOOM_MOUSE, e.wheel.y);
break;
case SDL_MOUSEMOTION:
+ SDL_ShowCursor(SDL_ENABLE);
if(e.motion.state & SDL_BUTTON_LMASK) {
imv_viewport_move(&view, e.motion.xrel, e.motion.yrel);
}
@@ -409,6 +410,7 @@ int main(int argc, char** argv)
}
if(view.redraw) {
+ SDL_ShowCursor(SDL_DISABLE);
if(g_options.solid_bg) {
SDL_SetRenderDrawColor(renderer,
g_options.bg_r, g_options.bg_g, g_options.bg_b, 255);
A user sent this screenshot: http://i.imgur.com/jx8RYST.png
We need to figure out why it doesn't tile, and resolve that.
This is useful for people wishing to use imv as part of a image selection pipeline. They can open a bunch of images, filter out the ones they dislike with x
, and then hit q
to quit imv, and the paths of the images they kept will be printed to stdout, one per line.
We always create a chequered background texture, even when we're only displaying a solid background. Instead we should only create it if it's actually needed to save time and memory.
A way to specifiy a picture to start at when launched (similar to sxiv's "-n" or feh's "-|") would be great.
Originally I wanted to just submit a pull request, however after starting to work I noticed your way of parsing arguments can't handle a value after an option. Should I rewrite it using getopt and submit a PR for that as well? Or do you want to solve it another way?
This gif renders as blank: http://deptford.tv/about/pics/test.gif
As far as I can tell, the default behavior is to resize all images to fit the view port, even if the images are smaller, and the 'actual size' mode doesn't resize at all.
So I would like to request a third mode, where images, that are larger than the view, will be resized to fit and smaller images stay unchanged (but centered, like 'actual size' does for smaller images).
A point @czarkoff raised is that imv currently uses inotify
to watch files. We should either use a portable interface, or provide platform dependent sourced files for the reload subsystem. That is, keep reload.h
the same, but rename reload.c
to reload_inotify.c
and provide realod_kqueue.c
or similar as an alternative. Then whichever implementation is available on the current platform can be used at build-time.
Example use case: gpg --decrypt image.png.pgp | imv -r
From #44.
Images distort when zooming/panning using SDL's software renderer.
The overlay resources and logic could be cleaned up by creating text.c
and text.h
. An interface could then be exposed that would provide a clean way to draw text from the main loop in a generic way.
Program crashes after window appears for split second.
Had to install FreeImage-3.15.4 and libSDL2-2.0.3-r200 to compile imv.
This is on Gentoo Linux, kernel 4.3.
Installation:
$ make
COMPILING build/texture.o
COMPILING build/viewport.o
COMPILING build/main.o
COMPILING build/image.o
COMPILING build/navigator.o
LINKING imv
$ sudo make install
install -D -m 0755 imv /usr/bin/imv
install -D -m 0644 doc/imv.1 /usr/share/man/man1/imv.1
install -D -m 0644 files/imv.desktop /usr/share/applications/imv.desktop
Running:
$ imv image.png
Floating point exception
I would be nice to be able to make a slideshow go faster
We should eventually add a "gallery" mode, where users can view low-resolution thumbnails as a gallery. They should be able to toggle in and out of gallery mode at run-time.
Currently the main loop runs ~100 times a second. This is far more often than needed. Instead we should block when waiting for events, so the kernel can schedule imv more efficiently.
Events we should respond to immediately:
Events that can be checked less frequently:
SDL_WaitEventTimeout
looks promising, but does not cater to events such as data sent back from the loader thread.
This should be doable:
imv http://i.imgur.com/iyTZBxt.png
libcurl is probably the best way to do this
Running on 64bit Gentoo, i3 WM 4.10.4, Xorg server 1.16.4, SDL2 2.0.3-r200, Freeimage 3.15.4.
When I try loading any type of image (jpg, png) the code crashes with a Floating point exception
. Looking through the code the crash occurs at imv_texture_set_image
in texture.c
line 62.
45| int imv_texture_set_image(struct imv_texture *tex, FIBITMAP *image)
46| {
47| FIBITMAP *frame = FreeImage_ConvertTo32Bits(image);
48| tex->width = FreeImage_GetWidth(frame);
49| tex->height = FreeImage_GetHeight(frame);
50|
51| char* pixels = (char*)FreeImage_GetBits(frame);
52|
53| /* figure out how many chunks are needed, and create them */
54| if(tex->num_chunks > 0) {
55| for(int i = 0; i < tex->num_chunks; ++i) {
56| SDL_DestroyTexture(tex->chunks[i]);
57| }
58| free(tex->chunks);
59| }
60|
61| tex->num_chunks_wide = 1 + tex->width / tex->chunk_width;
62+> tex->num_chunks_tall = 1 + tex->height / tex->chunk_height;
void imv_init_texture
calls SDL_GetRendererInfo
which in my case returns a SDL_RendererInfo.max_texture_height
that equals zero. This value is then used in the calculating of chunks which causes the divide by zero.
20| void imv_init_texture(struct imv_texture *tex, SDL_Renderer *r)
21| {
22| tex->renderer = r;
23| tex->num_chunks = 0;
24| tex->chunks = NULL;
25|
26| SDL_RendererInfo ri;
27| SDL_GetRendererInfo(r, &ri);
28| tex->chunk_width = ri.max_texture_width;
29+> tex->chunk_height = ri.max_texture_height;
30| }
I like imv
a lot, really, and I want to use it as my default image viewer to use it with ranger
(actually I'm using it like that already), a terminal file manager, but it lacks of two things that still does not make it ideal for the task, and make me think of return to sxiv
:
a) An option, it not has to be a default one (sxiv
and feh
make this by default), to be able to navigate through all the image files in the current directory even when a unique image file is specified via the command line. Thus, you do not to have to select all the images in a directory to explore all of them and at the same time you still can decide which image you would see first.
b) A thumbnail option (sxiv
and feh
have both this option) that allows you to previsualize all the image files in the directory in small thumbnails and navigate through them. The thumbnail mode in sxiv
is specially handy as you can switch between image mode and thumbnail mode easily.
How you see this? doable?
Thanks for create imv anyway 😄
With Krita becoming more popular, it might be worth adding support for these formats. They're both open specifications. Mypaint, another painting application, defaults to .ora
I've uploaded a tar archive with an example of each file. (1)
Renaming either file with a .zip extension allows you to extract them.
Both formats contain a mergedimage.png
in the root file directory after extraction, which is what imv would want to open.
I believe .kra was based on .ora. (2)
Chequered should also be possible, with support for transparency.
We should support a basic ini-style config file for our options.
We can use this to parse the ini file: https://github.com/eXeC64/ini_parser
And SirCmpwn has kindly donated this function to imv under CC0, so we can use that to locate the config file.
I suggest the configuration format look something (this isn't a hard spec) like this:
[display]
background = solid
background_color = #000000
[input]
mwheelup = zoom 1
mwheeldown = zoom -1
h = pan -1 0
j = pan 0 1
k = pan 0 -1
l = pan 1 0
left = previous
right = next
Running:
imv -fs path/to/image.jpg
Results in the error:
Unknown argument 's'. Aborting.
Installed from the Arch Linux AUR. I'll Give things a quick look in the repository here, but I'm not confident enough in my programming to actually know what exactly will fix this. Possibly the '-s' option not even existing?
Is there interest in adding a slideshow option?
I propose something super simple like a command line option -s
that expects an integer argument and just skips to the next image after the specified number of seconds.
Thoughts?
If there is interest, I'd go ahead and try to come up with a solution.
Test-Driven-Development is pretty trendy right now, but we don't have it in our budget this quarter. So for now, let's just try and refactor our main subsystem's interfaces a little so they can be tested more easily, and write some unit tests for them.
Hi, I saw your post on reddit and decided to check this out! I like it pretty well, although one minor thing I noticed is that it doesn't draw any window borders. I have my tiling wm (bspwm) setup so that the focused window draws a small border. How hard would this be to implement for imv
?
So that it can be set as default for xdg-open etc...
Based on the feh one, this is what it could look like. The Icon is probably not necessary for tiling WM.
[Desktop Entry]
Name=IMV
GenericName=Image viewer
GenericName[en_US]=Image viewer
Comment=Fast freeimage-based Image Viewer
Exec=imv %F
Terminal=false
Type=Application
Icon=/path/to/icon.png
Categories=Graphics;2DGraphics;Viewer;
MimeType=image/bmp;image/gif;image/jpeg;image/jpg;image/pjpeg;image/png;image/tiff;image/x-bmp;image/x-pcx;image/x-png;image/x-portable-anymap;image/x-portable-bitmap;image/x-portable-graymap;image/x-portable-pixmap;image/x-tga;image/x-xbitmap;
Name[en_US]=imv
In feh
I can press d
to toggle a display where I can see the filename and number as a text overlay on the image. I find this feature really handy and find it painful to use imv
because of the lack of this feature.
The quality of the code is "good enough", but would ideally be better. Let's start commenting things more, and cleaning up the interfaces.
Users should be able to switch between bilinear and nearest neighbour resampling. This is for the sake of pixel art.
I keymap to reload the image, and an option to automatically do so, would be very useful.
FreeImage doesn't support SVG so we'll have to use another library to support this.
With the image reload support, I started using imv instead of sxiv to display album art. However, I noticed two things:
Might be related to SDL as with #6? I will try this with some other SDL programs when I have the time to do so.
If the mentioned problems are unclear (I assume you don't use bspwm) I can make a sxiv/imv comparision webm.
Idea:
-i
echo 2.png | imv 1.png - 3.png
is equivalent to imv 1.png 2.png 3.png
.-
when you want to use stdin.it would be great if this app could be passed in a file or comma seperated list of urls.
and than use curl to download one at a time while being displayed, and once transitioning to the next gif
delete the previous file from /tmp. or even keep file, in a predefine directory if user presses a key to trigger the action.
Add a key that causes imv to print the file path of the current image to stdout. With that you can use it as a image filter or selector in the middle of a pipeline:
custom-set-wallpaper-script "$(find ./wallpaper -type f -name '*.jpg' | imv | tail -n1)"
find -type f -name '*.jpg' | imv | xargs rm -v
find ./holiday_pics -type f -name '*.jpg' | imv | xargs cp -t ~/outbox
Trying to compile and link imv on Fedora 22 and getting the following compiler and linker error:
imv/ $ make
COMPILING build/texture.o
COMPILING build/viewport.o
COMPILING build/main.o
COMPILING build/image.o
src/image.c: In function ‘imv_image_load_next_frame’:
src/image.c:163:26: warning: implicit declaration of function ‘FreeImage_EnlargeCanvas’ [-Wimplicit-function-declaration]
FIBITMAP *expanded = FreeImage_EnlargeCanvas(frame32,
^
src/image.c:163:26: warning: initialization makes pointer from integer without a cast [-Wint-conversion]
COMPILING build/navigator.o
LINKING imv
build/image.o: In function `imv_image_load_next_frame':
image.c:(.text+0x5c2): undefined reference to `FreeImage_EnlargeCanvas'
collect2: error: ld returned 1 exit status
Makefile:19: recipe for target 'imv' failed
make: *** [imv] Error 1
I have the freeimage headers installed, version 3.10.0-23:
imv/ $ rpm -qa | grep freeimage
freeimage-3.10.0-23.fc22.x86_64
freeimage-devel-3.10.0-23.fc22.x86_64
Do you have any idea as to what the problem could be?
Thanks
This is Gentoo Linux running:
libSDL2-2.0.3-r200
sdl2-ttf-2.0.12-r1
I'm not very good with debugging yet, so all I can give is the valgrind output :/
~ $ make
COMPILING build/texture.o
COMPILING build/loader.o
COMPILING build/viewport.o
COMPILING build/main.o
COMPILING build/util.o
COMPILING build/navigator.o
~ $ ./imv ~/pictures/img_0.jpg
Segmentation fault
~ $ valgrind ./imv ~/pictures/img_0.jpg
==22726== Memcheck, a memory error detector
==22726== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==22726== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==22726== Command: ./imv /home/shana/pictures/img_0.jpg
==22726==
==22726== Syscall param writev(vector[...]) points to uninitialised byte(s)
==22726== at 0x5B08990: __writev_nocancel (in /lib64/libc-2.21.so)
==22726== by 0x8A76D9A: _xcb_conn_wait (in /usr/lib64/libxcb.so.1.1.0)
==22726== by 0x8A77190: _xcb_out_send (in /usr/lib64/libxcb.so.1.1.0)
==22726== by 0x8A77214: xcb_writev (in /usr/lib64/libxcb.so.1.1.0)
==22726== by 0x65CE40D: _XSend (in /usr/lib64/libX11.so.6.3.0)
==22726== by 0x65CE901: _XReply (in /usr/lib64/libX11.so.6.3.0)
==22726== by 0x65B9A86: XInternAtom (in /usr/lib64/libX11.so.6.3.0)
==22726== by 0x4EE0CAA: SetWindowBordered (in /usr/lib64/libSDL2-2.0.so.0.2.1)
==22726== by 0x4EE1AE1: X11_CreateWindow (in /usr/lib64/libSDL2-2.0.so.0.2.1)
==22726== by 0x4ED77EB: SDL_CreateWindow_REAL (in /usr/lib64/libSDL2-2.0.so.0.2.1)
==22726== by 0x4047AF: main (in /home/shana/builds/imv/imv)
==22726== Address 0x9919973 is 35 bytes inside a block of size 16,384 alloc'd
==22726== at 0x4C2C060: calloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==22726== by 0x65BEB51: XOpenDisplay (in /usr/lib64/libX11.so.6.3.0)
==22726== by 0x4EDFB04: X11_CreateDevice (in /usr/lib64/libSDL2-2.0.so.0.2.1)
==22726== by 0x4ED7690: SDL_VideoInit_REAL (in /usr/lib64/libSDL2-2.0.so.0.2.1)
==22726== by 0x4E4BDD6: SDL_InitSubSystem_REAL (in /usr/lib64/libSDL2-2.0.so.0.2.1)
==22726== by 0x404741: main (in /home/shana/builds/imv/imv)
==22726==
==22726== Conditional jump or move depends on uninitialised value(s)
==22726== at 0x40568D: create_chequered (in /home/shana/builds/imv/imv)
==22726== by 0x404808: main (in /home/shana/builds/imv/imv)
==22726==
==22726== Conditional jump or move depends on uninitialised value(s)
==22726== at 0x405698: create_chequered (in /home/shana/builds/imv/imv)
==22726== by 0x404808: main (in /home/shana/builds/imv/imv)
==22726==
==22726== Conditional jump or move depends on uninitialised value(s)
==22726== at 0x4056A8: create_chequered (in /home/shana/builds/imv/imv)
==22726== by 0x404808: main (in /home/shana/builds/imv/imv)
==22726==
==22726== Conditional jump or move depends on uninitialised value(s)
==22726== at 0x4027AF: imv_init_texture (in /home/shana/builds/imv/imv)
==22726== by 0x404893: main (in /home/shana/builds/imv/imv)
==22726==
==22726== Conditional jump or move depends on uninitialised value(s)
==22726== at 0x4027C7: imv_init_texture (in /home/shana/builds/imv/imv)
==22726== by 0x404893: main (in /home/shana/builds/imv/imv)
==22726==
==22726== Conditional jump or move depends on uninitialised value(s)
==22726== at 0x402970: imv_texture_set_image (in /home/shana/builds/imv/imv)
==22726== by 0x404E71: main (in /home/shana/builds/imv/imv)
==22726==
==22726== Conditional jump or move depends on uninitialised value(s)
==22726== at 0x4C29F1D: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==22726== by 0x4029C5: imv_texture_set_image (in /home/shana/builds/imv/imv)
==22726== by 0x404E71: main (in /home/shana/builds/imv/imv)
==22726==
==22726== Conditional jump or move depends on uninitialised value(s)
==22726== at 0x402B0E: imv_texture_set_image (in /home/shana/builds/imv/imv)
==22726== by 0x404E71: main (in /home/shana/builds/imv/imv)
==22726==
==22726== Conditional jump or move depends on uninitialised value(s)
==22726== at 0x402A5A: imv_texture_set_image (in /home/shana/builds/imv/imv)
==22726== by 0x404E71: main (in /home/shana/builds/imv/imv)
==22726==
==22726== Use of uninitialised value of size 8
==22726== at 0x402A88: imv_texture_set_image (in /home/shana/builds/imv/imv)
==22726== by 0x404E71: main (in /home/shana/builds/imv/imv)
==22726==
==22726== Use of uninitialised value of size 8
==22726== at 0x402AAE: imv_texture_set_image (in /home/shana/builds/imv/imv)
==22726== by 0x404E71: main (in /home/shana/builds/imv/imv)
==22726==
==22726== Use of uninitialised value of size 8
==22726== at 0x402AE1: imv_texture_set_image (in /home/shana/builds/imv/imv)
==22726== by 0x404E71: main (in /home/shana/builds/imv/imv)
==22726==
==22726== Conditional jump or move depends on uninitialised value(s)
==22726== at 0x402B2C: imv_texture_set_image (in /home/shana/builds/imv/imv)
==22726== by 0x404E71: main (in /home/shana/builds/imv/imv)
==22726==
==22726== Conditional jump or move depends on uninitialised value(s)
==22726== at 0x402B61: imv_texture_set_image (in /home/shana/builds/imv/imv)
==22726== by 0x404E71: main (in /home/shana/builds/imv/imv)
==22726==
==22726== Conditional jump or move depends on uninitialised value(s)
==22726== at 0x402E23: imv_texture_draw (in /home/shana/builds/imv/imv)
==22726== by 0x4052CD: main (in /home/shana/builds/imv/imv)
==22726==
==22726== Use of uninitialised value of size 8
==22726== at 0x402D44: imv_texture_draw (in /home/shana/builds/imv/imv)
==22726== by 0x4052CD: main (in /home/shana/builds/imv/imv)
==22726==
==22726== Invalid read of size 8
==22726== at 0x402D44: imv_texture_draw (in /home/shana/builds/imv/imv)
==22726== by 0x4052CD: main (in /home/shana/builds/imv/imv)
==22726== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==22726==
==22726==
==22726== Process terminating with default action of signal 11 (SIGSEGV)
==22726== Access not within mapped region at address 0x0
==22726== at 0x402D44: imv_texture_draw (in /home/shana/builds/imv/imv)
==22726== by 0x4052CD: main (in /home/shana/builds/imv/imv)
==22726== If you believe this happened as a result of a stack
==22726== overflow in your program's main thread (unlikely but
==22726== possible), you can try to increase the size of the
==22726== main thread stack using the --main-stacksize= flag.
==22726== The main thread stack size used in this run was 8388608.
==22726==
==22726== HEAP SUMMARY:
==22726== in use at exit: 3,599,060 bytes in 4,233 blocks
==22726== total heap usage: 9,866 allocs, 5,633 frees, 10,872,704 bytes allocated
==22726==
==22726== LEAK SUMMARY:
==22726== definitely lost: 152 bytes in 1 blocks
==22726== indirectly lost: 62,771 bytes in 1,944 blocks
==22726== possibly lost: 3,147,891 bytes in 19 blocks
==22726== still reachable: 388,246 bytes in 2,269 blocks
==22726== suppressed: 0 bytes in 0 blocks
==22726== Rerun with --leak-check=full to see details of leaked memory
==22726==
==22726== For counts of detected and suppressed errors, rerun with: -v
==22726== Use --track-origins=yes to see where uninitialised values come from
==22726== ERROR SUMMARY: 21 errors from 18 contexts (suppressed: 0 from 0)
Segmentation fault
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.