1
0
mirror of https://github.com/gryf/wmaker.git synced 2025-12-28 17:32:29 +01:00

util/wmiv: add image auto orientation detection

Based on libexif feature, this patch is adding orientation
detection and provides 2 more shortcuts for live
right/left rotation. Internal version was bumped to 0.7.
This commit is contained in:
David Maciejak
2014-06-02 18:27:36 +08:00
committed by Carlos R. Mafra
parent 9b65f55f53
commit 97d281e310
4 changed files with 220 additions and 15 deletions

View File

@@ -640,6 +640,12 @@ dnl ===============================================
dnl End of stuff that uses X dnl End of stuff that uses X
dnl =============================================== dnl ===============================================
dnl EXIF Support
dnl ===========
WM_CHECK_LIBEXIF
AS_IF([test "x$LIBEXIF" != "x"],
[AC_DEFINE(HAVE_EXIF, 1, [Define if EXIF can be used])])
dnl PNG Support dnl PNG Support
dnl =========== dnl ===========
AC_ARG_ENABLE([png], AC_ARG_ENABLE([png],

34
m4/wm_libexif.m4 Normal file
View File

@@ -0,0 +1,34 @@
# wm_libexif.m4 - Macros to check proper libexif
#
# Copyright (c) 2014 Window Maker Team
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
# WM_CHECK_LIBEXIF
# -------------
#
# Checks the needed library link flags
# Sets variable LIBEXIF with the appropriates flags
AC_DEFUN_ONCE([WM_CHECK_LIBEXIF],
[AC_CHECK_HEADER([libexif/exif-data.h],
[AC_CHECK_FUNC(exif_data_new_from_file,
[LIBEXIF=],
[AC_CHECK_LIB(exif, [exif_data_new_from_file],
[LIBEXIF=-lexif],
[AC_MSG_WARN(Could not find EXIF library, you may experience problems)
LIBEXIF=] )] )],
[AC_MSG_WARN([header for EXIF library not found])])
AC_SUBST(LIBEXIF) dnl
])

View File

@@ -73,7 +73,7 @@ wmmenugen_SOURCES = wmmenugen.c wmmenugen.h wmmenugen_misc.c \
wmiv_LDADD = \ wmiv_LDADD = \
$(top_builddir)/wrlib/libwraster.la \ $(top_builddir)/wrlib/libwraster.la \
@XLFLAGS@ @XLIBS@ \ @XLFLAGS@ @XLIBS@ \
@GFXLIBS@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) @GFXLIBS@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) $(LIBEXIF)
wmiv_SOURCES = wmiv.c wmiv.h wmiv_SOURCES = wmiv.c wmiv.h

View File

