mirror of
https://github.com/gryf/wmaker.git
synced 2026-02-02 06:05:45 +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 ===============================================
|
||||
|
||||
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 ===========
|
||||
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 = \
|
||||
$(top_builddir)/wrlib/libwraster.la \
|
||||
@XLFLAGS@ @XLIBS@ \
|
||||
@GFXLIBS@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS)
|
||||
@GFXLIBS@ $(PTHREAD_CFLAGS) $(PTHREAD_LIBS) $(LIBEXIF)
|
||||
|
||||
wmiv_SOURCES = wmiv.c wmiv.h
|
||||
|
||||
|
||||
193
util/wmiv.c
193
util/wmiv.c
@@ -21,6 +21,7 @@
|
||||
#if !defined(_GNU_SOURCE)
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#include <X11/keysym.h>
|
||||
#include <X11/XKBlib.h>
|
||||
#include <X11/Xatom.h>
|
||||
@@ -34,6 +35,11 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include "config.h"
|
||||
|
||||
#ifdef HAVE_EXIF
|
||||
#include <libexif/exif-data.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PTHREAD
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
@@ -57,7 +63,7 @@ Pixmap pix;
|
||||
|
||||
const char *APPNAME = "wmiv";
|
||||
int APPVERSION_MAJOR = 0;
|
||||
int APPVERSION_MINOR = 6;
|
||||
int APPVERSION_MINOR = 7;
|
||||
int NEXT = 0;
|
||||
int PREV = 1;
|
||||
float zoom_factor = 0;
|
||||
@@ -66,6 +72,7 @@ int max_height = 0;
|
||||
|
||||
Bool fullscreen_flag = False;
|
||||
Bool focus = False;
|
||||
Bool back_from_fullscreen = False;
|
||||
|
||||
#ifdef HAVE_PTHREAD
|
||||
Bool diaporama_flag = False;
|
||||
@@ -98,6 +105,90 @@ typedef struct linked_list {
|
||||
linked_list_t list;
|
||||
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
|
||||
return EXIT_SUCCESS on success, 1 on failure
|
||||
@@ -211,6 +302,59 @@ int merge_with_background(RImage *i)
|
||||
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
|
||||
return the image on success, NULL on failure
|
||||
@@ -250,6 +394,7 @@ int full_screen(void)
|
||||
if (fullscreen_flag) {
|
||||
fullscreen_flag = False;
|
||||
zoom_factor = 0;
|
||||
back_from_fullscreen = True;
|
||||
} else {
|
||||
fullscreen_flag = True;
|
||||
zoom_factor = 1000;
|
||||
@@ -279,7 +424,7 @@ int full_screen(void)
|
||||
int zoom_in_out(int z)
|
||||
{
|
||||
RImage *old_img = img;
|
||||
RImage *tmp = RLoadImage(ctx, current_link->data, 0);
|
||||
RImage *tmp = load_oriented_image(ctx, current_link->data, 0);
|
||||
if (!tmp)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
@@ -368,7 +513,7 @@ int change_image(int way)
|
||||
}
|
||||
if (DEBUG)
|
||||
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) {
|
||||
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. */
|
||||
link = calloc(1, sizeof(link_t));
|
||||
if (!link) {
|
||||
fprintf(stderr, "calloc failed.\n");
|
||||
fprintf(stderr, "Error: memory allocation failed\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
link->data = data;
|
||||
@@ -572,7 +717,9 @@ int main(int argc, char **argv)
|
||||
#ifdef HAVE_PTHREAD
|
||||
"d: launch diaporama mode\n"
|
||||
#endif
|
||||
"l: rotate image on the left\n"
|
||||
"q: quit\n"
|
||||
"r: rotate image on the right\n"
|
||||
"right: next image\n"
|
||||
"left: previous 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) {
|
||||
fprintf(stderr, "Error: %s %s\n", reading_filename, RMessageForError(RErrorCode));
|
||||
@@ -703,21 +850,33 @@ int main(int argc, char **argv)
|
||||
XConfigureEvent xce = e.xconfigure;
|
||||
if (xce.width != img->width || xce.height != img->height) {
|
||||
RImage *old_img = img;
|
||||
img = RLoadImage(ctx, current_link->data, 0);
|
||||
img = load_oriented_image(ctx, current_link->data, 0);
|
||||
if (!img) {
|
||||
/* keep the old img and window size */
|
||||
img = old_img;
|
||||
XResizeWindow(dpy, win, img->width, img->height);
|
||||
} else {
|
||||
img = RScaleImage(img, xce.width, xce.height);
|
||||
if (!img) {
|
||||
img = old_img;
|
||||
XResizeWindow(dpy, win, img->width, img->height);
|
||||
} else {
|
||||
merge_with_background(img);
|
||||
if (RConvertImage(ctx, img, &pix))
|
||||
RReleaseImage(old_img);
|
||||
RImage *tmp2;
|
||||
if (!back_from_fullscreen)
|
||||
/* manually resized window */
|
||||
tmp2 = RScaleImage(img, xce.width, xce.height);
|
||||
else {
|
||||
/* back from fullscreen mode, maybe img was rotated */
|
||||
tmp2 = 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);
|
||||
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:
|
||||
full_screen();
|
||||
break;
|
||||
case XK_r:
|
||||
turn_image_right();
|
||||
break;
|
||||
case XK_l:
|
||||
turn_image_left();
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user