summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'base/gxdownscale.c')
-rw-r--r--base/gxdownscale.c937
1 files changed, 579 insertions, 358 deletions
diff --git a/base/gxdownscale.c b/base/gxdownscale.c
index 8721d1db..1a348da5 100644
--- a/base/gxdownscale.c
+++ b/base/gxdownscale.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2019 Artifex Software, Inc.
+/* Copyright (C) 2001-2020 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -32,6 +32,11 @@ void gx_ht_threshold_row_bit_sub(byte *contone, byte *threshold_strip,
int dithered_stride, int width, int num_rows,
int offset_bits);
+struct gx_downscale_liner_s {
+ int (*get_line)(gx_downscale_liner *, void *, int);
+ void (*drop)(gx_downscale_liner *, gs_memory_t *);
+};
+
enum
{
MAX_ETS_PLANES = 8
@@ -918,7 +923,8 @@ static void down_core4_ht(gx_downscaler_t *ds,
else if ((31 & (intptr_t)in_buffer) == 0)
downscaled_data = in_buffer; /* Already aligned! Yay! */
else
- memcpy(downscaled_data, in_buffer, nc*ds->width); /* Copy to align */
+ memcpy(downscaled_data, in_buffer,
+ (size_t)nc*ds->width); /* Copy to align */
/* Do the halftone */
for (i = 0; i < nc; i++)
@@ -1688,7 +1694,7 @@ static void down_core32(gx_downscaler_t *ds,
}
}
-static void decode_factor(int factor, int *up, int *down)
+void gx_downscaler_decode_factor(int factor, int *up, int *down)
{
if (factor == 32)
*down = 3, *up = 2;
@@ -1703,7 +1709,7 @@ gx_downscaler_scale(int width, int factor)
{
int up, down;
- decode_factor(factor, &up, &down);
+ gx_downscaler_decode_factor(factor, &up, &down);
return (width*up)/down;
}
@@ -1711,7 +1717,7 @@ int gx_downscaler_adjust_bandheight(int factor, int band_height)
{
int up, down;
- decode_factor(factor, &up, &down);
+ gx_downscaler_decode_factor(factor, &up, &down);
return (band_height/down)*down;
}
@@ -1720,47 +1726,67 @@ gx_downscaler_scale_rounded(int width, int factor)
{
int up, down;
- decode_factor(factor, &up, &down);
+ gx_downscaler_decode_factor(factor, &up, &down);
return (width*up + down-1)/down;
}
+typedef struct {
+ gx_downscale_liner base;
+ ClapTrap *claptrap;
+ int y;
+ int width;
+ int height;
+ int num_comps;
+ gs_get_bits_params_t *params;
+ gx_downscale_liner *chain;
+} liner_claptrap_planar;
+
+static int
+claptrap_planar_line(gx_downscale_liner *liner_, void *buffer, int row)
+{
+ liner_claptrap_planar *liner = (liner_claptrap_planar *)liner_;
+ gs_get_bits_params_t *params = (gs_get_bits_params_t *)buffer;
+
+ liner->params = params;
+ return ClapTrap_GetLinePlanar(liner->claptrap, params->data);
+}
+
+static void
+claptrap_planar_drop(gx_downscale_liner *liner_, gs_memory_t *mem)
+{
+ liner_claptrap_planar *liner = (liner_claptrap_planar *)liner_;
+ gx_downscale_liner *next;
+
+ if (!liner)
+ return;
+ ClapTrap_Fin(mem, liner->claptrap);
+ next = liner->chain;
+ gs_free_object(mem, liner, "liner_claptrap_planar");
+ if (next)
+ next->drop(next, mem);
+}
+
static int get_planar_line_for_trap(void *arg, unsigned char *buf)
{
- gx_downscaler_t *ds = (gx_downscaler_t *)arg;
- gs_int_rect rect;
- gs_get_bits_params_t params; /* params (if trapping) */
- int nc = ds->num_planes;
+ liner_claptrap_planar *ct = (liner_claptrap_planar *)arg;
+ gs_get_bits_params_t params;
+ int nc = ct->num_comps;
int i, code;
unsigned char *buf2;
- rect.p.x = 0;
- rect.p.y = ds->claptrap_y++;
- rect.q.x = ds->dev->width;
- rect.q.y = rect.p.y+1;
- /* Allow for devices (like psdcmyk) that make several passes through
- * the image. */
- if (ds->claptrap_y == ds->dev->height)
- ds->claptrap_y = 0;
-
- params = *ds->claptrap_params;
+ params = *ct->params;
buf2 = buf;
for (i = 0; i < nc; i++)
{
params.data[i] = buf2;
- buf2 += ds->width;
+ buf2 += ct->width;
}
- code = (*dev_proc(ds->dev, get_bits_rectangle))(ds->dev, &rect, &params, NULL);
- if (code < 0)
- return code;
-
- /* Now cope with the fact we might have been returned pointers */
- for (i = 0; i < nc; i++)
- {
- if (params.data[i] != buf)
- memcpy(buf, params.data[i], ds->width);
- buf += ds->width;
- }
+ code = ct->chain->get_line(ct->chain, &params, ct->y++);
+ /* Allow for devices (like psdcmyk) that make several passes through
+ * the image. */
+ if (ct->y == ct->height)
+ ct->y = 0;
return code;
}
@@ -1945,49 +1971,202 @@ static int init_ht(gx_downscaler_t *ds, int num_planes, gx_downscale_core *downs
int gx_downscaler_init_planar(gx_downscaler_t *ds,
gx_device *dev,
- gs_get_bits_params_t *params,
- int num_comps,
- int factor,
- int mfs,
int src_bpc,
- int dst_bpc)
+ int dst_bpc,
+ int num_comps,
+ const gx_downscaler_params *params,
+ const gs_get_bits_params_t *gb_params)
+{
+ return gx_downscaler_init_planar_cm(ds, dev, src_bpc, dst_bpc,
+ num_comps, params, gb_params,
+ NULL, NULL, num_comps);
+}
+
+typedef struct {
+ gx_downscale_liner base;
+ gx_device *dev;
+} liner_getbits_chunky;
+
+static int
+getbits_chunky_line(gx_downscale_liner *liner_, void *buffer, int row)
+{
+ liner_getbits_chunky *liner = (liner_getbits_chunky *)liner_;
+
+ return (*dev_proc(liner->dev, get_bits))(liner->dev, row, buffer, NULL);
+}
+
+static void
+getbits_chunky_drop(gx_downscale_liner *liner_, gs_memory_t *mem)
+{
+ liner_getbits_chunky *liner = (liner_getbits_chunky *)liner_;
+
+ gs_free_object(mem, liner, "liner_getbits_chunky");
+}
+
+typedef struct {
+ gx_downscale_liner base;
+ gx_device *dev;
+ int raster;
+ int num_comps;
+} liner_getbits_planar;
+
+static int
+getbits_planar_line(gx_downscale_liner *liner_, void *output, int row)
+{
+ liner_getbits_planar *liner = (liner_getbits_planar *)liner_;
+ gs_get_bits_params_t *params = (gs_get_bits_params_t *)output;
+ gs_get_bits_params_t params2;
+ gs_int_rect rect;
+ int i, code, n;
+
+ rect.p.x = 0;
+ rect.p.y = row;
+ rect.q.x = liner->dev->width;
+ rect.q.y = row+1;
+
+ n = liner->dev->width;
+ if (liner->dev->color_info.depth > liner->dev->color_info.num_components * 8 + 8)
+ n *= 2;
+
+ params2 = *params;
+
+ code = (*dev_proc(liner->dev, get_bits_rectangle))(liner->dev, &rect, &params2, NULL);
+
+ /* 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);
+
+ return code;
+}
+
+static void
+getbits_planar_drop(gx_downscale_liner *liner_, gs_memory_t *mem)
+{
+ liner_getbits_planar *liner = (liner_getbits_planar *)liner_;
+
+ gs_free_object(mem, liner, "liner_getbits_planar");
+}
+
+typedef struct {
+ gx_downscale_liner base;
+ ClapTrap *claptrap;
+ int y;
+ int height;
+ gx_downscale_liner *chain;
+} liner_claptrap;
+
+static int
+claptrap_line(gx_downscale_liner *liner_, void *buffer, int row)
{
- return gx_downscaler_init_planar_trapped_cm(ds, dev, params, num_comps,
- factor, mfs, src_bpc, dst_bpc, 0, 0, NULL, NULL, NULL, num_comps);
+ liner_claptrap *liner = (liner_claptrap *)liner_;
+
+ return ClapTrap_GetLine(liner->claptrap, buffer);
}
-int gx_downscaler_init_planar_trapped(gx_downscaler_t *ds,
- gx_device *dev,
- gs_get_bits_params_t *params,
- int num_comps,
- int factor,
- int mfs,
- int src_bpc,
- int dst_bpc,
- int trap_w,
- int trap_h,
- const int *comp_order)
-{
- return gx_downscaler_init_planar_trapped_cm(ds, dev, params, num_comps,
- factor, mfs, src_bpc, dst_bpc,
- trap_w, trap_h, comp_order,
- NULL, NULL, num_comps);
+static void
+claptrap_drop(gx_downscale_liner *liner_, gs_memory_t *mem)
+{
+ liner_claptrap *liner = (liner_claptrap *)liner_;
+ gx_downscale_liner *next;
+
+ if (!liner)
+ return;
+ ClapTrap_Fin(mem, liner->claptrap);
+ next = liner->chain;
+ gs_free_object(mem, liner, "liner_claptrap");
+ if (next)
+ next->drop(next, mem);
+}
+
+#ifdef WITH_CAL
+typedef struct {
+ gx_downscale_liner base;
+ cal_deskewer *deskewer;
+ cal_deskewer_bander *bander;
+ int height;
+ int get_row;
+ int got_row;
+ gx_downscale_liner *chain;
+} liner_skew;
+
+static int
+skew_line(gx_downscale_liner *liner_, void *buffer, int row)
+{
+ liner_skew *liner = (liner_skew *)liner_;
+ int code;
+
+ if (row < liner->got_row)
+ liner->get_row = 0;
+
+ liner->got_row = row;
+
+ while (1) {
+ code = cal_deskewer_band_pull(liner->bander, buffer);
+ if (code == 1)
+ return 0; /* We got a line! */
+
+ code = liner->chain->get_line(liner->chain,
+ buffer,
+ liner->get_row++);
+ if (code < 0)
+ return code;
+ code = cal_deskewer_band_push(liner->bander,
+ buffer);
+ if (code < 0)
+ return code;
+ }
+}
+
+static void
+skew_drop(gx_downscale_liner *liner_, gs_memory_t *mem)
+{
+ liner_skew *liner = (liner_skew *)liner_;
+ gx_downscale_liner *next;
+
+ if (!liner)
+ return;
+ cal_deskewer_band_end(liner->bander, mem);
+ cal_deskewer_fin(liner->deskewer, mem);
+ next = liner->chain;
+ gs_free_object(mem, liner, "liner_skew");
+ if (next)
+ next->drop(next, mem);
+}
+#endif
+
+#define alloc_liner(mem, type, get, drop, res) \
+ do_alloc_liner(mem, sizeof(type), #type, get, drop,\
+ (gx_downscale_liner **)res)
+
+static int
+do_alloc_liner(gs_memory_t *mem, size_t size, const char *type,
+ int (*get_line)(gx_downscale_liner *, void *, int),
+ void (*drop)(gx_downscale_liner *, gs_memory_t *),
+ gx_downscale_liner **res)
+{
+ gx_downscale_liner *liner;
+
+ liner = (gx_downscale_liner *)gs_alloc_bytes(mem, size, type);
+ *res = liner;
+ if (liner == NULL)
+ return_error(gs_error_VMerror);
+ liner->get_line = get_line;
+ liner->drop = drop;
+ return 0;
}
-int gx_downscaler_init_planar_trapped_cm(gx_downscaler_t *ds,
- gx_device *dev,
- gs_get_bits_params_t *params,
- int num_comps,
- int factor,
- int mfs,
- int src_bpc,
- int dst_bpc,
- int trap_w,
- int trap_h,
- const int *comp_order,
- gx_downscale_cm_fn *apply_cm,
- void *apply_cm_arg,
- int post_cm_num_comps)
+int gx_downscaler_init_planar_cm(gx_downscaler_t *ds,
+ gx_device *dev,
+ int src_bpc,
+ int dst_bpc,
+ int num_comps,
+ const gx_downscaler_params *params,
+ const gs_get_bits_params_t *gb_params,
+ gx_downscale_cm_fn *apply_cm,
+ void *apply_cm_arg,
+ int post_cm_num_comps)
{
int span = bitmap_raster(dev->width * src_bpc);
int post_span = bitmap_raster(dev->width * src_bpc);
@@ -1996,8 +2175,10 @@ int gx_downscaler_init_planar_trapped_cm(gx_downscaler_t *ds,
gx_downscale_core *core;
int i;
int upfactor, downfactor;
+ int factor = params->downscale_factor;
+ int mfs = params->min_feature_size;
- decode_factor(factor, &upfactor, &downfactor);
+ gx_downscaler_decode_factor(factor, &upfactor, &downfactor);
/* width = scaled width */
width = (dev->width*upfactor)/downfactor;
@@ -2018,8 +2199,9 @@ int gx_downscaler_init_planar_trapped_cm(gx_downscaler_t *ds,
if (apply_cm) {
for (i = 0; i < post_cm_num_comps; i++) {
- ds->post_cm[i] = gs_alloc_bytes(dev->memory, post_span * downfactor,
- "gx_downscaler(planar_data)");
+ 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;
@@ -2027,33 +2209,74 @@ int gx_downscaler_init_planar_trapped_cm(gx_downscaler_t *ds,
}
}
- code = check_trapping(dev->memory, trap_w, trap_h, num_comps, comp_order);
+ /* The primary line source for planar comes always from
+ * get_bits_rectangle. */
+ {
+ liner_getbits_planar *gb_liner;
+
+ code = alloc_liner(dev->memory,
+ liner_getbits_planar,
+ getbits_planar_line,
+ getbits_planar_drop,
+ &gb_liner);
+ if (code < 0)
+ goto cleanup;
+ gb_liner->dev = dev;
+ gb_liner->num_comps = num_comps;
+ ds->liner = &gb_liner->base;
+ }
+
+ code = check_trapping(dev->memory, params->trap_w, params->trap_h,
+ num_comps, params->trap_order);
if (code < 0)
return code;
- if (trap_w > 0 || trap_h > 0) {
- ds->claptrap = ClapTrap_Init(dev->memory, width, dev->height, num_comps, comp_order, trap_w, trap_h, get_planar_line_for_trap, ds);
- if (ds->claptrap == NULL) {
+ if (params->trap_w > 0 || params->trap_h > 0) {
+ liner_claptrap_planar *ct_liner;
+
+ code = alloc_liner(dev->memory,
+ liner_claptrap_planar,
+ claptrap_planar_line,
+ claptrap_planar_drop,
+ &ct_liner);
+ if (code < 0)
+ goto cleanup;
+ ct_liner->chain = ds->liner;
+ ct_liner->y = 0;
+ ct_liner->height = dev->height;
+ ct_liner->num_comps = ds->num_comps;
+ ct_liner->width = dev->width;
+ ds->liner = &ct_liner->base;
+ ct_liner->claptrap = ClapTrap_Init(dev->memory,
+ dev->width,
+ dev->height,
+ num_comps,
+ params->trap_order,
+ params->trap_w,
+ params->trap_h,
+ get_planar_line_for_trap,
+ ct_liner);
+ if (ct_liner->claptrap == NULL) {
emprintf(dev->memory, "Trapping initialisation failed");
code = gs_note_error(gs_error_VMerror);
goto cleanup;
}
}
- else
- ds->claptrap = NULL;
- memcpy(&ds->params, params, sizeof(*params));
+ 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, span * downfactor,
- "gx_downscaler(planar_data)");
+ 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;
}
}
if (upfactor > 1) {
- ds->scaled_data = gs_alloc_bytes(dev->memory, ds->scaled_span * upfactor * num_comps,
+ ds->scaled_data = gs_alloc_bytes(dev->memory,
+ (size_t)ds->scaled_span * upfactor * num_comps,
"gx_downscaler(scaled_data)");
if (ds->scaled_data == NULL) {
code = gs_note_error(gs_error_VMerror);
@@ -2097,23 +2320,23 @@ int gx_downscaler_init_planar_trapped_cm(gx_downscaler_t *ds,
if (mfs > 1) {
ds->mfs_data = (byte *)gs_alloc_bytes(dev->memory,
- (width+1) * num_comps,
+ (size_t)(width+1) * num_comps,
"gx_downscaler(mfs)");
if (ds->mfs_data == NULL) {
code = gs_note_error(gs_error_VMerror);
goto cleanup;
}
- memset(ds->mfs_data, 0, (width+1) * num_comps);
+ memset(ds->mfs_data, 0, (size_t)num_comps * (width+1));
}
if (dst_bpc == 1) {
ds->errors = (int *)gs_alloc_bytes(dev->memory,
- num_comps*(width+3)*sizeof(int),
+ (size_t)num_comps*(width+3)*sizeof(int),
"gx_downscaler(errors)");
if (ds->errors == NULL) {
code = gs_note_error(gs_error_VMerror);
goto cleanup;
}
- memset(ds->errors, 0, num_comps * (width+3) * sizeof(int));
+ memset(ds->errors, 0, (size_t)num_comps * (width+3) * sizeof(int));
}
return 0;
@@ -2125,189 +2348,53 @@ int gx_downscaler_init_planar_trapped_cm(gx_downscaler_t *ds,
static int get_line_for_trap(void *arg, unsigned char *buf)
{
- gx_downscaler_t *ds = (gx_downscaler_t *)arg;
+ liner_claptrap *ct = (liner_claptrap *)arg;
/* Allow for devices (like psdcmyk) that make several passes through
- * the image. */
- if (ds->claptrap_y == ds->dev->height)
- ds->claptrap_y = 0;
+ * the image. This is a bit crap cos it assumes that we will pass
+ * through strictly from top to bottom (possibly repeatedly). */
+ if (ct->y == ct->height)
+ ct->y = 0;
- return (*dev_proc(ds->dev, get_bits))(ds->dev, ds->claptrap_y++, buf, NULL);
+ return ct->chain->get_line(ct->chain, buf, ct->y++);
}
-int gx_downscaler_init(gx_downscaler_t *ds,
- gx_device *dev,
- int src_bpc,
- int dst_bpc,
- int num_comps,
- int factor,
- int mfs,
- int (*adjust_width_proc)(int, int),
- int adjust_width)
-{
- return gx_downscaler_init_trapped_cm_ets(ds, dev, src_bpc, dst_bpc, num_comps,
- factor, mfs, adjust_width_proc, adjust_width, 0, 0, NULL, NULL, NULL, 0, 0);
-}
-
-
-int gx_downscaler_init_ets(gx_downscaler_t *ds,
- gx_device *dev,
- int src_bpc,
- int dst_bpc,
- int num_comps,
- int factor,
- int mfs,
- int (*adjust_width_proc)(int, int),
- int adjust_width,
- int ets)
+int gx_downscaler_init(gx_downscaler_t *ds,
+ gx_device *dev,
+ int src_bpc,
+ int dst_bpc,
+ int num_comps,
+ const gx_downscaler_params *params,
+ int (*adjust_width_proc)(int, int),
+ int adjust_width)
{
- return gx_downscaler_init_trapped_cm_ets(ds, dev, src_bpc, dst_bpc, num_comps,
- factor, mfs, adjust_width_proc, adjust_width, 0, 0, NULL, NULL, NULL, 0, ets);
-}
-
-int gx_downscaler_init_trapped(gx_downscaler_t *ds,
- gx_device *dev,
- int src_bpc,
- int dst_bpc,
- int num_comps,
- int factor,
- int mfs,
- int (*adjust_width_proc)(int, int),
- int adjust_width,
- int trap_w,
- int trap_h,
- const int *comp_order)
-{
- return gx_downscaler_init_trapped_cm_ets(ds, dev, src_bpc, dst_bpc,
- num_comps, factor, mfs,
- adjust_width_proc, adjust_width,
- trap_w, trap_h, comp_order,
- NULL, NULL, 0, 0);
-}
-
-int gx_downscaler_init_trapped_ets(gx_downscaler_t *ds,
- gx_device *dev,
- int src_bpc,
- int dst_bpc,
- int num_comps,
- int factor,
- int mfs,
- int (*adjust_width_proc)(int, int),
- int adjust_width,
- int trap_w,
- int trap_h,
- const int *comp_order,
- int ets)
-{
- return gx_downscaler_init_trapped_cm_ets(ds, dev, src_bpc, dst_bpc,
- num_comps, factor, mfs,
- adjust_width_proc, adjust_width,
- trap_w, trap_h, comp_order,
- NULL, NULL, 0, ets);
-}
-int gx_downscaler_init_cm(gx_downscaler_t *ds,
- gx_device *dev,
- int src_bpc,
- int dst_bpc,
- int num_comps,
- int factor,
- int mfs,
- int (*adjust_width_proc)(int, int),
- int adjust_width,
- gx_downscale_cm_fn *apply_cm,
- void *apply_cm_arg,
- int post_cm_num_comps)
-{
- return gx_downscaler_init_trapped_cm_ets(ds, dev, src_bpc, dst_bpc,
- num_comps, factor, mfs,
- adjust_width_proc, adjust_width,
- 0, 0, NULL,
- apply_cm, apply_cm_arg, post_cm_num_comps, 0);
-}
-
-int gx_downscaler_init_cm_ets(gx_downscaler_t *ds,
- gx_device *dev,
- int src_bpc,
- int dst_bpc,
- int num_comps,
- int factor,
- int mfs,
- int (*adjust_width_proc)(int, int),
- int adjust_width,
- gx_downscale_cm_fn *apply_cm,
- void *apply_cm_arg,
- int post_cm_num_comps,
- int ets)
-{
- return gx_downscaler_init_trapped_cm_ets(ds, dev, src_bpc, dst_bpc,
- num_comps, factor, mfs,
- adjust_width_proc, adjust_width,
- 0, 0, NULL,
- apply_cm, apply_cm_arg, post_cm_num_comps, ets);
-}
-
-int gx_downscaler_init_trapped_cm(gx_downscaler_t *ds,
- gx_device *dev,
- int src_bpc,
- int dst_bpc,
- int num_comps,
- int factor,
- int mfs,
- int (*adjust_width_proc)(int, int),
- int adjust_width,
- int trap_w,
- int trap_h,
- const int *comp_order,
- gx_downscale_cm_fn *apply_cm,
- void *apply_cm_arg,
- int post_cm_num_comps)
-{
- return gx_downscaler_init_trapped_cm_ets(ds, dev, src_bpc, dst_bpc,
- num_comps, factor, mfs,
- adjust_width_proc, adjust_width,
- trap_w, trap_h, comp_order,
- apply_cm, apply_cm_arg, post_cm_num_comps,
- 0);
+ return gx_downscaler_init_cm(ds, dev, src_bpc, dst_bpc, num_comps,
+ params, adjust_width_proc, adjust_width,
+ NULL, NULL, 0);
}
static gx_downscaler_ht_t bogus_ets_halftone;
-int gx_downscaler_init_trapped_cm_ets(gx_downscaler_t *ds,
- gx_device *dev,
- int src_bpc,
- int dst_bpc,
- int num_comps,
- int factor,
- int mfs,
- int (*adjust_width_proc)(int, int),
- int adjust_width,
- int trap_w,
- int trap_h,
- const int *comp_order,
- gx_downscale_cm_fn *apply_cm,
- void *apply_cm_arg,
- int post_cm_num_comps,
- int ets)
-{
- return gx_downscaler_init_trapped_cm_halftone(ds,
- dev,
- src_bpc,
- dst_bpc,
- num_comps,
- factor,
- mfs,
- adjust_width_proc,
- adjust_width,
- trap_w,
- trap_h,
- comp_order,
- apply_cm,
- apply_cm_arg,
- post_cm_num_comps,
- ets ? &bogus_ets_halftone : NULL);
+int gx_downscaler_init_cm(gx_downscaler_t *ds,
+ gx_device *dev,
+ int src_bpc,
+ int dst_bpc,
+ int num_comps,
+ const gx_downscaler_params *params,
+ int (*adjust_width_proc)(int, int),
+ int adjust_width,
+ gx_downscale_cm_fn *apply_cm,
+ void *apply_cm_arg,
+ int post_cm_num_comps)
+{
+ return gx_downscaler_init_cm_halftone(ds, dev, src_bpc, dst_bpc,
+ num_comps, params,
+ adjust_width_proc, adjust_width,
+ apply_cm, apply_cm_arg,
+ post_cm_num_comps,
+ params->ets ? &bogus_ets_halftone : NULL);
}
-
static gx_downscale_core *
select_8_to_8_core(int nc, int factor)
{
@@ -2332,23 +2419,25 @@ select_8_to_8_core(int nc, int factor)
return NULL;
}
+#ifdef WITH_CAL
+static unsigned char bg0[GX_DEVICE_COLOR_MAX_COMPONENTS] = {0};
+static unsigned char bg1[GX_DEVICE_COLOR_MAX_COMPONENTS] = {
+ 0xFF, 0xFF, 0xFF, 0xFF };
+#endif
+
int
-gx_downscaler_init_trapped_cm_halftone(gx_downscaler_t *ds,
- gx_device *dev,
- int src_bpc,
- int dst_bpc,
- int num_comps,
- int factor,
- int mfs,
- int (*adjust_width_proc)(int, int),
- int adjust_width,
- int trap_w,
- int trap_h,
- const int *comp_order,
- gx_downscale_cm_fn *apply_cm,
- void *apply_cm_arg,
- int post_cm_num_comps,
- gx_downscaler_ht_t *ht)
+gx_downscaler_init_cm_halftone(gx_downscaler_t *ds,
+ gx_device *dev,
+ int src_bpc,
+ int dst_bpc,
+ int num_comps,
+ const gx_downscaler_params *params,
+ int (*adjust_width_proc)(int, int),
+ int adjust_width,
+ gx_downscale_cm_fn *apply_cm,
+ void *apply_cm_arg,
+ int post_cm_num_comps,
+ gx_downscaler_ht_t *ht)
{
int size;
int post_size;
@@ -2356,16 +2445,18 @@ gx_downscaler_init_trapped_cm_halftone(gx_downscaler_t *ds,
int width;
int awidth;
int pad_white;
- int code;
+ int code = 0;
gx_downscale_core *core;
int upfactor;
int downfactor;
int nc;
+ int factor = params->downscale_factor;
+ int mfs = params->min_feature_size;
size = gdev_mem_bytes_per_scan_line((gx_device *)dev);
post_size = bitmap_raster(dev->width * src_bpc * post_cm_num_comps);
- decode_factor(factor, &upfactor, &downfactor);
+ gx_downscaler_decode_factor(factor, &upfactor, &downfactor);
/* width = scaled width */
width = (dev->width * upfactor)/downfactor;
@@ -2393,20 +2484,140 @@ gx_downscaler_init_trapped_cm_halftone(gx_downscaler_t *ds,
ds->ht = ht;
ds->dst_bpc = dst_bpc;
ds->num_comps = num_comps;
+ ds->do_skew_detection = params->do_skew_detection;
+
+ /* The primary line source comes always from getbits. */
+ {
+ liner_getbits_chunky *gb_liner;
- code = check_trapping(dev->memory, trap_w, trap_h, num_comps, comp_order);
+ code = alloc_liner(dev->memory,
+ liner_getbits_chunky,
+ getbits_chunky_line,
+ getbits_chunky_drop,
+ &gb_liner);
+ if (code < 0)
+ goto cleanup;
+ gb_liner->dev = dev;
+ ds->liner = &gb_liner->base;
+ }
+
+#ifdef WITH_CAL
+ if (ds->do_skew_detection) {
+ /* Do a skew detection pass */
+ int j;
+ int w = ds->dev->width;
+ int h = ds->dev->height;
+ int n = ds->dev->color_info.num_components;
+ cal_skew *skew;
+ byte *buffer = gs_alloc_bytes(ds->dev->memory, w*n, "skew_row");
+ if (buffer == NULL)
+ return_error(gs_error_VMerror);
+ skew = cal_skew_init(ds->dev->memory->gs_lib_ctx->core->cal_ctx,
+ ds->dev->memory,
+ w, h);
+ if (skew == NULL)
+ code = gs_error_VMerror;
+ for (j = 0; code >= 0 && j < h; j++) {
+ code = ds->liner->get_line(ds->liner, buffer, j);
+ /* Craply turn that into "greyscale" */
+ if (n > 1) {
+ int i, k;
+ const byte *src = buffer;
+ byte *dst = buffer;
+ for (i = w; i > 0; i--) {
+ int v = 0;
+ for (k = n; k > 0; k--)
+ v += *src++;
+ *dst++ = (v+(n>>1))/n;
+ }
+ }
+ code = cal_skew_process(skew, ds->dev->memory, buffer);
+ }
+ if (code >= 0)
+ ds->skew_angle = cal_skew_detect(skew, ds->dev->memory);
+ gs_free_object(ds->dev->memory, buffer, "skew_row");
+ cal_skew_fin(skew, ds->dev->memory);
+ if (code < 0)
+ goto cleanup;
+
+ if (ds->skew_angle != 0) {
+ liner_skew *sk_liner;
+ unsigned int dw, dh;
+
+ code = alloc_liner(dev->memory,
+ liner_skew,
+ skew_line,
+ skew_drop,
+ &sk_liner);
+ if (code < 0)
+ goto cleanup;
+ sk_liner->chain = ds->liner;
+ sk_liner->get_row = 0;
+ sk_liner->got_row = 0;
+ sk_liner->height = dev->height;
+ ds->liner = &sk_liner->base;
+ sk_liner->deskewer = cal_deskewer_init(
+ ds->dev->memory->gs_lib_ctx->core->cal_ctx,
+ ds->dev->memory,
+ ds->dev->width, ds->dev->height,
+ &dw,
+ &dh,
+ ds->skew_angle,
+ 1, /* Keep the page size constant */
+ 1.0, 1.0, 1.0, 1.0,
+ (ds->num_comps <= 3 ? bg1 : bg0),
+ ds->num_comps);
+ if (sk_liner->deskewer == NULL) {
+ emprintf(dev->memory, "Deskewer initialisation failed");
+ code = gs_note_error(gs_error_VMerror);
+ goto cleanup;
+ }
+ sk_liner->bander = cal_deskewer_band_begin(sk_liner->deskewer,
+ ds->dev->memory,
+ 0, 0);
+ if (sk_liner->bander == NULL) {
+ emprintf(dev->memory, "Deskewer initialisation(2) failed");
+ code = gs_note_error(gs_error_VMerror);
+ goto cleanup;
+ }
+ }
+ }
+#endif
+
+ code = check_trapping(dev->memory, params->trap_w, params->trap_h,
+ num_comps, params->trap_order);
if (code < 0)
return code;
- if (trap_w > 0 || trap_h > 0) {
- ds->claptrap = ClapTrap_Init(dev->memory, width, dev->height, num_comps, comp_order, trap_w, trap_h, get_line_for_trap, ds);
- if (ds->claptrap == NULL) {
+ if (params->trap_w > 0 || params->trap_h > 0) {
+ liner_claptrap *ct_liner;
+
+ code = alloc_liner(dev->memory,
+ liner_claptrap,
+ claptrap_line,
+ claptrap_drop,
+ &ct_liner);
+ if (code < 0)
+ goto cleanup;
+ ct_liner->chain = ds->liner;
+ ct_liner->y = 0;
+ ct_liner->height = dev->height;
+ ds->liner = &ct_liner->base;
+ ct_liner->claptrap = ClapTrap_Init(dev->memory,
+ width,
+ dev->height,
+ num_comps,
+ params->trap_order,
+ params->trap_w,
+ params->trap_h,
+ get_line_for_trap,
+ ct_liner);
+ if (ct_liner->claptrap == NULL) {
emprintf(dev->memory, "Trapping initialisation failed");
code = gs_note_error(gs_error_VMerror);
goto cleanup;
}
- } else
- ds->claptrap = NULL;
+ }
/* Choose an appropriate core. Try to honour our early_cm
* choice, and fallback to late cm if we can't. */
@@ -2488,7 +2699,7 @@ gx_downscaler_init_trapped_cm_halftone(gx_downscaler_t *ds,
if (apply_cm) {
ds->post_cm[0] = gs_alloc_bytes(dev->memory,
- post_size * downfactor,
+ (size_t)post_size * downfactor,
"gx_downscaler(data)");
if (ds->post_cm[0] == NULL) {
code = gs_note_error(gs_error_VMerror);
@@ -2498,8 +2709,8 @@ gx_downscaler_init_trapped_cm_halftone(gx_downscaler_t *ds,
if (core != NULL || apply_cm) {
ds->pre_cm[0] = gs_alloc_bytes(dev->memory,
- span * downfactor,
- "gx_downscaler(data)");
+ (size_t)span * downfactor,
+ "gx_downscaler(data)");
if (ds->pre_cm[0] == NULL) {
code = gs_note_error(gs_error_VMerror);
goto cleanup;
@@ -2508,23 +2719,23 @@ gx_downscaler_init_trapped_cm_halftone(gx_downscaler_t *ds,
if (core != NULL) {
if (mfs > 1) {
ds->mfs_data = (byte *)gs_alloc_bytes(dev->memory,
- (awidth+1)*nc,
+ (size_t)(awidth+1)*nc,
"gx_downscaler(mfs)");
if (ds->mfs_data == NULL) {
code = gs_note_error(gs_error_VMerror);
goto cleanup;
}
- memset(ds->mfs_data, 0, (awidth+1)*nc);
+ memset(ds->mfs_data, 0, (size_t)nc*(awidth+1));
}
if (dst_bpc == 1) {
ds->errors = (int *)gs_alloc_bytes(dev->memory,
- nc*(awidth+3)*sizeof(int),
+ (size_t)nc*(awidth+3)*sizeof(int),
"gx_downscaler(errors)");
if (ds->errors == NULL) {
code = gs_note_error(gs_error_VMerror);
goto cleanup;
}
- memset(ds->errors, 0, nc * (awidth+3) * sizeof(int));
+ memset(ds->errors, 0, (size_t)nc * (awidth+3) * sizeof(int));
}
}
@@ -2538,11 +2749,17 @@ gx_downscaler_init_trapped_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;
}
ds->num_planes = 0;
@@ -2556,11 +2773,13 @@ void gx_downscaler_fin(gx_downscaler_t *ds)
ds->htrow = NULL;
ds->htrow_alloc = NULL;
- if (ds->claptrap)
- ClapTrap_Fin(ds->dev->memory, ds->claptrap);
+ if (ds->liner)
+ ds->liner->drop(ds->liner, ds->dev->memory);
+ ds->liner = NULL;
if (ds->ets_config)
ets_destroy(ds->dev->memory, ds->ets_config);
+ ds->ets_config = NULL;
}
/* Chunky case */
@@ -2573,14 +2792,13 @@ int gx_downscaler_getbits(gx_downscaler_t *ds,
byte *data_ptr;
int upfactor, downfactor;
- decode_factor(ds->factor, &upfactor, &downfactor);
+ gx_downscaler_decode_factor(ds->factor, &upfactor, &downfactor);
/* Check for the simple case */
if (ds->down_core == NULL) {
- if (ds->claptrap)
- code = ClapTrap_GetLine(ds->claptrap, ds->apply_cm ? ds->pre_cm[0] : out_data);
- else
- code = (*dev_proc(ds->dev, get_bits))(ds->dev, row, ds->apply_cm ? ds->pre_cm[0] : out_data, NULL);
+ code = ds->liner->get_line(ds->liner,
+ ds->apply_cm ? ds->pre_cm[0] : out_data,
+ row);
if (code < 0)
return code;
if (ds->apply_cm) {
@@ -2594,23 +2812,13 @@ int gx_downscaler_getbits(gx_downscaler_t *ds,
y = row * downfactor;
y_end = y + downfactor;
data_ptr = ds->pre_cm[0];
- if (ds->claptrap) {
- do {
- code = ClapTrap_GetLine(ds->claptrap, data_ptr);
- if (code < 0)
- return code;
- data_ptr += ds->span;
- y++;
- } while (y < y_end);
- } else {
- do {
- code = (*dev_proc(ds->dev, get_bits))(ds->dev, y, data_ptr, NULL);
- if (code < 0)
- return code;
- data_ptr += ds->span;
- y++;
- } while (y < y_end);
- }
+ do {
+ code = ds->liner->get_line(ds->liner, data_ptr, y);
+ if (code < 0)
+ return code;
+ data_ptr += ds->span;
+ y++;
+ } while (y < y_end);
if (ds->apply_cm) {
if (ds->early_cm) {
@@ -2636,7 +2844,7 @@ int gx_downscaler_get_bits_rectangle(gx_downscaler_t *ds,
gs_get_bits_params_t *params,
int row)
{
- int code;
+ int code = 0;
gs_int_rect rect;
int plane;
int factor = ds->factor;
@@ -2644,9 +2852,13 @@ int gx_downscaler_get_bits_rectangle(gx_downscaler_t *ds,
int upfactor, downfactor;
int subrow;
int copy = (ds->dev->width * ds->src_bpc + 7)>>3;
- int i, j;
+ int i, j, n;
- decode_factor(factor, &upfactor, &downfactor);
+ n = ds->dev->width;
+ if (ds->dev->color_info.depth > ds->dev->color_info.num_components*8+8)
+ n *= 2;
+
+ gx_downscaler_decode_factor(factor, &upfactor, &downfactor);
subrow = row % upfactor;
if (subrow) {
@@ -2662,7 +2874,7 @@ int gx_downscaler_get_bits_rectangle(gx_downscaler_t *ds,
rect.q.y = ((row/upfactor) + 1) * downfactor;
/* Check for the simple case */
- if (ds->down_core == NULL && ds->claptrap == NULL) {
+ if (ds->down_core == NULL) {
gs_get_bits_params_t saved;
if (ds->apply_cm) {
/* Always do the request giving our own workspace,
@@ -2672,7 +2884,7 @@ int gx_downscaler_get_bits_rectangle(gx_downscaler_t *ds,
params->data[i] = ds->pre_cm[i];
params->options |= GB_RETURN_POINTER;
}
- code = (*dev_proc(ds->dev, get_bits_rectangle))(ds->dev, &rect, params, NULL);
+ code = ds->liner->get_line(ds->liner, params, row);
if (code < 0)
return code;
if (ds->apply_cm) {
@@ -2697,46 +2909,37 @@ int gx_downscaler_get_bits_rectangle(gx_downscaler_t *ds,
for (i = 0; i < ds->num_planes; i++)
params2.data[i] = ds->pre_cm[i];
- /* Get downfactor rows worth of data */
- if (ds->claptrap)
- code = gs_error_rangecheck; /* Always work a line at a time with claptrap */
- else
- code = (*dev_proc(ds->dev, get_bits_rectangle))(ds->dev, &rect, &params2, NULL);
- if (code == gs_error_rangecheck) {
- /* At the bottom of a band, the get_bits_rectangle call can fail to be
- * able to return us enough lines of data at the same time. We therefore
- * drop back to reading them one at a time, and copying them into our
- * own buffer. */
- for (i = 0; i < downfactor; i++) {
- rect.q.y = rect.p.y+1;
- if (rect.q.y > ds->dev->height)
- break;
- memcpy(&params2, &ds->params, sizeof(params2));
- for (j = 0; j < ds->num_planes; j++)
- params2.data[j] = ds->pre_cm[j] + i * ds->span;
- if (ds->claptrap) {
- ds->claptrap_params = &params2;
- code = ClapTrap_GetLinePlanar(ds->claptrap, &params2.data[0]);
- } else {
- /* We always want a copy */
- params2.options &= ~GB_RETURN_POINTER;
- params2.options |= GB_RETURN_COPY;
- code = (*dev_proc(ds->dev, get_bits_rectangle))(ds->dev, &rect, &params2, NULL);
- }
- if (code < 0)
- break;
- rect.p.y++;
+ /* Get downfactor rows worth of data - we always work a line at a
+ * time now. */
+ for (i = 0; i < downfactor; i++) {
+ rect.q.y = rect.p.y+1;
+ if (rect.q.y > ds->dev->height)
+ break;
+ memcpy(&params2, &ds->params, sizeof(params2));
+ for (j = 0; j < ds->num_planes; j++)
+ params2.data[j] = ds->pre_cm[j] + i * ds->span;
+ code = ds->liner->get_line(ds->liner, &params2, rect.p.y);
+ if (code < 0)
+ break;
+ for (j = 0; j < ds->num_planes; j++) {
+ byte *tgt = ds->pre_cm[j] + i * ds->span;
+ if (params2.data[j] != tgt)
+ memcpy(tgt, params2.data[j], n);
}
- if (i == 0)
- return code;
- /* If we still haven't got enough, we've hit the end of the page; just
- * duplicate the last line we did get. */
- for (;i < downfactor; i++)
- 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);
+ rect.p.y++;
}
+ if (i == 0)
+ return code;
if (code < 0)
return code;
+ /* If we still haven't got enough, we've hit the end of the page; just
+ * duplicate the last line we did get. */
+ for (; i < downfactor; i++)
+ 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);
+
+ for (j = 0; j < ds->num_planes; j++)
+ params2.data[j] = ds->pre_cm[j];
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);
@@ -2878,7 +3081,7 @@ static int downscaler_process_fn(void *arg_, gx_device *dev, gx_device *bdev, co
}
/* Pass on to further processing */
- if (code >= 0 && arg->orig_options && arg->orig_options->process_fn) {
+ if (arg->orig_options && arg->orig_options->process_fn) {
out_rect.p.y = rect->p.y*arg->upfactor/arg->downfactor;
out_rect.q.y += out_rect.p.y;
code = arg->orig_options->process_fn(arg->orig_options->arg, dev,
@@ -2925,7 +3128,7 @@ int gx_downscaler_process_page(gx_device *dev,
gx_downscale_core *core;
arg.orig_options = options;
- decode_factor(factor, &arg.upfactor, &arg.downfactor);
+ gx_downscaler_decode_factor(factor, &arg.upfactor, &arg.downfactor);
arg.ds.dev = dev;
arg.ds.width = (dev->width * arg.upfactor + arg.downfactor-1)/arg.downfactor;
arg.ds.awidth = arg.ds.width;
@@ -2981,7 +3184,7 @@ int gx_downscaler_read_params(gs_param_list *plist,
int features)
{
int code;
- int downscale, mfs, ets;
+ int downscale, mfs, ets, deskew;
int trap_w, trap_h;
const char *param_name;
gs_param_int_array trap_order;
@@ -3004,6 +3207,22 @@ int gx_downscaler_read_params(gs_param_list *plist,
return code;
}
+ switch (code = param_read_int(plist,
+ (param_name = "Deskew"),
+ &deskew)) {
+ case 1:
+ break;
+ case 0:
+ if (deskew >= 0) {
+ params->do_skew_detection = deskew;
+ break;
+ }
+ code = gs_error_rangecheck;
+ default:
+ param_signal_error(plist, param_name, code);
+ return code;
+ }
+
if (features & GX_DOWNSCALER_PARAMS_MFS)
{
switch (code = param_read_int(plist, (param_name = "MinFeatureSize"), &mfs)) {
@@ -3136,6 +3355,8 @@ int gx_downscaler_write_params(gs_param_list *plist,
if ((code = param_write_int(plist, "DownScaleFactor", &params->downscale_factor)) < 0)
ecode = code;
+ if ((code = param_write_int(plist, "Deskew", &params->do_skew_detection)) < 0)
+ ecode = code;
if (features & GX_DOWNSCALER_PARAMS_MFS)
{
if ((code = param_write_int(plist, "MinFeatureSize", &params->min_feature_size)) < 0)
@@ -3167,9 +3388,9 @@ void *ets_malloc(void *malloc_arg, int size)
void *ets_calloc(void *malloc_arg, int count, int size)
{
- void *p = ets_malloc(malloc_arg, count * size);
+ void *p = ets_malloc(malloc_arg, (size_t)count * size);
if (p)
- memset(p, 0, count * size);
+ memset(p, 0, (size_t)count * size);
return p;
}