@@ -21,6 +21,7 @@
#if !defined(_GNU_SOURCE) #if !defined(_GNU_SOURCE)
#define _GNU_SOURCE #define _GNU_SOURCE
#endif #endif
#include <X11/keysym.h> #include <X11/keysym.h>
#include <X11/XKBlib.h> #include <X11/XKBlib.h>
#include <X11/Xatom.h> #include <X11/Xatom.h>
@@ -34,6 +35,11 @@
#include <unistd.h> #include <unistd.h>
#include <sys/stat.h> #include <sys/stat.h>
#include "config.h" #include "config.h"
#ifdef HAVE_EXIF
#include <libexif/exif-data.h>
#endif
#ifdef HAVE_PTHREAD #ifdef HAVE_PTHREAD
#include <pthread.h> #include <pthread.h>
#endif #endif
@@ -57,7 +63,7 @@ Pixmap pix;
const char *APPNAME = "wmiv"; const char *APPNAME = "wmiv";
int APPVERSION_MAJOR = 0; int APPVERSION_MAJOR = 0;
int APPVERSION_MINOR = 6; int APPVERSION_MINOR = 7;
int NEXT = 0; int NEXT = 0;
int PREV = 1; int PREV = 1;
float zoom_factor = 0; float zoom_factor = 0;
@@ -66,6 +72,7 @@ int max_height = 0;
Bool fullscreen_flag = False; Bool fullscreen_flag = False;
Bool focus = False; Bool focus = False;
Bool back_from_fullscreen = False;
#ifdef HAVE_PTHREAD #ifdef HAVE_PTHREAD
Bool diaporama_flag = False; Bool diaporama_flag = False;
@@ -98,6 +105,90 @@ typedef struct linked_list {
linked_list_t list; linked_list_t list;
link_t *current_link; link_t *current_link;
/*
load_oriented_image: used to load an image and optionally
get its orientation if libexif is available
return the image on success, NULL on failure
*/
RImage *load_oriented_image(RContext *context, const char *file, int index)
{
RImage *image;
#ifdef HAVE_EXIF
int orientation = 0;
#endif
image = RLoadImage(context, file, index);
if (!image)
return NULL;
#ifdef HAVE_EXIF
ExifData *exifData = exif_data_new_from_file(file);
if (exifData) {
ExifByteOrder byteOrder = exif_data_get_byte_order(exifData);
ExifEntry *exifEntry = exif_data_get_entry(exifData, EXIF_TAG_ORIENTATION);
if (exifEntry)
orientation = exif_get_short(exifEntry->data, byteOrder);
exif_data_free(exifData);
}
/*
0th Row 0th Column
1 top left side
2 top right side
3 bottom right side
4 bottom left side
5 left side top
6 right side top
7 right side bottom
8 left side bottom
*/
if (image && (orientation > 1)) {
RImage *tmp = NULL;
switch (orientation) {
case 2:
tmp = RHorizontalFlipImage(image);
break;
case 3:
tmp = RRotateImage(image, 180);
break;
case 4:
tmp = RVerticalFlipImage(image);
break;
case 5: {
RImage *tmp2;
tmp2 = RVerticalFlipImage(image);
if (tmp2) {
tmp = RRotateImage(tmp2, 90);
RReleaseImage(tmp2);
}
}
break;
case 6:
tmp = RRotateImage(image, 90);
break;
case 7: {
RImage *tmp2;
tmp2 = RVerticalFlipImage(image);
if (tmp2) {
tmp = RRotateImage(tmp2, 270);
RReleaseImage(tmp2);
}
}
break;
case 8:
tmp = RRotateImage(image, 270);
break;
}
if (tmp) {
RReleaseImage(image);
image = tmp;
}
}
#endif
return image;
}
/* /*
change_title: used to change window title change_title: used to change window title
return EXIT_SUCCESS on success, 1 on failure return EXIT_SUCCESS on success, 1 on failure
@@ -211,6 +302,59 @@ int merge_with_background(RImage *i)
return EXIT_FAILURE; return EXIT_FAILURE;
} }
/*
turn_image: rotate the image by the angle passed
return EXIT_SUCCESS on success, EXIT_FAILURE on failure
*/
int turn_image(float angle)
{
RImage *tmp;
if (!img)
return EXIT_FAILURE;
tmp = RRotateImage(img, angle);
if (!tmp)
return EXIT_FAILURE;
if (!fullscreen_flag) {
if (img->width != tmp->width || img->height != tmp->height)
XResizeWindow(dpy, win, tmp->width, tmp->height);
}
RReleaseImage(img);
img = tmp;
rescale_image();
if (!fullscreen_flag) {
XCopyArea(dpy, pix, win, ctx->copy_gc, 0, 0, img->width, img->height, 0, 0);
} else {
XClearWindow(dpy, win);
XCopyArea(dpy, pix, win, ctx->copy_gc, 0, 0,
img->width, img->height, max_width/2-img->width/2, max_height/2-img->height/2);
}
return EXIT_SUCCESS;
}
/*
turn_image_right: rotate the image by 90 degree
return EXIT_SUCCESS on success, EXIT_FAILURE on failure
*/
int turn_image_right(void)
{
return turn_image(90.0);
}
/*
turn_image_left: rotate the image by -90 degree
return EXIT_SUCCESS on success, 1 on failure
*/
int turn_image_left(void)
{
return turn_image(-90.0);
}
/* /*
draw_failed_image: create a red crossed image to indicate an error loading file draw_failed_image: create a red crossed image to indicate an error loading file
return the image on success, NULL on failure return the image on success, NULL on failure
@@ -250,6 +394,7 @@ int full_screen(void)
if (fullscreen_flag) { if (fullscreen_flag) {
fullscreen_flag = False; fullscreen_flag = False;
zoom_factor = 0; zoom_factor = 0;
back_from_fullscreen = True;
} else { } else {
fullscreen_flag = True; fullscreen_flag = True;
zoom_factor = 1000; zoom_factor = 1000;
@@ -279,7 +424,7 @@ int full_screen(void)
int zoom_in_out(int z) int zoom_in_out(int z)
{ {
RImage *old_img = img; RImage *old_img = img;
RImage *tmp = RLoadImage(ctx, current_link->data, 0); RImage *tmp = load_oriented_image(ctx, current_link->data, 0);
if (!tmp) if (!tmp)
return EXIT_FAILURE; return EXIT_FAILURE;
@@ -368,7 +513,7 @@ int change_image(int way)
} }
if (DEBUG) if (DEBUG)
fprintf(stderr, "current file is> %s\n", (char *)current_link->data); fprintf(stderr, "current file is> %s\n", (char *)current_link->data);
img = RLoadImage(ctx, current_link->data, 0); img = load_oriented_image(ctx, current_link->data, 0);
if (!img) { if (!img) {
fprintf(stderr, "Error: %s %s\n", (char *)current_link->data, fprintf(stderr, "Error: %s %s\n", (char *)current_link->data,
@@ -453,7 +598,7 @@ int linked_list_add(linked_list_t *list, const void *data)
/* calloc sets the "next" field to zero. */ /* calloc sets the "next" field to zero. */
link = calloc(1, sizeof(link_t)); link = calloc(1, sizeof(link_t));
if (!link) { if (!link) {
fprintf(stderr, "calloc failed.\n"); fprintf(stderr, "Error: memory allocation failed\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
link->data = data; link->data = data;
@@ -572,7 +717,9 @@ int main(int argc, char **argv)
#ifdef HAVE_PTHREAD #ifdef HAVE_PTHREAD
"d: launch diaporama mode\n" "d: launch diaporama mode\n"
#endif #endif
"l: rotate image on the left\n"
"q: quit\n" "q: quit\n"
"r: rotate image on the right\n"
"right: next image\n" "right: next image\n"
"left: previous image\n" "left: previous image\n"
"up: first image\n" "up: first image\n"
@@ -618,7 +765,7 @@ int main(int argc, char **argv)
} }
} }
img = RLoadImage(ctx, reading_filename, 0); img = load_oriented_image(ctx, reading_filename, 0);
if (!img) { if (!img) {
fprintf(stderr, "Error: %s %s\n", reading_filename, RMessageForError(RErrorCode)); fprintf(stderr, "Error: %s %s\n", reading_filename, RMessageForError(RErrorCode));
@@ -703,21 +850,33 @@ int main(int argc, char **argv)
XConfigureEvent xce = e.xconfigure; XConfigureEvent xce = e.xconfigure;
if (xce.width != img->width || xce.height != img->height) { if (xce.width != img->width || xce.height != img->height) {
RImage *old_img = img; RImage *old_img = img;
img = RLoadImage(ctx, current_link->data, 0); img = load_oriented_image(ctx, current_link->data, 0);
if (!img) { if (!img) {
/* keep the old img and window size */ /* keep the old img and window size */
img = old_img; img = old_img;
XResizeWindow(dpy, win, img->width, img->height); XResizeWindow(dpy, win, img->width, img->height);
} else { } else {
img = RScaleImage(img, xce.width, xce.height); RImage *tmp2;
if (!img) { if (!back_from_fullscreen)
img = old_img; /* manually resized window */
XResizeWindow(dpy, win, img->width, img->height); tmp2 = RScaleImage(img, xce.width, xce.height);
} else { else {
merge_with_background(img); /* back from fullscreen mode, maybe img was rotated */
if (RConvertImage(ctx, img, &pix)) tmp2 = img;
RReleaseImage(old_img); back_from_fullscreen = False;
XClearWindow(dpy, win);
}
merge_with_background(tmp2);
if (RConvertImage(ctx, tmp2, &pix)) {
RReleaseImage(old_img);
img = RCloneImage(tmp2);
RReleaseImage(tmp2);
change_title(&title_property, (char *)current_link->data);
XSync(dpy, True);
XResizeWindow(dpy, win, img->width, img->height); XResizeWindow(dpy, win, img->width, img->height);
XCopyArea(dpy, pix, win, ctx->copy_gc, 0, 0,
img->width, img->height, 0, 0);
} }
} }
} }
@@ -814,6 +973,12 @@ int main(int argc, char **argv)
case XK_f: case XK_f:
full_screen(); full_screen();
break; break;
case XK_r:
turn_image_right();
break;
case XK_l:
turn_image_left();
break;
} }
} }