Logo Search packages:      
Sourcecode: lebiniou version File versions  Download package

buffer_8bits.c

/*
 *  Copyright 1994-2011 Olivier Girondel
 *
 *  This file is part of lebiniou.
 *
 *  lebiniou is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  lebiniou is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with lebiniou. If not, see <http://www.gnu.org/licenses/>.
 */

#include "buffer_8bits.h"
#include "brandom.h"

/* TODO: Cleanup, remove XXDEBUG code when we are sure draw_line is ok */

/*!
 * \brief Create a pixel buffer
 */
Buffer8_t *
Buffer8_new()
{
  Buffer8_t *buff = xcalloc(1, sizeof(Buffer8_t));
  buff->buffer = xcalloc(BUFFSIZE, sizeof(Pixel_t));

  return buff;
}


void
Buffer8_delete(Buffer8_t *buff)
{
  xfree(buff->buffer);
  xfree(buff);
}


inline u_char
ks_clip_line(short *exists, Point2d_t *p0, Point2d_t *q0, Point2d_t *p, Point2d_t *q)
{
  short x1 = (short)p->x, x2 = (short)q->x, y1 = (short)p->y, y2 = (short)q->y;
  short reg1, reg2;
  short outside = 0;
  *exists = 1;
  
  ks_region(&reg1, x1, y1);
  ks_region(&reg2, x2, y2);
  
  if (reg1)
    ++outside;
  if (reg2)
    ++outside;
  
  if (!outside)
    return 0;
  
  while (reg1 | reg2) {
    if (reg1 & reg2) {
      *exists = 0;
      return 1;
    }
    
    if (!reg1) {
      swap(&reg1, &reg2);
      swap(&x1, &x2);
      swap(&y1, &y2);
    }
    
    if (reg1 & KS_LEFT) {
      y1 += (short)(((y2-y1)*(MINX-x1))/(float)(x2-x1));
      x1 = MINX;
    } else if (reg1 & KS_RIGHT) {
      y1 += (short)(((y2-y1)*(MAXX-x1))/(float)(x2-x1));
      x1 = MAXX;
    } else if (reg1 & KS_ABOVE) {
      x1 += (short)(((x2-x1)*(MAXY-y1))/(float)(y2-y1));
      y1 = MAXY;
    } else if (reg1 & KS_BELOW) {
      x1 += (short)(((x2-x1)*(MINY-y1))/(float)(y2-y1));
      y1 = MINY;
    }
            
    ks_region(&reg1, x1, y1);
  }
  
  p0->x = x1; 
  p0->y = y1; 
  q0->x = x2; 
  q0->y = y2;
  
  return 1;
}


void
draw_line(Buffer8_t *buff, short x1, short y1, short x2, short y2, const Pixel_t c)
{
  short exists = 0;
  Point2d_t p, q, p0, q0;
  short dx, dy, mod;
  char  sgn_dy;

#ifdef XXDEBUG
  printf("oOo draw_line: (%d, %d) -> (%d, %d)\n", x1, y1, x2, y2);
#endif

  if ((x1 == x2) && (y1 == y2)) {
#ifdef XXDEBUG
    printf("(1) set_pixel_nc(%d, %d)\n", x1, y1);
#endif
    set_pixel(buff, x1, y1, c);
    return;
  };
      
  p.x = x1; p.y = y1;
  q.x = x2; q.y = y2;

  if (!ks_clip_line (&exists, &p0, &q0, &p, &q)) {
#ifdef XXDEBUG
    printf ("inside\n");
#endif
  } else if (exists) {
#ifdef XXDEBUG
    printf ("clipping (%d, %d) (%d, %d)\t=> ", x1, y1, x2, y2);
#endif

    x1 = (short)q0.x;
    y1 = (short)q0.y;
    x2 = (short)p0.x;
    y2 = (short)p0.y;
#ifdef XXDEBUG
    printf ("clipped (%d, %d) (%d, %d)\n", x1, y1, x2, y2);
#endif
  } else {
#ifdef XXDEBUG
    printf ("outside\n");
#endif
    return;
  }
      
#ifdef XDEBUG
  if ((x1 < MINX) || (x1 > MAXX) || (y1 < MINY) || (y1 > MAXY)
      || (x2 < MINX) || (x2 > MAXX) || (y2 < MINY) || (y2 > MAXY))
    assert(0); /* xerror("draw_line\n"); */
#endif
      
  /* Bresenham Algorithm */
  if (x1 > x2) {
    swap(&x1, &x2);
    swap(&y1, &y2);
  }
  
  dx = x2 - x1;
  
  if (y2 > y1) {
    dy = y2 - y1;
    sgn_dy = 1;
  } else {
    dy = y1 - y2;
    sgn_dy = -1;
  }
      
  if (dy <= dx) {
    for (mod = -((dx + 1) >> 1); ; x1++, mod += dy) {
      if (mod >/*=*/ 0)
      y1 += sgn_dy, mod -= dx;

#ifdef XXDEBUG
      printf("(2) set_pixel_nc(%d, %d)... ", x1, y1);
      fflush(stdout);
#endif
      set_pixel_nc(buff, x1, y1, c);
#ifdef XXDEBUG
      printf("done\n");
#endif
      
      if (x1 == x2)
      return;
    }
  } else {
    for (mod = -((dy + 1) >> 1); ; y1 += sgn_dy, mod += dx) {
      if (mod >/*=*/ 0)
      x1++, mod -= dy;
                  
#ifdef XXDEBUG
      printf("(3) set_pixel_nc(%d, %d)... ", x1, y1);
      fflush(stdout);
#endif
      set_pixel_nc(buff, x1, y1, c);
#ifdef XXDEBUG
      printf("done\n");
#endif                  

      if (y1 == y2)
      return;
    }
  }
}


