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

buffer_8bits.h

/*
 *  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/>.
 */

#ifndef __BINIOU_BUFFER_8BITS_H
#define __BINIOU_BUFFER_8BITS_H

#include "utils.h"
#include "constants.h"
#include "point2d.h"


/**
 * \typedef Pixel_t
 * \brief A pixel (color index in a RGBA colormap)
 */
typedef u_char Pixel_t;

00034 typedef struct Line_s {
  short x1;
  short y1;
  short x2;
  short y2;
} Line_t;

/* Alias */
00042 typedef struct Buffer8_s {
  Pixel_t *buffer;
} Buffer8_t;


Buffer8_t *Buffer8_new(void);
void Buffer8_delete(Buffer8_t *);


/* Pixel operations */
static inline Pixel_t
get_pixel_nc(const Buffer8_t *buf, const short x, const short y)
{
#ifndef UNSAFE
#ifdef DEBUG
  /*  if ((x < MINX) || (y < MINY) || (x > MAXX) || (y > MAXY)) { */
  if (!((unsigned)(x-MINX) < (WIDTH-MINX)) || !((unsigned)(y-MINY) < (HEIGHT-MINY))) {
    printf("[!] want to get_pixel_nc(%d, %d)\n", x, y);
#ifdef XDEBUG
    exit(1);
#else
    return 0;
#endif /* XDEBUG */
  }
#endif /* DEBUG */
#endif /* !UNSAFE */

  return buf->buffer[y*WIDTH+x];
}


static inline void
set_pixel_nc(Buffer8_t *buf, const short x, const short y, const Pixel_t col)
{
#ifndef UNSAFE
#ifdef DEBUG
  /* if ((x < MINX) || (y < MINY) || (x > MAXX) || (y > MAXY)) { */
  if (!((unsigned)(x-MINX) < (WIDTH-MINX)) || !((unsigned)(y-MINY) < (HEIGHT-MINY))) {
    printf("[!] want to set_pixel_nc(%d, %d, %d)\n", x, y, col);
#ifdef XDEBUG
    exit(1);
#else
    return;
#endif /* XDEBUG */
  }
#endif /* DEBUG */
#endif /* !UNSAFE */

  buf->buffer[y*WIDTH+x] = col;
}


static inline void
neg_pixel_nc(Buffer8_t *buf, const short x, const short y)
{
#ifndef UNSAFE
#ifdef DEBUG
  /* if ((x < MINX) || (y < MINY) || (x > MAXX) || (y > MAXY)) { */
  if (!((unsigned)(x-MINX) < (WIDTH-MINX)) || !((unsigned)(y-MINY) < (HEIGHT-MINY))) {
    printf("[!] want to neg_pixel_nc(%d, %d)\n", x, y);
#ifdef XDEBUG
    exit(1);
#else
    return;
#endif /* XDEBUG */
  }
#endif /* DEBUG */
#endif /* !UNSAFE */ 

  buf->buffer[y*WIDTH+x] = (Pixel_t)(255-buf->buffer[y*WIDTH+x]);
}


static inline Pixel_t
get_pixel(const Buffer8_t *buff, const short x, const short y)
{
  /* if ((x>=MINX) && (x<=MAXX) && (y>=MINY) && (y<=MAXY)) */
  if (((unsigned)(x-MINX) < (WIDTH-MINX)) && ((unsigned)(y-MINY) < (HEIGHT-MINY)))
    return get_pixel_nc(buff, x, y);
  else
    return 0;
}


static inline void
set_pixel(Buffer8_t *buff, const short x, const short y, const Pixel_t col) 
{
  /* if ((x>=MINX) && (x<=MAXX) && (y>=MINY) && (y<=MAXY)) */
  if (((unsigned)(x-MINX) < (WIDTH-MINX)) && ((unsigned)(y-MINY) < (HEIGHT-MINY)))
    set_pixel_nc(buff, x, y, col);
}


static inline void
neg_pixel(Buffer8_t *buff, const short x, const short y)
{
  /* if ((x>=MINX) && (x<=MAXX) && (y>=MINY) && (y<=MAXY)) */
  if (((unsigned)(x-MINX) < (WIDTH-MINX)) && ((unsigned)(y-MINY) < (HEIGHT-MINY)))
    neg_pixel_nc(buff, x, y);
}


/* Line operations */
static inline void
h_line_nc(Buffer8_t *buff, const short lig, const short start, const short end, const Pixel_t c)
{
#if 1
  int s, e, n;

  assert(lig >= MINY);
  assert(lig <= MAXY);
  assert(start >= MINX);
  assert(start <= MAXX);
  assert(end >= MINX);
  assert(end <= MAXX);

  if (start <= end) {
    s = start;
    e = end;
  } else {
    s = end;
    e = start;
  }

  n = e-s+1;
  memset((void *)&buff->buffer[lig*WIDTH+s], (int)c, n*sizeof(Pixel_t));
#else
  short i;

  for (i = start; i <= end; i++)
    set_pixel_nc(buff, i, lig, c);
#endif
}


