diff --git a/examples/Makefile.am b/examples/Makefile.am index 80f7d1d..6da32a0 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -2,7 +2,7 @@ AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/pipi -bin_PROGRAMS = edd img2rubik sharpen floodfill line bezier +bin_PROGRAMS = edd img2rubik sharpen floodfill line bezier histogram edd_SOURCES = edd.c edd_LDADD = ../pipi/libpipi.la @@ -21,3 +21,6 @@ line_LDADD = ../pipi/libpipi.la bezier_SOURCES = bezier.c bezier_LDADD = ../pipi/libpipi.la + +histogram_SOURCES = histogram.c +histogram_LDADD = ../pipi/libpipi.la diff --git a/examples/histogram.c b/examples/histogram.c new file mode 100644 index 0000000..9f6726d --- /dev/null +++ b/examples/histogram.c @@ -0,0 +1,49 @@ +#include "config.h" +#include "common.h" + +#include +#include +#include + +#include + +int main(int argc, char *argv[]) +{ + char *srcname = NULL, *dstname = NULL; + pipi_image_t *img, *newimg, *tmp; + pipi_histogram_t* histogram; + int ret = 0; + if(argc < 2) + { + fprintf(stderr, "%s: too few arguments\n", argv[0]); + fprintf(stderr, "Usage: %s \n", argv[0]); + return EXIT_FAILURE; + } + + srcname = argv[1]; + dstname = argv[2]; + + img = pipi_load(srcname); + + if(!img) { + fprintf(stderr, "Can't open %s for reading\n", srcname); + } + + newimg = pipi_copy(img); + pipi_free(img); + + + tmp = pipi_copy(newimg); + + histogram = pipi_new_histogram(); + pipi_get_image_histogram(tmp, histogram, PIPI_COLOR_R|PIPI_COLOR_G|PIPI_COLOR_B); + + + pipi_render_histogram(tmp, histogram, PIPI_COLOR_R|PIPI_COLOR_G|PIPI_COLOR_B); + + pipi_save(tmp, dstname); + pipi_free(newimg); + + return ret; +} + diff --git a/pipi/Makefile.am b/pipi/Makefile.am index 325589e..bf1c08f 100644 --- a/pipi/Makefile.am +++ b/pipi/Makefile.am @@ -31,6 +31,7 @@ libpipi_la_SOURCES = \ $(filter_sources) \ $(quantize_sources) \ $(dither_sources) \ + $(histogram_sources) \ $(NULL) libpipi_la_CFLAGS = $(codec_cflags) libpipi_la_LDFLAGS = $(codec_libs) \ @@ -79,6 +80,9 @@ dither_sources = \ dither/dbs.c \ dither/random.c +histogram_sources = \ + histogram/histogram.c + if USE_SDL codec_cflags += `sdl-config --cflags` codec_libs += `sdl-config --libs` -lSDL_image diff --git a/pipi/histogram/histogram.c b/pipi/histogram/histogram.c new file mode 100644 index 0000000..51ddb57 --- /dev/null +++ b/pipi/histogram/histogram.c @@ -0,0 +1,171 @@ +/* + * libpipi Proper image processing implementation library + * Copyright (c) 2004-2008 Sam Hocevar + * 2008 Jean-Yves Lamoureux +#include +#include + +#include "pipi.h" +#include "pipi_internals.h" + + +pipi_histogram_t* pipi_new_histogram(void) +{ + return malloc(sizeof(pipi_histogram_t)); +} + + +int pipi_get_image_histogram(pipi_image_t *img, pipi_histogram_t*h, int flags) +{ + int i; + + if(!h) return -1; + + uint8_t *data = (uint8_t *)pipi_getpixels(img, PIPI_PIXELS_RGBA_C)->pixels; + + for(i=0; i< img->w*img->h*4; i+=4) + { + if(flags&PIPI_COLOR_A) + h->a[data[i+3]]++; + if(flags&PIPI_COLOR_R) + h->r[data[i+2]]++; + if(flags&PIPI_COLOR_G) + h->g[data[i+1]]++; + if(flags&PIPI_COLOR_B) + h->b[data[i]]++; + if(flags&PIPI_COLOR_Y) + { + uint32_t p = 0.; + p += 0.299 * data[i]; + p += 0.587 * data[i+1]; + p += 0.114 * data[i+2]; + + h->y[p>255?255:p]++; + } + } + + /* Normalize dataset */ + unsigned int max; + float n; + + if(flags&PIPI_COLOR_R) + { + max = 0; + for(i=0; i<256; i++) + if(h->r[i] > max) max = h->r[i]; + n = 255.0f / max; + for(i=0; i<256; i++) + h->r[i]*=n; + } + if(flags&PIPI_COLOR_G) + { + max = 0; + for(i=0; i<256; i++) + if(h->g[i] > max) max = h->g[i]; + n = 255.0f / max; + for(i=0; i<256; i++) + h->g[i]*=n; + } + if(flags&PIPI_COLOR_B) + { + max = 0; + for(i=0; i<256; i++) + if(h->b[i] > max) max = h->b[i]; + n = 255.0f / max; + for(i=0; i<256; i++) + h->b[i]*=n; + } + if(flags&PIPI_COLOR_A) + { + max = 0; + for(i=0; i<256; i++) + if(h->a[i] > max) max = h->a[i]; + n = 255.0f / max; + for(i=0; i<256; i++) + h->a[i]*=n; + } + if(flags&PIPI_COLOR_Y) + { + max = 0; + for(i=0; i<256; i++) + if(h->y[i] > max) max = h->y[i]; + n = 255.0f / max; + for(i=0; i<256; i++) + h->y[i]*=n; + } + + + return 0; +} + +int pipi_render_histogram(pipi_image_t *img, pipi_histogram_t*h, int flags) +{ + if(!img || !h) return -1; + + int x; + + + for(x=0; x<256; x++) + { + if(flags&PIPI_COLOR_R) + pipi_draw_line(img, + x, 255, + x, 255 - h->r[x], + 0x00FF0000, + 0); + if(flags&PIPI_COLOR_G) + pipi_draw_line(img, + x, 255, + x, 255 - h->g[x], + 0x0000FF00, + 0); + if(flags&PIPI_COLOR_B) + pipi_draw_line(img, + x, 255, + x, 255 - h->b[x], + 0x000000FF, + 0); + if(flags&PIPI_COLOR_A) + pipi_draw_line(img, + x, 255, + x, 255 - h->a[x], + 0x00000FFF, + 0); + if(flags&PIPI_COLOR_Y) + pipi_draw_line(img, + x, 255, + x, 255 - h->y[x], + 0x00FFFFFF, + 0); + } + + return 0; +} + + +int pipi_free_histogram(pipi_histogram_t* h) +{ + if(h) free(h); + else return -1; + + return 0; +} diff --git a/pipi/pipi.h b/pipi/pipi.h index d9ada04..c5e04fc 100644 --- a/pipi/pipi.h +++ b/pipi/pipi.h @@ -54,6 +54,17 @@ typedef enum } pipi_format_t; + +typedef enum +{ + PIPI_COLOR_R = 1, + PIPI_COLOR_G = 2, + PIPI_COLOR_B = 4, + PIPI_COLOR_A = 8, + PIPI_COLOR_Y = 16 +} +pipi_color_flag_t; + struct pixel_u32 { uint8_t r, g, b, a; @@ -88,6 +99,8 @@ typedef struct pipi_image pipi_image_t; /* pipi_context_t: the processing stack */ typedef struct pipi_context pipi_context_t; +/* pipi_histogram_t: the histogram type */ +typedef struct pipi_histogram pipi_histogram_t; extern pipi_context_t *pipi_create_context(void); extern void pipi_destroy_context(pipi_context_t *); @@ -170,6 +183,11 @@ extern pipi_image_t *pipi_dither_ostromoukhov(pipi_image_t *, pipi_scan_t); extern pipi_image_t *pipi_dither_dbs(pipi_image_t *); extern void pipi_dither_24to16(pipi_image_t *); +extern pipi_histogram_t* pipi_new_histogram(void); +extern int pipi_get_image_histogram(pipi_image_t *, pipi_histogram_t *, int); +extern int pipi_free_histogram(pipi_histogram_t*); +extern int pipi_render_histogram(pipi_image_t *, pipi_histogram_t*, int); + #ifdef __cplusplus } diff --git a/pipi/pipi_internals.h b/pipi/pipi_internals.h index 775ded8..dd30098 100644 --- a/pipi/pipi_internals.h +++ b/pipi/pipi_internals.h @@ -23,6 +23,17 @@ #define SET_FLAG_WRAP 0x00000002 #define SET_FLAG_8BIT 0x00000004 +struct pipi_histogram +{ + int r_present, g_present, b_present, y_present; + unsigned int a[256]; + unsigned int r[256]; + unsigned int g[256]; + unsigned int b[256]; + unsigned int y[256]; +}; + + /* pipi_image_t: the image structure. This is probably going to be the most * complex structure in the library, but right now it only has fairly normal * stuff, like width and height and pointers to pixel areas. */