1/* 2 * "$Id: dither-very-fast.c,v 1.15 2004/09/17 18:38:20 rleigh Exp $" 3 * 4 * Very fast dither algorithm 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#ifdef HAVE_CONFIG_H 29#include <config.h> 30#endif 31#include <gutenprint/gutenprint.h> 32#include "gutenprint-internal.h" 33#include <gutenprint/gutenprint-intl-internal.h> 34#include "dither-impl.h" 35#include "dither-inlined-functions.h" 36 37static inline void 38print_color_very_fast(const stpi_dither_t *d, stpi_dither_channel_t *dc, 39 int val, int x, int y, unsigned char bit, 40 unsigned bits, int length) 41{ 42 int j; 43 if (bits && val >= ditherpoint(d, &(dc->dithermat), x)) 44 { 45 unsigned char *tptr = dc->ptr + d->ptr_offset; 46 47 /* 48 * Lay down all of the bits in the pixel. 49 */ 50 set_row_ends(dc, x); 51 for (j = 1; j <= bits; j += j, tptr += length) 52 { 53 if (j & bits) 54 tptr[0] |= bit; 55 } 56 } 57} 58 59void 60stpi_dither_very_fast(stp_vars_t *v, 61 int row, 62 const unsigned short *raw, 63 int duplicate_line, 64 int zero_mask, 65 const unsigned char *mask) 66{ 67 stpi_dither_t *d = (stpi_dither_t *) stp_get_component_data(v, "Dither"); 68 int x, 69 length; 70 unsigned char *bit_patterns; 71 unsigned char bit; 72 int i; 73 int one_bit_only = 1; 74 75 int xerror, xstep, xmod; 76 77 if ((zero_mask & ((1 << CHANNEL_COUNT(d)) - 1)) == 78 ((1 << CHANNEL_COUNT(d)) - 1)) 79 return; 80 81 length = (d->dst_width + 7) / 8; 82 83 bit = 128; 84 xstep = CHANNEL_COUNT(d) * (d->src_width / d->dst_width); 85 xmod = d->src_width % d->dst_width; 86 xerror = 0; 87 88 bit_patterns = stp_zalloc(sizeof(unsigned char) * CHANNEL_COUNT(d)); 89 for (i = 0; i < CHANNEL_COUNT(d); i++) 90 { 91 stpi_dither_channel_t *dc = &(CHANNEL(d, i)); 92 if (dc->nlevels > 0) 93 bit_patterns[i] = dc->ranges[dc->nlevels - 1].upper->bits; 94 if (bit_patterns[i] != 1) 95 one_bit_only = 0; 96 } 97 if (one_bit_only) 98 { 99 for (x = 0; x < d->dst_width; x ++) 100 { 101 if (!mask || (*(mask + d->ptr_offset) & bit)) 102 { 103 for (i = 0; i < CHANNEL_COUNT(d); i++) 104 { 105 if (raw[i] && 106 raw[i] >= ditherpoint(d, &(CHANNEL(d, i).dithermat), x)) 107 { 108 set_row_ends(&(CHANNEL(d, i)), x); 109 CHANNEL(d, i).ptr[d->ptr_offset] |= bit; 110 } 111 } 112 } 113 ADVANCE_UNIDIRECTIONAL(d, bit, raw, CHANNEL_COUNT(d), 114 xerror, xstep, xmod); 115 } 116 } 117 else 118 { 119 for (x = 0; x < d->dst_width; x ++) 120 { 121 if (!mask || (*(mask + d->ptr_offset) & bit)) 122 { 123 for (i = 0; i < CHANNEL_COUNT(d); i++) 124 { 125 if (CHANNEL(d, i).ptr && raw[i]) 126 print_color_very_fast(d, &(CHANNEL(d, i)), raw[i], x, row, 127 bit, bit_patterns[i], length); 128 } 129 } 130 ADVANCE_UNIDIRECTIONAL(d, bit, raw, CHANNEL_COUNT(d), 131 xerror, xstep, xmod); 132 } 133 } 134 stp_free(bit_patterns); 135} 136