瀏覽代碼

* line.c: merge the antialiased line template back into line.c.

git-svn-id: file:///srv/caca.zoy.org/var/lib/svn/libpipi/trunk@2798 92316355-f0b4-4df1-b90c-862c8a59935f
remotes/tiles
sam 16 年之前
父節點
當前提交
e13a1527e4
共有 3 個檔案被更改,包括 178 行新增179 行删除
  1. +1
    -1
      pipi/Makefile.am
  2. +0
    -132
      pipi/paint/aline_template.h
  3. +177
    -46
      pipi/paint/line.c

+ 1
- 1
pipi/Makefile.am 查看文件

@@ -44,7 +44,7 @@ codec_sources =
# Submodules
paint_sources = \
paint/floodfill.c \
paint/line.c paint/aline_template.h \
paint/line.c \
paint/bezier.c \
paint/tile.c



+ 0
- 132
pipi/paint/aline_template.h 查看文件

@@ -1,132 +0,0 @@
/*
* libpipi Proper image processing implementation library
* Copyright (c) 2004-2008 Sam Hocevar <sam@zoy.org>
* 2008 Jean-Yves Lamoureux <jylam@lnxscene.org
* 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.
*/

/*
* aline_template.c: antialiased (Wu) line rendering template
*/

float x1 = s->x1, y1 = s->y1, x2 = s->x2, y2 = s->y2;
float g, xd, yd, xgap, xend, yend, xf, yf, val1, val2;
int x, y, ix1, ix2, iy1, iy2;

xd = x2 - x1;
yd = y2 - y1;

/* "Horizontal" line (X greater than Y)*/
if (fabsf(xd) > fabsf(yd))
{
if (x1 > x2)
{
float tmp;
tmp = x1; x1 = x2; x2 = tmp;
tmp = y1; y1 = y2; y2 = tmp;
xd = (x2-x1);
yd = (y2-y1);
}
g = yd/xd;

xend = truncf(x1+0.5);
yend = y1 + g*(xend-x1);
xgap = fractinvf(x1+0.5);
ix1 = (int)xend;
iy1 = (int)yend;
val1 = fractinvf(yend)*xgap;
val2 = fractf(yend)*xgap;

PLOT(ix1, iy1, val1);
PLOT(ix1, (iy1+1)<y1?(iy1+1):iy1, val2);

yf = yend+g;
xend = truncf(x2+0.5);
yend = y2 + g*(xend-x2);
xgap = fractinvf(x2-0.5);
ix2 = (int)xend;
iy2 = (int)yend;
val1 = fractinvf(yend)*xgap;
val2 = fractf(yend)*xgap;

PLOT(ix2, iy2, val1);
PLOT(ix2, iy2+1<y2?iy2+1:iy2, val2);

for (x = (ix1+1); x < ix2; x++)
{
float focus;

val1 = fractinvf(yf);
val2 = fractf(yf);
focus = (1.0 - fabsf(val1-val2));
val1 += 0.3*focus;
val2 += 0.3*focus;

PLOT(x, yf, val1);
PLOT(x, (yf+1)<y1?(yf+1):yf, val2);

yf = yf + g;
}
}
/* "Vertical" line (Y greater than X)*/
else
{
if (x1 > x2)
{
float tmp;
tmp = x1; x1 = x2; x2 = tmp;
tmp = y1; y1 = y2; y2 = tmp;
xd = (x2-x1);
yd = (y2-y1);
}

g = xd/yd;

xend = truncf(x1+0.5);
yend = y1 + g*(xend-x1);
xgap = fractf(x1+0.5);
ix1 = (int)xend;
iy1 = (int)yend;
val1 = fractinvf(yend)*xgap;
val2 = fractf(yend)*xgap;

PLOT(ix1, iy1, val1);
PLOT(ix1, (iy1+1)<y1?(iy1+1):iy1, val2);

xf = xend + g;

xend = truncf(x2+0.5);
yend = y2 + g*(xend-x2);
xgap = fractinvf(x2-0.5);
ix2 = (int)xend;
iy2 = (int)yend;
val1 = fractinvf(yend)*xgap;
val2 = fractf(yend)*xgap;

PLOT(ix2, iy2, val1);
PLOT(ix2, (iy2+1)<y2?(iy2+1):iy2, val2);


for (y = (iy1+1); y < iy2; y++)
{
float focus;
int vx = xf;
val1 = fractinvf(xf);
val2 = fractf(xf);
focus = (1.0 - fabsf(val1-val2));
val1 += 0.3*focus;
val2 += 0.3*focus;
PLOT(vx, y, val1);
vx++;
PLOT(vx, y, val2);
xf = xf + g;
}
}

