source: libpipi/trunk/pipi/paint/line.c @ 2795

Revision 2795, 10.8 KB checked in by sam, 5 years ago (diff)
  • line.c: convert the aliased line drawing to the template system.
RevLine 
[2776]1/*
2 *  libpipi       Proper image processing implementation library
3 *  Copyright (c) 2004-2008 Sam Hocevar <sam@zoy.org>
4 *                2008 Jean-Yves Lamoureux <jylam@lnxscene.org
5 *                All Rights Reserved
6 *
7 *  $Id$
8 *
9 *  This library is free software. It comes without any warranty, to
10 *  the extent permitted by applicable law. You can redistribute it
11 *  and/or modify it under the terms of the Do What The Fuck You Want
12 *  To Public License, Version 2, as published by Sam Hocevar. See
13 *  http://sam.zoy.org/wtfpl/COPYING for more details.
14 */
15
16/*
17 * line.c: line rendering functions
18 */
19
20#include "config.h"
21#include "common.h"
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26
[2788]27#undef __USE_MISC  /* THAT sucks */
28#undef __USE_XOPEN /* THAT sucks, too (avoid declaring y1 in math.h) */
29#include <math.h>
30
[2776]31#include "pipi.h"
32#include "pipi_internals.h"
33
[2795]34#if !defined TEMPLATE_FILE /* This file uses the template system */
35
[2776]36struct line
37{
38    int x1, y1;
39    int x2, y2;
40    void (*draw) (pipi_image_t*, struct line*);
41    union {
42        uint32_t color32;
43        float    colorf[3];
44    };
45
46    union {
47        uint32_t *buf_u32;
48        float    *buf_f;
49    };
50
51};
[2795]52
53#define TEMPLATE_FLAGS SET_FLAG_GRAY | SET_FLAG_8BIT
54#define TEMPLATE_FILE "paint/line.c"
55#include "pipi_template.h"
56
[2776]57static void clip_line(pipi_image_t*, struct line*);
58static uint8_t clip_bits(pipi_image_t*, int, int);
[2777]59static void draw_antialiased_line_float(pipi_image_t *img, struct line* s);
60static void draw_antialiased_line_gray(pipi_image_t *img, struct line* s);
[2776]61
[2777]62int pipi_draw_line(pipi_image_t *img , int x1, int y1, int x2, int y2, uint32_t c, int aa)
[2776]63{
64    struct line s;
65    s.x1 = x1;
66    s.y1 = y1;
67    s.x2 = x2;
68    s.y2 = y2;
69
[2777]70    /* No Transparency routine for u32 yet, fallback to float version */
71    if(img->last_modified == PIPI_PIXELS_RGBA_C)
72    {
73        if(!aa)
74        {
75            uint32_t  *dstdata;
76            dstdata = (uint32_t *)pipi_getpixels(img, PIPI_PIXELS_RGBA_C)->pixels;
77            s.color32 = c;
78            s.buf_u32 = dstdata;
[2795]79            s.draw = aliased_line_8bit;
[2777]80        }
81        else
82        {
83            float  *dstdata;
84            dstdata = (float *)pipi_getpixels(img, PIPI_PIXELS_RGBA_F)->pixels;
85            s.colorf[2] = ((c&0x00FF0000)>>16)/255.0f; /* XXX FIXME */
86            s.colorf[1] = ((c&0x0000FF00)>>8)/255.0f;  /* XXX FIXME */
87            s.colorf[0] = (c&0x000000FF)/255.0f;       /* XXX FIXME */
88            s.buf_f = dstdata;
89            s.draw = draw_antialiased_line_float;
90        }
91    }
92    else if(img->last_modified == PIPI_PIXELS_Y_F)
93    {
[2776]94        float  *dstdata;
95        dstdata = (float *)pipi_getpixels(img, PIPI_PIXELS_Y_F)->pixels;
[2795]96        s.colorf[0] = (c & 0xff) / 255.0f; /* XXX FIXME */
[2776]97        s.buf_f = dstdata;
[2795]98        s.draw = aa==0?aliased_line_gray:draw_antialiased_line_gray;
[2777]99    }
100    else
101    {
[2776]102        float  *dstdata;
103        dstdata = (float *)pipi_getpixels(img, PIPI_PIXELS_RGBA_F)->pixels;
[2777]104        s.colorf[2] = ((c&0x00FF0000)>>16)/255.0f; /* XXX FIXME */
105        s.colorf[1] = ((c&0x0000FF00)>>8)/255.0f;  /* XXX FIXME */
106        s.colorf[0] = (c&0x000000FF)/255.0f;       /* XXX FIXME */
[2776]107        s.buf_f = dstdata;
[2795]108        s.draw = aa==0?aliased_line:draw_antialiased_line_float;
[2776]109    }
110
111    clip_line(img, &s);
112    return 0;
113}
114
115
116int pipi_draw_polyline(pipi_image_t *img, int const x[], int const y[],
[2778]117                       int n, uint32_t c, int aa)
[2776]118{
119    int i;
120    struct line s;
121
[2777]122    if(img->last_modified == PIPI_PIXELS_RGBA_C)
123    {
[2778]124        if(!aa)
125        {
126            uint32_t  *dstdata;
127            dstdata = (uint32_t *)pipi_getpixels(img, PIPI_PIXELS_RGBA_C)->pixels;
128            s.color32 = c;
129            s.buf_u32 = dstdata;
[2795]130            s.draw = aliased_line_8bit;
[2778]131        }
132        else
133        {
134            float  *dstdata;
135            dstdata = (float *)pipi_getpixels(img, PIPI_PIXELS_RGBA_F)->pixels;
136            s.colorf[2] = ((c&0x00FF0000)>>16)/255.0f; /* XXX FIXME */
137            s.colorf[1] = ((c&0x0000FF00)>>8)/255.0f;  /* XXX FIXME */
138            s.colorf[0] = (c&0x000000FF)/255.0f;       /* XXX FIXME */
139            s.buf_f = dstdata;
140            s.draw = draw_antialiased_line_float;
141        }
[2777]142    }
[2778]143    else if(img->last_modified == PIPI_PIXELS_Y_F)
144    {
145        float  *dstdata;
146        dstdata = (float *)pipi_getpixels(img, PIPI_PIXELS_Y_F)->pixels;
147        s.colorf[0] = c/255.0f; /* XXX FIXME */
148        s.buf_f = dstdata;
[2795]149        s.draw = aa==0?aliased_line_gray:draw_antialiased_line_gray;
[2778]150    }
[2777]151    else
152    {
[2776]153        float  *dstdata;
154        dstdata = (float *)pipi_getpixels(img, PIPI_PIXELS_RGBA_F)->pixels;
155        s.colorf[0] = (c&0x00FF0000)/255.0f; /* XXX FIXME */
156        s.colorf[1] = (c&0x0000FF00)/255.0f; /* XXX FIXME */
157        s.colorf[2] = (c&0x000000FF)/255.0f; /* XXX FIXME */
158        s.buf_f = dstdata;
[2795]159        s.draw = aa==0?aliased_line:draw_antialiased_line_float;
[2776]160        img->last_modified = PIPI_PIXELS_RGBA_F;
161    }
162
163    for(i = 0; i < n; i++)
164    {
165        s.x1 = x[i];
166        s.y1 = y[i];
167        s.x2 = x[i+1];
168        s.y2 = y[i+1];
169        clip_line(img, &s);
170    }
171    return 0;
172}
173
174/*
175 * XXX: The following functions are local.
176 */
[2795]177
[2776]178/* Generic Cohen-Sutherland line clipping function. */
179static void clip_line(pipi_image_t *img, struct line* s)
180{
181    uint8_t bits1, bits2;
182
183    bits1 = clip_bits(img, s->x1, s->y1);
184    bits2 = clip_bits(img, s->x2, s->y2);
185
186    if(bits1 & bits2)
187        return;
188
189    if(bits1 == 0)
190    {
191        if(bits2 == 0)
192            s->draw(img, s);
193        else
194        {
195            int tmp;
196            tmp = s->x1; s->x1 = s->x2; s->x2 = tmp;
197            tmp = s->y1; s->y1 = s->y2; s->y2 = tmp;
198            clip_line(img, s);
199        }
200        return;
201    }
202
203    if(bits1 & (1<<0))
204    {
205        s->y1 = s->y2 - (s->x2 - 0) * (s->y2 - s->y1) / (s->x2 - s->x1);
206        s->x1 = 0;
207    }
208    else if(bits1 & (1<<1))
209    {
210        int xmax = img->w - 1;
211        s->y1 = s->y2 - (s->x2 - xmax) * (s->y2 - s->y1) / (s->x2 - s->x1);
212        s->x1 = xmax;
213    }
214    else if(bits1 & (1<<2))
215    {
216        s->x1 = s->x2 - (s->y2 - 0) * (s->x2 - s->x1) / (s->y2 - s->y1);
217        s->y1 = 0;
218    }
219    else if(bits1 & (1<<3))
220    {
221        int ymax = img->h - 1;
222        s->x1 = s->x2 - (s->y2 - ymax) * (s->x2 - s->x1) / (s->y2 - s->y1);
223        s->y1 = ymax;
224    }
225
226    clip_line(img, s);
227}
228
229/* Helper function for clip_line(). */
230static uint8_t clip_bits(pipi_image_t *img, int x, int y)
231{
232    uint8_t b = 0;
233
234    if(x < 0)
235        b |= (1<<0);
236    else if(x >= (int)img->w)
237        b |= (1<<1);
238
239    if(y < 0)
240        b |= (1<<2);
241    else if(y >= (int)img->h)
242        b |= (1<<3);
243
244    return b;
245}
246
[2777]247/* Xiaolin Wu's line algorithm, as seen at http://portal.acm.org/citation.cfm?id=122734 */
248
[2788]249/* math.h doesn't like y1 (sucker) */
[2777]250float floorf(float x);
251float truncf(float x);
252float fabsf(float x);
[2788]253
[2777]254static float fractf(float d) { return (d - floorf(d)); }
255static float fractinvf(float d) { return (1 - (d - floorf(d))); }
256
257static void draw_antialiased_line_float(pipi_image_t *img, struct line* s)
258{
259/* Is that an horrible mess ? Yes, it is. */
260#undef  PLOT
261#define PLOT(x, y, c)  \
[2787]262    { int qwer = (((int)(x)*4))+((int)(y))*(img->w*4);\
263      int qweg = (1+((int)(x)*4))+((int)(y))*(img->w*4); \
264      int qweb = (2+((int)(x)*4))+((int)(y))*(img->w*4); \
265    s->buf_f[qwer] = (c*s->colorf[0]) + (1-c) * s->buf_f[qwer]; \
266    s->buf_f[qweg] = (c*s->colorf[1]) + (1-c) * s->buf_f[qweg]; \
267    s->buf_f[qweb] = (c*s->colorf[2]) + (1-c) * s->buf_f[qweb]; \
[2788]268    if(s->buf_f[qwer] > 1.0f) s->buf_f[qwer] = 1.0f; \
269    if(s->buf_f[qwer] < 0.0f || isnan(s->buf_f[qwer])) s->buf_f[qwer] = 0.0f; \
270    if(s->buf_f[qweg] > 1.0f) s->buf_f[qweg] = 1.0f; \
271    if(s->buf_f[qweg] < 0.0f || isnan(s->buf_f[qweg])) s->buf_f[qweg] = 0.0f; \
272    if(s->buf_f[qweb] > 1.0f) s->buf_f[qweb] = 1.0f; \
273    if(s->buf_f[qweb] < 0.0f || isnan(s->buf_f[qweb])) s->buf_f[qweb] = 0.0f;  }
274
[2778]275#include "aline_template.h"
[2777]276}
277
278
279static void draw_antialiased_line_gray(pipi_image_t *img, struct line* s)
280{
281#undef  PLOT
282#define PLOT(x, y, c) s->buf_f[((int)(x))+((int)(y))*img->w] =  \
[2788]283    (c*s->colorf[0]) + (1-c) * s->buf_f[((int)(x))+((int)(y))*img->w]; \
284    if(s->buf_f[((int)(x))+((int)(y))*img->w] > 1.0f) s->buf_f[((int)(x))+((int)(y))*img->w] = 1.0f; \
285    if(s->buf_f[((int)(x))+((int)(y))*img->w] < 0.0f) s->buf_f[((int)(x))+((int)(y))*img->w] = 0.0f; \
286    if(isnan(s->buf_f[((int)(x))+((int)(y))*img->w])) s->buf_f[((int)(x))+((int)(y))*img->w] = 0.0f;
287
[2778]288#include "aline_template.h"
[2777]289}
[2795]290
291#else /* XXX: the following functions use the template system */
292
293/* Solid line drawing function, using Bresenham's mid-point line
294 * scan-conversion algorithm. */
295static void SUFFIX(aliased_line)(pipi_image_t *img, struct line* s)
296{
297    int x1, y1, x2, y2;
298    int dx, dy;
299    int xinc, yinc;
300
301    x1 = s->x1; y1 = s->y1; x2 = s->x2; y2 = s->y2;
302
303    dx = abs(x2 - x1);
304    dy = abs(y2 - y1);
305
306    xinc = (x1 > x2) ? -1 : 1;
307    yinc = (y1 > y2) ? -1 : 1;
308
309    if(dx >= dy)
310    {
311        int dpr = dy << 1;
312        int dpru = dpr - (dx << 1);
313        int delta = dpr - dx;
314
315        for(; dx >= 0; dx--)
316        {
317            if(FLAG_GRAY)
318            {
319                if(FLAG_8BIT)
320                    /* TODO */;
321                else
322                    s->buf_f[x1 + y1 * img->w] = s->colorf[0];
323            }
324            else
325            {
326                if(FLAG_8BIT)
327                    s->buf_u32[x1 + y1 * img->w] = s->color32;
328                else
329                {
330                    s->buf_f[4 * (y1 * img->w + x1)] = s->colorf[0];
331                    s->buf_f[4 * (y1 * img->w + x1) + 1] = s->colorf[1];
332                    s->buf_f[4 * (y1 * img->w + x1) + 2] = s->colorf[2];
333                }
334            }
335
336            if(delta > 0)
337            {
338                x1 += xinc;
339                y1 += yinc;
340                delta += dpru;
341            }
342            else
343            {
344                x1 += xinc;
345                delta += dpr;
346            }
347        }
348    }
349    else
350    {
351        int dpr = dx << 1;
352        int dpru = dpr - (dy << 1);
353        int delta = dpr - dy;
354
355        for(; dy >= 0; dy--)
356        {
357            if(FLAG_GRAY)
358            {
359                if(FLAG_8BIT)
360                    /* TODO */;
361                else
362                    s->buf_f[x1 + y1 * img->w] = s->colorf[0];
363            }
364            else
365            {
366                if(FLAG_8BIT)
367                    s->buf_u32[x1 + y1 * img->w] = s->color32;
368                else
369                {
370                    s->buf_f[4 * (y1 * img->w + x1)] = s->colorf[0];
371                    s->buf_f[4 * (y1 * img->w + x1) + 1] = s->colorf[1];
372                    s->buf_f[4 * (y1 * img->w + x1) + 2] = s->colorf[2];
373                }
374            }
375
376            if(delta > 0)
377            {
378                x1 += xinc;
379                y1 += yinc;
380                delta += dpru;
381            }
382            else
383            {
384                y1 += yinc;
385                delta += dpr;
386            }
387        }
388    }
389}
390
391#endif
392
Note: See TracBrowser for help on using the repository browser.