1/* 2 * "$Id: dither-impl.h,v 1.32 2008/02/18 14:20:17 rlk Exp $" 3 * 4 * Internal implementation of dither algorithms 5 * 6 * Copyright 1997-2003 Michael Sweet (mike@easysw.com) and 7 * Robert Krawitz (rlk@alum.mit.edu) 8 * 9 * This program is free software; you can redistribute it and/or modify it 10 * under the terms of the GNU General Public License as published by the Free 11 * Software Foundation; either version 2 of the License, or (at your option) 12 * any later version. 13 * 14 * This program is distributed in the hope that it will be useful, but 15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 17 * for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 22 * 23 * Revision History: 24 * 25 * See ChangeLog 26 */ 27 28/* 29 * This file must include only standard C header files. The core code must 30 * compile on generic platforms that don't support glib, gimp, gtk, etc. 31 */ 32 33#ifndef GUTENPRINT_INTERNAL_DITHER_IMPL_H 34#define GUTENPRINT_INTERNAL_DITHER_IMPL_H 35 36#ifdef __cplusplus 37extern "C" { 38#endif 39 40#include <limits.h> 41 42#ifdef __GNUC__ 43#define inline __inline__ 44#endif 45 46#define D_FLOYD_HYBRID 0 47#define D_ADAPTIVE_BASE 4 48#define D_ADAPTIVE_HYBRID (D_ADAPTIVE_BASE | D_FLOYD_HYBRID) 49#define D_ORDERED_BASE 8 50#define D_ORDERED (D_ORDERED_BASE) 51#define D_FAST_BASE 16 52#define D_FAST (D_FAST_BASE) 53#define D_VERY_FAST (D_FAST_BASE + 1) 54#define D_EVENTONE 32 55#define D_UNITONE 64 56#define D_EVENBETTER 128 57#define D_HYBRID_EVENTONE (D_ORDERED_BASE | D_EVENTONE) 58#define D_HYBRID_UNITONE (D_ORDERED_BASE | D_UNITONE) 59#define D_HYBRID_EVENBETTER (D_ORDERED_BASE | D_EVENBETTER) 60#define D_PREDITHERED 256 61#define D_ORDERED_NEW 512 62#define D_ORDERED_SEGMENTED 1024 63#define D_ORDERED_SEGMENTED_NEW (D_ORDERED_SEGMENTED | D_ORDERED_NEW) 64#define D_INVALID -2 65 66#define DITHER_FAST_STEPS (6) 67 68typedef struct 69{ 70 const char *name; 71 const char *text; 72 int id; 73} stpi_dither_algorithm_t; 74 75#define ERROR_ROWS 2 76 77#define MAX_SPREAD 32 78 79typedef void stpi_ditherfunc_t(stp_vars_t *, int, const unsigned short *, int, 80 int, const unsigned char *); 81 82/* 83 * An end of a dither segment, describing one ink 84 */ 85 86typedef struct ink_defn 87{ 88 unsigned range; 89 unsigned value; 90 unsigned bits; 91} stpi_ink_defn_t; 92 93/* 94 * A segment of the entire 0-65535 intensity range. 95 */ 96 97typedef struct dither_segment 98{ 99 stpi_ink_defn_t *lower; 100 stpi_ink_defn_t *upper; 101 unsigned range_span; 102 unsigned value_span; 103 int is_same_ink; 104 int is_equal; 105} stpi_dither_segment_t; 106 107typedef struct dither_channel 108{ 109 unsigned randomizer; /* With Floyd-Steinberg dithering, control */ 110 /* how much randomness is applied to the */ 111 /* threshold values (0-65535). */ 112 unsigned bit_max; 113 unsigned signif_bits; 114 unsigned density; 115 double darkness; /* Relative darkness of this ink */ 116 117 int v; 118 int o; 119 int b; 120 int very_fast; 121 122 stpi_ink_defn_t *ink_list; 123 124 int nlevels; 125 stpi_dither_segment_t *ranges; 126 127 int error_rows; 128 int **errs; 129 130 stp_dither_matrix_impl_t pick; 131 stp_dither_matrix_impl_t dithermat; 132 int row_ends[2]; 133 unsigned char *ptr; 134 void *aux_data; /* aux_freefunc for dither should free this */ 135} stpi_dither_channel_t; 136 137typedef struct dither 138{ 139 int src_width; /* Input width */ 140 int dst_width; /* Output width */ 141 142 int spread; /* With Floyd-Steinberg, how widely the */ 143 int spread_mask; /* error is distributed. This should be */ 144 /* between 12 (very broad distribution) and */ 145 /* 19 (very narrow) */ 146 147 int stpi_dither_type; 148 149 int adaptive_limit; 150 151 int x_aspect; /* Aspect ratio numerator */ 152 int y_aspect; /* Aspect ratio denominator */ 153 154 155 int *offset0_table; 156 int *offset1_table; 157 158 int d_cutoff; 159 160 int last_line_was_empty; 161 int ptr_offset; 162 int error_rows; 163 164 int finalized; /* When dither is first called, calculate 165 * some things */ 166 167 stp_dither_matrix_impl_t dither_matrix; 168 stpi_dither_channel_t *channel; 169 unsigned channel_count; 170 unsigned total_channel_count; 171 unsigned *channel_index; 172 unsigned *subchannel_count; 173 174 stpi_ditherfunc_t *ditherfunc; 175 void *aux_data; 176 void (*aux_freefunc)(struct dither *); 177} stpi_dither_t; 178 179#define CHANNEL(d, c) ((d)->channel[(c)]) 180#define CHANNEL_COUNT(d) ((d)->total_channel_count) 181 182#define USMIN(a, b) ((a) < (b) ? (a) : (b)) 183 184 185extern stpi_ditherfunc_t stpi_dither_predithered; 186extern stpi_ditherfunc_t stpi_dither_very_fast; 187extern stpi_ditherfunc_t stpi_dither_ordered; 188extern stpi_ditherfunc_t stpi_dither_ed; 189extern stpi_ditherfunc_t stpi_dither_et; 190extern stpi_ditherfunc_t stpi_dither_ut; 191 192extern void stpi_dither_reverse_row_ends(stpi_dither_t *d); 193extern int stpi_dither_translate_channel(stp_vars_t *v, unsigned channel, 194 unsigned subchannel); 195extern void stpi_dither_channel_destroy(stpi_dither_channel_t *channel); 196extern void stpi_dither_finalize(stp_vars_t *v); 197extern int *stpi_dither_get_errline(stpi_dither_t *d, int row, int color); 198 199 200#define ADVANCE_UNIDIRECTIONAL(d, bit, input, width, xerror, xstep, xmod) \ 201do \ 202{ \ 203 bit >>= 1; \ 204 if (bit == 0) \ 205 { \ 206 d->ptr_offset++; \ 207 bit = 128; \ 208 } \ 209 input += xstep; \ 210 if (xmod) \ 211 { \ 212 xerror += xmod; \ 213 if (xerror >= d->dst_width) \ 214 { \ 215 xerror -= d->dst_width; \ 216 input += (width); \ 217 } \ 218 } \ 219} while (0) 220 221#define ADVANCE_REVERSE(d, bit, input, width, xerror, xstep, xmod) \ 222do \ 223{ \ 224 if (bit == 128) \ 225 { \ 226 d->ptr_offset--; \ 227 bit = 1; \ 228 } \ 229 else \ 230 bit <<= 1; \ 231 input -= xstep; \ 232 if (xmod) \ 233 { \ 234 xerror -= xmod; \ 235 if (xerror < 0) \ 236 { \ 237 xerror += d->dst_width; \ 238 input -= (width); \ 239 } \ 240 } \ 241} while (0) 242 243#define ADVANCE_BIDIRECTIONAL(d,bit,in,dir,width,xer,xstep,xmod,err,S) \ 244do \ 245{ \ 246 int ii; \ 247 int jj; \ 248 for (ii = 0; ii < width; ii++) \ 249 for (jj = 0; jj < S; jj++) \ 250 err[ii][jj] += dir; \ 251 if (dir == 1) \ 252 ADVANCE_UNIDIRECTIONAL(d, bit, in, width, xer, xstep, xmod); \ 253 else \ 254 ADVANCE_REVERSE(d, bit, in, width, xer, xstep, xmod); \ 255} while (0) 256 257#ifdef __cplusplus 258 } 259#endif 260 261#endif /* GUTENPRINT_INTERNAL_DITHER_IMPL_H */ 262/* 263 * End of "$Id: dither-impl.h,v 1.32 2008/02/18 14:20:17 rlk Exp $". 264 */ 265