+ 177
- 46
pipi/paint/line.c 查看文件

@@ -31,8 +31,16 @@
#include "pipi.h"
#include "pipi_internals.h"

/* math.h doesn't like y1 (sucker) */
float floorf(float x);
float truncf(float x);
float fabsf(float x);

#if !defined TEMPLATE_FILE /* This file uses the template system */

static float fractf(float d) { return (d - floorf(d)); }
static float fractinvf(float d) { return (1 - (d - floorf(d))); }

struct line
{
int x1, y1;
@@ -56,8 +64,6 @@ struct line

static void clip_line(pipi_image_t*, struct line*);
static uint8_t clip_bits(pipi_image_t*, int, int);
static void draw_antialiased_line_float(pipi_image_t *img, struct line* s);
static void draw_antialiased_line_gray(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, int aa)
{
@@ -86,7 +92,7 @@ int pipi_draw_line(pipi_image_t *img , int x1, int y1, int x2, int y2, uint32_t
s.colorf[1] = ((c&0x0000FF00)>>8)/255.0f; /* XXX FIXME */
s.colorf[0] = (c&0x000000FF)/255.0f; /* XXX FIXME */
s.buf_f = dstdata;
s.draw = draw_antialiased_line_float;
s.draw = antialiased_line;
}
}
else if(img->last_modified == PIPI_PIXELS_Y_F)
@@ -95,7 +101,7 @@ int pipi_draw_line(pipi_image_t *img , int x1, int y1, int x2, int y2, uint32_t
dstdata = (float *)pipi_getpixels(img, PIPI_PIXELS_Y_F)->pixels;
s.colorf[0] = (c & 0xff) / 255.0f; /* XXX FIXME */
s.buf_f = dstdata;
s.draw = aa==0?aliased_line_gray:draw_antialiased_line_gray;
s.draw = aa == 0 ? aliased_line_gray : antialiased_line_gray;
}
else
{
@@ -105,7 +111,7 @@ int pipi_draw_line(pipi_image_t *img , int x1, int y1, int x2, int y2, uint32_t
s.colorf[1] = ((c&0x0000FF00)>>8)/255.0f; /* XXX FIXME */
s.colorf[0] = (c&0x000000FF)/255.0f; /* XXX FIXME */
s.buf_f = dstdata;
s.draw = aa==0?aliased_line:draw_antialiased_line_float;
s.draw = aa == 0 ? aliased_line : antialiased_line;
}

clip_line(img, &s);
@@ -137,16 +143,16 @@ int pipi_draw_polyline(pipi_image_t *img, int const x[], int const y[],
s.colorf[1] = ((c&0x0000FF00)>>8)/255.0f; /* XXX FIXME */
s.colorf[0] = (c&0x000000FF)/255.0f; /* XXX FIXME */
s.buf_f = dstdata;
s.draw = draw_antialiased_line_float;
s.draw = antialiased_line;
}
}
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.colorf[0] = (c & 0xff) / 255.0f; /* XXX FIXME */
s.buf_f = dstdata;
s.draw = aa==0?aliased_line_gray:draw_antialiased_line_gray;
s.draw = aa == 0 ? aliased_line_gray : antialiased_line_gray;
}
else
{
@@ -156,7 +162,7 @@ int pipi_draw_polyline(pipi_image_t *img, int const x[], int const y[],
s.colorf[1] = (c&0x0000FF00)/255.0f; /* XXX FIXME */
s.colorf[2] = (c&0x000000FF)/255.0f; /* XXX FIXME */
s.buf_f = dstdata;
s.draw = aa==0?aliased_line:draw_antialiased_line_float;
s.draw = aa == 0 ? aliased_line : antialiased_line;
img->last_modified = PIPI_PIXELS_RGBA_F;
}

@@ -244,51 +250,176 @@ static uint8_t clip_bits(pipi_image_t *img, int x, int y)
return b;
}

/* Xiaolin Wu's line algorithm, as seen at http://portal.acm.org/citation.cfm?id=122734 */
#else /* XXX: the following functions use the template system */