static inline void
h_line(Buffer8_t *buff, const short lig, const short start, const short end, const Pixel_t c) 
{
#if 1
  int s, e, n;

  assert(lig >= MINY);
  assert(lig <= MAXY);
  assert(start >= MINX);
  assert(start <= MAXX);
  assert(end >= MINX);
  assert(end <= MAXX);

  if (start <= end) {
    s = start;
    e = end;
  } else {
    s = end;
    e = start;
  }

  n = e-s+1;
  memset((void *)&buff->buffer[lig*WIDTH+s], (int)c, n*sizeof(Pixel_t));
#else
  short i;

  for (i = start; i <= end; i++)
    set_pixel(buff, i, lig, c);
#endif
}


static inline void
v_line_nc(Buffer8_t *buff, const short col, const short start, const short end, const Pixel_t c) 
{
  short s, e, j;

  if (start <= end) {
    s = start;
    e = end;
  } else {
    s = end;
    e = start;
  }

  for (j = s; j <= e; j++)
    set_pixel_nc(buff, col, j, c);
}


static inline void
v_line(Buffer8_t *buff, const short col, const short start, const short end, const Pixel_t c) 
{
  short s, e, j;

  if (start <= end) {
    s = start;
    e = end;
  } else {
    s = end;
    e = start;
  }

  for (j = s; j <= e; j++)
    set_pixel(buff, col, j, c);
}


static inline void
Buffer8_clear(Buffer8_t *buff)
{
  memset(buff->buffer, 0, BUFFSIZE*sizeof(Pixel_t));
}


static inline void
Buffer8_clear_border(Buffer8_t *buff)
{
  h_line_nc(buff, 0, 0, MAXX, 0);
  h_line_nc(buff, MAXY, 0, MAXX, 0);
  v_line_nc(buff, 0, 0, MAXY, 0);
  v_line_nc(buff, MAXX, 0, MAXY, 0);
}


static inline void
Buffer8_copy(const Buffer8_t *from, Buffer8_t *to) 
{
  memcpy(to->buffer, from->buffer, BUFFSIZE*sizeof(Pixel_t));
}


static inline void
Buffer8_add(const Buffer8_t *from, Buffer8_t *to, const Pixel_t min)
{
  u_long i;
  for (i = 0; i < BUFFSIZE*sizeof(Pixel_t); i++)
    if (from->buffer[i] > min)
      to->buffer[i] = from->buffer[i];
}


void
Buffer8_color_bar(Buffer8_t *, const u_short);

static inline void
swap(short *a, short *b)
{
  short t;

  t = *a;
  *a = *b;
  *b = t;
}


static inline void
draw_box(Buffer8_t *buff, short x1, short y1, short x2, short y2, const Pixel_t c)
{
  if (x1 < 0) x1 = 0;
  else if (x1 > MAXX) x1 = MAXX;

  if (x2 < 0) x2 = 0;
  else if (x2 > MAXX) x2 = MAXX;

  if (y1 < 0) y1 = 0;
  else if (y1 > MAXY) y1 = MAXY;

  if (y2 < 0) y2 = 0;
  else if (y2 > MAXY) y2 = MAXY;

  if (x1 > x2) swap(&x1, &x2);
  if (y1 > y2) swap(&y1, &y2);

  h_line(buff, y1, x1, x2, c);
  h_line(buff, y2, x1, x2, c);
  v_line(buff, x1, y1, y2, c);
  v_line(buff, x2, y1, y2, c);
}


static inline void
draw_box_nc(Buffer8_t *buff, short x1, short y1, short x2, short y2, const Pixel_t c)
{
  if (x1 > x2) swap(&x1, &x2);
  if (y1 > y2) swap(&y1, &y2);

  h_line_nc(buff, y1, x1, x2, c);
  h_line_nc(buff, y2, x1, x2, c);
  v_line_nc(buff, x1, y1, y2, c);
  v_line_nc(buff, x2, y1, y2, c);
}


static inline void
draw_filled_box(Buffer8_t *b, short x1, short y1, short x2, short y2, const Pixel_t c)
{
  short j;

  if (x1 > x2) swap(&x1, &x2);
  if (y1 > y2) swap(&y1, &y2);

  for (j = y1; j <= y2; j++)
    h_line(b, j, x1, x2, c);
}


static inline void
draw_filled_box_nc(Buffer8_t *b, short x1, short y1, short x2, short y2, const Pixel_t c)
{
  short j;

  if (x1 > x2) swap(&x1, &x2);
  if (y1 > y2) swap(&y1, &y2);

  for (j = y1; j <= y2; j++)
    h_line_nc(b, j, x1, x2, c);
}