void
draw(Buffer8_t *buff, const Line_t *l, const Pixel_t c)
{
  draw_line(buff, l->x1, l->y1, l->x2, l->y2, c);
}


void
Buffer8_color_bar(Buffer8_t *buff, const u_short height)
{
  int i;

  for (i = 0; i < WIDTH; i++) {
    Pixel_t color = (Pixel_t)((float)i / (float)WIDTH * 255.0);
    draw_line(buff, i, 0, i, height, color);
  }
}


void
Buffer8_mix_interlaced2(Buffer8_t *s1, const Buffer8_t *s2)
{
  /* copy half of s2 into s1 */
  Pixel_t *d = s1->buffer;
  Pixel_t *s = (Pixel_t *)s2->buffer;

  for (; d < s1->buffer + BUFFSIZE*sizeof(Pixel_t); d += 2, s += 2)
    *d = *s;
}


void
Buffer8_mix_random(Buffer8_t *s1, const Buffer8_t *s2)
{
  /* copy half of s2 into s1 with random probability */
  Pixel_t *d = s1->buffer;
  Pixel_t *s = (Pixel_t *)s2->buffer;

  for ( ; d < s1->buffer + BUFFSIZE*sizeof(Pixel_t); d++, s++)
    if (b_rand_boolean())
      *d = *s;
}


void
Buffer8_randomize(Buffer8_t *buff)
{
  Pixel_t *p = buff->buffer;

  for ( ; p < buff->buffer + BUFFSIZE*sizeof(Pixel_t); p++)
    *p = b_rand_int_range(0, 255);
}


void
Buffer8_overlay(Buffer8_t *s1, const Buffer8_t *s2)
{
  /* Take pixels from s2 if they are != 0 */
  Pixel_t *d = s1->buffer;
  Pixel_t *s = (Pixel_t *)s2->buffer;

  for ( ; d < s1->buffer + BUFFSIZE*sizeof(Pixel_t); d++, s++)
    *d = (Pixel_t)((*s) ? *s : *d);
}


void
Buffer8_XOR(Buffer8_t *s1, const Buffer8_t *s2)
{
  /* XOR pixels from s2 with pixels from s1 */
  Pixel_t *d = s1->buffer;
  Pixel_t *s = (Pixel_t *)s2->buffer;

  for ( ; d < s1->buffer + BUFFSIZE*sizeof(Pixel_t); d++, s++)
    *d ^= *s;
}


void
Buffer8_average(Buffer8_t *s1, const Buffer8_t *s2)
{
  /* mix pixels from s2 with pixels from s1 */
  Pixel_t *d = s1->buffer;
  Pixel_t *s = (Pixel_t *)s2->buffer;

  for ( ; d < s1->buffer + BUFFSIZE*sizeof(Pixel_t); d++, s++)
    *d = (Pixel_t)((u_short)*d + (u_short)*s) >> 1;
}

Generated by  Doxygen 1.6.0   Back to index