summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Vrhel <michael.vrhel@artifex.com>2011-02-16 18:11:08 +0000
committerMichael Vrhel <michael.vrhel@artifex.com>2011-02-16 18:11:08 +0000
commit5a435470d3b21c6466825bd1534a5b136a1bb7d8 (patch)
tree7b82a63c6b8c621afb84a18024dbf1315d27a872
parent570f1ca049b942a5a90b9abf90c2794deb473f68 (diff)
Fix so that the threshold values when applied will match the results given by the HT tiling code. Source of problem was due to the lack of a correction to account for the number of shading levels that are represented by the threshold array versus the number of levels indicated in the whitening order structure. The transition point was made in the same manner that it is handled in the HT tiling code. With the threshold fixed, there is a remaining phase issue in gximono.c to tackle.
git-svn-id: http://svn.ghostscript.com/ghostscript/branches/halftone@12162 a1074d23-0009-0410-80fe-cf8c14f379e6
-rw-r--r--gs/base/gsht.c117
-rw-r--r--gs/base/gximono.c8
-rw-r--r--gs/base/gzht.h2
3 files changed, 60 insertions, 67 deletions
diff --git a/gs/base/gsht.c b/gs/base/gsht.c
index da0521edd..016aa9cae 100644
--- a/gs/base/gsht.c
+++ b/gs/base/gsht.c
@@ -1368,88 +1368,81 @@ gx_set_effective_transfer(gs_state * pgs)
array from the tiles. Threshold is allocated in non-gc memory and is
not known to the gc */
int
-gx_ht_construct_threshold( gx_ht_order *d_order)
+gx_ht_construct_threshold( gx_ht_order *d_order, gx_device *dev, int plane_index)
{
- int i, j, l, prev_l;
- unsigned char *thresh;
- gx_ht_bit *bits = (gx_ht_bit *)d_order->bit_data;
- gs_memory_t *memory = d_order->data_memory->non_gc_memory;
+ int i, j, l, prev_l;
+ unsigned char *thresh;
+ gx_ht_bit *bits = (gx_ht_bit *)d_order->bit_data;
+ gs_memory_t *memory = d_order->data_memory->non_gc_memory;
+ uint max_value;
+ unsigned long hsize, nshades;
+ int t_level, t_level_adjust;
+ int row, col;
+ int delta, delta_sum = 0;
+
+ if (d_order == NULL) return -1;
+ if (d_order->threshold != NULL) return 0;
+ thresh = (byte *)gs_malloc(memory, d_order->num_bits, 1,
+ "gx_ht_construct_threshold");
+ if( thresh == NULL ) {
+ return -1 ; /* error if allocation failed */
+ }
+ /* Adjustments to ensure that we properly map our 256 levels into
+ the number of shades that we have in our halftone screen. For example
+ if we have a 16x16 screen, we have 257 shadings that we can represent
+ if we have a 4x4 screen, we have 5 shadings that we can represent.
+ Calculations are performed to match what happens in the tile filling
+ code */
+ max_value = (dev->color_info.gray_index == plane_index) ?
+ dev->color_info.dither_grays - 1 :
+ dev->color_info.dither_colors - 1;
+ hsize = d_order->num_levels;
+ nshades = hsize * max_value + 1;
if (d_order == NULL) return -1;
if (d_order->threshold != NULL) return 0;
-
-#ifdef DEBUG
-if ( gs_debug_c('h') ) {
- dprintf2(" width=%d, height=%d,",
- d_order->width, d_order->height );
- dprintf2(" num_levels=%d, raster=%d\n",
- d_order->num_levels, d_order->raster );
-}
-#endif
-
thresh = (byte *)gs_malloc(memory, d_order->num_bits, 1,
"gx_ht_construct_threshold");
if( thresh == NULL ) {
-#ifdef DEBUG
- emprintf(memory, "threshold_from_order, malloc failed\n");
- emprintf2(memory, " width=%d, height=%d,",
- d_order->width, d_order->height );
- emprintf2(memory, " num_levels=%d, raster=%d\n",
- d_order->num_levels, d_order->raster );
-#endif
return -1 ; /* error if allocation failed */
}
- for( i=0; i<d_order->num_bits; i++ )
- thresh[i] = 1;
-
+ for( i = 0; i < d_order->num_bits; i++ ) {
+ thresh[i] = 255;
+ }
prev_l = 0;
l = 1;
- while( l < d_order->num_levels ) {
- if( d_order->levels[l] > d_order->levels[prev_l] ) {
- int t_level = (256*l)/d_order->num_levels;
- int row, col;
-#ifdef DEBUG
- if ( gs_debug_c('h') )
- dprintf2(" level[%3d]=%3d\n", l, d_order->levels[l]);
-#endif
- for( j=d_order->levels[prev_l]; j<d_order->levels[l]; j++) {
-#ifdef DEBUG
- if ( gs_debug_c('h') )
- dprintf2(" bits.offset=%3d, bits.mask=%8x ",
- bits[j].offset, bits[j].mask);
-#endif
+ while (l < d_order->num_levels) {
+ /* If we have some dots to turn on then proceed */
+ if (d_order->levels[l] > d_order->levels[prev_l]) {
+ t_level = (256 * l) / d_order->num_levels;
+ t_level_adjust = byte2frac(t_level) * nshades / (frac_1_long + 1);
+ delta = t_level_adjust - t_level;
+ if (delta > delta_sum) {
+ /* We had a change in our value. We need to do some adjustments.
+ This particular level stays were it is and subsequent ones
+ will be offset by delta_sum. */
+ t_level -= delta_sum;
+ delta_sum += delta;
+ } else {
+ t_level -= delta_sum;
+ }
+ /* Loop over the number of dots that we have to set in going
+ to this new level from the old level */
+ for (j = d_order->levels[prev_l]; j < d_order->levels[l]; j++) {
row = bits[j].offset / d_order->raster;
- for( col=0; col < (8*sizeof(ht_mask_t)); col++ ) {
- if( bits[j].mask & bit_order[col] )
+ for (col = 0; col < (8*sizeof(ht_mask_t)); col++) {
+ if (bits[j].mask & bit_order[col])
break;
}
- col += 8 * ( bits[j].offset - (row * d_order->raster) );
-#ifdef DEBUG
- if ( gs_debug_c('h') )
- dprintf3("row=%2d, col=%2d, t_level=%3d\n",
- row, col, t_level);
-#endif
- if( col < (int)d_order->width )
- *(thresh+col+(row * d_order->width)) = 256 - t_level;
+ col += 8 * ( bits[j].offset - (row * d_order->raster));
+ if (col < (int)d_order->width)
+ *(thresh + col + (row * d_order->width)) = t_level;
}
prev_l = l;
}
l++;
}
-
-#ifdef DEBUG
- if ( gs_debug_c('h') ) {
- for( i=0; i<(int)d_order->height; i++ ) {
- dprintf1("threshold array row %3d= ", i);
- for( j=(int)d_order->width-1; j>=0; j-- )
- dprintf1("%3d ", *(thresh+j+(i*d_order->width)) );
- dprintf("\n");
- }
- }
-#endif
d_order->threshold = thresh;
return 0;
}
-
-
diff --git a/gs/base/gximono.c b/gs/base/gximono.c
index c873eaa39..d15a2f62d 100644
--- a/gs/base/gximono.c
+++ b/gs/base/gximono.c
@@ -168,7 +168,7 @@ gs_image_class_3_mono(gx_image_enum * penum)
if (penum->pis != NULL && penum->pis->dev_ht != NULL) {
gx_ht_order *d_order =
&(penum->pis->dev_ht->components[0].corder);
- code = gx_ht_construct_threshold(d_order);
+ code = gx_ht_construct_threshold(d_order, penum->dev, 0);
} else {
code = -1;
}
@@ -1624,7 +1624,7 @@ flush:
switch (posture) {
case image_portrait:
/* Compute the tiling positions with dest_width */
- dx = fixed2int(xrun % int2fixed(thresh_width));
+ dx = fixed2int_var(xrun) % thresh_width;
/* Left remainder part */
left_rem_end = min(dx + dest_width, thresh_width);
left_width = left_rem_end - dx; /* The left width of our tile part */
@@ -1671,7 +1671,7 @@ flush:
/* Now do the copy mono operation */
/* First the left remainder bits */
if (offset_bits > 0) {
- int x_pos = fixed2int_var_rounded(xrun);
+ int x_pos = fixed2int_var(xrun);
(*dev_proc(dev, copy_mono)) (dev, halftone, 0, dithered_stride,
gx_no_bitmap_id, x_pos, y_pos,
offset_bits, vdi,
@@ -1682,7 +1682,7 @@ flush:
/* Now the primary aligned bytes */
byte *curr_ptr = halftone;
int curr_width = dest_width - offset_bits;
- int x_pos = fixed2int_var_rounded(xrun) + offset_bits;
+ int x_pos = fixed2int_var(xrun) + offset_bits;
if (offset_bits > 0) {
curr_ptr += 2; /* If the first 2 bytes had the left part then increment */
}
diff --git a/gs/base/gzht.h b/gs/base/gzht.h
index f8a0f24a2..04f46ae6d 100644
--- a/gs/base/gzht.h
+++ b/gs/base/gzht.h
@@ -43,7 +43,7 @@ void gx_ht_construct_spot_order(gx_ht_order *);
int gx_ht_construct_threshold_order(gx_ht_order *, const byte *);
void gx_ht_construct_bit(gx_ht_bit * bit, int width, int bit_num);
void gx_ht_construct_bits(gx_ht_order *);
-int gx_ht_construct_threshold( gx_ht_order *d_order);
+int gx_ht_construct_threshold(gx_ht_order *d_order, gx_device *dev, int plane_index);
/* Halftone enumeration structure */
struct gs_screen_enum_s {