1/* 2 * "$Id: dither-predithered.c,v 1.3 2005/07/28 01:00:51 rlk 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 bit, int length) 40{ 41 int i, j; 42 unsigned char *tptr = dc->ptr + d->ptr_offset; 43 44 /* 45 * Lay down all of the bits in the pixel. 46 */ 47 set_row_ends(dc, x); 48 for (i = 0, j = 1; i < dc->signif_bits; i++, j += j, tptr += length) 49 { 50 if (j & val) 51 tptr[0] |= bit; 52 } 53} 54 55void 56stpi_dither_predithered(stp_vars_t *v, 57 int row, 58 const unsigned short *raw, 59 int duplicate_line, 60 int zero_mask, 61 const unsigned char *mask) 62{ 63 stpi_dither_t *d = (stpi_dither_t *) stp_get_component_data(v, "Dither"); 64 int x, 65 length; 66 unsigned char bit; 67 int i; 68 int one_bit_only = 1; 69 70 int xerror, xstep, xmod; 71 72 if ((zero_mask & ((1 << CHANNEL_COUNT(d)) - 1)) == 73 ((1 << CHANNEL_COUNT(d)) - 1)) 74 return; 75 76 length = (d->dst_width + 7) / 8; 77 78 bit = 128; 79 xstep = CHANNEL_COUNT(d) * (d->src_width / d->dst_width); 80 xmod = d->src_width % d->dst_width; 81 xerror = 0; 82 83 for (i = 0; i < CHANNEL_COUNT(d); i++) 84 { 85 stpi_dither_channel_t *dc = &(CHANNEL(d, i)); 86 if (dc->signif_bits > 1) 87 { 88 one_bit_only = 0; 89 break; 90 } 91 } 92 if (one_bit_only) 93 { 94 for (x = 0; x < d->dst_width; x ++) 95 { 96 if (!mask || (*(mask + d->ptr_offset) & bit)) 97 { 98 for (i = 0; i < CHANNEL_COUNT(d); i++) 99 { 100 if (raw[i] & 1) 101 { 102 set_row_ends(&(CHANNEL(d, i)), x); 103 CHANNEL(d, i).ptr[d->ptr_offset] |= bit; 104 } 105 } 106 } 107 ADVANCE_UNIDIRECTIONAL(d, bit, raw, CHANNEL_COUNT(d), 108 xerror, xstep, xmod); 109 } 110 } 111 else 112 { 113 for (x = 0; x < d->dst_width; x ++) 114 { 115 if (!mask || (*(mask + d->ptr_offset) & bit)) 116 { 117 for (i = 0; i < CHANNEL_COUNT(d); i++) 118 { 119 if (CHANNEL(d, i).ptr && raw[i]) 120 print_color_very_fast(d, &(CHANNEL(d, i)), raw[i], x, row, 121 bit, length); 122 } 123 } 124 ADVANCE_UNIDIRECTIONAL(d, bit, raw, CHANNEL_COUNT(d), 125 xerror, xstep, xmod); 126 } 127 } 128} 129