#ifndef GIMP_PRINT_INTERNAL_DITHER_IMPL_H
#define GIMP_PRINT_INTERNAL_DITHER_IMPL_H
#ifdef __cplusplus
extern "C" {
#endif
#include <limits.h>
#ifdef __GNUC__
#define inline __inline__
#endif
#define D_FLOYD_HYBRID 0
#define D_ADAPTIVE_BASE 4
#define D_ADAPTIVE_HYBRID (D_ADAPTIVE_BASE | D_FLOYD_HYBRID)
#define D_ORDERED_BASE 8
#define D_ORDERED (D_ORDERED_BASE)
#define D_FAST_BASE 16
#define D_FAST (D_FAST_BASE)
#define D_VERY_FAST (D_FAST_BASE + 1)
#define D_EVENTONE 32
#define D_UNITONE 64
#define D_HYBRID_EVENTONE (D_ORDERED_BASE | D_EVENTONE)
#define D_HYBRID_UNITONE (D_ORDERED_BASE | D_UNITONE)
#define D_PREDITHERED 128
#define DITHER_FAST_STEPS (6)
typedef struct
{
const char *name;
const char *text;
int id;
} stpi_dither_algorithm_t;
#define ERROR_ROWS 2
#define MAX_SPREAD 32
typedef void stpi_ditherfunc_t(stp_vars_t *, int, const unsigned short *, int,
int, const unsigned char *);
typedef struct ink_defn
{
unsigned range;
unsigned value;
unsigned bits;
} stpi_ink_defn_t;
typedef struct dither_segment
{
stpi_ink_defn_t *lower;
stpi_ink_defn_t *upper;
unsigned range_span;
unsigned value_span;
int is_same_ink;
int is_equal;
} stpi_dither_segment_t;
typedef struct dither_channel
{
unsigned randomizer;
unsigned bit_max;
unsigned signif_bits;
unsigned density;
double darkness;
int v;
int o;
int b;
int very_fast;
stpi_ink_defn_t *ink_list;
int nlevels;
stpi_dither_segment_t *ranges;
int error_rows;
int **errs;
stp_dither_matrix_impl_t pick;
stp_dither_matrix_impl_t dithermat;
int row_ends[2];
unsigned char *ptr;
void *aux_data;
} stpi_dither_channel_t;
typedef struct dither
{
int src_width;
int dst_width;
int spread;
int spread_mask;
int stpi_dither_type;
int adaptive_limit;
int x_aspect;
int y_aspect;
double transition;
int *offset0_table;
int *offset1_table;
int d_cutoff;
int last_line_was_empty;
int ptr_offset;
int error_rows;
int finalized;
stp_dither_matrix_impl_t dither_matrix;
stp_dither_matrix_impl_t transition_matrix;
stpi_dither_channel_t *channel;
unsigned channel_count;
unsigned total_channel_count;
unsigned *channel_index;
unsigned *subchannel_count;
stpi_ditherfunc_t *ditherfunc;
void *aux_data;
void (*aux_freefunc)(struct dither *);
} stpi_dither_t;
#define CHANNEL(d, c) ((d)->channel[(c)])
#define CHANNEL_COUNT(d) ((d)->total_channel_count)
#define USMIN(a, b) ((a) < (b) ? (a) : (b))
extern stpi_ditherfunc_t stpi_dither_predithered;
extern stpi_ditherfunc_t stpi_dither_very_fast;
extern stpi_ditherfunc_t stpi_dither_ordered;
extern stpi_ditherfunc_t stpi_dither_ed;
extern stpi_ditherfunc_t stpi_dither_et;
extern stpi_ditherfunc_t stpi_dither_ut;
extern void stpi_dither_reverse_row_ends(stpi_dither_t *d);
extern int stpi_dither_translate_channel(stp_vars_t *v, unsigned channel,
unsigned subchannel);
extern void stpi_dither_channel_destroy(stpi_dither_channel_t *channel);
extern void stpi_dither_finalize(stp_vars_t *v);
extern int *stpi_dither_get_errline(stpi_dither_t *d, int row, int color);
#define ADVANCE_UNIDIRECTIONAL(d, bit, input, width, xerror, xstep, xmod) \
do \
{ \
bit >>= 1; \
if (bit == 0) \
{ \
d->ptr_offset++; \
bit = 128; \
} \
input += xstep; \
if (xmod) \
{ \
xerror += xmod; \
if (xerror >= d->dst_width) \
{ \
xerror -= d->dst_width; \
input += (width); \
} \
} \
} while (0)
#define ADVANCE_REVERSE(d, bit, input, width, xerror, xstep, xmod) \
do \
{ \
if (bit == 128) \
{ \
d->ptr_offset--; \
bit = 1; \
} \
else \
bit <<= 1; \
input -= xstep; \
if (xmod) \
{ \
xerror -= xmod; \
if (xerror < 0) \
{ \
xerror += d->dst_width; \
input -= (width); \
} \
} \
} while (0)
#define ADVANCE_BIDIRECTIONAL(d,bit,in,dir,width,xer,xstep,xmod,err,S) \
do \
{ \
int ii; \
int jj; \
for (ii = 0; ii < width; ii++) \
for (jj = 0; jj < S; jj++) \
err[ii][jj] += dir; \
if (dir == 1) \
ADVANCE_UNIDIRECTIONAL(d, bit, in, width, xer, xstep, xmod); \
else \
ADVANCE_REVERSE(d, bit, in, width, xer, xstep, xmod); \
} while (0)
#ifdef __cplusplus
}
#endif
#endif