/* math.h doesn't like y1 (sucker) */
float floorf(float x);
float truncf(float x);
float fabsf(float x);
/* Xiaolin Wu's line algorithm, as seen at http://portal.acm.org/citation.cfm?id=122734 */

static float fractf(float d) { return (d - floorf(d)); }
static float fractinvf(float d) { return (1 - (d - floorf(d))); }
#define PLOT(x, y, c) \
if(FLAG_GRAY) \
{ \
if(FLAG_8BIT) \
{ \
/* TODO */ \
} \
else \
{ \
s->buf_f[((int)(x))+((int)(y))*img->w] = \
(c*s->colorf[0]) + (1-c) * s->buf_f[((int)(x))+((int)(y))*img->w]; \
if(s->buf_f[((int)(x))+((int)(y))*img->w] > 1.0f) \
s->buf_f[((int)(x))+((int)(y))*img->w] = 1.0f; \
if(s->buf_f[((int)(x))+((int)(y))*img->w] < 0.0f) \
s->buf_f[((int)(x))+((int)(y))*img->w] = 0.0f; \
if(isnan(s->buf_f[((int)(x))+((int)(y))*img->w])) \
s->buf_f[((int)(x))+((int)(y))*img->w] = 0.0f; \
} \
} \
else \
{ \
if(FLAG_8BIT) \
{ \
/* TODO */ \
} \
else \
{ \
int qwer = (((int)(x)*4))+((int)(y))*(img->w*4);\
int qweg = (1+((int)(x)*4))+((int)(y))*(img->w*4); \
int qweb = (2+((int)(x)*4))+((int)(y))*(img->w*4); \
s->buf_f[qwer] = (c*s->colorf[0]) + (1-c) * s->buf_f[qwer]; \
s->buf_f[qweg] = (c*s->colorf[1]) + (1-c) * s->buf_f[qweg]; \
s->buf_f[qweb] = (c*s->colorf[2]) + (1-c) * s->buf_f[qweb]; \
if(s->buf_f[qwer] > 1.0f) \
s->buf_f[qwer] = 1.0f; \
if(s->buf_f[qwer] < 0.0f || isnan(s->buf_f[qwer])) \
s->buf_f[qwer] = 0.0f; \
if(s->buf_f[qweg] > 1.0f) \
s->buf_f[qweg] = 1.0f; \
if(s->buf_f[qweg] < 0.0f || isnan(s->buf_f[qweg])) \
s->buf_f[qweg] = 0.0f; \
if(s->buf_f[qweb] > 1.0f) \
s->buf_f[qweb] = 1.0f; \
if(s->buf_f[qweb] < 0.0f || isnan(s->buf_f[qweb])) \
s->buf_f[qweb] = 0.0f; \
} \
}

static void draw_antialiased_line_float(pipi_image_t *img, struct line* s)
static void SUFFIX(antialiased_line)(pipi_image_t *img, struct line* s)
{
/* Is that an horrible mess ? Yes, it is. */
#undef PLOT
#define PLOT(x, y, c) \
{ int qwer = (((int)(x)*4))+((int)(y))*(img->w*4);\
int qweg = (1+((int)(x)*4))+((int)(y))*(img->w*4); \
int qweb = (2+((int)(x)*4))+((int)(y))*(img->w*4); \
s->buf_f[qwer] = (c*s->colorf[0]) + (1-c) * s->buf_f[qwer]; \
s->buf_f[qweg] = (c*s->colorf[1]) + (1-c) * s->buf_f[qweg]; \
s->buf_f[qweb] = (c*s->colorf[2]) + (1-c) * s->buf_f[qweb]; \
if(s->buf_f[qwer] > 1.0f) s->buf_f[qwer] = 1.0f; \
if(s->buf_f[qwer] < 0.0f || isnan(s->buf_f[qwer])) s->buf_f[qwer] = 0.0f; \
if(s->buf_f[qweg] > 1.0f) s->buf_f[qweg] = 1.0f; \
if(s->buf_f[qweg] < 0.0f || isnan(s->buf_f[qweg])) s->buf_f[qweg] = 0.0f; \
if(s->buf_f[qweb] > 1.0f) s->buf_f[qweb] = 1.0f; \
if(s->buf_f[qweb] < 0.0f || isnan(s->buf_f[qweb])) s->buf_f[qweb] = 0.0f; }

#include "aline_template.h"
}
float x1 = s->x1, y1 = s->y1, x2 = s->x2, y2 = s->y2;
float g, xd, yd, xgap, xend, yend, xf, yf, val1, val2;
int x, y, ix1, ix2, iy1, iy2;

