mirror of
https://github.com/gryf/wmaker.git
synced 2025-12-28 09:22:27 +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:
committed by
Carlos R. Mafra
parent
9b65f55f53
commit
97d281e310
@@ -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
34
m4/wm_libexif.m4
Normal 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
|
||||||
|
])
|
||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
193
util/wmiv.c
193
util/wmiv.c
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user