/* Kohen-Sutherland clipping */
#define KS_LEFT  0x01
#define KS_RIGHT 0x02
#define KS_ABOVE 0x04
#define KS_BELOW 0x08


static inline void
ks_region(short *reg, const short x, const short y)
{
  *reg = 0;
  
  if (x > MAXX)
    *reg |= KS_RIGHT;
  else if (x < MINX)
    *reg |= KS_LEFT;
      
  if (y > MAXY)
    *reg |= KS_ABOVE;
  else if (y < MINY)
    *reg |= KS_BELOW;
}


u_char ks_clip_line(short *, Point2d_t *, Point2d_t *, Point2d_t *, Point2d_t *);
void draw_line(Buffer8_t *, short, short, short, short, const Pixel_t);
void draw(Buffer8_t *, const Line_t *, const Pixel_t);


static inline void
Buffer8_init_mask_3x3(Buffer8_t *buff)
{
  short i , j;
  
  for (i = 1; i < MAXX; i++) {
    /* copy hor bottom */
    set_pixel_nc(buff, i, 0, get_pixel_nc(buff, i, MAXY - 1));
    /* copy hor top */
    set_pixel_nc(buff, i, MAXY, get_pixel_nc(buff, i, 1));
  }
  
  for (j = 1; j < MAXY; j++) {
    /* copy ver right */
    set_pixel_nc(buff, 0, j, get_pixel_nc(buff, MAXX - 1, j));
    /* copy ver left */
    set_pixel_nc(buff, MAXX, j, get_pixel_nc(buff, 1, j));
  }
  
  /* copy 4 corners */
  set_pixel_nc(buff, 0, 0, get_pixel_nc(buff, MAXX - 1, MAXY - 1));
  set_pixel_nc(buff, MAXX, 0, get_pixel_nc(buff, 1, MAXY - 1));
  set_pixel_nc(buff, 0, MAXY, get_pixel_nc(buff, MAXX - 1, 1));
  set_pixel_nc(buff, MAXX, MAXY, get_pixel_nc(buff, 1, 1));
}


static inline void
Buffer8_expand_border(Buffer8_t *buff)
{
  short i, j;

  /* ok we cheat a little little little bit to save 4 annoying corner pixels:
   * horizontally we set from MINX to MAXX
   * vertically we set from MINY+1 to MAXY-1
   */

  /* set bottom and top lines */
  /* we use +-2 since most blurs only act within that range */
  for (i = MINX; i <= MAXX; i++) {
    Pixel_t sum = (Pixel_t)((get_pixel_nc(buff, i, MINY+2)
                              + get_pixel_nc(buff, i, MAXY-2)) >> 1);
    set_pixel_nc(buff, i, MINY, sum);
    set_pixel_nc(buff, i, MAXY, sum);
  }
      
  /* set left and right */
  for (j = MINY+1; j < MAXY; j++) {
    Pixel_t sum = (Pixel_t)((get_pixel_nc(buff, MINX+2, j)
                              + get_pixel_nc(buff, MAXX-2, j)) >> 1);
    set_pixel_nc(buff, MINX, j, sum);
    set_pixel_nc(buff, MAXX, j, sum);
  }
}

/* TODO mix(s1, s2, C) => s1' = s1*C+s2*(1-C) 
   void Buffer8_mix_weighted(const Buffer8_t *, const Buffer8_t *, const float); */

void Buffer8_mix_interlaced2(Buffer8_t *, const Buffer8_t *); /* TODO find a better name */
void Buffer8_mix_random(Buffer8_t *, const Buffer8_t *);

void Buffer8_randomize(Buffer8_t *);

void Buffer8_overlay(Buffer8_t *, const Buffer8_t *);
void Buffer8_XOR(Buffer8_t *, const Buffer8_t *);
void Buffer8_average(Buffer8_t *, const Buffer8_t *);


static inline void
Buffer8_flip_x(Buffer8_t *buff)
{
  u_short j;

  for (j = 0; j < HHEIGHT; j++) {
    Pixel_t tmp[WIDTH];
    
    memcpy(tmp, &buff->buffer[j*WIDTH], WIDTH * sizeof(Pixel_t));
    memcpy(&buff->buffer[j*WIDTH], &buff->buffer[(MAXY-j)*WIDTH], WIDTH * sizeof(Pixel_t));
    memcpy(&buff->buffer[(MAXY-j)*WIDTH], tmp, WIDTH * sizeof(Pixel_t));
  }
}

#endif /* __BINIOU_BUFFER_8BITS_H */

Generated by  Doxygen 1.6.0   Back to index