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

Last change on this file since 2904 was 2904, checked in by Sam Hocevar, 12 years ago

Start writing Visual Studio projects.

File size: 11.5 KB
Line 
1/*
2 *  libpipi       Pathetic image processing interface 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
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25
26#include <math.h>
27
28#include "pipi.h"
29#include "pipi_internals.h"
30
31#if !defined TEMPLATE_FILE /* This file uses the template system */
32
33static float fractf(float d) { return (d - floorf(d)); }
34static float fractinvf(float d) { return (1 - (d - floorf(d))); }
35
36struct line
37{
38    int xa, ya;
39    int xb, yb;
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};
52
53#define TEMPLATE_FLAGS SET_FLAG_GRAY | SET_FLAG_8BIT
54#define TEMPLATE_FILE "paint/line.c"
55#include "pipi_template.h"
56
57static void clip_line(pipi_image_t*, struct line*);
58static uint8_t clip_bits(pipi_image_t*, int, int);
59
60int pipi_draw_line(pipi_image_t *img , int xa, int ya, int xb, int yb, uint32_t c, int aa)
61{
62    struct line s;
63    s.xa = xa;
64    s.ya = ya;
65    s.xb = xb;
66    s.yb = yb;
67
68
69    /* No Transparency routine for u32 yet, fallback to float version */
70    if(img->last_modified == PIPI_PIXELS_RGBA_C)
71    {
72        if(!aa)
73        {
74            uint32_t  *dstdata;
75            dstdata = (uint32_t *)pipi_getpixels(img, PIPI_PIXELS_RGBA_C)->pixels;
76            s.color32 = c;
77            s.buf_u32 = dstdata;
78            s.draw = line_8bit;
79        }
80        else
81        {
82            float  *dstdata;
83            dstdata = (float *)pipi_getpixels(img, PIPI_PIXELS_RGBA_F)->pixels;
84            s.colorf[2] = ((c&0x00FF0000)>>16)/255.0f; /* XXX FIXME */
85            s.colorf[1] = ((c&0x0000FF00)>>8)/255.0f;  /* XXX FIXME */
86            s.colorf[0] = (c&0x000000FF)/255.0f;       /* XXX FIXME */
87            s.buf_f = dstdata;
88            s.draw = aaline;
89        }
90    }
91    else if(img->last_modified == PIPI_PIXELS_Y_F)
92    {
93        float  *dstdata;
94        dstdata = (float *)pipi_getpixels(img, PIPI_PIXELS_Y_F)->pixels;
95        s.colorf[0] = (c & 0xff) / 255.0f; /* XXX FIXME */
96        s.buf_f = dstdata;
97        s.draw = aa ? aaline_gray : line_gray;
98    }
99    else
100    {
101        float  *dstdata;
102        dstdata = (float *)pipi_getpixels(img, PIPI_PIXELS_RGBA_F)->pixels;
103        s.colorf[2] = ((c&0x00FF0000)>>16)/255.0f; /* XXX FIXME */
104        s.colorf[1] = ((c&0x0000FF00)>>8)/255.0f;  /* XXX FIXME */
105        s.colorf[0] = (c&0x000000FF)/255.0f;       /* XXX FIXME */
106        s.buf_f = dstdata;
107        s.draw = aa ? aaline : line;
108    }
109
110    clip_line(img, &s);
111    return 0;
112}
113
114int pipi_draw_polyline(pipi_image_t *img, int const x[], int const y[],
115                       int n, uint32_t c, int aa)
116{
117    int i;
118
119    for(i = 0; i < n; i++)
120        pipi_draw_line(img, x[i], y[i], x[i + 1], y[i + 1], c, aa);
121
122    return 0;
123}
124
125/*
126 * XXX: The following functions are local.
127 */
128
129/* Generic Cohen-Sutherland line clipping function. */
130static void clip_line(pipi_image_t *img, struct line* s)
131{
132    uint8_t bits1, bits2;
133
134    bits1 = clip_bits(img, s->xa, s->ya);
135    bits2 = clip_bits(img, s->xb, s->yb);
136
137    if(bits1 & bits2)
138        return;
139
140    if(bits1 == 0)
141    {
142        if(bits2 == 0)
143            s->draw(img, s);
144        else
145        {
146            int tmp;
147            tmp = s->xa; s->xa = s->xb; s->xb = tmp;
148            tmp = s->ya; s->ya = s->yb; s->yb = tmp;
149            clip_line(img, s);
150        }
151        return;
152    }
153
154    if(bits1 & (1<<0))
155    {
156        s->ya = s->yb - (s->xb - 0) * (s->yb - s->ya) / (s->xb - s->xa);
157        s->xa = 0;
158    }
159    else if(bits1 & (1<<1))
160    {
161        int xmax = img->w - 1;
162        s->ya = s->yb - (s->xb - xmax) * (s->yb - s->ya) / (s->xb - s->xa);
163        s->xa = xmax;
164    }
165    else if(bits1 & (1<<2))
166    {
167        s->xa = s->xb - (s->yb - 0) * (s->xb - s->xa) / (s->yb - s->ya);
168        s->ya = 0;
169    }
170    else if(bits1 & (1<<3))
171    {
172        int ymax = img->h - 1;
173        s->xa = s->xb - (s->yb - ymax) * (s->xb - s->xa) / (s->yb - s->ya);
174        s->ya = ymax;
175    }
176
177    clip_line(img, s);
178}
179
180/* Helper function for clip_line(). */
181static uint8_t clip_bits(pipi_image_t *img, int x, int y)
182{
183    uint8_t b = 0;
184
185    if(x < 0)
186        b |= (1<<0);
187    else if(x >= (int)img->w)
188        b |= (1<<1);
189
190    if(y < 0)
191        b |= (1<<2);
192    else if(y >= (int)img->h)
193        b |= (1<<3);
194
195    return b;
196}
197
198#else /* XXX: the following functions use the template system */
199
200/* Xiaolin Wu's line algorithm, as seen at http://portal.acm.org/citation.cfm?id=122734 */
201
202#define PLOT(x, y, c) \
203    if(FLAG_8BIT) \
204    { \
205        /* TODO */ \
206    } \
207    else \
208    { \
209        if(FLAG_GRAY) \
210        { \
211            s->buf_f[((int)(x))+((int)(y))*img->w] =  \
212            (c*s->colorf[0]) + (1-c) * s->buf_f[((int)(x))+((int)(y))*img->w]; \
213            if(s->buf_f[((int)(x))+((int)(y))*img->w] > 1.0f) \
214                s->buf_f[((int)(x))+((int)(y))*img->w] = 1.0f; \
215            if(s->buf_f[((int)(x))+((int)(y))*img->w] < 0.0f) \
216                s->buf_f[((int)(x))+((int)(y))*img->w] = 0.0f; \
217        } \
218        else \
219        { \
220            int qwer = (((int)(x)*4))+((int)(y))*(img->w*4);\
221            int qweg = (1+((int)(x)*4))+((int)(y))*(img->w*4); \
222            int qweb = (2+((int)(x)*4))+((int)(y))*(img->w*4); \
223            s->buf_f[qwer] = (c*s->colorf[0]) + (1-c) * s->buf_f[qwer]; \
224            s->buf_f[qweg] = (c*s->colorf[1]) + (1-c) * s->buf_f[qweg]; \
225            s->buf_f[qweb] = (c*s->colorf[2]) + (1-c) * s->buf_f[qweb]; \
226            if(s->buf_f[qwer] > 1.0f) s->buf_f[qwer] = 1.0f; \
227            if(s->buf_f[qwer] < 0.0f) s->buf_f[qwer] = 0.0f; \
228            if(s->buf_f[qweg] > 1.0f) s->buf_f[qweg] = 1.0f; \
229            if(s->buf_f[qweg] < 0.0f) s->buf_f[qweg] = 0.0f; \
230            if(s->buf_f[qweb] > 1.0f) s->buf_f[qweb] = 1.0f; \
231            if(s->buf_f[qweb] < 0.0f) s->buf_f[qweb] = 0.0f; \
232        } \
233    }
234
235static void T(aaline)(pipi_image_t *img, struct line* s)
236{
237    float xa = s->xa, ya = s->ya, xb = s->xb, yb = s->yb;
238    float g, xd, yd, xgap, xend, yend, xf, yf, val1, val2;
239    int x, y, ixa, ixb, iya, iyb;
240
241    xd = xb - xa;
242    yd = yb - ya;
243
244    /* "Horizontal" line (X greater than Y)*/
245    if (fabsf(xd) > fabsf(yd))
246    {
247        if (xa > xb)
248        {
249            float tmp;
250            tmp = xa; xa = xb; xb = tmp;
251            tmp = ya; ya = yb; yb = tmp;
252            xd = (xb-xa);
253            yd = (yb-ya);
254        }
255        g = yd/xd;
256
257        xend = (float)(int)(xa+0.5);
258        yend = ya + g*(xend-xa);
259        xgap = fractinvf(xa+0.5);
260        ixa = (int)xend;
261        iya = (int)yend;
262        val1 = fractinvf(yend)*xgap;
263        val2 = fractf(yend)*xgap;
264
265        PLOT(ixa, iya,   val1);
266        PLOT(ixa, (iya+1)<ya?(iya+1):iya, val2);
267
268        yf = yend+g;
269        xend = (float)(int)(xb+0.5);
270        yend = yb + g*(xend-xb);
271        xgap = fractinvf(xb-0.5);
272        ixb = (int)xend;
273        iyb = (int)yend;
274        val1 = fractinvf(yend)*xgap;
275        val2 = fractf(yend)*xgap;
276
277        PLOT(ixb, iyb,   val1);
278        PLOT(ixb, iyb+1<yb?iyb+1:iyb, val2);
279
280        for (x = (ixa+1); x < ixb; x++)
281        {
282            float focus;
283
284            val1 = fractinvf(yf);
285            val2 = fractf(yf);
286            focus = (1.0 - fabsf(val1-val2));
287            val1 += 0.3*focus;
288            val2 += 0.3*focus;
289
290            PLOT(x, yf, val1);
291            PLOT(x, (yf+1)<ya?(yf+1):yf, val2);
292
293            yf = yf + g;
294        }
295    }
296    /* "Vertical" line (Y greater than X)*/
297    else
298    {
299        if (xa > xb)
300        {
301            float tmp;
302            tmp = xa; xa = xb; xb = tmp;
303            tmp = ya; ya = yb; yb = tmp;
304            xd = (xb-xa);
305            yd = (yb-ya);
306        }
307
308        g = xd/yd;
309
310        xend = (float)(int)(xa+0.5);
311        yend = ya + g*(xend-xa);
312        xgap = fractf(xa+0.5);
313        ixa = (int)xend;
314        iya = (int)yend;
315        val1 = fractinvf(yend)*xgap;
316        val2 = fractf(yend)*xgap;
317
318        PLOT(ixa, iya, val1);
319        PLOT(ixa, (iya+1)<ya?(iya+1):iya, val2);
320
321        xf = xend + g;
322
323        xend = (float)(int)(xb+0.5);
324        yend = yb + g*(xend-xb);
325        xgap = fractinvf(xb-0.5);
326        ixb = (int)xend;
327        iyb = (int)yend;
328        val1 = fractinvf(yend)*xgap;
329        val2 = fractf(yend)*xgap;
330
331        PLOT(ixb, iyb,   val1);
332        PLOT(ixb, (iyb+1)<yb?(iyb+1):iyb, val2);
333
334
335        for (y = (iya+1); y < iyb; y++)
336        {
337            float focus;
338            int   vx = xf;
339            val1 = fractinvf(xf);
340            val2 = fractf(xf);
341            focus = (1.0 - fabsf(val1-val2));
342            val1 += 0.3*focus;
343            val2 += 0.3*focus;
344            PLOT(vx, y, val1);
345            vx++;
346            PLOT(vx, y, val2);
347            xf = xf + g;
348        }
349    }
350}
351
352#undef PLOT
353
354/* Solid line drawing function, using Bresenham's mid-point line
355 * scan-conversion algorithm. */
356static void T(line)(pipi_image_t *img, struct line* s)
357{
358    int xa, ya, xb, yb;
359    int dx, dy;
360    int xinc, yinc;
361
362    xa = s->xa; ya = s->ya; xb = s->xb; yb = s->yb;
363
364    dx = abs(xb - xa);
365    dy = abs(yb - ya);
366
367    xinc = (xa > xb) ? -1 : 1;
368    yinc = (ya > yb) ? -1 : 1;
369
370    if(dx >= dy)
371    {
372        int dpr = dy << 1;
373        int dpru = dpr - (dx << 1);
374        int delta = dpr - dx;
375
376        for(; dx >= 0; dx--)
377        {
378            if(FLAG_GRAY)
379            {
380                if(FLAG_8BIT)
381                    /* TODO */;
382                else
383                    s->buf_f[xa + ya * img->w] = s->colorf[0];
384            }
385            else
386            {
387                if(FLAG_8BIT)
388                    s->buf_u32[xa + ya * img->w] = s->color32;
389                else
390                {
391                    s->buf_f[4 * (ya * img->w + xa)] = s->colorf[0];
392                    s->buf_f[4 * (ya * img->w + xa) + 1] = s->colorf[1];
393                    s->buf_f[4 * (ya * img->w + xa) + 2] = s->colorf[2];
394                }
395            }
396
397            if(delta > 0)
398            {
399                xa += xinc;
400                ya += yinc;
401                delta += dpru;
402            }
403            else
404            {
405                xa += xinc;
406                delta += dpr;
407            }
408        }
409    }
410    else
411    {
412        int dpr = dx << 1;
413        int dpru = dpr - (dy << 1);
414        int delta = dpr - dy;
415
416        for(; dy >= 0; dy--)
417        {
418            if(FLAG_GRAY)
419            {
420                if(FLAG_8BIT)
421                    /* TODO */;
422                else
423                    s->buf_f[xa + ya * img->w] = s->colorf[0];
424            }
425            else
426            {
427                if(FLAG_8BIT)
428                    s->buf_u32[xa + ya * img->w] = s->color32;
429                else
430                {
431                    s->buf_f[4 * (ya * img->w + xa)] = s->colorf[0];
432                    s->buf_f[4 * (ya * img->w + xa) + 1] = s->colorf[1];
433                    s->buf_f[4 * (ya * img->w + xa) + 2] = s->colorf[2];
434                }
435            }
436
437            if(delta > 0)
438            {
439                xa += xinc;
440                ya += yinc;
441                delta += dpru;
442            }
443            else
444            {
445                ya += yinc;
446                delta += dpr;
447            }
448        }
449    }
450}
451
452#endif
453
Note: See TracBrowser for help on using the repository browser.