summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 372cde854..bdf57bde6 100644
--- a/base/gsicc_cache.c
+++ b/base/gsicc_cache.c
@@ -260,10 +260,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 40f3979f0..4dc6c26e9 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
@@ -1404,12 +1404,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 6124af47c..a7838a7ed 100644
--- a/devices/devs.mak
+++ b/devices/devs.mak
@@ -1811,8 +1811,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 2b7d9c777..06caa447e 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;
@@ -1325,8 +1291,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;
@@ -1338,39 +1302,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 f5f38f8c1..9c629afa7 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 c1f556379..52a15708e 100644
--- a/devices/gdevtsep.c
+++ b/devices/gdevtsep.c
@@ -1594,7 +1594,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();
@@ -1681,41 +1680,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;
}
@@ -1771,11 +1739,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)