From 53aa513e3e4ad1d179f703873d629bd22b95027f Mon Sep 17 00:00:00 2001 From: sam Date: Sun, 24 Feb 2008 18:49:39 +0000 Subject: [PATCH] * Import image loading features from PWNtcha. As they are more than 4-year old, they will certainly require some cleanup, eg. pkg-config transitions. git-svn-id: file:///srv/caca.zoy.org/var/lib/svn/libpipi/trunk@2228 92316355-f0b4-4df1-b90c-862c8a59935f --- .gitignore | 2 + Makefile.am | 2 +- common.h | 80 ++++++++++++++++++ configure.ac | 62 +++++++++++--- pipi/Makefile.am | 24 +++++- pipi/io.c | 188 ++++++++++++++++++++++++++++++++++++++++++ pipi/pipi.h | 45 ++++++++++ pipi/pipi_internals.h | 30 +++++++ pipi/pixels.c | 71 ++++++++++++++++ 9 files changed, 490 insertions(+), 14 deletions(-) create mode 100644 common.h create mode 100644 pipi/io.c create mode 100644 pipi/pipi_internals.h create mode 100644 pipi/pixels.c diff --git a/.gitignore b/.gitignore index ea3469c..323b7e0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ aclocal.m4 +autom4te.cache configure config.h.in config.h @@ -8,6 +9,7 @@ Makefile.in Makefile libtool pipi/pipi.pc +genethumb/genethumb stamp-h1 .auto .deps diff --git a/Makefile.am b/Makefile.am index b924749..5007324 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,6 +2,6 @@ SUBDIRS = pipi genethumb -EXTRA_DIST = bootstrap +EXTRA_DIST = bootstrap common.h AUTOMAKE_OPTIONS = dist-bzip2 diff --git a/common.h b/common.h new file mode 100644 index 0000000..4769102 --- /dev/null +++ b/common.h @@ -0,0 +1,80 @@ +/* + * libpipi Proper image processing implementation library + * Copyright (c) 2004-2008 Sam Hocevar + * All Rights Reserved + * + * $Id$ + * + * This library is free software. It comes without any warranty, to + * the extent permitted by applicable law. You can redistribute it + * and/or modify it under the terms of the Do What The Fuck You Want + * To Public License, Version 2, as published by Sam Hocevar. See + * http://sam.zoy.org/wtfpl/COPYING for more details. + */ + +/* + * This file contains replacements for commonly found object types and + * function prototypes that are sometimes missing. + */ + +/* C99 types */ +#if defined HAVE_INTTYPES_H && !defined __KERNEL__ +# include +#else +typedef signed char int8_t; +typedef signed short int16_t; +typedef signed long int int32_t; + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned long int uint32_t; + +typedef long int intptr_t; +typedef unsigned long int uintptr_t; +#endif + +/* hton16() and hton32() */ +#if defined HAVE_HTONS +# if defined __KERNEL__ + /* Nothing to do */ +# elif defined HAVE_ARPA_INET_H +# include +# elif defined HAVE_NETINET_IN_H +# include +# endif +# define hton16 htons +# define hton32 htonl +#else +# if defined HAVE_ENDIAN_H +# include +# endif +static inline uint16_t hton16(uint16_t x) +{ + /* This is compile-time optimised with at least -O1 or -Os */ +#if defined HAVE_ENDIAN_H + if(__BYTE_ORDER == __BIG_ENDIAN) +#else + uint32_t const dummy = 0x12345678; + if(*(uint8_t const *)&dummy == 0x12) +#endif + return x; + else + return (x >> 8) | (x << 8); +} + +static inline uint32_t hton32(uint32_t x) +{ + /* This is compile-time optimised with at least -O1 or -Os */ +#if defined HAVE_ENDIAN_H + if(__BYTE_ORDER == __BIG_ENDIAN) +#else + uint32_t const dummy = 0x12345678; + if(*(uint8_t const *)&dummy == 0x12) +#endif + return x; + else + return (x >> 24) | ((x >> 8) & 0x0000ff00) + | ((x << 8) & 0x00ff0000) | (x << 24); +} +#endif + diff --git a/configure.ac b/configure.ac index a834b7e..892087c 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_INIT(libpipi, 0.0) AC_CONFIG_AUX_DIR(.auto) AM_INIT_AUTOMAKE([no-define tar-ustar]) -AM_MAINTAINER_MODE +dnl AM_MAINTAINER_MODE AM_CONFIG_HEADER(config.h) @@ -25,9 +25,6 @@ AC_LIBTOOL_CXX AC_C_CONST AC_C_INLINE -AC_ARG_ENABLE(imlib2, - [ --enable-imlib2 Imlib2 graphics support (autodetected)]) - AC_CHECK_HEADERS(stdio.h stdarg.h inttypes.h endian.h stdint.h) # Optimizations @@ -35,13 +32,58 @@ CFLAGS="${CFLAGS} -g -O2 -fno-strength-reduce -fomit-frame-pointer" # Code qui fait des warnings == code de porc == deux baffes dans ta gueule CFLAGS="${CFLAGS} -Wall -Wpointer-arith -Wcast-align -Wcast-qual -Wstrict-prototypes -Wshadow -Waggregate-return -Wmissing-prototypes -Wnested-externs -Wsign-compare" +# Use DevIL? +#AC_CHECK_HEADERS(IL/il.h, +# [ac_cv_my_have_il="yes"], +# [ac_cv_my_have_il="no"]) +#CPPFLAGS="${save_CPPFLAGS}" +#AM_CONDITIONAL(USE_IL, test "${ac_cv_my_have_il}" = "yes") + +# Use Windows? +#AC_CHECK_HEADERS(olectl.h, +# [ac_cv_my_have_ole="yes"], +# [ac_cv_my_have_ole="no"]) +#CPPFLAGS="${save_CPPFLAGS}" +#AM_CONDITIONAL(USE_OLE, test "${ac_cv_my_have_ole}" = "yes") + +# Use SDL? +ac_cv_my_have_sdl="no" +save_CPPFLAGS="${CPPFLAGS}" +AC_PATH_PROG(SDL_CONFIG, sdl-config, no) +if test "${SDL_CONFIG}" != "no"; then + CPPFLAGS="${CPPFLAGS} `sdl-config --cflags`" +fi +AC_CHECK_HEADERS(SDL_image.h, + [ac_cv_my_have_sdl="yes"], + [ac_cv_my_have_sdl="no"]) +CPPFLAGS="${save_CPPFLAGS}" +AM_CONDITIONAL(USE_SDL, test "${ac_cv_my_have_sdl}" = "yes") + +# Use OpenCV? +ac_cv_my_have_opencv="no" +save_CPPFLAGS="${CPPFLAGS}" +AC_PATH_PROG(OPENCV_CONFIG, opencv-config, no) +if test "${OPENCV_CONFIG}" != "no"; then + CPPFLAGS="${CPPFLAGS} `opencv-config --cflags`" +fi +AC_CHECK_HEADERS(cv.h, + [ac_cv_my_have_opencv="yes"], + [ac_cv_my_have_opencv="no"]) +CPPFLAGS="${save_CPPFLAGS}" +AM_CONDITIONAL(USE_OPENCV, test "${ac_cv_my_have_opencv}" = "yes") + # Use Imlib2? -if test "${enable_imlib2}" != "no"; then - IMLIB2="no" - PKG_CHECK_MODULES(IMLIB2, imlib2, [IMLIB2="yes"], [AC_MSG_RESULT(no)]) - if test "${IMLIB2}" != "no"; then - AC_DEFINE(USE_IMLIB2, 1, Define to 1 to use Imlib2) - fi +ac_cv_my_have_imlib2="no" +IMLIB2="no" +PKG_CHECK_MODULES(IMLIB2, imlib2, [ac_cv_my_have_imlib2="yes"]) +AC_MSG_RESULT($ac_cv_my_have_imlib2) +if test "${ac_cv_my_have_imlib2}" != "no"; then + AC_DEFINE(USE_IMLIB2, 1, Define to 1 to use Imlib2) +fi +AM_CONDITIONAL(USE_IMLIB2, test "${ac_cv_my_have_imlib2}" = "yes") + +if test "${ac_cv_my_have_il}" = "no" -a "${ac_cv_my_have_ole}" = "no" -a "${ac_cv_my_have_sdl}" = "no" -a "${ac_cv_my_have_imlib2}" = "no" -a "${ac_cv_my_have_opencv}" = "no"; then + AC_MSG_ERROR([[cannot find DevIL, OLE, SDL_Image, Imlib2 or OpenCV, please install one of them]]) fi AC_CONFIG_FILES([ diff --git a/pipi/Makefile.am b/pipi/Makefile.am index b08b55c..b30cdf0 100644 --- a/pipi/Makefile.am +++ b/pipi/Makefile.am @@ -14,8 +14,26 @@ lib_LTLIBRARIES = libpipi.la libpipi_la_SOURCES = \ pipi.c \ pipi.h \ + pipi_internals.h \ + io.c \ + pixels.c \ $(NULL) -libpipi_la_CFLAGS = $(IMLIB2_CFLAGS) -libpipi_la_LDFLAGS = -no-undefined -version-number @LT_VERSION@ -libpipi_la_LIBADD = $(IMLIB2_LIBS) +libpipi_la_CFLAGS = $(CFLAGS_EXTRA) +libpipi_la_LDFLAGS = $(LDFLAGS_EXTRA) \ + -no-undefined -version-number @LT_VERSION@ + +if USE_SDL +CFLAGS_EXTRA = `sdl-config --cflags` +LDFLAGS_EXTRA = `sdl-config --libs` -lSDL_image +else +if USE_IMLIB2 +CFLAGS_EXTRA = @IMLIB2_CFLAGS@ +LDFLAGS_EXTRA = @IMLIB2_LIBS@ +else +if USE_OPENCV +CFLAGS_EXTRA = `opencv-config --cflags` +LDFLAGS_EXTRA = `opencv-config --libs opencv highgui` +endif +endif +endif diff --git a/pipi/io.c b/pipi/io.c new file mode 100644 index 0000000..08e5437 --- /dev/null +++ b/pipi/io.c @@ -0,0 +1,188 @@ +/* + * libpipi Proper image processing implementation library + * Copyright (c) 2004-2008 Sam Hocevar + * All Rights Reserved + * + * $Id$ + * + * This library is free software. It comes without any warranty, to + * the extent permitted by applicable law. You can redistribute it + * and/or modify it under the terms of the Do What The Fuck You Want + * To Public License, Version 2, as published by Sam Hocevar. See + * http://sam.zoy.org/wtfpl/COPYING for more details. + */ + +/* + * image.c: image I/O functions + */ + +#include +#include +#include + +#include "config.h" +#include "common.h" + +#if defined(HAVE_SDL_IMAGE_H) +# include +#elif defined(HAVE_IMLIB2_H) +# include +#elif defined(HAVE_CV_H) +# include +# include +#else +# error "No imaging library" +#endif + +#include "pipi_internals.h" +#include "pipi.h" + +pipi_image_t *pipi_load(const char *name) +{ + pipi_image_t *img; +#if defined(HAVE_SDL_IMAGE_H) + SDL_Surface *priv = IMG_Load(name); +#elif defined(HAVE_IMLIB2_H) + Imlib_Image priv = imlib_load_image(name); +#elif defined(HAVE_CV_H) + IplImage *priv = cvLoadImage(name, -1); +#endif + + if(!priv) + return NULL; + +#if defined(HAVE_SDL_IMAGE_H) + if(priv->format->BytesPerPixel == 1) + { + img = pipi_new(priv->w, priv->h); + SDL_BlitSurface(priv, NULL, img->priv, NULL); + SDL_FreeSurface(priv); + return img; + } +#endif + + img = (pipi_image_t *)malloc(sizeof(pipi_image_t)); +#if defined(HAVE_SDL_IMAGE_H) + img->width = priv->w; + img->height = priv->h; + img->pitch = priv->pitch; + img->channels = priv->format->BytesPerPixel; + img->pixels = priv->pixels; +#elif defined(HAVE_IMLIB2_H) + imlib_context_set_image(priv); + img->width = imlib_image_get_width(); + img->height = imlib_image_get_height(); + img->pitch = 4 * imlib_image_get_width(); + img->channels = 4; + img->pixels = (char *)imlib_image_get_data(); +#elif defined(HAVE_CV_H) + img->width = priv->width; + img->height = priv->height; + img->pitch = priv->widthStep; + img->channels = priv->nChannels; + img->pixels = priv->imageData; +#endif + img->priv = (void *)priv; + + return img; +} + +pipi_image_t *pipi_new(int width, int height) +{ + pipi_image_t *img; +#if defined(HAVE_SDL_IMAGE_H) + SDL_Surface *priv; + Uint32 rmask, gmask, bmask, amask; +# if SDL_BYTEORDER == SDL_BIG_ENDIAN + rmask = 0xff000000; + gmask = 0x00ff0000; + bmask = 0x0000ff00; + amask = 0x00000000; +# else + rmask = 0x000000ff; + gmask = 0x0000ff00; + bmask = 0x00ff0000; + amask = 0x00000000; +# endif + priv = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32, + rmask, gmask, bmask, amask); +#elif defined(HAVE_IMLIB2_H) + Imlib_Image priv = imlib_create_image(width, height); +#elif defined(HAVE_CV_H) + IplImage *priv = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 3); +#endif + + if(!priv) + return NULL; + + img = (pipi_image_t *)malloc(sizeof(pipi_image_t)); +#if defined(HAVE_SDL_IMAGE_H) + img->width = priv->w; + img->height = priv->h; + img->pitch = priv->pitch; + img->channels = priv->format->BytesPerPixel; + img->pixels = priv->pixels; +#elif defined(HAVE_IMLIB2_H) + imlib_context_set_image(priv); + img->width = imlib_image_get_width(); + img->height = imlib_image_get_height(); + img->pitch = 4 * imlib_image_get_width(); + img->channels = 4; + img->pixels = (char *)imlib_image_get_data(); +#elif defined(HAVE_CV_H) + img->width = priv->width; + img->height = priv->height; + img->pitch = priv->widthStep; + img->channels = priv->nChannels; + img->pixels = priv->imageData; +#endif + img->priv = (void *)priv; + + return img; +} + +pipi_image_t *pipi_copy(pipi_image_t const *img) +{ + pipi_image_t *dst; + int x, y; + dst = pipi_new(img->width, img->height); + for(y = 0; y < img->height; y++) + { + for(x = 0; x < img->width; x++) + { + int r, g, b; + pipi_getpixel(img, x, y, &r, &g, &b); + pipi_setpixel(dst, x, y, r, g, b); + } + } + return dst; +} + +void pipi_free(pipi_image_t *img) +{ +#if defined(HAVE_SDL_IMAGE_H) + SDL_FreeSurface(img->priv); +#elif defined(HAVE_IMLIB2_H) + imlib_context_set_image(img->priv); + imlib_free_image(); +#elif defined(HAVE_CV_H) + IplImage *iplimg; + iplimg = (IplImage *)img->priv; + cvReleaseImage(&iplimg); +#endif + + free(img); +} + +void pipi_save(pipi_image_t *img, const char *name) +{ +#if defined(HAVE_SDL_IMAGE_H) + SDL_SaveBMP(img->priv, name); +#elif defined(HAVE_IMLIB2_H) + imlib_context_set_image(img->priv); + imlib_save_image(name); +#elif defined(HAVE_CV_H) + cvSaveImage(name, img->priv); +#endif +} + diff --git a/pipi/pipi.h b/pipi/pipi.h index e69de29..97e840b 100644 --- a/pipi/pipi.h +++ b/pipi/pipi.h @@ -0,0 +1,45 @@ +/* + * libpipi Proper image processing implementation library + * Copyright (c) 2004-2008 Sam Hocevar + * All Rights Reserved + * + * $Id$ + * + * This library is free software. It comes without any warranty, to + * the extent permitted by applicable law. You can redistribute it + * and/or modify it under the terms of the Do What The Fuck You Want + * To Public License, Version 2, as published by Sam Hocevar. See + * http://sam.zoy.org/wtfpl/COPYING for more details. + */ + +/* + * pipi.h: the full libpipi public API + */ + +#ifndef __PIPI_H__ +#define __PIPI_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef struct pipi_image pipi_image_t; + +extern pipi_image_t *pipi_load(const char *name); +extern pipi_image_t *pipi_new(int width, int height); +extern pipi_image_t *pipi_copy(const pipi_image_t *img); +extern void pipi_free(pipi_image_t *img); +extern void pipi_save(pipi_image_t *img, const char *name); + +extern int pipi_getgray(pipi_image_t const *img, int x, int y, int *g); +extern int pipi_getpixel(pipi_image_t const *img, + int x, int y, int *r, int *g, int *b); +extern int pipi_setpixel(pipi_image_t *img, int x, int y, int r, int g, int b); + +#ifdef __cplusplus +} +#endif + +#endif /* __PIPI_H__ */ + diff --git a/pipi/pipi_internals.h b/pipi/pipi_internals.h new file mode 100644 index 0000000..17f7efd --- /dev/null +++ b/pipi/pipi_internals.h @@ -0,0 +1,30 @@ +/* + * libpipi Proper image processing implementation library + * Copyright (c) 2004-2008 Sam Hocevar + * All Rights Reserved + * + * $Id$ + * + * This library is free software. It comes without any warranty, to + * the extent permitted by applicable law. You can redistribute it + * and/or modify it under the terms of the Do What The Fuck You Want + * To Public License, Version 2, as published by Sam Hocevar. See + * http://sam.zoy.org/wtfpl/COPYING for more details. + */ + +/* + * pipi_internals.h: internal types + */ + +#ifndef __CACA_INTERNALS_H__ +#define __CACA_INTERNALS_H__ + +struct pipi_image +{ + int width, height, pitch, channels; + unsigned char *pixels; + void *priv; +}; + +#endif /* __PIPI_INTERNALS_H__ */ + diff --git a/pipi/pixels.c b/pipi/pixels.c new file mode 100644 index 0000000..c487c9c --- /dev/null +++ b/pipi/pixels.c @@ -0,0 +1,71 @@ +/* + * libpipi Proper image processing implementation library + * Copyright (c) 2004-2008 Sam Hocevar + * All Rights Reserved + * + * $Id$ + * + * This library is free software. It comes without any warranty, to + * the extent permitted by applicable law. You can redistribute it + * and/or modify it under the terms of the Do What The Fuck You Want + * To Public License, Version 2, as published by Sam Hocevar. See + * http://sam.zoy.org/wtfpl/COPYING for more details. + */ + +/* + * pixels.c: pixel-level image manipulation + */ + +#include +#include +#include + +#include "config.h" +#include "common.h" + +#include "pipi_internals.h" +#include "pipi.h" + +int pipi_getgray(pipi_image_t const *img, int x, int y, int *g) +{ + if(x < 0 || y < 0 || x >= img->width || y >= img->height) + { + *g = 255; + return -1; + } + + *g = (unsigned char)img->pixels[y * img->pitch + x * img->channels + 1]; + + return 0; +} + +int pipi_getpixel(pipi_image_t const *img, + int x, int y, int *r, int *g, int *b) +{ + if(x < 0 || y < 0 || x >= img->width || y >= img->height) + { + *r = 255; + *g = 255; + *b = 255; + return -1; + } + + *b = (unsigned char)img->pixels[y * img->pitch + x * img->channels]; + *g = (unsigned char)img->pixels[y * img->pitch + x * img->channels + 1]; + *r = (unsigned char)img->pixels[y * img->pitch + x * img->channels + 2]; + + return 0; +} + +int pipi_setpixel(pipi_image_t *img, int x, int y, int r, int g, int b) +{ + if(x < 0 || y < 0 || x >= img->width || y >= img->height) + return -1; + + img->pixels[y * img->pitch + x * img->channels] = b; + img->pixels[y * img->pitch + x * img->channels + 1] = g; + img->pixels[y * img->pitch + x * img->channels + 2] = r; + + return 0; +} +