diff options
Diffstat (limited to 'devices/gdevtsep.c')
-rw-r--r-- | devices/gdevtsep.c | 240 |
1 files changed, 114 insertions, 126 deletions
diff --git a/devices/gdevtsep.c b/devices/gdevtsep.c index 5fb1025e..7fddf1c7 100644 --- a/devices/gdevtsep.c +++ b/devices/gdevtsep.c @@ -38,6 +38,7 @@ #include "gsequivc.h" #include "gxdht.h" #include "gxiodev.h" +#include "gzht.h" #include "stdio_.h" #include "ctype_.h" #include "gxgetbit.h" @@ -49,6 +50,9 @@ #include "gsicc_cache.h" #include "gxdevsop.h" #include "gsicc.h" +#ifdef WITH_CAL +#include "cal.h" +#endif /* * Some of the code in this module is based upon the gdevtfnx.c module. @@ -1184,7 +1188,7 @@ tiffsep_put_params(gx_device * pdev, gs_param_list * plist) } switch (code = param_read_int(plist, (param_name = "MaxSpots"), &max_spots)) { case 0: - if ((max_spots >= 0) || (max_spots <= GS_CLIENT_COLOR_MAX_COMPONENTS-4)) { + if ((max_spots >= 0) && (max_spots <= GS_CLIENT_COLOR_MAX_COMPONENTS-4)) { pdevn->max_spots = max_spots; break; } @@ -1230,9 +1234,7 @@ tiffsep1_put_params(gx_device * pdev, gs_param_list * plist) static void build_comp_to_sep_map(tiffsep_device *, short *); static int number_output_separations(int, int, int, int); static int create_separation_file_name(tiffsep_device *, char *, uint, int, bool); -static byte * threshold_from_order( gx_ht_order *, int *, int *, gs_memory_t *); static int sep1_ht_order_to_thresholds(gx_device *pdev, const gs_gstate *pgs); -static void sep1_free_thresholds(tiffsep1_device *); dev_proc_fill_path(clist_fill_path); /* Open the tiffsep1 device. This will now be using planar buffers so that @@ -1372,10 +1374,6 @@ tiffsep1_prn_close(gx_device * pdev) tfdev->tiff[comp_num] = NULL; } } - /* If we have thresholds, free them and clear the pointers */ - if( tfdev->thresholds[0].dstart != NULL) { - sep1_free_thresholds(tfdev); - } done: @@ -1796,6 +1794,9 @@ tiffsep_prn_open(gx_device * pdev) profile_struct->device_profile[0], profile_struct->postren_profile, &rendering_params); } + if (pdev_sep->icclink == NULL) { + return_error(gs_error_VMerror); + } /* If it is identity, release it now and set link to NULL */ if (pdev_sep->icclink->is_identity) { pdev_sep->icclink->procs.free_link(pdev_sep->icclink); @@ -2110,10 +2111,11 @@ sep1_ht_order_to_thresholds(gx_device *pdev, const gs_gstate *pgs) { tiffsep1_device * const tfdev = (tiffsep1_device *)pdev; gs_memory_t *mem = pdev->memory; + int code; - /* If we have thresholds, free them and clear the pointers */ + /* If we have thresholds, clear the pointers */ if( tfdev->thresholds[0].dstart != NULL) { - sep1_free_thresholds(tfdev); + tfdev->thresholds[0].dstart = NULL; } else { int nc, j; gx_ht_order *d_order; @@ -2125,130 +2127,39 @@ sep1_ht_order_to_thresholds(gx_device *pdev, const gs_gstate *pgs) } nc = pgs->dev_ht->num_comp; for( j=0; j<nc; j++ ) { + int x, y; + d_order = &(pgs->dev_ht->components[j].corder); dptr = &(tfdev->thresholds[j]); - dptr->dstart = threshold_from_order( d_order, &(dptr->dwidth), &(dptr->dheight), mem); - if( dptr->dstart == NULL ) { + /* In order to use the function from gsht.c we need to set the color_info */ + /* values it uses to reflect the eventual 1-bit output, not contone */ + pdev->color_info.dither_grays = pdev->color_info.dither_colors = 2; + pdev->color_info.polarity = GX_CINFO_POLARITY_ADDITIVE; + code = gx_ht_construct_threshold(d_order, pdev, pgs, j); + if( code < 0 ) { emprintf(mem, "sep1_order_to_thresholds: conversion to thresholds failed.\n"); - return_error(gs_error_rangecheck); /* error condition */ + return_error(code); /* error condition */ } + pdev->color_info.dither_grays = pdev->color_info.dither_colors = 256; + pdev->color_info.polarity = GX_CINFO_POLARITY_SUBTRACTIVE; + /* Invert the thresholds so we (almost) match pbmraw dithered output */ + for (y=0; y<d_order->full_height; y++) { + byte *s = d_order->threshold; + int s_offset = y * d_order->width; + + for (x=0; x<d_order->width; x++) { + s[s_offset + x] = 256 - s[s_offset + x]; + } + } + dptr->dstart = d_order->threshold; + dptr->dwidth = d_order->width; + dptr->dheight = d_order->full_height; } } return 0; } -static void -sep1_free_thresholds(tiffsep1_device *tfdev) -{ - int i; - - for (i=0; i < GX_DEVICE_COLOR_MAX_COMPONENTS + 1; i++) { - threshold_array_t *dptr = &(tfdev->thresholds[i]); - - if (dptr->dstart != NULL) { - gs_free(tfdev->memory, dptr->dstart, dptr->dwidth * dptr->dheight, 1, - "tiffsep1_threshold_array"); - dptr->dstart = NULL; - } - } -} - -/************************************************************************/ -/* This routine generates a threshold matrix for use in */ -/* the color dithering routine from the "order" info in */ -/* the current graphics state. */ -/* */ -/************************************************************************/ - -static byte* -threshold_from_order( gx_ht_order *d_order, int *Width, int *Height, gs_memory_t *memory) -{ - int i, j, l, prev_l; - unsigned char *thresh; - int num_repeat, shift; - - /* We can have simple or complete orders. Simple ones tile the threshold - with shifts. To handle those we simply loop over the number of - repeats making sure to shift columns when we set our threshold values */ - num_repeat = d_order->full_height / d_order->height; - shift = d_order->shift; - -#ifdef DEBUG -if ( gs_debug_c('h') ) { - dmprintf2(memory, " width=%d, height=%d,", - d_order->width, d_order->height ); - dmprintf2(memory, " num_levels=%d, raster=%d\n", - d_order->num_levels, d_order->raster ); -} -#endif - - thresh = (byte *)gs_malloc(memory, d_order->width * d_order->full_height, 1, - "tiffsep1_threshold_array"); - 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 thresh ; /* error if allocation failed */ - } - for( i=0; i<d_order->num_bits; i++ ) - thresh[i] = 1; - - *Width = d_order->width; - *Height = d_order->full_height; - - 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; - -#ifdef DEBUG - if ( gs_debug_c('h') ) - dmprintf2(memory, " level[%3d]=%3d\n", l, d_order->levels[l]); -#endif - for( j=d_order->levels[prev_l]; j<d_order->levels[l]; j++) { - gs_int_point col_row = { 0, 0 }; - int col_kk, row_kk, kk; - - d_order->procs->bit_index(d_order, j, &col_row); -#ifdef DEBUG - if ( gs_debug_c('h') ) - dmprintf3(memory, "row=%2d, col=%2d, t_level=%3d\n", - col_row.y, col_row.x, t_level); -#endif - if( col_row.x < (int)d_order->width ) { - for (kk = 0; kk < num_repeat; kk++) { - row_kk = col_row.y + kk * d_order->height; - col_kk = col_row.x + kk * shift; - col_kk = col_kk % d_order->width; - *(thresh + col_kk + (row_kk * 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++ ) { - dmprintf1(memory, "threshold array row %3d= ", i); - for( j=(int)d_order->width-1; j>=0; j-- ) - dmprintf1(memory, "%3d ", *(thresh+j+(i*d_order->width)) ); - dmprintf(memory, "\n"); - } - } -#endif - - return thresh; -} - /* * This function prints out CMYK value with separation name for every * separation. Where the original alternate colour space was DeviceCMYK, and the output @@ -2365,6 +2276,7 @@ tiffsep_print_page(gx_device_printer * pdev, gp_file * file) "\nUse of the %%d format is required to output more than one page to tiffsep.\n" "See doc/Devices.htm#TIFF for details.\n\n"); code = gs_note_error(gs_error_ioerror); + goto done; } /* Write the page directory for the CMYK equivalent file. */ if (!tfdev->comp_file) { @@ -2679,6 +2591,26 @@ done: return code; } +#ifdef WITH_CAL +static void +ht_callback(cal_halftone_data_t *ht, void *arg) +{ + tiffsep1_device *tfdev = (tiffsep1_device *)arg; + int num_std_colorants = tfdev->devn_params.num_std_colorant_names; + int num_order = tfdev->devn_params.num_separation_order_names; + int num_spot = tfdev->devn_params.separations.num_separations; + int comp_num; + int num_comp = number_output_separations(tfdev->color_info.num_components, + num_std_colorants, num_order, num_spot); + /* Deliberately cast away const, cos tifflib has a bad interface. */ + unsigned char *data = (unsigned char *)ht->data; + + for (comp_num = 0; comp_num < num_comp; comp_num++) { + TIFFWriteScanline(tfdev->tiff[comp_num], &data[ht->raster*comp_num], ht->y, 0); + } +} +#endif + /* * Output the image data for the tiff separation (tiffsep1) device. The data * for the tiffsep1 device is written in separate planes to separate files. @@ -2726,6 +2658,7 @@ tiffsep1_print_page(gx_device_printer * pdev, gp_file * file) "\nUse of the %%d format is required to output more than one page to tiffsep1.\n" "See doc/Devices.htm#TIFF for details.\n\n"); code = gs_note_error(gs_error_ioerror); + goto done; } /* If the output file is on disk and the name contains a page #, */ /* then delete the previous file. */ @@ -2809,8 +2742,41 @@ tiffsep1_print_page(gx_device_printer * pdev, gp_file * file) int pixel, y; gs_get_bits_params_t params; gs_int_rect rect; + uint32_t *dithered_line = NULL; + +#ifdef WITH_CAL + cal_context *cal = pdev->memory->gs_lib_ctx->core->cal_ctx; + cal_halftone *cal_ht = NULL; + cal_matrix matrix = { 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f }; + + cal_ht = cal_halftone_init(cal, + pdev->memory->non_gc_memory, + pdev->width, + pdev->height, + &matrix, + comp_num, + NULL, + 0, + 0, + pdev->width, + pdev->height, + 0); + if (cal_ht != NULL) { + for (comp_num = 0; comp_num < num_comp; comp_num++) + if (cal_halftone_add_screen(cal, + pdev->memory->non_gc_memory, + cal_ht, + 0, + tfdev->thresholds[comp_num].dwidth, + tfdev->thresholds[comp_num].dheight, + 0, + 0, + tfdev->thresholds[comp_num].dstart) < 0) + goto cal_fail; + } else +#endif /* the dithered_line is assumed to be 32-bit aligned by the alloc */ - uint32_t *dithered_line = (uint32_t *)gs_alloc_bytes(pdev->memory, dithered_raster, + dithered_line = (uint32_t *)gs_alloc_bytes(pdev->memory, dithered_raster, "tiffsep1_print_page"); memset(planes, 0, sizeof(*planes) * GS_CLIENT_COLOR_MAX_COMPONENTS); @@ -2832,7 +2798,11 @@ tiffsep1_print_page(gx_device_printer * pdev, gp_file * file) } } +#ifdef WITH_CAL + if (code < 0 || (cal_ht == NULL && dithered_line == NULL)) { +#else if (code < 0 || dithered_line == NULL) { +#endif code = gs_note_error(gs_error_VMerror); goto cleanup; } @@ -2853,6 +2823,16 @@ tiffsep1_print_page(gx_device_printer * pdev, gp_file * file) if (code < 0) break; +#ifdef WITH_CAL + if(cal_ht != NULL) { + if (cal_halftone_process_planar(cal_ht, + pdev->memory->non_gc_memory, + (const byte * const *)¶ms.data[0], + ht_callback, + tfdev) < 0) + goto cal_fail; + } else +#endif /* Dither the separation and write it out */ for (comp_num = 0; comp_num < num_comp; comp_num++ ) { @@ -2869,8 +2849,8 @@ tiffsep1_print_page(gx_device_printer * pdev, gp_file * file) */ #define USE_32_BIT_WRITES byte *thresh_line_base = tfdev->thresholds[comp_num].dstart + - ((y % tfdev->thresholds[comp_num].dheight) * - tfdev->thresholds[comp_num].dwidth) ; + ((y % tfdev->thresholds[comp_num].dheight) * + tfdev->thresholds[comp_num].dwidth) ; byte *thresh_ptr = thresh_line_base; byte *thresh_limit = thresh_ptr + tfdev->thresholds[comp_num].dwidth; byte *src = params.data[comp_num]; @@ -2941,6 +2921,14 @@ tiffsep1_print_page(gx_device_printer * pdev, gp_file * file) } code = code1; +#ifdef WITH_CAL + if(0) { +cal_fail: + code = gs_error_unknownerror; + } + cal_halftone_fin(cal_ht, pdev->memory->non_gc_memory); +#endif + /* free any allocations and exit with code */ cleanup: gs_free_object(pdev->memory, dithered_line, "tiffsep1_print_page"); |