From 971efb124e930f2c5fe2f51a62c588e74137794b Mon Sep 17 00:00:00 2001 From: jylam Date: Tue, 26 Aug 2008 13:09:36 +0000 Subject: [PATCH] * Added simple Bresenham line drawing routines (RGBA_32, RGBA_F, Y_F) git-svn-id: file:///srv/caca.zoy.org/var/lib/svn/libpipi/trunk@2776 92316355-f0b4-4df1-b90c-862c8a59935f --- examples/Makefile.am | 4 +- examples/line.c | 47 ++++++++ pipi/Makefile.am | 1 + pipi/paint/line.c | 224 +++++++++++++++++++++++++++++++++++++ pipi/paint/line_template.c | 57 ++++++++++ pipi/pipi.h | 4 +- 6 files changed, 335 insertions(+), 2 deletions(-) create mode 100644 examples/line.c create mode 100644 pipi/paint/line.c create mode 100644 pipi/paint/line_template.c diff --git a/examples/Makefile.am b/examples/Makefile.am index 4f1f127..88fd0d0 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 +bin_PROGRAMS = edd img2rubik sharpen floodfill line edd_SOURCES = edd.c edd_LDADD = ../pipi/libpipi.la @@ -16,3 +16,5 @@ sharpen_LDADD = ../pipi/libpipi.la floodfill_SOURCES = floodfill.c floodfill_LDADD = ../pipi/libpipi.la +line_SOURCES = line.c +line_LDADD = ../pipi/libpipi.la diff --git a/examples/line.c b/examples/line.c new file mode 100644 index 0000000..1de2282 --- /dev/null +++ b/examples/line.c @@ -0,0 +1,47 @@ +#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; + int count = 1000; + 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); + + while(count--) { + pipi_draw_line(newimg, + rand() % 500, rand() % 500, + rand() % 500, rand() % 500, + rand()); + } + pipi_save(newimg, dstname); + + pipi_free(newimg); + + return ret; +} + diff --git a/pipi/Makefile.am b/pipi/Makefile.am index 1810970..c65d278 100644 --- a/pipi/Makefile.am +++ b/pipi/Makefile.am @@ -43,6 +43,7 @@ codec_sources = # Submodules paint_sources = \ paint/floodfill.c \ + paint/line.c \ paint/tile.c render_sources = \ diff --git a/pipi/paint/line.c b/pipi/paint/line.c new file mode 100644 index 0000000..d4e7a28 --- /dev/null +++ b/pipi/paint/line.c @@ -0,0 +1,224 @@ +/* + * 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" + +struct line +{ + int x1, y1; + int x2, y2; + void (*draw) (pipi_image_t*, struct line*); + union { + uint32_t color32; + float colorf[3]; + }; + + union { + uint32_t *buf_u32; + float *buf_f; + }; + +}; +static void clip_line(pipi_image_t*, struct line*); +static uint8_t clip_bits(pipi_image_t*, int, int); +static void draw_aliased_line_u32(pipi_image_t*, struct line*); +static void draw_aliased_line_gray(pipi_image_t *img, struct line* s); +static void draw_aliased_line_float(pipi_image_t *img, struct line* s); + + + +int pipi_draw_line(pipi_image_t *img , int x1, int y1, int x2, int y2, uint32_t c) +{ + struct line s; + s.x1 = x1; + s.y1 = y1; + s.x2 = x2; + s.y2 = y2; + + if(img->last_modified == PIPI_PIXELS_RGBA_C) { + uint32_t *dstdata; + dstdata = (uint32_t *)pipi_getpixels(img, PIPI_PIXELS_RGBA_C)->pixels; + s.color32 = c; + s.buf_u32 = dstdata; + s.draw = draw_aliased_line_u32; + } else if(img->last_modified == PIPI_PIXELS_Y_F) { + float *dstdata; + dstdata = (float *)pipi_getpixels(img, PIPI_PIXELS_Y_F)->pixels; + s.colorf[0] = c/255.0f; /* XXX FIXME */ + s.buf_f = dstdata; + s.draw = draw_aliased_line_gray; + + + } else { + float *dstdata; + dstdata = (float *)pipi_getpixels(img, PIPI_PIXELS_RGBA_F)->pixels; + s.colorf[0] = (c&0x00FF0000)/255.0f; /* XXX FIXME */ + s.colorf[1] = (c&0x0000FF00)/255.0f; /* XXX FIXME */ + s.colorf[2] = (c&0x000000FF)/255.0f; /* XXX FIXME */ + s.buf_f = dstdata; + s.draw = draw_aliased_line_float; + } + + clip_line(img, &s); + return 0; +} + + +int pipi_draw_polyline(pipi_image_t *img, int const x[], int const y[], + int n, uint32_t c) +{ + int i; + struct line s; + + if(img->last_modified == PIPI_PIXELS_RGBA_C) { + uint32_t *dstdata; + dstdata = (uint32_t *)pipi_getpixels(img, PIPI_PIXELS_RGBA_C)->pixels; + s.color32 = c; + s.buf_u32 = dstdata; + s.draw = draw_aliased_line_u32; + } else { + float *dstdata; + dstdata = (float *)pipi_getpixels(img, PIPI_PIXELS_RGBA_F)->pixels; + s.colorf[0] = (c&0x00FF0000)/255.0f; /* XXX FIXME */ + s.colorf[1] = (c&0x0000FF00)/255.0f; /* XXX FIXME */ + s.colorf[2] = (c&0x000000FF)/255.0f; /* XXX FIXME */ + s.buf_f = dstdata; + s.draw = draw_aliased_line_float; + img->last_modified = PIPI_PIXELS_RGBA_F; + } + + for(i = 0; i < n; i++) + { + s.x1 = x[i]; + s.y1 = y[i]; + s.x2 = x[i+1]; + s.y2 = y[i+1]; + clip_line(img, &s); + } + return 0; +} + + + + + +/* + * XXX: The following functions are local. + */ +/* Generic Cohen-Sutherland line clipping function. */ +static void clip_line(pipi_image_t *img, struct line* s) +{ + uint8_t bits1, bits2; + + bits1 = clip_bits(img, s->x1, s->y1); + bits2 = clip_bits(img, s->x2, s->y2); + + if(bits1 & bits2) + return; + + if(bits1 == 0) + { + if(bits2 == 0) + s->draw(img, s); + else + { + int tmp; + tmp = s->x1; s->x1 = s->x2; s->x2 = tmp; + tmp = s->y1; s->y1 = s->y2; s->y2 = tmp; + clip_line(img, s); + } + return; + } + + if(bits1 & (1<<0)) + { + s->y1 = s->y2 - (s->x2 - 0) * (s->y2 - s->y1) / (s->x2 - s->x1); + s->x1 = 0; + } + else if(bits1 & (1<<1)) + { + int xmax = img->w - 1; + s->y1 = s->y2 - (s->x2 - xmax) * (s->y2 - s->y1) / (s->x2 - s->x1); + s->x1 = xmax; + } + else if(bits1 & (1<<2)) + { + s->x1 = s->x2 - (s->y2 - 0) * (s->x2 - s->x1) / (s->y2 - s->y1); + s->y1 = 0; + } + else if(bits1 & (1<<3)) + { + int ymax = img->h - 1; + s->x1 = s->x2 - (s->y2 - ymax) * (s->x2 - s->x1) / (s->y2 - s->y1); + s->y1 = ymax; + } + + clip_line(img, s); +} + +/* Helper function for clip_line(). */ +static uint8_t clip_bits(pipi_image_t *img, int x, int y) +{ + uint8_t b = 0; + + if(x < 0) + b |= (1<<0); + else if(x >= (int)img->w) + b |= (1<<1); + + if(y < 0) + b |= (1<<2); + else if(y >= (int)img->h) + b |= (1<<3); + + return b; +} + + + +/* Solid line drawing function, using Bresenham's mid-point line + * scan-conversion algorithm. */ +static void draw_aliased_line_u32(pipi_image_t *img, struct line* s) +{ + #undef ASSIGN + #define ASSIGN(x, y, w) s->buf_u32[x+y*w] = s->color32; + #include "line_template.c" +} +static void draw_aliased_line_float(pipi_image_t *img, struct line* s) +{ + #undef ASSIGN + #define ASSIGN(x, y, w) s->buf_f[(x*4)+y*(w*4)] = s->colorf[0]; \ + s->buf_f[1 + (x*4)+y*(w*4)] = s->colorf[1]; \ + s->buf_f[2 + (x*4)+y*(w*4)] = s->colorf[2]; + #include "line_template.c" +} +static void draw_aliased_line_gray(pipi_image_t *img, struct line* s) +{ + #undef ASSIGN + #define ASSIGN(x, y, w) s->buf_f[x+y*w] = s->colorf[0]; + #include "line_template.c" +} diff --git a/pipi/paint/line_template.c b/pipi/paint/line_template.c new file mode 100644 index 0000000..1eb1669 --- /dev/null +++ b/pipi/paint/line_template.c @@ -0,0 +1,57 @@ + int x1, y1, x2, y2; + int dx, dy; + int xinc, yinc; + + x1 = s->x1; y1 = s->y1; x2 = s->x2; y2 = s->y2; + + dx = abs(x2 - x1); + dy = abs(y2 - y1); + + xinc = (x1 > x2) ? -1 : 1; + yinc = (y1 > y2) ? -1 : 1; + + if(dx >= dy) + { + int dpr = dy << 1; + int dpru = dpr - (dx << 1); + int delta = dpr - dx; + + for(; dx>=0; dx--) + { + ASSIGN(x1, y1, img->w); + + if(delta > 0) + { + x1 += xinc; + y1 += yinc; + delta += dpru; + } + else + { + x1 += xinc; + delta += dpr; + } + } + } + else + { + int dpr = dx << 1; + int dpru = dpr - (dy << 1); + int delta = dpr - dy; + + for(; dy >= 0; dy--) + { + ASSIGN(x1, y1, img->w); + if(delta > 0) + { + x1 += xinc; + y1 += yinc; + delta += dpru; + } + else + { + y1 += yinc; + delta += dpr; + } + } + } diff --git a/pipi/pipi.h b/pipi/pipi.h index a2a32ea..74d89ab 100644 --- a/pipi/pipi.h +++ b/pipi/pipi.h @@ -150,7 +150,9 @@ extern pipi_image_t *pipi_erode(pipi_image_t *); extern pipi_image_t *pipi_tile(pipi_image_t *, int, int); extern int pipi_flood_fill(pipi_image_t *, int, int, float, float, float, float); - +extern int pipi_draw_line(pipi_image_t *, int, int, int, int, uint32_t); +extern int pipi_draw_polyline(pipi_image_t *, int const[], int const[], + int , uint32_t); extern pipi_image_t *pipi_reduce(pipi_image_t *, int, double const *); extern pipi_image_t *pipi_dither_ediff(pipi_image_t *, pipi_image_t *,