xd = x2 - x1;
yd = y2 - y1;

static void draw_antialiased_line_gray(pipi_image_t *img, struct line* s)
{
#undef PLOT
#define PLOT(x, y, c) s->buf_f[((int)(x))+((int)(y))*img->w] = \
(c*s->colorf[0]) + (1-c) * s->buf_f[((int)(x))+((int)(y))*img->w]; \
if(s->buf_f[((int)(x))+((int)(y))*img->w] > 1.0f) s->buf_f[((int)(x))+((int)(y))*img->w] = 1.0f; \
if(s->buf_f[((int)(x))+((int)(y))*img->w] < 0.0f) s->buf_f[((int)(x))+((int)(y))*img->w] = 0.0f; \
if(isnan(s->buf_f[((int)(x))+((int)(y))*img->w])) s->buf_f[((int)(x))+((int)(y))*img->w] = 0.0f;

#include "aline_template.h"
/* "Horizontal" line (X greater than Y)*/
if (fabsf(xd) > fabsf(yd))
{
if (x1 > x2)
{
float tmp;
tmp = x1; x1 = x2; x2 = tmp;
tmp = y1; y1 = y2; y2 = tmp;
xd = (x2-x1);
yd = (y2-y1);
}
g = yd/xd;

xend = truncf(x1+0.5);
yend = y1 + g*(xend-x1);
xgap = fractinvf(x1+0.5);
ix1 = (int)xend;
iy1 = (int)yend;
val1 = fractinvf(yend)*xgap;
val2 = fractf(yend)*xgap;

PLOT(ix1, iy1, val1);
PLOT(ix1, (iy1+1)<y1?(iy1+1):iy1, val2);

yf = yend+g;
xend = truncf(x2+0.5);
yend = y2 + g*(xend-x2);
xgap = fractinvf(x2-0.5);
ix2 = (int)xend;
iy2 = (int)yend;
val1 = fractinvf(yend)*xgap;
val2 = fractf(yend)*xgap;

PLOT(ix2, iy2, val1);
PLOT(ix2, iy2+1<y2?iy2+1:iy2, val2);

for (x = (ix1+1); x < ix2; x++)
{
float focus;

val1 = fractinvf(yf);
val2 = fractf(yf);
focus = (1.0 - fabsf(val1-val2));
val1 += 0.3*focus;
val2 += 0.3*focus;

PLOT(x, yf, val1);
PLOT(x, (yf+1)<y1?(yf+1):yf, val2);

yf = yf + g;
}
}
/* "Vertical" line (Y greater than X)*/
else
{
if (x1 > x2)
{
float tmp;
tmp = x1; x1 = x2; x2 = tmp;
tmp = y1; y1 = y2; y2 = tmp;
xd = (x2-x1);
yd = (y2-y1);
}

g = xd/yd;

xend = truncf(x1+0.5);
yend = y1 + g*(xend-x1);
xgap = fractf(x1+0.5);
ix1 = (int)xend;
iy1 = (int)yend;
val1 = fractinvf(yend)*xgap;
val2 = fractf(yend)*xgap;

PLOT(ix1, iy1, val1);
PLOT(ix1, (iy1+1)<y1?(iy1+1):iy1, val2);

xf = xend + g;

xend = truncf(x2+0.5);
yend = y2 + g*(xend-x2);
xgap = fractinvf(x2-0.5);
ix2 = (int)xend;
iy2 = (int)yend;
val1 = fractinvf(yend)*xgap;
val2 = fractf(yend)*xgap;

PLOT(ix2, iy2, val1);
PLOT(ix2, (iy2+1)<y2?(iy2+1):iy2, val2);


for (y = (iy1+1); y < iy2; y++)
{
float focus;
int vx = xf;
val1 = fractinvf(xf);
val2 = fractf(xf);
focus = (1.0 - fabsf(val1-val2));
val1 += 0.3*focus;
val2 += 0.3*focus;
PLOT(vx, y, val1);
vx++;
PLOT(vx, y, val2);
xf = xf + g;
}
}
}

#else /* XXX: the following functions use the template system */
#undef PLOT

/* Solid line drawing function, using Bresenham's mid-point line
* scan-conversion algorithm. */


Loading…
取消
儲存