diff options
author | kraxel <kraxel> | 2004-03-28 11:31:57 +0000 |
---|---|---|
committer | kraxel <kraxel> | 2004-03-28 11:31:57 +0000 |
commit | e9e9684117719204929821028ba9dbb7915ea119 (patch) | |
tree | 6dd2d71940b33a9f960945335e9124ef4fea9fe7 /dither.c | |
download | fbida-e9e9684117719204929821028ba9dbb7915ea119.tar.gz |
Initial revision
Diffstat (limited to 'dither.c')
-rw-r--r-- | dither.c | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/dither.c b/dither.c new file mode 100644 index 0000000..2eaeb31 --- /dev/null +++ b/dither.c @@ -0,0 +1,193 @@ +/* + * ordered dither rotines + * + * stolen from The GIMP and trimmed for speed + * + */ + +#include <stdlib.h> +#include "dither.h" + +#define DITHER_LEVEL 8 + +void (*dither_line)(unsigned char *, unsigned char *, int, int); + +static long red_mult, green_mult; +static long red_dither[256]; +static long green_dither[256]; +static long blue_dither[256]; +static long gray_dither[256]; + +typedef unsigned long vector[DITHER_LEVEL]; +typedef vector matrix[DITHER_LEVEL]; + +#if DITHER_LEVEL == 8 +#define DITHER_MASK 7 +static matrix DM = +{ + {0, 32, 8, 40, 2, 34, 10, 42}, + {48, 16, 56, 24, 50, 18, 58, 26}, + {12, 44, 4, 36, 14, 46, 6, 38}, + {60, 28, 52, 20, 62, 30, 54, 22}, + {3, 35, 11, 43, 1, 33, 9, 41}, + {51, 19, 59, 27, 49, 17, 57, 25}, + {15, 47, 7, 39, 13, 45, 5, 37}, + {63, 31, 55, 23, 61, 29, 53, 21} +}; + +#endif + +#if DITHER_LEVEL == 4 +#define DITHER_MASK 3 +static matrix DM = +{ + {0, 8, 2, 10}, + {12, 4, 14, 6}, + {3, 11, 1, 9}, + {15, 7, 13, 5} +}; + +#endif + +void +init_dither(int shades_r, int shades_g, int shades_b, int shades_gray) +{ + int i, j; + unsigned char low_shade, high_shade; + unsigned short index; + float red_colors_per_shade; + float green_colors_per_shade; + float blue_colors_per_shade; + float gray_colors_per_shade; + + red_mult = shades_g * shades_b; + green_mult = shades_b; + + red_colors_per_shade = 256.0 / (shades_r - 1); + green_colors_per_shade = 256.0 / (shades_g - 1); + blue_colors_per_shade = 256.0 / (shades_b - 1); + gray_colors_per_shade = 256.0 / (shades_gray - 1); + + /* this avoids a shift when checking these values */ + for (i = 0; i < DITHER_LEVEL; i++) + for (j = 0; j < DITHER_LEVEL; j++) + DM[i][j] *= 0x10000; + + /* setup arrays containing three bytes of information for red, green, & blue */ + /* the arrays contain : + * 1st byte: low end shade value + * 2nd byte: high end shade value + * 3rd & 4th bytes: ordered dither matrix index + */ + + for (i = 0; i < 256; i++) { + + /* setup the red information */ + { + low_shade = (unsigned char) (i / red_colors_per_shade); + high_shade = low_shade + 1; + + index = (unsigned short) + (((i - low_shade * red_colors_per_shade) / red_colors_per_shade) * + (DITHER_LEVEL * DITHER_LEVEL + 1)); + + low_shade *= red_mult; + high_shade *= red_mult; + + red_dither[i] = (index << 16) + (high_shade << 8) + (low_shade); + } + + /* setup the green information */ + { + low_shade = (unsigned char) (i / green_colors_per_shade); + high_shade = low_shade + 1; + + index = (unsigned short) + (((i - low_shade * green_colors_per_shade) / green_colors_per_shade) * + (DITHER_LEVEL * DITHER_LEVEL + 1)); + + low_shade *= green_mult; + high_shade *= green_mult; + + green_dither[i] = (index << 16) + (high_shade << 8) + (low_shade); + } + + /* setup the blue information */ + { + low_shade = (unsigned char) (i / blue_colors_per_shade); + high_shade = low_shade + 1; + + index = (unsigned short) + (((i - low_shade * blue_colors_per_shade) / blue_colors_per_shade) * + (DITHER_LEVEL * DITHER_LEVEL + 1)); + + blue_dither[i] = (index << 16) + (high_shade << 8) + (low_shade); + } + + /* setup the gray information */ + { + low_shade = (unsigned char) (i / gray_colors_per_shade); + high_shade = low_shade + 1; + + index = (unsigned short) + (((i - low_shade * gray_colors_per_shade) / gray_colors_per_shade) * + (DITHER_LEVEL * DITHER_LEVEL + 1)); + + gray_dither[i] = (index << 16) + (high_shade << 8) + (low_shade); + } + } +} + +void +dither_line_color(unsigned char *src, unsigned char *dest, int y, int width) +{ + register long a, b; + long *ymod, xmod; + + ymod = DM[y & DITHER_MASK]; + + while (width--) { + xmod = width & DITHER_MASK; + + b = red_dither[*(src++)]; + if (ymod[xmod] < b) + b >>= 8; + + a = green_dither[*(src++)]; + if (ymod[xmod] < a) + a >>= 8; + b += a; + + a = blue_dither[*(src++)]; + if (ymod[xmod] < a) + a >>= 8; + b += a; + + *(dest++) = b & 0xff; + } +} + +void +dither_line_gray(unsigned char *src, unsigned char *dest, int y, int width) +{ + long *ymod, xmod; + register long a,g; + + ymod = DM[y & DITHER_MASK]; + + while (width--) { + xmod = width & DITHER_MASK; + +#if 1 + g = (src[0]*3 + src[1]*6 + src[2]) / 10; + a = gray_dither[g]; + src += 3; +#else + a = gray_dither[*(src++)]; +#endif + if (ymod[xmod] < a) + a >>= 8; + + *(dest++) = a & 0xff; + } +} |