summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Watts <Robin.Watts@artifex.com>2022-03-03 11:28:24 +0000
committerRobin Watts <Robin.Watts@artifex.com>2022-03-11 12:22:32 +0000
commitec45c9ddf9f559b83ebd13ed7592a88eff0f9f58 (patch)
treec957c7ce7e022ab8dafc4baac3118addf5404bfb
parent167a3c05ffa5fa4f8785cc104e7eb7a4b9b4c781 (diff)
downloadghostpdl-9.55.0-customer470.tar.gz
Update plan devices to use the downscaler, plus various fixes.ghostpdl-9.55.0-customer470
Specifically this is intended to allow use of -sPostRenderProfile so we can (for example) use the plan device to render in RGB, then convert to cmyk as a post-process step. In preparing this commit, various problems were found in the planar downscaler, and these are fixed here too. In addition, to avoid every device that wants to support PostRenderProfile needing an identical batch of code to create the icclink, we extract that into a gx_downscaler_create_post_render_link helper function, and use that in the appropriate devices. As a knock on for that, we tweak gsicc_free_link. Firstly, it no longer takes a memory pointer, but rather uses the one in the link itself. This is a step up from the existing code that appears to allocate with 'stable_memory' and then free with 'non_gc_memory'. I suspect we've been getting away with this by chance because the two have always happened to be the same. Secondly, it performs the 'free_link' operation as part of the call. This enables all the call sites to be simplified.
-rw-r--r--base/gsicc_cache.c8
-rw-r--r--base/gsicc_cache.h4
-rw-r--r--base/gxdownscale.c146
-rw-r--r--base/gxdownscale.h7
-rw-r--r--base/lib.mak6
-rw-r--r--devices/devs.mak4
-rw-r--r--devices/gdevpdfimg.c88
-rw-r--r--devices/gdevplan.c174
-rw-r--r--devices/gdevtifs.c46
-rw-r--r--devices/gdevtsep.c46
10 files changed, 289 insertions, 240 deletions
diff --git a/base/gsicc_cache.c b/base/gsicc_cache.c
index ba3320604..e369cd264 100644
--- a/base/gsicc_cache.c
+++ b/base/gsicc_cache.c
@@ -258,10 +258,12 @@ gsicc_alloc_link_dev(gs_memory_t *memory, cmm_profile_t *src_profile,
/* And the related release of the link */
void
-gsicc_free_link_dev(gs_memory_t *memory, gsicc_link_t *link)
+gsicc_free_link_dev(gsicc_link_t *link)
{
- gs_memory_t *nongc_mem = memory->non_gc_memory;
- gs_free_object(nongc_mem, link, "gsicc_free_link_dev");
+ if (link == NULL)
+ return;
+ link->procs.free_link(link);
+ gs_free_object(link->memory, link, "gsicc_free_link_dev");
}
static gsicc_link_t *
diff --git a/base/gsicc_cache.h b/base/gsicc_cache.h
index 7aa87a43a..c9f51b3b4 100644
--- a/base/gsicc_cache.h
+++ b/base/gsicc_cache.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -66,5 +66,5 @@ bool gsicc_support_named_color(const gs_color_space *pcs, const gs_gstate *pgs);
int gsicc_get_device_profile_comps(const cmm_dev_profile_t *dev_profile);
gsicc_link_t * gsicc_alloc_link_dev(gs_memory_t *memory, cmm_profile_t *src_profile,
cmm_profile_t *des_profile, gsicc_rendering_param_t *rendering_params);
-void gsicc_free_link_dev(gs_memory_t *memory, gsicc_link_t *link);
+void gsicc_free_link_dev(gsicc_link_t *link);
#endif
diff --git a/base/gxdownscale.c b/base/gxdownscale.c
index 4e36c81ae..870b22558 100644
--- a/base/gxdownscale.c
+++ b/base/gxdownscale.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -19,6 +19,7 @@
#include "string_.h"
#include "gdevprn.h"
#include "assert_.h"
+#include "gsicc_cache.h"
#ifdef WITH_CAL
#include "cal_ets.h"
@@ -2046,11 +2047,17 @@ getbits_planar_line(gx_downscale_liner *liner_, void *output, int row)
code = (*dev_proc(liner->dev, get_bits_rectangle))(liner->dev, &rect, &params2);
- /* get_bits_rectangle doesn't like doing planar copies, only return
- * pointers. This is a problem for us, so fudge it here. */
- for (i = 0; i < liner->num_comps; i++)
- if (params->data[i] != params2.data[1])
- memcpy(params->data[i], params2.data[i], n);
+ /* If our caller can't accept a pointer, we need to do some work. */
+ if (params->options & GB_RETURN_POINTER) {
+ for (i = 0; i < liner->num_comps; i++)
+ params->data[i] = params2.data[i];
+ } else {
+ /* get_bits_rectangle doesn't like doing planar copies, only return
+ * pointers. This is a problem for us, so fudge it here. */
+ for (i = 0; i < liner->num_comps; i++)
+ if (params->data[i] != params2.data[i])
+ memcpy(params->data[i], params2.data[i], n);
+ }
return code;
}
@@ -2268,23 +2275,25 @@ int gx_downscaler_init_planar_cm(gx_downscaler_t *ds,
ds->factor = factor;
ds->num_planes = num_comps;
ds->src_bpc = src_bpc;
+ ds->dst_bpc = dst_bpc;
ds->scaled_data = NULL;
ds->scaled_span = bitmap_raster((dst_bpc*dev->width*upfactor + downfactor-1)/downfactor);
ds->apply_cm = apply_cm;
ds->apply_cm_arg = apply_cm_arg;
- ds->early_cm = dst_bpc < src_bpc;
+ ds->early_cm = dst_bpc < src_bpc || (dst_bpc == src_bpc && post_cm_num_comps < num_comps);
ds->post_cm_num_comps = post_cm_num_comps;
ds->do_skew_detection = params->do_skew_detection;
if (apply_cm) {
- for (i = 0; i < post_cm_num_comps; i++) {
- ds->post_cm[i] = gs_alloc_bytes(dev->memory,
- (size_t)post_span * downfactor,
- "gx_downscaler(planar_data)");
- if (ds->post_cm[i] == NULL) {
- code = gs_note_error(gs_error_VMerror);
- goto cleanup;
- }
+ ds->post_cm[0] = gs_alloc_bytes(dev->memory,
+ (size_t)post_span * downfactor * post_cm_num_comps,
+ "gx_downscaler(planar_data)");
+ if (ds->post_cm[0] == NULL) {
+ code = gs_note_error(gs_error_VMerror);
+ goto cleanup;
+ }
+ for (i = 1; i < post_cm_num_comps; i++) {
+ ds->post_cm[i] = ds->post_cm[i-1] + (size_t)post_span * downfactor;
}
}
@@ -2307,14 +2316,11 @@ int gx_downscaler_init_planar_cm(gx_downscaler_t *ds,
memcpy(&ds->params, gb_params, sizeof(*gb_params));
ds->params.raster = span;
- for (i = 0; i < num_comps; i++) {
- ds->pre_cm[i] = gs_alloc_bytes(dev->memory,
- (size_t)span * downfactor,
- "gx_downscaler(planar_data)");
- if (ds->pre_cm[i] == NULL) {
- code = gs_note_error(gs_error_VMerror);
- goto cleanup;
- }
+ ds->pre_cm[0] = gs_alloc_bytes(dev->memory,
+ (size_t)span * downfactor * num_comps,
+ "gx_downscaler(planar_data)");
+ for (i = 1; i < num_comps; i++) {
+ ds->pre_cm[i] = ds->pre_cm[i-1] + (size_t)span * downfactor;
}
#ifdef WITH_CAL
@@ -2462,7 +2468,9 @@ int gx_downscaler_init_planar_cm(gx_downscaler_t *ds,
code = gs_note_error(gs_error_rangecheck);
goto cleanup;
} else if (dst_bpc == 1) {
- if (mfs > 1)
+ if (src_bpc == dst_bpc)
+ core = NULL;
+ else if (mfs > 1)
core = &down_core_mfs;
else if (factor == 4)
core = &down_core_4;
@@ -2913,19 +2921,15 @@ gx_downscaler_init_cm_halftone(gx_downscaler_t *ds,
void gx_downscaler_fin(gx_downscaler_t *ds)
{
- int plane;
-
if (ds->dev == NULL)
return;
- for (plane=0; plane < GS_CLIENT_COLOR_MAX_COMPONENTS; plane++) {
- gs_free_object(ds->dev->memory, ds->pre_cm[plane],
- "gx_downscaler(planar_data)");
- gs_free_object(ds->dev->memory, ds->post_cm[plane],
- "gx_downscaler(planar_data)");
- ds->pre_cm[plane] = NULL;
- ds->post_cm[plane] = NULL;
- }
+ gs_free_object(ds->dev->memory, ds->pre_cm[0],
+ "gx_downscaler(planar_data)");
+ gs_free_object(ds->dev->memory, ds->post_cm[0],
+ "gx_downscaler(planar_data)");
+ ds->pre_cm[0] = NULL;
+ ds->post_cm[0] = NULL;
ds->num_planes = 0;
gs_free_object(ds->dev->memory, ds->mfs_data, "gx_downscaler(mfs)");
@@ -3018,11 +3022,14 @@ int gx_downscaler_get_bits_rectangle(gx_downscaler_t *ds,
int subrow;
int copy = (ds->dev->width * ds->src_bpc + 7)>>3;
int i, j, n;
+ int num_planes_to_downscale;
n = ds->dev->width;
if (ds->dev->color_info.depth > ds->dev->color_info.num_components*8+8)
n *= 2;
+ n = (n*ds->src_bpc+7)/8;
+
gx_downscaler_decode_factor(factor, &upfactor, &downfactor);
subrow = row % upfactor;
@@ -3059,11 +3066,10 @@ int gx_downscaler_get_bits_rectangle(gx_downscaler_t *ds,
params->options &= ~GB_RETURN_POINTER;
buffer = saved.data;
} else
- buffer = ds->pre_cm;
- code = ds->apply_cm(ds->apply_cm_arg, params->data, buffer, ds->dev->width, rect.q.y - rect.p.y, params->raster);
- if ((saved.options & GB_RETURN_COPY) == 0)
- for (i = 0; i < ds->num_planes; i++)
- params->data[i] = buffer[i];
+ buffer = ds->post_cm;
+ code = ds->apply_cm(ds->apply_cm_arg, buffer, params->data, ds->dev->width, rect.q.y - rect.p.y, params->raster);
+ for (i = 0; i < ds->post_cm_num_comps; i++)
+ params->data[i] = buffer[i];
}
return code;
}
@@ -3103,42 +3109,56 @@ int gx_downscaler_get_bits_rectangle(gx_downscaler_t *ds,
for (j = 0; j < ds->num_planes; j++)
memcpy(ds->pre_cm[j] + i*ds->span, ds->pre_cm[j] + (i-1)*ds->span, copy);
+ /* All the data is now in ds->pre_cm. Update params2.data so that this points to
+ * it. From here on in, we will keep params2.data pointing to whereever the
+ * latest processed version of the data is. */
for (j = 0; j < ds->num_planes; j++)
params2.data[j] = ds->pre_cm[j];
+ num_planes_to_downscale = ds->num_planes;
if (ds->early_cm && ds->apply_cm) {
- code = ds->apply_cm(ds->apply_cm_arg, ds->params.data, ds->post_cm, ds->dev->width, downfactor, params->raster);
+ code = ds->apply_cm(ds->apply_cm_arg, ds->post_cm, params2.data, ds->dev->width, downfactor, ds->span);
if (code < 0)
return code;
- for (j = 0; j < ds->num_planes; j++)
+ for (j = 0; j < ds->post_cm_num_comps; j++)
params2.data[j] = ds->post_cm[j];
+ num_planes_to_downscale = ds->post_cm_num_comps;
}
if (upfactor > 1) {
/* Downscale the block of lines into our output buffer */
- for (plane=0; plane < ds->num_planes; plane++) {
+ for (plane=0; plane < num_planes_to_downscale; plane++) {
byte *scaled = ds->scaled_data + upfactor * plane * ds->scaled_span;
(ds->down_core)(ds, scaled, params2.data[plane], row, plane, params2.raster);
- params->data[plane] = scaled;
+ params2.data[plane] = scaled;
}
} else if (ds->down_core != NULL) {
/* Downscale direct into output buffer */
- for (plane=0; plane < ds->num_planes; plane++)
+ for (plane=0; plane < num_planes_to_downscale; plane++) {
(ds->down_core)(ds, params->data[plane], params2.data[plane], row, plane, params2.raster);
+ params2.data[plane] = params->data[plane];
+ }
} else {
/* Copy into output buffer */
/* No color management can be required here */
assert(!ds->early_cm || ds->apply_cm == NULL);
- for (plane=0; plane < ds->num_planes; plane++)
+ for (plane=0; plane < num_planes_to_downscale; plane++) {
memcpy(params->data[plane], params2.data[plane], params2.raster);
+ params2.data[plane] = params->data[plane];
+ }
}
if (!ds->early_cm && ds->apply_cm) {
- code = ds->apply_cm(ds->apply_cm_arg, ds->params.data, params2.data, ds->width, 1, params->raster);
+ code = ds->apply_cm(ds->apply_cm_arg, params->data, params2.data, ds->width, 1, params->raster);
if (code < 0)
return code;
+ for (plane=0; plane < num_planes_to_downscale; plane++)
+ params2.data[plane] = params->data[plane];
}
+ for (plane=0; plane < num_planes_to_downscale; plane++)
+ params->data[plane] = params->data[plane];
+
return code;
}
@@ -3566,3 +3586,37 @@ void ets_free(void *malloc_arg, void *p)
gs_free_object((gs_memory_t *)malloc_arg, p, "ets_malloc");
}
+
+int gx_downscaler_create_post_render_link(gx_device *dev, gsicc_link_t **link)
+{
+ cmm_dev_profile_t *profile_struct;
+ gsicc_rendering_param_t rendering_params;
+ int code = dev_proc(dev, get_profile)(dev, &profile_struct);
+ if (code < 0)
+ return_error(gs_error_undefined);
+
+ *link = NULL;
+ if (profile_struct->postren_profile == NULL) {
+ return 0;
+ }
+
+ rendering_params.black_point_comp = gsBLACKPTCOMP_ON;
+ rendering_params.graphics_type_tag = GS_UNKNOWN_TAG;
+ rendering_params.override_icc = false;
+ rendering_params.preserve_black = gsBLACKPRESERVE_OFF;
+ rendering_params.rendering_intent = gsRELATIVECOLORIMETRIC;
+ rendering_params.cmm = gsCMM_DEFAULT;
+ *link = gsicc_alloc_link_dev(dev->memory,
+ profile_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE],
+ profile_struct->postren_profile,
+ &rendering_params);
+ if (*link == NULL)
+ return_error(gs_error_VMerror);
+
+ /* If it is identity, release it now and set link to NULL */
+ if ((*link)->is_identity) {
+ gsicc_free_link_dev(*link);
+ *link = NULL;
+ }
+ return 0;
+}
diff --git a/base/gxdownscale.h b/base/gxdownscale.h
index ed945b461..b8b9fc9a4 100644
--- a/base/gxdownscale.h
+++ b/base/gxdownscale.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -248,4 +248,9 @@ int gx_downscaler_write_params(gs_param_list *plist,
gx_downscaler_params *params,
int features);
+/* A helper function for creating the post render ICC link.
+ * This should be destroyed using gsicc_free_link_dev.*/
+int gx_downscaler_create_post_render_link(gx_device *dev,
+ gsicc_link_t **link);
+
#endif
diff --git a/base/lib.mak b/base/lib.mak
index e8d5719da..2285b1cd8 100644
--- a/base/lib.mak
+++ b/base/lib.mak
@@ -1,4 +1,4 @@
-# Copyright (C) 2001-2021 Artifex Software, Inc.
+# Copyright (C) 2001-2022 Artifex Software, Inc.
# All Rights Reserved.
#
# This software is provided AS-IS with no warranty, either express or
@@ -1403,12 +1403,12 @@ downscale_=$(GLOBJ)gxdownscale.$(OBJ) $(claptrap) $(ets)
$(GLOBJ)gxdownscale_0.$(OBJ) : $(GLSRC)gxdownscale.c $(AK) $(string__h)\
$(gxdownscale_h) $(gserrors_h) $(gdevprn_h) $(assert__h) $(ets_h)\
- $(LIB_MAK) $(MAKEDIRS)
+ $(gsicc_cache_h) $(LIB_MAK) $(MAKEDIRS)
$(GLCC) $(GLO_)gxdownscale_0.$(OBJ) $(C_) $(GLSRC)gxdownscale.c
$(GLOBJ)gxdownscale_1.$(OBJ) : $(GLSRC)gxdownscale.c $(AK) $(string__h)\
$(gxdownscale_h) $(gserrors_h) $(gdevprn_h) $(assert__h) $(ets_h)\
- $(LIB_MAK) $(MAKEDIRS)
+ $(gsicc_cache_h) $(LIB_MAK) $(MAKEDIRS)
$(GLCC) $(D_)WITH_CAL$(_D) $(I_)$(CALSRCDIR)$(_I) $(GLO_)gxdownscale_1.$(OBJ) $(C_) $(GLSRC)gxdownscale.c
$(GLOBJ)gxdownscale.$(OBJ) : $(GLOBJ)gxdownscale_$(WITH_CAL).$(OBJ) $(AK) $(gp_h)
diff --git a/devices/devs.mak b/devices/devs.mak
index 484e0e368..853d09dda 100644
--- a/devices/devs.mak
+++ b/devices/devs.mak
@@ -1799,8 +1799,8 @@ $(DD)tiffsep1.dev : $(tiffsep_) $(DD)tiffs.dev $(minftrsz_h)\
plan_=$(DEVOBJ)gdevplan.$(OBJ) $(DEVOBJ)gdevppla.$(OBJ) $(DEVOBJ)gdevmpla.$(OBJ)
-$(DEVOBJ)gdevplan.$(OBJ) : $(DEVSRC)gdevplan.c $(PDEVH)\
- $(gdevmpla_h) $(gdevplnx_h) $(gdevppla_h)\
+$(DEVOBJ)gdevplan.$(OBJ) : $(DEVSRC)gdevplan.c $(PDEVH) $(gxdevsop_h)\
+ $(gdevmpla_h) $(gdevplnx_h) $(gdevppla_h) $(gxdownscale_h) $(gsicc_cache_h)\
$(gscdefs_h) $(gscspace_h) $(gxgetbit_h) $(gxiparam_h) $(gxlum_h) \
$(DEVS_MAK) $(MAKEDIRS)
$(DEVCC) $(DEVO_)gdevplan.$(OBJ) $(C_) $(DEVSRC)gdevplan.c
diff --git a/devices/gdevpdfimg.c b/devices/gdevpdfimg.c
index 81e7a48ec..cb63d3b36 100644
--- a/devices/gdevpdfimg.c
+++ b/devices/gdevpdfimg.c
@@ -200,8 +200,6 @@ static int gdev_pdf_image_begin_page(gx_device_pdf_image *pdf_dev,
gp_file *file)
{
gx_device_printer *const pdev = (gx_device_printer *)pdf_dev;
- cmm_dev_profile_t *profile_struct;
- gsicc_rendering_param_t rendering_params;
int code;
pdfimage_page *page;
@@ -213,39 +211,11 @@ static int gdev_pdf_image_begin_page(gx_device_pdf_image *pdf_dev,
if (gdev_prn_file_is_new(pdev)) {
/* Set up the icc link settings at this time */
- code = dev_proc(pdev, get_profile)((gx_device *)pdev, &profile_struct);
- if (code < 0)
- return_error(gs_error_undefined);
- if (profile_struct->postren_profile != NULL) {
- rendering_params.black_point_comp = gsBLACKPTCOMP_ON;
- rendering_params.graphics_type_tag = GS_UNKNOWN_TAG;
- rendering_params.override_icc = false;
- rendering_params.preserve_black = gsBLACKPRESERVE_OFF;
- rendering_params.rendering_intent = gsRELATIVECOLORIMETRIC;
- rendering_params.cmm = gsCMM_DEFAULT;
- if (profile_struct->oi_profile != NULL) {
- pdf_dev->icclink = gsicc_alloc_link_dev(pdev->memory,
- profile_struct->oi_profile, profile_struct->postren_profile,
- &rendering_params);
- } else if (profile_struct->link_profile != NULL) {
- pdf_dev->icclink = gsicc_alloc_link_dev(pdev->memory,
- profile_struct->link_profile, profile_struct->postren_profile,
- &rendering_params);
- } else {
- pdf_dev->icclink = gsicc_alloc_link_dev(pdev->memory,
- profile_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE], profile_struct->postren_profile,
- &rendering_params);
- }
- if (pdf_dev->icclink == NULL) {
- gs_free_object(pdf_dev->memory->non_gc_memory, page, "pdfimage create new page");
- return_error(gs_error_VMerror);
- }
- /* If it is identity, release it now and set link to NULL */
- if (pdf_dev->icclink->is_identity) {
- pdf_dev->icclink->procs.free_link(pdf_dev->icclink);
- gsicc_free_link_dev(pdev->memory, pdf_dev->icclink);
- pdf_dev->icclink = NULL;
- }
+ code = gx_downscaler_create_post_render_link((gx_device *)pdev,
+ &pdf_dev->icclink);
+ if (code < 0) {
+ gs_free_object(pdf_dev->memory->non_gc_memory, page, "pdfimage create new page");
+ return code;
}
/* Set up the stream and insert the file header */
@@ -851,12 +821,8 @@ static int pdf_image_finish_file(gx_device_pdf_image *pdf_dev, int PCLm)
pdf_dev->Pages = NULL;
pdf_dev->NumPages = 0;
}
- if (pdf_dev->icclink != NULL)
- {
- pdf_dev->icclink->procs.free_link(pdf_dev->icclink);
- gsicc_free_link_dev(pdf_dev->memory, pdf_dev->icclink);
- pdf_dev->icclink = NULL;
- }
+ gsicc_free_link_dev(pdf_dev->icclink);
+ pdf_dev->icclink = NULL;
pdf_dev->RootOffset = 0;
pdf_dev->PagesOffset = 0;
pdf_dev->xrefOffset = 0;
@@ -1328,8 +1294,6 @@ static int gdev_PCLm_begin_page(gx_device_pdf_image *pdf_dev,
gp_file *file)
{
gx_device_printer *const pdev = (gx_device_printer *)pdf_dev;
- cmm_dev_profile_t *profile_struct;
- gsicc_rendering_param_t rendering_params;
int code;
pdfimage_page *page;
@@ -1341,39 +1305,11 @@ static int gdev_PCLm_begin_page(gx_device_pdf_image *pdf_dev,
if (gdev_prn_file_is_new(pdev)) {
/* Set up the icc link settings at this time */
- code = dev_proc(pdev, get_profile)((gx_device *)pdev, &profile_struct);
- if (code < 0)
- return_error(gs_error_undefined);
- if (profile_struct->postren_profile != NULL) {
- rendering_params.black_point_comp = gsBLACKPTCOMP_ON;
- rendering_params.graphics_type_tag = GS_UNKNOWN_TAG;
- rendering_params.override_icc = false;
- rendering_params.preserve_black = gsBLACKPRESERVE_OFF;
- rendering_params.rendering_intent = gsRELATIVECOLORIMETRIC;
- rendering_params.cmm = gsCMM_DEFAULT;
- if (profile_struct->oi_profile != NULL) {
- pdf_dev->icclink = gsicc_alloc_link_dev(pdev->memory,
- profile_struct->oi_profile, profile_struct->postren_profile,
- &rendering_params);
- } else if (profile_struct->link_profile != NULL) {
- pdf_dev->icclink = gsicc_alloc_link_dev(pdev->memory,
- profile_struct->link_profile, profile_struct->postren_profile,
- &rendering_params);
- } else {
- pdf_dev->icclink = gsicc_alloc_link_dev(pdev->memory,
- profile_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE], profile_struct->postren_profile,
- &rendering_params);
- }
- if (pdf_dev->icclink == NULL) {
- gs_free_object(pdf_dev->memory->non_gc_memory, page, "pdfimage create new page");
- return_error(gs_error_VMerror);
- }
- /* If it is identity, release it now and set link to NULL */
- if (pdf_dev->icclink->is_identity) {
- pdf_dev->icclink->procs.free_link(pdf_dev->icclink);
- gsicc_free_link_dev(pdev->memory, pdf_dev->icclink);
- pdf_dev->icclink = NULL;
- }
+ code = gx_downscaler_create_post_render_link((gx_device *)pdev,
+ &pdf_dev->icclink);
+ if (code < 0) {
+ gs_free_object(pdf_dev->memory->non_gc_memory, page, "pdfimage create new page");
+ return code;
}
/* Set up the stream and insert the file header */
diff --git a/devices/gdevplan.c b/devices/gdevplan.c
index 0ce82cda4..0cf28518f 100644
--- a/devices/gdevplan.c
+++ b/devices/gdevplan.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2021 Artifex Software, Inc.
+/* Copyright (C) 2001-2022 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -24,6 +24,9 @@
#include "gdevplnx.h"
#include "gdevppla.h"
#include "gdevmem.h"
+#include "gxdownscale.h"
+#include "gsicc_cache.h"
+#include "gxdevsop.h"
/* This file defines 5 different devices:
*
@@ -48,6 +51,13 @@
/* ------ The device descriptors ------ */
+typedef struct {
+ gx_device_common;
+ gx_prn_device_common;
+ gx_downscaler_params downscale;
+ gsicc_link_t *icclink;
+} gx_device_plan;
+
/*
* Default X and Y resolution.
*/
@@ -61,6 +71,7 @@ static dev_proc_decode_color(plang_decode_color);
static dev_proc_encode_color(planc_encode_color);
static dev_proc_decode_color(planc_decode_color);
static dev_proc_map_color_rgb(planc_map_color_rgb);
+static dev_proc_dev_spec_op(plan_spec_op);
static dev_proc_open_device(plan_open);
static dev_proc_close_device(plan_close);
@@ -77,6 +88,31 @@ static int planr_print_page(gx_device_printer * pdev, gp_file * pstream);
/* The device procedures */
+static int
+plan_get_params(gx_device * dev, gs_param_list * plist)
+{
+ gx_device_plan *pdev = (gx_device_plan *)dev;
+ int code = gdev_prn_get_params(dev, plist);
+
+ if (code < 0)
+ return code;
+
+ return gx_downscaler_write_params(plist, &pdev->downscale, 0);
+}
+
+static int
+plan_put_params(gx_device *dev, gs_param_list * plist)
+{
+ gx_device_plan *pdev = (gx_device_plan *)dev;
+ int code;
+
+ code = gx_downscaler_read_params(plist, &pdev->downscale, 0);
+ if (code < 0)
+ return code;
+
+ return gdev_prn_put_params(dev, plist);
+}
+
static void
plan_base_initialize_device_procs(gx_device *dev,
dev_proc_map_color_rgb(map_color_rgb),
@@ -91,6 +127,8 @@ plan_base_initialize_device_procs(gx_device *dev,
set_dev_proc(dev, get_page_device, gx_page_device_get_page_device);
set_dev_proc(dev, encode_color, encode_color);
set_dev_proc(dev, decode_color, decode_color);
+ set_dev_proc(dev, get_params, plan_get_params);
+ set_dev_proc(dev, put_params, plan_put_params);
}
static void
@@ -109,6 +147,7 @@ plang_initialize_device_procs(gx_device *dev)
plang_decode_color,
plang_encode_color,
plang_decode_color);
+ set_dev_proc(dev, dev_spec_op, plan_spec_op);
}
static void
@@ -118,6 +157,7 @@ plan_initialize_device_procs(gx_device *dev)
plan_decode_color,
gx_default_rgb_map_rgb_color,
plan_decode_color);
+ set_dev_proc(dev, dev_spec_op, plan_spec_op);
}
static void
@@ -127,6 +167,7 @@ planc_initialize_device_procs(gx_device *dev)
planc_map_color_rgb,
planc_encode_color,
planc_decode_color);
+ set_dev_proc(dev, dev_spec_op, plan_spec_op);
}
static void
@@ -149,30 +190,31 @@ planr_initialize_device_procs(gx_device *dev)
/* Macro for generating device descriptors. */
#define plan_prn_device(init, dev_name, num_comp, depth, max_gray, max_rgb, print_page) \
-{ prn_device_body(gx_device_printer, init, dev_name,\
+{ prn_device_body(gx_device_plan, init, dev_name,\
DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS, X_DPI, Y_DPI,\
0, 0, 0, 0,\
num_comp, depth, max_gray, max_rgb, max_gray + 1, max_rgb + 1,\
- print_page)\
+ print_page),\
+ GX_DOWNSCALER_PARAMS_DEFAULTS\
}
/* The device descriptors themselves */
-const gx_device_printer gs_plan_device =
+const gx_device_plan gs_plan_device =
plan_prn_device(plan_initialize_device_procs, "plan",
3, 24, 255, 255, plan_print_page);
-const gx_device_printer gs_plang_device =
+const gx_device_plan gs_plang_device =
plan_prn_device(plang_initialize_device_procs, "plang",
1, 8, 255, 0, plang_print_page);
-const gx_device_printer gs_planm_device =
+const gx_device_plan gs_planm_device =
plan_prn_device(planm_initialize_device_procs, "planm",
1, 1, 1, 0, planm_print_page);
-const gx_device_printer gs_plank_device =
+const gx_device_plan gs_plank_device =
plan_prn_device(plank_initialize_device_procs, "plank",
4, 4, 1, 1, plank_print_page);
-const gx_device_printer gs_planc_device =
+const gx_device_plan gs_planc_device =
plan_prn_device(planc_initialize_device_procs, "planc",
4, 32, 255, 255, planc_print_page);
-const gx_device_printer gs_planr_device =
+const gx_device_plan gs_planr_device =
plan_prn_device(planr_initialize_device_procs, "planr",
3, 3, 1, 1, planr_print_page);
@@ -363,10 +405,14 @@ plan_open(gx_device * pdev)
static int
plan_close(gx_device *pdev)
{
+ gx_device_plan *dev = (gx_device_plan *)pdev;
+
#ifdef DEBUG_PRINT
emprintf(pdev->memory, "plan_close\n");
#endif
+ gsicc_free_link_dev(dev->icclink);
+ dev->icclink = NULL;
return gdev_prn_close(pdev);
}
@@ -486,26 +532,71 @@ planc_encode_color(gx_device * dev, const gx_color_value cv[])
return (color == gx_no_color_index ? color ^ 1 : color);
}
+static int
+plan_spec_op(gx_device *dev, int op, void *data, int datasize)
+{
+ if (op == gxdso_supports_iccpostrender) {
+ int bpc = dev->color_info.depth / dev->color_info.num_components;
+ return bpc == 8;
+ }
+ return gdev_prn_dev_spec_op(dev, op, data, datasize);
+}
+
/* ------ Internal routines ------ */
+static int post_cm(void *arg,
+ byte **dst,
+ byte **src,
+ int w,
+ int h,
+ int raster)
+{
+ gsicc_bufferdesc_t input_buffer_desc, output_buffer_desc;
+ gsicc_link_t *icclink = (gsicc_link_t*)arg;
+
+ gsicc_init_buffer(&input_buffer_desc, icclink->num_input, 1, false,
+ false, true, src[1] - src[0], raster, h, w);
+ gsicc_init_buffer(&output_buffer_desc, icclink->num_output, 1, false,
+ false, true, dst[1] - dst[0], raster, h, w);
+ icclink->procs.map_buffer(NULL, icclink, &input_buffer_desc, &output_buffer_desc,
+ src[0], dst[0]);
+ return 0;
+}
+
/* Print a page using a given row printing routine. */
static int
-plan_print_page_loop(gx_device_printer * pdev, int log2bits, int numComps,
+plan_print_page_loop(gx_device_printer *pdev, int log2bits, int numComps,
gp_file *pstream)
{
- int lnum;
+ gx_device_plan *dev = (gx_device_plan *)pdev;
+ int i, lnum;
int code = 0;
gs_get_bits_options_t options;
+ gx_downscaler_t ds;
+ gs_get_bits_params_t params;
+ int post_cm_comps;
+ byte *planes[GS_CLIENT_COLOR_MAX_COMPONENTS];
+ int factor = dev->downscale.downscale_factor;
+ int width = gx_downscaler_scale(pdev->width, factor);
+ int height = gx_downscaler_scale(pdev->height, factor);
+ int raster_plane = bitmap_raster(width << log2bits);
+
#ifdef DEBUG_DUMP
dump_row row_proc = NULL;
int output_is_nul = !strncmp(pdev->fname, "nul:", min(strlen(pdev->fname), 4)) ||
!strncmp(pdev->fname, "/dev/null", min(strlen(pdev->fname), 9));
-
- if (!output_is_nul)
- row_proc = dump_start(pdev->width, pdev->height, numComps, log2bits, pstream);
#endif
+
+ if (gdev_prn_file_is_new(pdev)) {
+ code = gx_downscaler_create_post_render_link((gx_device *)pdev,
+ &dev->icclink);
+ if (code < 0)
+ return code;
+ }
+
options = GB_ALIGN_ANY |
GB_RETURN_POINTER |
+ GB_RETURN_COPY |
GB_OFFSET_0 |
GB_RASTER_STANDARD |
GB_COLORS_NATIVE |
@@ -514,25 +605,54 @@ plan_print_page_loop(gx_device_printer * pdev, int log2bits, int numComps,
options |= GB_PACKING_CHUNKY;
else
options |= GB_PACKING_PLANAR;
- for (lnum = 0; lnum < pdev->height; lnum++) {
- gs_int_rect rect;
- gs_get_bits_params_t params;
-
- rect.p.x = 0;
- rect.p.y = lnum;
- rect.q.x = pdev->width;
- rect.q.y = lnum+1;
- memset(&params, 0, sizeof(params));
- params.options = options;
- params.x_offset = 0;
- code = (*dev_proc(pdev, get_bits_rectangle))((gx_device *)pdev, &rect, &params);
+
+ memset(&params, 0, sizeof(params));
+ params.options = options;
+ params.x_offset = 0;
+ post_cm_comps = dev->icclink ? dev->icclink->num_output : numComps;
+
+ planes[0] = gs_alloc_bytes(pdev->memory, raster_plane * post_cm_comps,
+ "plan_print_page_loop");
+ if (planes[0] == NULL)
+ return_error(gs_error_VMerror);
+ for (i = 1; i < post_cm_comps; i++) {
+ planes[i] = planes[i-1] + raster_plane;
+ params.data[i] = planes[i];
+ }
+
+ code = gx_downscaler_init_planar_cm(&ds,
+ (gx_device *)dev,
+ 1<<log2bits, /* src_bpc */
+ 1<<log2bits, /* dst_bpc */
+ numComps,
+ &dev->downscale,
+ &params,
+ dev->icclink ? post_cm : NULL,
+ dev->icclink,
+ post_cm_comps);
+ if (code < 0)
+ goto fail;
+
+#ifdef DEBUG_DUMP
+ if (!output_is_nul)
+ row_proc = dump_start(width, height, post_cm_comps, log2bits, pstream);
+#endif
+
+ for (lnum = 0; lnum < height; lnum++) {
+ for (i = 0; i < post_cm_comps; i++)
+ params.data[i] = planes[i];
+ code = gx_downscaler_get_bits_rectangle(&ds, &params, lnum);
if (code < 0)
break;
#ifdef DEBUG_DUMP
if (row_proc)
- (*row_proc)(pdev->width, params.data, pstream);
+ (*row_proc)(width, params.data, pstream);
#endif
}
+
+ gx_downscaler_fin(&ds);
+fail:
+ gs_free_object(pdev->memory, planes[0], "plan_print_page_loop");
return (code < 0 ? code : 0);
}
diff --git a/devices/gdevtifs.c b/devices/gdevtifs.c
index b937d0e32..516609f8b 100644
--- a/devices/gdevtifs.c
+++ b/devices/gdevtifs.c
@@ -76,12 +76,9 @@ tiff_close(gx_device * pdev)
if (tfdev->tif)
TIFFClose(tfdev->tif);
- if (tfdev->icclink != NULL)
- {
- tfdev->icclink->procs.free_link(tfdev->icclink);
- gsicc_free_link_dev(pdev->memory, tfdev->icclink);
- tfdev->icclink = NULL;
- }
+ gsicc_free_link_dev(tfdev->icclink);
+ tfdev->icclink = NULL;
+
return gdev_prn_close(pdev);
}
@@ -298,8 +295,6 @@ int gdev_tiff_begin_page(gx_device_tiff *tfdev,
gp_file *file)
{
gx_device_printer *const pdev = (gx_device_printer *)tfdev;
- cmm_dev_profile_t *profile_struct;
- gsicc_rendering_param_t rendering_params;
int code;
if (gdev_prn_file_is_new(pdev)) {
@@ -308,39 +303,10 @@ int gdev_tiff_begin_page(gx_device_tiff *tfdev,
if (!tfdev->tif)
return_error(gs_error_invalidfileaccess);
/* Set up the icc link settings at this time */
- code = dev_proc(pdev, get_profile)((gx_device *)pdev, &profile_struct);
+ code = gx_downscaler_create_post_render_link((gx_device *)pdev,
+ &tfdev->icclink);
if (code < 0)
- return_error(gs_error_undefined);
- if (profile_struct->postren_profile != NULL) {
- rendering_params.black_point_comp = gsBLACKPTCOMP_ON;
- rendering_params.graphics_type_tag = GS_UNKNOWN_TAG;
- rendering_params.override_icc = false;
- rendering_params.preserve_black = gsBLACKPRESERVE_OFF;
- rendering_params.rendering_intent = gsRELATIVECOLORIMETRIC;
- rendering_params.cmm = gsCMM_DEFAULT;
- if (profile_struct->oi_profile != NULL) {
- tfdev->icclink = gsicc_alloc_link_dev(pdev->memory,
- profile_struct->oi_profile, profile_struct->postren_profile,
- &rendering_params);
- } else if (profile_struct->link_profile != NULL) {
- tfdev->icclink = gsicc_alloc_link_dev(pdev->memory,
- profile_struct->link_profile, profile_struct->postren_profile,
- &rendering_params);
- } else {
- tfdev->icclink = gsicc_alloc_link_dev(pdev->memory,
- profile_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE],
- profile_struct->postren_profile, &rendering_params);
- }
- if (tfdev->icclink == NULL) {
- return_error(gs_error_VMerror);
- }
- /* If it is identity, release it now and set link to NULL */
- if (tfdev->icclink->is_identity) {
- tfdev->icclink->procs.free_link(tfdev->icclink);
- gsicc_free_link_dev(pdev->memory, tfdev->icclink);
- tfdev->icclink = NULL;
- }
- }
+ return code;
}
return tiff_set_fields_for_printer(pdev, tfdev->tif, tfdev->downscale.downscale_factor,
diff --git a/devices/gdevtsep.c b/devices/gdevtsep.c
index 10d3b6335..700df3674 100644
--- a/devices/gdevtsep.c
+++ b/devices/gdevtsep.c
@@ -1575,7 +1575,6 @@ tiffsep_prn_open(gx_device * pdev)
tiffsep_device *pdev_sep = (tiffsep_device *) pdev;
int code, k;
cmm_dev_profile_t *profile_struct;
- gsicc_rendering_param_t rendering_params;
/* Use our own warning and error message handlers in libtiff */
tiff_set_handlers();
@@ -1662,41 +1661,10 @@ tiffsep_prn_open(gx_device * pdev)
/* Set up the icc link settings at this time. Only CMYK post render profiles
are allowed */
- code = dev_proc(pdev, get_profile)((gx_device *)pdev, &profile_struct);
+ code = gx_downscaler_create_post_render_link((gx_device *)pdev,
+ &pdev_sep->icclink);
if (code < 0)
- return_error(gs_error_undefined);
-
- if (profile_struct->postren_profile != NULL &&
- profile_struct->postren_profile->data_cs == gsCMYK) {
- rendering_params.black_point_comp = gsBLACKPTCOMP_ON;
- rendering_params.graphics_type_tag = GS_UNKNOWN_TAG;
- rendering_params.override_icc = false;
- rendering_params.preserve_black = gsBLACKPRESERVE_OFF;
- rendering_params.rendering_intent = gsRELATIVECOLORIMETRIC;
- rendering_params.cmm = gsCMM_DEFAULT;
- if (profile_struct->oi_profile != NULL) {
- pdev_sep->icclink = gsicc_alloc_link_dev(pdev->memory,
- profile_struct->oi_profile, profile_struct->postren_profile,
- &rendering_params);
- } else if (profile_struct->link_profile != NULL) {
- pdev_sep->icclink = gsicc_alloc_link_dev(pdev->memory,
- profile_struct->link_profile, profile_struct->postren_profile,
- &rendering_params);
- } else {
- pdev_sep->icclink = gsicc_alloc_link_dev(pdev->memory,
- profile_struct->device_profile[GS_DEFAULT_DEVICE_PROFILE],
- 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);
- gsicc_free_link_dev(pdev->memory, pdev_sep->icclink);
- pdev_sep->icclink = NULL;
- }
- }
+ return code;
return code;
}
@@ -1752,11 +1720,9 @@ tiffsep_prn_close(gx_device * pdev)
int comp_num;
int num_comp = number_output_separations(num_dev_comp, num_std_colorants,
num_order, num_spot);
- if (pdevn->icclink != NULL) {
- pdevn->icclink->procs.free_link(pdevn->icclink);
- gsicc_free_link_dev(pdevn->memory, pdevn->icclink);
- pdevn->icclink = NULL;
- }
+
+ gsicc_free_link_dev(pdevn->icclink);
+ pdevn->icclink = NULL;
name = (char *)gs_alloc_bytes(pdevn->memory, gp_file_name_sizeof, "tiffsep_prn_close(name)");
if (!name)