diff options
author | Robin Watts <robin.watts@artifex.com> | 2018-04-19 12:45:14 +0100 |
---|---|---|
committer | Robin Watts <Robin.Watts@artifex.com> | 2019-06-25 10:37:09 +0100 |
commit | 140a9359f3cc6739c7caf0796430bc3112cb3cd5 (patch) | |
tree | 91ef3f7e59c06fe13ecfff2d7d2461ebd8da1c2b /base | |
parent | dd75f619d0ae98e21e30ad89d2e7d2cd4277cc2e (diff) | |
download | ghostpdl-140a9359f3cc6739c7caf0796430bc3112cb3cd5.tar.gz |
Initial import of CAL.
Diffstat (limited to 'base')
-rw-r--r-- | base/cal.mak | 77 | ||||
-rw-r--r-- | base/gdevdrop.c | 372 | ||||
-rw-r--r-- | base/gs.mak | 1 | ||||
-rw-r--r-- | base/gxicolor.c | 180 | ||||
-rw-r--r-- | base/gxidata.c | 12 | ||||
-rw-r--r-- | base/gximage.h | 5 | ||||
-rw-r--r-- | base/gximono.c | 203 | ||||
-rw-r--r-- | base/gxiscale.c | 15 | ||||
-rw-r--r-- | base/lib.mak | 74 | ||||
-rw-r--r-- | base/siscale_cal.c | 393 | ||||
-rw-r--r-- | base/sisparam.h | 25 | ||||
-rw-r--r-- | base/unix-gcc.mak | 1 | ||||
-rw-r--r-- | base/winlib.mak | 1 |
13 files changed, 1313 insertions, 46 deletions
diff --git a/base/cal.mak b/base/cal.mak new file mode 100644 index 000000000..004379624 --- /dev/null +++ b/base/cal.mak @@ -0,0 +1,77 @@ +# Copyright (C) 2019 Artifex Software, Inc. +# All Rights Reserved. +# +# This software is provided AS-IS with no warranty, either express or +# implied. +# +# This software is distributed under license and may not be copied, +# modified or distributed except as expressly authorized under the terms +# of the license contained in the file LICENSE in this distribution. +# +# Refer to licensing information at http://www.artifex.com or contact +# Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, San Rafael, +# CA 94903, U.S.A., +1(415)492-9861, for further information. +# + +# makefile for CAL library code. +# Users of this makefile must define the following: +# WITH_CAL - whether to compile in or link to the library +# CALSRCDIR - the library source directory +# +# gs.mak and friends define the following: +# CALOBJDIR - the output obj directory +# CALGENDIR - generated (.dev) file directory +# + +CAL_MAK=$(GLSRC)cal.mak $(TOP_MAKEFILES) + +CAL_GEN=$(CALOBJDIR)$(D) + +CAL_PREFIX=cal_ +CAL_OBJ=$(CALOBJDIR)$(D) +CAL_SRC=$(CALSRCDIR)$(D) + +# source files to build from the CSDK source + +cal_OBJS = \ + $(CAL_OBJ)$(CAL_PREFIX)cal.$(OBJ) \ + $(CAL_OBJ)$(CAL_PREFIX)rescale.$(OBJ) \ + $(CAL_OBJ)$(CAL_PREFIX)halftone.$(OBJ) \ + $(CAL_OBJ)$(CAL_PREFIX)doubler.$(OBJ) + +cal_HDRS = \ + $(CAL_SRC)cal.h \ + $(CAL_SRC)cal-impl.h \ + +# external link .dev - empty, as we add the lib to LDFLAGS +#$(GLOBJ)cal.dev : $(CAL_MAK) $(ECHOGS_XE) \ +# $(CAL_MAK) $(MAKEDIRS) +# $(SETMOD) $(CAL_GEN)cal + +# compile our own .dev +$(GLOBJ)cal.dev : $(ECHOGS_XE) $(cal_OBJS) \ + $(CAL_MAK) $(MAKEDIRS) + $(SETMOD) $(GLOBJ)cal $(cal_OBJS) + +# define our specific compiler +CAL_CC=$(CC) $(CFLAGS) $(D_)OPJ_STATIC$(_D) $(D_)STANDARD_SLOW_VERSION$(_D) $(I_)$(CAL_GEN)$(_I) $(I_)$(CAL_SRC)$(_I) +CAL_O=$(O_)$(CAL_OBJ)$(CAL_PREFIX) + +CAL_DEP=$(AK) $(CAL_MAK) $(MAKEDIRS) + +# explicit rules for building each source file +# for simplicity we have every source file depend on all headers + +$(CAL_OBJ)$(CAL_PREFIX)cal.$(OBJ) : $(CAL_SRC)cal.c $(cal_HDRS) $(CAL_DEP) + $(CAL_CC) $(CAL_O)cal.$(OBJ) $(C_) $(CAL_SRC)cal.c + +$(CAL_OBJ)$(CAL_PREFIX)rescale.$(OBJ) : $(CAL_SRC)rescale.c $(cal_HDRS) $(CAL_DEP) $(CAL_SRC)rescale_c.h $(CAL_SRC)rescale_sse.h + $(CAL_CC) $(CAL_O)rescale.$(OBJ) $(C_) $(CAL_SRC)rescale.c + +$(CAL_OBJ)$(CAL_PREFIX)halftone.$(OBJ) : $(CAL_SRC)halftone.c $(cal_HDRS) $(CAL_DEP) $(CAL_SRC)halftone_c.h $(CAL_SRC)halftone_sse.h + $(CAL_CC) $(CAL_O)halftone.$(OBJ) $(C_) $(CAL_SRC)halftone.c + +$(CAL_OBJ)$(CAL_PREFIX)doubler.$(OBJ) : $(CAL_SRC)doubler.c $(cal_HDRS) $(CAL_DEP) $(CAL_SRC)double_c.h $(CAL_SRC)double_sse.h + $(CAL_CC) $(CAL_O)doubler.$(OBJ) $(C_) $(CAL_SRC)doubler.c + +# end of file diff --git a/base/gdevdrop.c b/base/gdevdrop.c index fe78cfc86..82e10fc8c 100644 --- a/base/gdevdrop.c +++ b/base/gdevdrop.c @@ -30,6 +30,38 @@ #include "gdevmrop.h" #include "gxdevsop.h" #include "stdint_.h" +#ifdef WITH_CAL +#include "cal.h" + +static void * +cal_do_malloc(void *opaque, size_t size) +{ + gs_memory_t *mem = (gs_memory_t *)opaque; + return gs_alloc_bytes(mem, size, "cal_do_malloc"); +} + +static void * +cal_do_realloc(void *opaque, void *ptr, size_t newsize) +{ + gs_memory_t *mem = (gs_memory_t *)opaque; + return gs_resize_object(mem, ptr, newsize, "cal_do_malloc"); +} + +static void +cal_do_free(void *opaque, void *ptr) +{ + gs_memory_t *mem = (gs_memory_t *)opaque; + gs_free_object(mem, ptr, "cal_do_malloc"); +} + +static cal_allocators cal_allocs = +{ + cal_do_malloc, + cal_do_realloc, + cal_do_free +}; + +#endif /* * Define the maximum amount of space we are willing to allocate for a @@ -1037,6 +1069,10 @@ struct mem_transform_pixel_region_state_s transform_pixel_region_posture posture; mem_transform_pixel_region_render_fn *render; void *passthru; +#ifdef WITH_CAL + cal_context *cal_ctx; + cal_doubler *cal_dbl; +#endif }; static void @@ -1307,6 +1343,295 @@ mem_transform_pixel_region_render_portrait_1to1(gx_device *dev, mem_transform_pi } } +#ifdef WITH_CAL +static inline int +template_mem_transform_pixel_region_render_portrait_1to2(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs, int spp) +{ + gx_device_memory *mdev = (gx_device_memory *)dev; + gx_dda_fixed_point pnext; + int vci, vdi; + int w = state->w; + int h = state->h; + int oleft, left, right; + + if (h == 0) + return 0; + + /* Clip on y */ + get_portrait_y_extent(state, &vci, &vdi); + if (vci < state->clip.p.y) + vdi += vci - state->clip.p.y, vci = state->clip.p.y; + if (vci+vdi > state->clip.q.y) + vdi = state->clip.q.y - vci; + if (vdi <= 0) + return 0; + + pnext = state->pixels; + dda_translate(pnext.x, (-fixed_epsilon)); + left = fixed2int_var_rounded(dda_current(pnext.x)); + if_debug5m('b', dev->memory, "[b]y=%d data_x=%d w=%d xt=%f yt=%f\n", + vci, data_x, w, fixed2float(dda_current(pnext.x)), fixed2float(dda_current(pnext.y))); + right = fixed2int_var_rounded(dda_current(pnext.x)) + w * 2; + + if (left > right) { + int tmp = left; left = right; right = tmp; + } + oleft = left; + if (left < state->clip.p.x) + left = state->clip.p.x; + if (right > state->clip.q.x) + right = state->clip.q.x; + if (left < right) { + byte *out[2]; + const byte *in = buffer[0] + (data_x + left - oleft) * spp; + int lines_out; + out[0] = mdev->base + left * spp + mdev->raster * vci; + out[1] = out[0] + (vdi > 1 ? mdev->raster : 0); + lines_out = cal_doubler_process(state->cal_dbl, dev->memory, + &in, &out[0]); + (void)lines_out; + /* assert(lines_out == 2) */ + } + + return 0; +} + +static int +mem_transform_pixel_region_render_portrait_1to2_1(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs) +{ + return template_mem_transform_pixel_region_render_portrait_1to2(dev, state, buffer, data_x, cmapper, pgs, 1); +} + +static int +mem_transform_pixel_region_render_portrait_1to2_3(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs) +{ + return template_mem_transform_pixel_region_render_portrait_1to2(dev, state, buffer, data_x, cmapper, pgs, 3); +} + +static int +mem_transform_pixel_region_render_portrait_1to2_4(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs) +{ + return template_mem_transform_pixel_region_render_portrait_1to2(dev, state, buffer, data_x, cmapper, pgs, 4); +} + +static int +mem_transform_pixel_region_render_portrait_1to2_n(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs) +{ + return template_mem_transform_pixel_region_render_portrait_1to2(dev, state, buffer, data_x, cmapper, pgs, state->spp); +} + +static int +mem_transform_pixel_region_render_portrait_1to2(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs) +{ + if (!cmapper->direct) + return mem_transform_pixel_region_render_portrait(dev, state, buffer, data_x, cmapper, pgs); + switch(state->spp) { + case 1: + return mem_transform_pixel_region_render_portrait_1to2_1(dev, state, buffer, data_x, cmapper, pgs); + case 3: + return mem_transform_pixel_region_render_portrait_1to2_3(dev, state, buffer, data_x, cmapper, pgs); + case 4: + return mem_transform_pixel_region_render_portrait_1to2_4(dev, state, buffer, data_x, cmapper, pgs); + default: + return mem_transform_pixel_region_render_portrait_1to2_n(dev, state, buffer, data_x, cmapper, pgs); + } +} + +static inline int +template_mem_transform_pixel_region_render_portrait_1to4(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs, int spp) +{ + gx_device_memory *mdev = (gx_device_memory *)dev; + gx_dda_fixed_point pnext; + int vci, vdi; + int w = state->w; + int h = state->h; + int oleft, left, right; + + if (h == 0) + return 0; + + /* Clip on y */ + get_portrait_y_extent(state, &vci, &vdi); + if (vci < state->clip.p.y) + vdi += vci - state->clip.p.y, vci = state->clip.p.y; + if (vci+vdi > state->clip.q.y) + vdi = state->clip.q.y - vci; + if (vdi <= 0) + return 0; + + pnext = state->pixels; + dda_translate(pnext.x, (-fixed_epsilon)); + left = fixed2int_var_rounded(dda_current(pnext.x)); + if_debug5m('b', dev->memory, "[b]y=%d data_x=%d w=%d xt=%f yt=%f\n", + vci, data_x, w, fixed2float(dda_current(pnext.x)), fixed2float(dda_current(pnext.y))); + right = fixed2int_var_rounded(dda_current(pnext.x)) + w * 4 * spp; + + if (left > right) { + int tmp = left; left = right; right = tmp; + } + oleft = left; + if (left < state->clip.p.x) + left = state->clip.p.x; + if (right > state->clip.q.x) + right = state->clip.q.x; + if (left < right) { + byte *out[4]; + const byte *in = buffer[0] + (data_x + left - oleft) * spp; + int lines_out; + out[0] = mdev->base + left * spp + mdev->raster * vci; + out[1] = out[0] + (vdi > 1 ? mdev->raster : 0); + out[2] = out[1] + (vdi > 2 ? mdev->raster : 0); + out[3] = out[2] + (vdi > 3 ? mdev->raster : 0); + lines_out = cal_doubler_process(state->cal_dbl, dev->memory, + &in, &out[0]); + (void)lines_out; + /* assert(lines_out == 4) */ + } + + return 0; +} + +static int +mem_transform_pixel_region_render_portrait_1to4_1(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs) +{ + return template_mem_transform_pixel_region_render_portrait_1to4(dev, state, buffer, data_x, cmapper, pgs, 1); +} + +static int +mem_transform_pixel_region_render_portrait_1to4_3(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs) +{ + return template_mem_transform_pixel_region_render_portrait_1to4(dev, state, buffer, data_x, cmapper, pgs, 3); +} + +static int +mem_transform_pixel_region_render_portrait_1to4_4(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs) +{ + return template_mem_transform_pixel_region_render_portrait_1to4(dev, state, buffer, data_x, cmapper, pgs, 4); +} + +static int +mem_transform_pixel_region_render_portrait_1to4_n(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs) +{ + return template_mem_transform_pixel_region_render_portrait_1to4(dev, state, buffer, data_x, cmapper, pgs, state->spp); +} + +static int +mem_transform_pixel_region_render_portrait_1to4(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs) +{ + if (!cmapper->direct) + return mem_transform_pixel_region_render_portrait(dev, state, buffer, data_x, cmapper, pgs); + switch(state->spp) { + case 1: + return mem_transform_pixel_region_render_portrait_1to4_1(dev, state, buffer, data_x, cmapper, pgs); + case 3: + return mem_transform_pixel_region_render_portrait_1to4_3(dev, state, buffer, data_x, cmapper, pgs); + case 4: + return mem_transform_pixel_region_render_portrait_1to4_4(dev, state, buffer, data_x, cmapper, pgs); + default: + return mem_transform_pixel_region_render_portrait_1to4_n(dev, state, buffer, data_x, cmapper, pgs); + } +} + +static inline int +template_mem_transform_pixel_region_render_portrait_1to8(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs, int spp) +{ + gx_device_memory *mdev = (gx_device_memory *)dev; + gx_dda_fixed_point pnext; + int vci, vdi; + int w = state->w; + int h = state->h; + int oleft, left, right; + + if (h == 0) + return 0; + + /* Clip on y */ + get_portrait_y_extent(state, &vci, &vdi); + if (vci < state->clip.p.y) + vdi += vci - state->clip.p.y, vci = state->clip.p.y; + if (vci+vdi > state->clip.q.y) + vdi = state->clip.q.y - vci; + if (vdi <= 0) + return 0; + + pnext = state->pixels; + dda_translate(pnext.x, (-fixed_epsilon)); + left = fixed2int_var_rounded(dda_current(pnext.x)); + if_debug5m('b', dev->memory, "[b]y=%d data_x=%d w=%d xt=%f yt=%f\n", + vci, data_x, w, fixed2float(dda_current(pnext.x)), fixed2float(dda_current(pnext.y))); + right = fixed2int_var_rounded(dda_current(pnext.x)) + w * 8; + + if (left > right) { + int tmp = left; left = right; right = tmp; + } + oleft = left; + if (left < state->clip.p.x) + left = state->clip.p.x; + if (right > state->clip.q.x) + right = state->clip.q.x; + if (left < right) { + byte *out[8]; + const byte *in = buffer[0] + (data_x + left - oleft) * spp; + int lines_out; + out[0] = mdev->base + left * spp + mdev->raster * vci; + out[1] = out[0] + (vdi > 1 ? mdev->raster : 0); + out[2] = out[1] + (vdi > 2 ? mdev->raster : 0); + out[3] = out[2] + (vdi > 3 ? mdev->raster : 0); + out[4] = out[3] + (vdi > 4 ? mdev->raster : 0); + out[5] = out[4] + (vdi > 5 ? mdev->raster : 0); + out[6] = out[5] + (vdi > 6 ? mdev->raster : 0); + out[7] = out[6] + (vdi > 7 ? mdev->raster : 0); + lines_out = cal_doubler_process(state->cal_dbl, dev->memory, + &in, &out[0]); + (void)lines_out; + /* assert(lines_out == 8) */ + } + + return 0; +} + +static int +mem_transform_pixel_region_render_portrait_1to8_1(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs) +{ + return template_mem_transform_pixel_region_render_portrait_1to8(dev, state, buffer, data_x, cmapper, pgs, 1); +} + +static int +mem_transform_pixel_region_render_portrait_1to8_3(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs) +{ + return template_mem_transform_pixel_region_render_portrait_1to8(dev, state, buffer, data_x, cmapper, pgs, 3); +} + +static int +mem_transform_pixel_region_render_portrait_1to8_4(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs) +{ + return template_mem_transform_pixel_region_render_portrait_1to8(dev, state, buffer, data_x, cmapper, pgs, 4); +} + +static int +mem_transform_pixel_region_render_portrait_1to8_n(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs) +{ + return template_mem_transform_pixel_region_render_portrait_1to8(dev, state, buffer, data_x, cmapper, pgs, state->spp); +} + +static int +mem_transform_pixel_region_render_portrait_1to8(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs) +{ + if (!cmapper->direct) + return mem_transform_pixel_region_render_portrait(dev, state, buffer, data_x, cmapper, pgs); + switch(state->spp) { + case 1: + return mem_transform_pixel_region_render_portrait_1to8_1(dev, state, buffer, data_x, cmapper, pgs); + case 3: + return mem_transform_pixel_region_render_portrait_1to8_3(dev, state, buffer, data_x, cmapper, pgs); + case 4: + return mem_transform_pixel_region_render_portrait_1to8_4(dev, state, buffer, data_x, cmapper, pgs); + default: + return mem_transform_pixel_region_render_portrait_1to8_n(dev, state, buffer, data_x, cmapper, pgs); + } +} +#endif + static inline int template_mem_transform_pixel_region_render_landscape(gx_device *dev, mem_transform_pixel_region_state_t *state, const unsigned char **buffer, int data_x, gx_cmapper_t *cmapper, const gs_gstate *pgs, int spp) { @@ -1482,8 +1807,55 @@ mem_transform_pixel_region_begin(gx_device *dev, int w, int h, int spp, state->h = h; state->spp = spp; state->posture = posture; +#ifdef WITH_CAL + state->cal_ctx = NULL; + state->cal_dbl = NULL; +#endif if (state->posture == transform_pixel_region_portrait) { +#ifdef WITH_CAL + int factor; + if (pixels->x.step.dQ == fixed_1*8 && pixels->x.step.dR == 0 && rows->y.step.dQ == fixed_1*8 && rows->y.step.dR == 0) { + state->render = mem_transform_pixel_region_render_portrait_1to8; + factor = 8; + goto use_doubler; + } else if (pixels->x.step.dQ == fixed_1*4 && pixels->x.step.dR == 0 && rows->y.step.dQ == fixed_1*4 && rows->y.step.dR == 0) { + state->render = mem_transform_pixel_region_render_portrait_1to4; + factor = 4; + goto use_doubler; + } else if (pixels->x.step.dQ == fixed_1*2 && pixels->x.step.dR == 0 && rows->y.step.dQ == fixed_1*2 && rows->y.step.dR == 0) { + unsigned int in_lines; + int l, r; + factor = 2; + state->render = mem_transform_pixel_region_render_portrait_1to2; + use_doubler: + l = fixed2int_var_rounded(dda_current(pixels->x)); + r = fixed2int_var_rounded(dda_current(pixels->x) - fixed_epsilon) + w * factor; + if (l > r) { + int t = l; l = r; r = t; + } + if (l < state->clip.p.x || r > state->clip.q.x) + goto no_cal; + state->cal_ctx = cal_init(&cal_allocs, mem); + if (state->cal_ctx == NULL) + goto no_cal; + state->cal_dbl = cal_doubler_init(state->cal_ctx, + mem, + w, + h, + factor, + CAL_DOUBLE_NEAREST, + spp, + &in_lines); + /* assert(in_lines == 1) */ + if (state->cal_dbl == NULL) { + cal_fin(state->cal_ctx, mem); + state->cal_ctx = NULL; + goto no_cal; + } + } else +no_cal: +#endif if (pixels->x.step.dQ == fixed_1 && pixels->x.step.dR == 0) state->render = mem_transform_pixel_region_render_portrait_1to1; else diff --git a/base/gs.mak b/base/gs.mak index c011d51a8..ffb31e366 100644 --- a/base/gs.mak +++ b/base/gs.mak @@ -232,6 +232,7 @@ LCUPSGENDIR=$(GLGENDIR) LCUPSOBJDIR=$(GLOBJDIR) LCUPSIGENDIR=$(GLGENDIR) LCUPSIOBJDIR=$(GLOBJDIR) +CALOBJDIR=$(GLOBJDIR) #**************** END PATCHES diff --git a/base/gxicolor.c b/base/gxicolor.c index 34cfaa469..7d7ea4aa3 100644 --- a/base/gxicolor.c +++ b/base/gxicolor.c @@ -59,7 +59,139 @@ iclass_proc(gs_image_class_4_color); static irender_proc(image_render_color_DeviceN); static irender_proc(image_render_color_icc_tpr); +#ifndef WITH_CAL static irender_proc(image_render_color_thresh); +#else +static irender_proc(image_render_color_ht_cal); + +static void * +cal_do_malloc(void *opaque, size_t size) +{ + gs_memory_t *mem = (gs_memory_t *)opaque; + return gs_alloc_bytes(mem, size, "cal_do_malloc"); +} + +static void * +cal_do_realloc(void *opaque, void *ptr, size_t newsize) +{ + gs_memory_t *mem = (gs_memory_t *)opaque; + return gs_resize_object(mem, ptr, newsize, "cal_do_malloc"); +} + +static void +cal_do_free(void *opaque, void *ptr) +{ + gs_memory_t *mem = (gs_memory_t *)opaque; + gs_free_object(mem, ptr, "cal_do_malloc"); +} + +static cal_allocators cal_allocs = +{ + cal_do_malloc, + cal_do_realloc, + cal_do_free +}; + +static void +color_halftone_callback(cal_halftone_data_t *ht, void *arg) +{ + gx_device *dev = arg; + gx_color_index dev_white = gx_device_white(dev); + gx_color_index dev_black = gx_device_black(dev); + + if (dev->is_planar) { + (*dev_proc(dev, copy_planes)) (dev, ht->data, ht->x + (ht->offset_x<<3), ht->raster, + gx_no_bitmap_id, ht->x, ht->y, ht->w, ht->h, + ht->plane_raster); + } else { + (*dev_proc(dev, copy_mono)) (dev, ht->data, ht->x + (ht->offset_x<<3), ht->raster, + gx_no_bitmap_id, ht->x, ht->y, ht->w, ht->h, dev_white, + dev_black); + } +} + +static cal_halftone* +color_halftone_init(gx_image_enum *penum) +{ + void *callback; + void *args; + int ox; + int dd_curr_y; + int dev_width; + cal_halftone *cal_ht = NULL; + gx_dda_fixed dda_ht; + cal_context *ctx; + int k; + gx_ht_order *d_order; + int code; + byte *cache = (penum->color_cache != NULL ? penum->color_cache->device_contone : NULL); + cal_matrix matrix; + int clip_x, clip_y; + + if (!gx_device_must_halftone(penum->dev)) + return NULL; + + if (penum->pgs == NULL || penum->pgs->dev_ht == NULL) + return NULL; + ctx = cal_init(&cal_allocs, penum->memory->non_gc_memory); + if (ctx == NULL) + return NULL; + penum->cal_ctx = ctx; + dda_ht = penum->dda.pixel0.x; + if (penum->dxx > 0) + dda_translate(dda_ht, -fixed_epsilon); + ox = dda_current(dda_ht); + dd_curr_y = dda_current(penum->dda.pixel0.y); + dev_width = gxht_dda_length(&dda_ht, penum->rect.w); + matrix.xx = penum->matrix.xx; + matrix.xy = penum->matrix.xy; + matrix.yx = penum->matrix.yx; + matrix.yy = penum->matrix.yy; + matrix.tx = penum->matrix.tx + matrix.xx * penum->rect.x + matrix.yx * penum->rect.y; + matrix.ty = penum->matrix.ty + matrix.xy * penum->rect.x + matrix.yy * penum->rect.y; + clip_x = fixed2int(penum->clip_outer.p.x); + clip_y = fixed2int(penum->clip_outer.p.y); + cal_ht = cal_halftone_init(ctx, + penum->memory->non_gc_memory, + penum->rect.w, + penum->rect.h, + &matrix, + penum->dev->color_info.num_components, + cache, + clip_x, + clip_y, + fixed2int_ceiling(penum->clip_outer.q.x) - clip_x, + fixed2int_ceiling(penum->clip_outer.q.y) - clip_y, + penum->adjust); + if (cal_ht == NULL) + goto fail; + + for (k = 0; k < penum->pgs->dev_ht->num_comp; k++) { + d_order = &(penum->pgs->dev_ht->components[k].corder); + code = gx_ht_construct_threshold(d_order, penum->dev, penum->pgs, k); + if (code < 0) + goto fail; + if (cal_halftone_add_screen(ctx, + penum->memory->non_gc_memory, + cal_ht, + penum->pgs->dev_ht->components[k].corder.threshold_inverted, + penum->pgs->dev_ht->components[k].corder.width, + penum->pgs->dev_ht->components[k].corder.full_height, + -penum->pgs->screen_phase[k].x, + -penum->pgs->screen_phase[k].y, + penum->pgs->dev_ht->components[k].corder.threshold) < 0) + goto fail; + } + + return cal_ht; + +fail: + cal_halftone_fin(cal_ht, penum->memory->non_gc_memory); + cal_fin(ctx, penum->memory->non_gc_memory); + penum->cal_ctx = NULL; + return NULL; +} +#endif static int image_skip_color_icc_tpr(gx_image_enum *penum, gx_device *dev); @@ -190,6 +322,14 @@ gs_image_class_4_color(gx_image_enum * penum, irender_proc_t *render_fn) if ((bpc == 1) && transfer_is_monotonic && (penum->dev->color_info.num_components == 1 || penum->dev->is_planar) && penum->bps == 8) { +#ifdef WITH_CAL + penum->cal_ht = color_halftone_init(penum); + if (penum->cal_ht != NULL) + { + penum->skip_render = image_render_color_ht_cal; + return code; + } +#else code = gxht_thresh_image_init(penum); if (code == 0) { /* NB: transfer function is pickled into the threshold arrray */ @@ -197,6 +337,7 @@ gs_image_class_4_color(gx_image_enum * penum, irender_proc_t *render_fn) *render_fn = &image_render_color_thresh; return code; } +#endif } } { @@ -469,9 +610,41 @@ image_color_icc_prep(gx_image_enum *penum_orig, const byte *psrc, uint w, return 0; } +#ifdef WITH_CAL +static int +image_render_color_ht_cal(gx_image_enum *penum, const byte *buffer, int data_x, + uint w, int h, gx_device * dev) +{ + const byte *psrc = buffer + data_x; + int code = 0; + int spp_cm = 0; + byte *psrc_cm = NULL, *psrc_cm_start = NULL; + byte *bufend = NULL; + byte *input[GX_DEVICE_COLOR_MAX_COMPONENTS]; /* to ensure 128 bit boundary */ + + if (h == 0 || penum->line_size == 0) /* line_size == 0, nothing to do */ + return 0; + + /* Get the buffer into the device color space */ + code = image_color_icc_prep(penum, psrc, w, dev, &spp_cm, &psrc_cm, + &psrc_cm_start, &bufend, true); + if (code < 0) + return code; + + code = cal_halftone_process_planar(penum->cal_ht, penum->memory->non_gc_memory, + input, halftone_callback, dev); + + /* Free cm buffer, if it was used */ + if (psrc_cm_start != NULL) { + gs_free_object(penum->pgs->memory, (byte *)psrc_cm_start, + "image_render_color_thresh"); + } + return code; +} +#else static int image_render_color_thresh(gx_image_enum *penum_orig, const byte *buffer, int data_x, - uint w, int h, gx_device * dev) + uint w, int h, gx_device * dev) { gx_image_enum *penum = penum_orig; /* const within proc */ image_posture posture = penum->posture; @@ -884,7 +1057,7 @@ flush: thresh_align = penum->thresh_buffer + offset_threshold; code = gxht_thresh_planes(penum, xrun, dest_width, dest_height, thresh_align, dev, offset_contone, - contone_stride); + contone_stride); /* Free cm buffer, if it was used */ if (psrc_cm_start != NULL) { gs_free_object(penum->pgs->memory, (byte *)psrc_cm_start, @@ -892,9 +1065,10 @@ flush: } return code; } +#endif /* Render a color image with 8 or fewer bits per sample using ICC profile. */ -static int +static int image_skip_color_icc_tpr(gx_image_enum *penum, gx_device *dev) { transform_pixel_region_data data; diff --git a/base/gxidata.c b/base/gxidata.c index dcdb2c41e..e55e5791c 100644 --- a/base/gxidata.c +++ b/base/gxidata.c @@ -22,6 +22,9 @@ #include "gxcpath.h" #include "gximage.h" #include "gsicc_cache.h" +#ifdef WITH_CAL +#include "cal.h" +#endif /* Forward declarations */ static void update_strip(gx_image_enum *penum); @@ -519,6 +522,15 @@ gx_image1_end_image(gx_image_enum_common_t * info, bool draw_last) } gs_free_object(mem, penum->line, "image line"); gs_free_object(mem, penum->buffer, "image buffer"); + +#ifdef WITH_CAL + if (penum->cal_ht != NULL) { + cal_halftone_fin(penum->cal_ht, mem->non_gc_memory); + } + if (penum->cal_ctx != NULL) { + cal_fin(penum->cal_ctx, mem->non_gc_memory); + } +#endif gx_image_free_enum(&info); return 0; } diff --git a/base/gximage.h b/base/gximage.h index 70e7c6b6a..08281e9e7 100644 --- a/base/gximage.h +++ b/base/gximage.h @@ -294,6 +294,11 @@ struct gx_image_enum_s { gx_image_icc_setup_t icc_setup; bool use_cie_range; /* Needed potentially if CS was PS CIE based */ void *tpr_state; + /* The following 2 pointers are only used if the CAL library is + * in place, but it's too much makefile upheaval to only have them + * here in CAL builds, so we live with them in all builds. */ + void *cal_ht; /* CAL halftone state pointer */ + void *cal_ctx; /* CAL context pointer */ }; /* Enumerate the pointers in an image enumerator. */ diff --git a/base/gximono.c b/base/gximono.c index 5516b5cd6..709294431 100644 --- a/base/gximono.c +++ b/base/gximono.c @@ -42,6 +42,9 @@ #include "gxht_thresh.h" #include "gxdda.h" #include "gxdevsop.h" +#ifdef WITH_CAL +#include "cal.h" +#endif #define fastfloor(x) (((int)(x)) - (((x)<0) && ((x) != (float)(int)(x)))) @@ -57,7 +60,133 @@ iclass_proc(gs_image_class_3_mono); static irender_proc(image_render_mono); +#ifndef WITH_CAL static irender_proc(image_render_mono_ht); +#else +static irender_proc(image_render_mono_ht_cal); +static int image_render_mono_ht_cal_skip_line(gx_image_enum *penum); + +static void * +cal_do_malloc(void *opaque, size_t size) +{ + gs_memory_t *mem = (gs_memory_t *)opaque; + return gs_alloc_bytes(mem, size, "cal_do_malloc"); +} + +static void * +cal_do_realloc(void *opaque, void *ptr, size_t newsize) +{ + gs_memory_t *mem = (gs_memory_t *)opaque; + return gs_resize_object(mem, ptr, newsize, "cal_do_malloc"); +} + +static void +cal_do_free(void *opaque, void *ptr) +{ + gs_memory_t *mem = (gs_memory_t *)opaque; + gs_free_object(mem, ptr, "cal_do_malloc"); +} + +static cal_allocators cal_allocs = +{ + cal_do_malloc, + cal_do_realloc, + cal_do_free +}; + +static void +halftone_callback(cal_halftone_data_t *ht, void *arg) +{ + gx_device *dev = arg; + gx_color_index dev_white = gx_device_white(dev); + gx_color_index dev_black = gx_device_black(dev); + + if (dev->is_planar) { + (*dev_proc(dev, copy_planes)) (dev, ht->data, ht->x + (ht->offset_x<<3), ht->raster, + gx_no_bitmap_id, ht->x, ht->y, ht->w, ht->h, + ht->plane_raster); + } else { + (*dev_proc(dev, copy_mono)) (dev, ht->data, ht->x + (ht->offset_x<<3), ht->raster, + gx_no_bitmap_id, ht->x, ht->y, ht->w, ht->h, dev_white, + dev_black); + } +} + +static cal_halftone* +halftone_init(gx_image_enum *penum) +{ + cal_halftone *cal_ht = NULL; + gx_dda_fixed dda_ht; + cal_context *ctx; + int k; + gx_ht_order *d_order; + int code; + byte *cache = (penum->color_cache != NULL ? penum->color_cache->device_contone : NULL); + cal_matrix matrix; + int clip_x, clip_y; + + if (!gx_device_must_halftone(penum->dev)) + return NULL; + + if (penum->pgs == NULL || penum->pgs->dev_ht == NULL) + return NULL; + ctx = cal_init(&cal_allocs, penum->memory->non_gc_memory); + if (ctx == NULL) + return NULL; + penum->cal_ctx = ctx; + dda_ht = penum->dda.pixel0.x; + if (penum->dxx > 0) + dda_translate(dda_ht, -fixed_epsilon); + matrix.xx = penum->matrix.xx; + matrix.xy = penum->matrix.xy; + matrix.yx = penum->matrix.yx; + matrix.yy = penum->matrix.yy; + matrix.tx = penum->matrix.tx + matrix.xx * penum->rect.x + matrix.yx * penum->rect.y; + matrix.ty = penum->matrix.ty + matrix.xy * penum->rect.x + matrix.yy * penum->rect.y; + + clip_x = fixed2int(penum->clip_outer.p.x); + clip_y = fixed2int(penum->clip_outer.p.y); + cal_ht = cal_halftone_init(ctx, + penum->memory->non_gc_memory, + penum->rect.w, + penum->rect.h, + &matrix, + penum->dev->color_info.num_components, + cache, + clip_x, + clip_y, + fixed2int_ceiling(penum->clip_outer.q.x) - clip_x, + fixed2int_ceiling(penum->clip_outer.q.y) - clip_y, + penum->adjust); + if (cal_ht == NULL) + goto fail; + + for (k = 0; k < penum->pgs->dev_ht->num_comp; k++) { + d_order = &(penum->pgs->dev_ht->components[k].corder); + code = gx_ht_construct_threshold(d_order, penum->dev, penum->pgs, k); + if (code < 0) + goto fail; + if (cal_halftone_add_screen(ctx, + penum->memory->non_gc_memory, + cal_ht, + penum->pgs->dev_ht->components[k].corder.threshold_inverted, + penum->pgs->dev_ht->components[k].corder.width, + penum->pgs->dev_ht->components[k].corder.full_height, + -penum->pgs->screen_phase[k].x, + -penum->pgs->screen_phase[k].y, + penum->pgs->dev_ht->components[k].corder.threshold) < 0) + goto fail; + } + + return cal_ht; + +fail: + cal_halftone_fin(cal_ht, penum->memory->non_gc_memory); + cal_fin(ctx, penum->memory->non_gc_memory); + penum->cal_ctx = NULL; + return NULL; +} +#endif int gs_image_class_3_mono(gx_image_enum * penum, irender_proc_t *render_fn) @@ -169,11 +298,21 @@ gs_image_class_3_mono(gx_image_enum * penum, irender_proc_t *render_fn) be done via thresholding we will keep clues in continuous tone */ code = image_init_color_cache(penum, penum->bps, penum->spp); if (code >= 0) { +#ifdef WITH_CAL + penum->cal_ht = halftone_init(penum); + if (penum->cal_ht != NULL) + { + penum->skip_next_line = image_render_mono_ht_cal_skip_line; + *render_fn = &image_render_mono_ht_cal; + return code; + } +#else code = gxht_thresh_image_init(penum); if (code >= 0) { *render_fn = &image_render_mono_ht; return code; } +#endif } } not_fast_halftoning: @@ -879,6 +1018,25 @@ err: return code; } +#ifdef WITH_CAL +static int image_render_mono_ht_cal_skip_line(gx_image_enum *penum) +{ + return !cal_halftone_next_line_required(penum->cal_ht); +} + +static int +image_render_mono_ht_cal(gx_image_enum * penum, const byte * buffer, int data_x, + uint w, int h, gx_device * dev) +{ + const byte *input = buffer + data_x; + + if (buffer == NULL) + return 0; + + return cal_halftone_process_planar(penum->cal_ht, penum->memory->non_gc_memory, + &input, halftone_callback, dev); +} +#else /* An image render case where the source color is monochrome or indexed and the output is to be halftoned. If the source color requires decoding, @@ -1044,26 +1202,26 @@ image_render_mono_ht(gx_image_enum * penum_orig, const byte * buffer, int data_x } else { /* Mono case, forward */ for (k=0; k<src_size; k++) { + byte c = *psrc++; dda_next(dda_ht); xn = fixed2int_var_rounded(dda_current(dda_ht)); while (xr < xn) { - *devc_contone_gray++ = *psrc; + *devc_contone_gray++ = c; xr++; } /* at loop exit xn will be >= xr */ - psrc++; } } } else { /* Mono case, backwards */ devc_contone_gray += (data_length - 1); for (k=0; k<src_size; k++) { + byte c = *psrc++; dda_next(dda_ht); xn = fixed2int_var_rounded(dda_current(dda_ht)); while (xr > xn) { - *devc_contone_gray-- = *psrc; + *devc_contone_gray-- = c; xr--; } /* at loop exit xn will be >= xr */ - psrc++; } } break; @@ -1075,14 +1233,14 @@ image_render_mono_ht(gx_image_enum * penum_orig, const byte * buffer, int data_x position = penum->ht_landscape.curr_pos + LAND_BITS * (data_length - 1); for (k=0; k<src_size; k++) { + byte c = *psrc++; dda_next(dda_ht); xn = fixed2int_var_rounded(dda_current(dda_ht)); while (xr > xn) { - devc_contone_gray[position] = *psrc; + devc_contone_gray[position] = c; position -= LAND_BITS; xr--; } /* at loop exit xn will be <= xr */ - psrc++; } } else { position = penum->ht_landscape.curr_pos; @@ -1104,14 +1262,14 @@ image_render_mono_ht(gx_image_enum * penum_orig, const byte * buffer, int data_x } else { /* use dda */ for (k=0; k<src_size; k++) { + byte c = *psrc++; dda_next(dda_ht); xn = fixed2int_var_rounded(dda_current(dda_ht)); while (xr < xn) { - devc_contone_gray[position] = *psrc; + devc_contone_gray[position] = c; position += LAND_BITS; xr++; } /* at loop exit xn will be >= xr */ - psrc++; } } } @@ -1137,27 +1295,26 @@ image_render_mono_ht(gx_image_enum * penum_orig, const byte * buffer, int data_x if (spp_out == 1) { /* Mono case, forward */ for (k=0; k<src_size; k++) { + byte c = color_cache[*psrc++]; dda_next(dda_ht); xn = fixed2int_var_rounded(dda_current(dda_ht)); while (xr < xn) { - *devc_contone_gray++ = color_cache[*psrc]; + *devc_contone_gray++ = c; xr++; } /* at loop exit xn will be >= xr */ - psrc++; } } else { /* CMYK case, forward */ for (k=0; k<src_size; k++) { + dev_value = &(color_cache[*psrc++ * spp_out]); dda_next(dda_ht); xn = fixed2int_var_rounded(dda_current(dda_ht)); while (xr < xn) { - dev_value = &(color_cache[*psrc * spp_out]); for (j = 0; j < spp_out; j++) { *(devc_contone[j])++ = dev_value[j]; } xr++; } /* at loop exit xn will be >= xr */ - psrc++; } } } else { @@ -1165,13 +1322,13 @@ image_render_mono_ht(gx_image_enum * penum_orig, const byte * buffer, int data_x /* Mono case, backwards */ devc_contone_gray += data_length - 1; /* move to end */ for (k=0; k<src_size; k++) { + byte c = color_cache[*psrc++]; dda_next(dda_ht); xn = fixed2int_var_rounded(dda_current(dda_ht)); while (xr > xn) { - *devc_contone_gray-- = color_cache[*psrc]; + *devc_contone_gray-- = c; xr--; } /* at loop exit xn will be <= xr */ - psrc++; } } else { /* CMYK case, backwards */ @@ -1180,16 +1337,15 @@ image_render_mono_ht(gx_image_enum * penum_orig, const byte * buffer, int data_x devc_contone[j] = devc_contone[j] + data_length - 1; } for (k=0; k<src_size; k++) { + dev_value = &(color_cache[*psrc++ * spp_out]); dda_next(dda_ht); xn = fixed2int_var_rounded(dda_current(dda_ht)); while (xr > xn) { - dev_value = &(color_cache[*psrc * spp_out]); for (j = 0; j < spp_out; j++) { *(devc_contone[j])-- = dev_value[j]; } xr--; } /* at loop exit xn will be <= xr */ - psrc++; } } } @@ -1206,29 +1362,28 @@ image_render_mono_ht(gx_image_enum * penum_orig, const byte * buffer, int data_x /* Mono case */ /* loop filling contone values selected from the source */ for (k=0; k<src_size; k++) { + byte c = color_cache[*psrc++]; dda_next(dda_ht); xn = fixed2int_var_rounded(dda_current(dda_ht)); while (xr > xn) { - devc_contone_gray[position] = color_cache[*psrc]; + devc_contone_gray[position] = c; position -= LAND_BITS; xr--; } /* at loop exit xn will be <= xr */ - psrc++; } } else { /* CMYK case */ for (k=0; k<src_size; k++) { + dev_value = &(color_cache[*psrc++ * spp_out]); dda_next(dda_ht); xn = fixed2int_var_rounded(dda_current(dda_ht)); while (xr > xn) { - dev_value = &(color_cache[*psrc * spp_out]); for (j = 0; j < spp_out; j++) { *(devc_contone[j] + position) = dev_value[j]; } position -= LAND_BITS; xr--; } /* at loop exit xn will be <= xr */ - psrc++; } } } else { /* Not flipped in Y */ @@ -1238,14 +1393,14 @@ image_render_mono_ht(gx_image_enum * penum_orig, const byte * buffer, int data_x /* Mono case */ /* loop filling contone values selected from the source */ for (k=0; k<src_size; k++) { + byte c = color_cache[*psrc++]; dda_next(dda_ht); xn = fixed2int_var_rounded(dda_current(dda_ht)); while (xr < xn) { - devc_contone_gray[position] = color_cache[*psrc]; + devc_contone_gray[position] = c; position += LAND_BITS; xr++; } /* at loop exit xn will be >= xr */ - psrc++; } } else { /* CMYK case */ @@ -1255,17 +1410,16 @@ image_render_mono_ht(gx_image_enum * penum_orig, const byte * buffer, int data_x } /* CMYK case */ for (k=0; k<src_size; k++) { + dev_value = &(color_cache[*psrc++ * spp_out]); dda_next(dda_ht); xn = fixed2int_var_rounded(dda_current(dda_ht)); while (xr < xn) { - dev_value = &(color_cache[*psrc * spp_out]); for (j = 0; j < spp_out; j++) { *(devc_contone[j] + position) = dev_value[j]; } position += LAND_BITS; xr++; } /* at loop exit xn will be >= xr */ - psrc++; } } } @@ -1288,3 +1442,4 @@ flush: contone_stride); return code; } +#endif diff --git a/base/gxiscale.c b/base/gxiscale.c index 4a5414435..8d733ba58 100644 --- a/base/gxiscale.c +++ b/base/gxiscale.c @@ -338,6 +338,15 @@ gs_image_class_0_interpolate(gx_image_enum * penum, irender_proc_t *render_fn) dw / penum->Width)); iss.LeftMarginOut = fixed2int_pixround_perfect((fixed)((int64_t)(penum->rrect.x - penum->rect.x) * dw / penum->Width)); + iss.TopMarginOut2 = fixed2int_pixround_perfect((fixed)((int64_t)penum->rrect.y * + dh / penum->Height)); + iss.PatchHeightOut2 = fixed2int_pixround_perfect((fixed)((int64_t)(penum->rrect.y + penum->rrect.h) * + dh / penum->Height)) + - iss.TopMarginOut2; + iss.pad_y = iss.TopMarginOut2 + - fixed2int_pixround_perfect( + (fixed)((int64_t)penum->rect.y * + dh / penum->Height)); } else { fixed dw = any_abs(penum->dst_width); fixed dh = any_abs(penum->dst_height); @@ -362,6 +371,12 @@ gs_image_class_0_interpolate(gx_image_enum * penum, irender_proc_t *render_fn) dh / penum->Width)); iss.LeftMarginOut = fixed2int_pixround_perfect((fixed)((int64_t)(penum->rrect.x - penum->rect.x) * dh / penum->Width)); + iss.TopMarginOut2 = fixed2int_pixround_perfect((fixed)((int64_t)penum->rrect.y * + dw / penum->Height)); + iss.PatchHeightOut2 = fixed2int_pixround_perfect((fixed)((int64_t)(penum->rrect.y + penum->rrect.h) * + dw / penum->Height)) + - iss.TopMarginOut2; + iss.pad_y = 0; } iss.PatchWidthOut = any_abs(iss.PatchWidthOut); if (iss.LeftMarginOut + iss.PatchWidthOut >= iss.WidthOut) { diff --git a/base/lib.mak b/base/lib.mak index ffea9be34..eddf10919 100644 --- a/base/lib.mak +++ b/base/lib.mak @@ -151,6 +151,8 @@ jerror_h=$(JSRCDIR)$(D)jerror.h jerror__h=$(GLSRC)jerror_.h $(MAKEFILE) jpeglib__h=$(GLGEN)jpeglib_.h +cal_h=$(CALSRCDIR)$(D)cal.h + # Miscellaneous gsio_h=$(GLSRC)gsio.h @@ -753,10 +755,20 @@ $(GLOBJ)gxht_thresh.$(OBJ) : $(GLSRC)gxht_thresh.c $(AK) $(memory__h)\ $(gxdevice_h) $(gxdht_h) $(gxht_thresh_h) $(gzht_h) $(gxdevsop_h) $(LIB_MAK) $(MAKEDIRS) $(GLCC) $(GLO_)gxht_thresh.$(OBJ) $(C_) $(GLSRC)gxht_thresh.c -$(GLOBJ)gxidata.$(OBJ) : $(GLSRC)gxidata.c $(AK) $(gx_h) $(gserrors_h)\ +$(GLOBJ)gxidata_0.$(OBJ) : $(GLSRC)gxidata.c $(AK) $(gx_h) $(gserrors_h)\ + $(memory__h) $(gxcpath_h) $(gxdevice_h) $(gximage_h) $(gsicc_cache_h)\ + $(LIB_MAK) $(MAKEDIRS) + $(GLCC) $(GLO_)gxidata_0.$(OBJ) $(C_) $(GLSRC)gxidata.c + +$(GLOBJ)gxidata_1.$(OBJ) : $(GLSRC)gxidata.c $(AK) $(cal_h) $(gx_h) $(gserrors_h)\ $(memory__h) $(gxcpath_h) $(gxdevice_h) $(gximage_h) $(gsicc_cache_h)\ $(LIB_MAK) $(MAKEDIRS) - $(GLCC) $(GLO_)gxidata.$(OBJ) $(C_) $(GLSRC)gxidata.c + $(GLCC) -DWITH_CAL $(I_)$(CALSRCDIR)$(_I) $(GLO_)gxidata_1.$(OBJ) $(C_) $(GLSRC)gxidata.c + +$(GLOBJ)gxidata.$(OBJ) : $(GLOBJ)gxidata_$(WITH_CAL).$(OBJ) $(AK) $(gx_h) $(gserrors_h)\ + $(memory__h) $(gxcpath_h) $(gxdevice_h) $(gximage_h) $(gsicc_cache_h)\ + $(LIB_MAK) $(MAKEDIRS) + $(CP_) $(GLOBJ)gxidata_$(WITH_CAL).$(OBJ) $(GLOBJ)gxidata.$(OBJ) $(GLOBJ)gxifast.$(OBJ) : $(GLSRC)gxifast.c $(AK) $(gx_h) $(gserrors_h)\ $(memory__h) $(gpcheck_h) $(gdevmem_h) $(gsbittab_h) $(gsccolor_h)\ @@ -774,13 +786,29 @@ $(GLOBJ)gximage1.$(OBJ) : $(GLSRC)gximage1.c $(AK) $(gx_h)\ $(gserrors_h) $(gximage_h) $(gxiparam_h) $(stream_h) $(memory__h) $(LIB_MAK) $(MAKEDIRS) $(GLCC) $(GLO_)gximage1.$(OBJ) $(C_) $(GLSRC)gximage1.c -$(GLOBJ)gximono.$(OBJ) : $(GLSRC)gximono.c $(AK) $(gx_h) $(gserrors_h)\ +$(GLOBJ)gximono_0.$(OBJ) : $(GLSRC)gximono.c $(AK) $(gx_h) $(gserrors_h)\ + $(memory__h) $(gpcheck_h) $(gdevmem_h) $(gsccolor_h) $(gspaint_h) $(gsutil_h)\ + $(gxarith_h) $(gxcmap_h) $(gxcpath_h) $(gxdcolor_h) $(gxdevice_h)\ + $(gxdevmem_h) $(gxfixed_h) $(gximage_h) $(gxgstate_h) $(gxmatrix_h)\ + $(gzht_h) $(gsicc_h) $(gsicc_cache_h) $(gsicc_cms_h)\ + $(gxcie_h) $(gscie_h) $(gxht_thresh_h) $(gxdda_h) $(gxdevsop_h) $(LIB_MAK) $(MAKEDIRS) + $(GLCC) $(GLO_)gximono_0.$(OBJ) $(C_) $(GLSRC)gximono.c + +$(GLOBJ)gximono_1.$(OBJ) : $(GLSRC)gximono.c $(AK) $(cal_h) $(gx_h) $(gserrors_h)\ $(memory__h) $(gpcheck_h) $(gdevmem_h) $(gsccolor_h) $(gspaint_h) $(gsutil_h)\ $(gxarith_h) $(gxcmap_h) $(gxcpath_h) $(gxdcolor_h) $(gxdevice_h)\ $(gxdevmem_h) $(gxfixed_h) $(gximage_h) $(gxgstate_h) $(gxmatrix_h)\ $(gzht_h) $(gsicc_h) $(gsicc_cache_h) $(gsicc_cms_h)\ $(gxcie_h) $(gscie_h) $(gxht_thresh_h) $(gxdda_h) $(gxdevsop_h) $(LIB_MAK) $(MAKEDIRS) - $(GLCC) $(GLO_)gximono.$(OBJ) $(C_) $(GLSRC)gximono.c + $(GLCC) -DWITH_CAL $(I_)$(CALSRCDIR)$(_I) $(GLO_)gximono_1.$(OBJ) $(C_) $(GLSRC)gximono.c + +$(GLOBJ)gximono.$(OBJ) : $(GLOBJ)gximono_$(WITH_CAL).$(OBJ) $(AK) $(gx_h) $(gserrors_h)\ + $(memory__h) $(gpcheck_h) $(gdevmem_h) $(gsccolor_h) $(gspaint_h) $(gsutil_h)\ + $(gxarith_h) $(gxcmap_h) $(gxcpath_h) $(gxdcolor_h) $(gxdevice_h)\ + $(gxdevmem_h) $(gxfixed_h) $(gximage_h) $(gxgstate_h) $(gxmatrix_h)\ + $(gzht_h) $(gsicc_h) $(gsicc_cache_h) $(gsicc_cms_h)\ + $(gxcie_h) $(gscie_h) $(gxht_thresh_h) $(gxdda_h) $(gxdevsop_h) $(LIB_MAK) $(MAKEDIRS) + $(CP_) $(GLOBJ)gximono_$(WITH_CAL).$(OBJ) $(GLOBJ)gximono.$(OBJ) $(GLOBJ)gximask.$(OBJ) : $(GLSRC)gximask.c $(AK) $(gx_h) $(gserrors_h)\ $(memory__h) $(gsptype1_h) $(gsptype2_h) $(gxdevice_h) $(gxdcolor_h)\ @@ -2275,10 +2303,31 @@ $(GLOBJ)siinterp.$(OBJ) : $(GLSRC)siinterp.c $(AK)\ $(siinterp_h) $(strimpl_h) $(LIB_MAK) $(MAKEDIRS) $(GLCC) $(GLO_)siinterp.$(OBJ) $(C_) $(GLSRC)siinterp.c -$(GLOBJ)siscale.$(OBJ) : $(GLSRC)siscale.c $(AK)\ +$(GLOBJ)siscale_0.$(OBJ) : $(GLSRC)siscale.c $(AK)\ + $(math__h) $(memory__h) $(stdio__h) $(stdint__h) $(gdebug_h) $(gxfrac_h)\ + $(siscale_h) $(strimpl_h) $(LIB_MAK) $(MAKEDIRS) + $(GLCC) $(GLO_)siscale_0.$(OBJ) $(C_) $(GLSRC)siscale.c + +$(GLOBJ)siscale_1.$(OBJ) : $(GLSRC)siscale_cal.c $(AK) $(cal_h)\ + $(math__h) $(memory__h) $(stdio__h) $(stdint__h) $(gdebug_h) $(gxfrac_h)\ + $(siscale_h) $(strimpl_h) $(LIB_MAK) $(MAKEDIRS) + $(GLCC) $(GLO_)siscale_1.$(OBJ) $(I_)$(CALSRCDIR)$(_I) $(C_) $(GLSRC)siscale_cal.c + +$(GLOBJ)siscale.$(OBJ) : $(GLOBJ)siscale_$(WITH_CAL).$(OBJ) $(AK)\ $(math__h) $(memory__h) $(stdio__h) $(stdint__h) $(gdebug_h) $(gxfrac_h)\ $(siscale_h) $(strimpl_h) $(LIB_MAK) $(MAKEDIRS) - $(GLCC) $(GLO_)siscale.$(OBJ) $(C_) $(GLSRC)siscale.c + $(CP_) $(GLOBJ)siscale_$(WITH_CAL).$(OBJ) $(GLOBJ)siscale.$(OBJ) + +# Dev file contains library files (or nothing) +$(GLOBJ)siscale.dev : $(GLOBJ)siscale_$(WITH_CAL).dev\ + $(CAL_MAK) $(MAKEDIRS) + $(CP_) $(GLOBJ)siscale_$(WITH_CAL).dev $(GLOBJ)siscale.dev + +$(GLOBJ)siscale_0.dev: $(ECHOGS_XE) $(MAKEDIRS) + $(SETMOD) $(GLOBJ)siscale_0 + +$(GLOBJ)siscale_1.dev: $(GLOBJ)cal.dev $(ECHOGS_XE) $(CAL_OBJS) $(MAKEDIRS) + $(SETMOD) $(GLOBJ)siscale_1 -include $(GLOBJ)cal.dev $(GLOBJ)sidscale.$(OBJ) : $(GLSRC)sidscale.c $(AK)\ $(math__h) $(memory__h) $(stdio__h) $(gdebug_h) $(gxdda_h) $(gxfixed_h)\ @@ -2321,11 +2370,20 @@ $(GLD)roplib.dev : $(LIB_MAK) $(ECHOGS_XE) $(roplib_) $(LIB_MAK) $(MAKEDIRS) $(ADDMOD) $(GLD)roplib $(roplib2_) $(ADDMOD) $(GLD)roplib $(roplib3_) -$(GLOBJ)gdevdrop.$(OBJ) : $(GLSRC)gdevdrop.c $(AK) $(gx_h) $(gserrors_h) \ +$(GLOBJ)gdevdrop_1.$(OBJ) : $(GLSRC)gdevdrop.c $(AK) $(gx_h) $(gserrors_h) \ + $(memory__h) $(gxdevsop_h) $(gsbittab_h) $(gsropt_h) $(gxcindex_h) \ + $(gxdcolor_h) $(gxdevice_h) $(gxdevmem_h) $(gxdevrop_h) $(gxgetbit_h) \ + $(gdevmem_h) $(gdevmrop_h) $(gdevmpla_h) $(stdint__h) $(LIB_MAK) $(MAKEDIRS) + $(GLCC) -DWITH_CAL $(I_)$(CALSRCDIR)$(_I) $(GLO_)gdevdrop_1.$(OBJ) $(C_) $(GLSRC)gdevdrop.c + +$(GLOBJ)gdevdrop_0.$(OBJ) : $(GLSRC)gdevdrop.c $(AK) $(gx_h) $(gserrors_h) \ $(memory__h) $(gxdevsop_h) $(gsbittab_h) $(gsropt_h) $(gxcindex_h) \ $(gxdcolor_h) $(gxdevice_h) $(gxdevmem_h) $(gxdevrop_h) $(gxgetbit_h) \ $(gdevmem_h) $(gdevmrop_h) $(gdevmpla_h) $(stdint__h) $(LIB_MAK) $(MAKEDIRS) - $(GLCC) $(GLO_)gdevdrop.$(OBJ) $(C_) $(GLSRC)gdevdrop.c + $(GLCC) $(GLO_)gdevdrop_0.$(OBJ) $(C_) $(GLSRC)gdevdrop.c + +$(GLOBJ)gdevdrop.$(OBJ) : $(GLOBJ)gdevdrop_$(WITH_CAL).$(OBJ) + $(CP_) $(GLOBJ)gdevdrop_$(WITH_CAL).$(OBJ) $(GLOBJ)gdevdrop.$(OBJ) $(GLOBJ)gdevmr1.$(OBJ) : $(GLSRC)gdevmr1.c $(AK) $(gx_h) $(gserrors_h)\ $(memory__h) $(gsbittab_h) $(gsropt_h)\ diff --git a/base/siscale_cal.c b/base/siscale_cal.c new file mode 100644 index 000000000..c8323aa0b --- /dev/null +++ b/base/siscale_cal.c @@ -0,0 +1,393 @@ +/* Copyright (C) 2001-2017 Artifex Software, Inc. + All Rights Reserved. + + This software is provided AS-IS with no warranty, either express or + implied. + + This software is distributed under license and may not be copied, + modified or distributed except as expressly authorized under the terms + of the license contained in the file LICENSE in this distribution. + + Refer to licensing information at http://www.artifex.com or contact + Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, San Rafael, + CA 94903, U.S.A., +1(415)492-9861, for further information. +*/ + +/* Image scaling filters */ +#include "math_.h" +#include "memory_.h" +#include "stdio_.h" +#include "stdint_.h" +#include "gdebug.h" +#include "strimpl.h" +#include "siscale.h" +#include "gxfrac.h" +#include "cal.h" +#include "assert_.h" + +/* ImageScaleEncode / ImageScaleDecode */ +typedef struct stream_IScale_cal_state_s { + /* The client sets the params values before initialization. */ + stream_image_scale_state_common; /* = state_common + params */ + /* The init procedure sets the following. */ + cal_context *context; + cal_rescaler *rescaler; + uint8_t *src; + uint8_t *dst; + byte *tmp; + int pre_scan_bytes; + int post_scan_bytes; + /* The following are updated dynamically. */ + int src_y; + uint src_offset, src_size; + int dst_y; + uint dst_offset, dst_size; +} stream_IScale_cal_state; + +/* FIXME: */ +gs_private_st_ptrs2(st_IScale_cal_state, stream_IScale_cal_state, + "ImageScaleEncode/Decode state", + iscale_state_enum_ptrs, iscale_state_reloc_ptrs, + dst, src); + +/* ------ Stream implementation ------ */ + +/* Forward references */ +static void s_IScale_cal_release(stream_state * st); + +/* Set default parameter values (actually, just clear pointers) */ +static void +s_IScale_cal_set_defaults(stream_state * st) +{ + stream_IScale_cal_state *const ss = (stream_IScale_cal_state *) st; + + ss->rescaler = NULL; +} + +static void * +cal_do_malloc(void *opaque, size_t size) +{ + gs_memory_t *mem = (gs_memory_t *)opaque; + return gs_alloc_bytes(mem, size, "cal_do_malloc"); +} + +static void * +cal_do_realloc(void *opaque, void *ptr, size_t newsize) +{ + gs_memory_t *mem = (gs_memory_t *)opaque; + return gs_resize_object(mem, ptr, newsize, "cal_do_malloc"); +} + +static void +cal_do_free(void *opaque, void *ptr) +{ + gs_memory_t *mem = (gs_memory_t *)opaque; + gs_free_object(mem, ptr, "cal_do_malloc"); +} + +static cal_allocators cal_allocs = +{ + cal_do_malloc, + cal_do_realloc, + cal_do_free +}; + +/* + + Some notes: + + (ss->params.XXXX is shown as XXXX in the following for sanity) + + Conceptually we are scaling a bitmap that was EntireWidthIn x EntireHeightIn + in size, to be EntireWidthOut x EntireHeightOut in size. + + But, we only actually care about a sub rectangle of this in the destination, + given by (LeftMarginOut, TopMarginOut) + (PatchWidthOut, PatchHeightOut). + Anything else is clipped away. There are times when this sub rectangle can + be very "sub" indeed, so the ability to avoid rescaling all the data we + don't care about is a vital one. + + To confuse this further, we don't get fed scanlines of EntireWidthIn pixels, + instead we get WidthIn pixels. Similarly we don't feed scanlines out of + EntireWidthOut pixels, but rather of WidthOut pixels. Width{In,Out} are not + (always) the same as PatchWidth{In,Out} either. + + Accordingly there may be padding before and after the active region. We make + the effort to ensure these bytes are set to zero. +*/ + + +static int +s_IScale_cal_init(stream_state * st) +{ + stream_IScale_cal_state *const ss = (stream_IScale_cal_state *) st; + gs_memory_t *mem = ss->memory; + int abs_interp_limit = ss->params.abs_interp_limit; + int limited_WidthOut = (ss->params.WidthOut + abs_interp_limit - 1) / abs_interp_limit; + int limited_PatchWidthOut = (ss->params.PatchWidthOut + abs_interp_limit - 1) / abs_interp_limit; + int limited_PatchHeightOut = (ss->params.PatchHeightOut2 + abs_interp_limit - 1) / abs_interp_limit; + int limited_EntireWidthOut = (ss->params.EntireWidthOut + abs_interp_limit - 1) / abs_interp_limit; + int limited_EntireHeightOut = (ss->params.EntireHeightOut + abs_interp_limit - 1) / abs_interp_limit; + int limited_LeftMarginOut = (ss->params.LeftMarginOut) / abs_interp_limit; + int limited_TopMarginOut = (ss->params.TopMarginOut2) / abs_interp_limit; + int limited_PadY = (ss->params.pad_y + abs_interp_limit/2 ) / abs_interp_limit; + int dst_bytes_per_pixel = ss->params.BitsPerComponentOut / 8; + int src_bytes_per_pixel = ss->params.BitsPerComponentIn / 8; + + ss->context = cal_init(&cal_allocs, mem->non_gc_memory); + if (ss->context == NULL) + return ERRC; + + ss->src_offset = 0; + ss->src_size = ss->params.WidthIn * ss->params.spp_interp * src_bytes_per_pixel; + ss->dst_offset = 0; + ss->dst_size = limited_WidthOut * ss->params.spp_interp * dst_bytes_per_pixel; + ss->dst_y = -limited_PadY; + ss->pre_scan_bytes = limited_LeftMarginOut * ss->params.spp_interp * dst_bytes_per_pixel; + ss->post_scan_bytes = (limited_WidthOut - limited_PatchWidthOut - limited_LeftMarginOut) * ss->params.spp_interp * dst_bytes_per_pixel; + + ss->dst = gs_alloc_byte_array(mem, ss->dst_size, 1, "image_scale dst"); + if (ss->dst == NULL) + goto fail; + + ss->src = gs_alloc_byte_array(mem, ss->params.EntireWidthIn * ss->params.spp_interp, + src_bytes_per_pixel, "image_scale dst"); + if (ss->src == NULL) + goto fail; + + ss->rescaler = cal_rescaler_init(ss->context, + mem->non_gc_memory, + ss->params.EntireWidthIn, + ss->params.EntireHeightIn, + 0, + ss->params.src_y_offset, + ss->params.WidthIn, + ss->params.HeightIn, + limited_EntireWidthOut, + limited_EntireHeightOut, + limited_LeftMarginOut, + limited_TopMarginOut, + limited_PatchWidthOut, + limited_PatchHeightOut, + CAL_MITCHELL, + src_bytes_per_pixel, + dst_bytes_per_pixel, + ss->params.spp_interp, + ss->params.MaxValueIn, + ss->params.MaxValueOut); + if (ss->rescaler == NULL) + goto fail; + + if (ss->pre_scan_bytes) + memset(ss->dst, 0, ss->pre_scan_bytes); + if (ss->post_scan_bytes) + memset(ss->dst + ss->dst_size - ss->post_scan_bytes, 0, ss->post_scan_bytes); + + return 0; + +fail: + if (ss->rescaler) + cal_rescaler_fin(ss->rescaler, mem->non_gc_memory); + if (ss->context != NULL) + cal_fin(ss->context, mem->non_gc_memory); + gs_free_object(mem, ss->src, "image_scale src"); + gs_free_object(mem, ss->dst, "image_scale dst"); + return ERRC; +} + +/* Process a buffer. Note that this handles Encode and Decode identically. */ +static int +s_IScale_cal_process(stream_state * st, stream_cursor_read * pr, + stream_cursor_write * pw, bool last) +{ + stream_IScale_cal_state *const ss = (stream_IScale_cal_state *) st; + gs_memory_t *mem = ss->memory; + int abs_interp_limit = ss->params.abs_interp_limit; + int limited_HeightOut = (ss->params.HeightOut + abs_interp_limit - 1) / abs_interp_limit; + uint wleft; + uint rleft; + int any_output = 0; + const byte *input = NULL; + + /* If we have no more data to pull out, we're done. */ + if (ss->dst_y == limited_HeightOut) + return EOFC; + + /* How much room do we have left in the output buffer? */ + wleft = pw->limit - pw->ptr; + + /* If no room left, exit */ + if (wleft == 0) + return 1; + + /* If we need to send some padding at the top, do so */ + if (ss->dst_y < 0) + { + uint wcount = ss->dst_size - ss->dst_offset; + uint ncopy = wcount; + + if (ncopy > wleft) + ncopy = wleft; + memset(pw->ptr + 1, 0, ncopy); + pw->ptr += ncopy; + wcount -= ncopy; + if (wcount == 0) + { + ss->dst_offset = 0; + ss->dst_y++; + } + else + ss->dst_offset += ncopy; + wleft -= ncopy; + /* Unless we can get a whole new line out, pass out what we have */ + if (wleft < ss->dst_size) + return 1; + any_output = 1; + } + + /* Pass out any buffered data we have */ + if (ss->dst_offset != 0) + { + uint wcount = ss->dst_size - ss->dst_offset; + uint ncopy = wcount; + + if (ncopy > wleft) + ncopy = wleft; + memcpy(pw->ptr + 1, (byte *) ss->dst + ss->dst_offset, ncopy); + pw->ptr += ncopy; + wcount -= ncopy; + if (wcount == 0) + { + ss->dst_offset = 0; + ss->dst_y++; + } + else + ss->dst_offset += ncopy; + wleft -= ncopy; + /* Unless we can get a whole new line out, pass out what we have */ + if (wleft < ss->dst_size) + return 1; + any_output = 1; + } + + /* How much data do we have in the incoming buffer? */ + rleft = pr->limit - pr->ptr; + if (rleft > 0 && ss->src_offset > 0) { + /* We have part of a line buffered. Let's fill that out. */ + uint ncopy = ss->src_size - ss->src_offset; + if (ncopy > rleft) + ncopy = rleft; + memcpy(ss->src + ss->src_offset, pr->ptr + 1, ncopy); + pr->ptr += ncopy; + rleft -= ncopy; + ss->src_offset += ncopy; + if (ss->src_offset == ss->src_size) + { + ss->src_offset = 0; + input = ss->src; + } + } + else if (rleft >= ss->src_size) + input = pr->ptr+1; + + /* If we can extract a whole extra output line, then try for that. + * Try anyway if we haven't managed to output anything. */ + while (wleft >= ss->dst_size || any_output == 0) + { + uint8_t *row; + int ret; + + if (wleft >= ss->dst_size) { + /* We can scale the row directly into the output. */ + row = pw->ptr + 1; + } else { + /* We'll have to buffer the row. */ + row = ss->dst; + } + ret = cal_rescaler_process(ss->rescaler, mem, input, row + ss->pre_scan_bytes); + if (ret & 1) + { + /* Input consumed */ + if (input != ss->src) + { + pr->ptr += ss->src_size; + rleft -= ss->src_size; + } + input = (rleft >= ss->src_size) ? pr->ptr+1 : NULL; + ss->src_y++; + } + if (ret & 2) + { + /* Output given */ + if (row == ss->dst) + { + /* Copy as much of the the buffered data out as + * possible - we can't manage a whole line. */ + memcpy(pw->ptr+1, ss->dst, wleft); + pw->ptr += wleft; + ss->dst_offset = wleft; + return 1; + } + else + { + /* We are scaling direct into the output. Clear any pre and + * post sections for neatness. */ + if (ss->pre_scan_bytes != 0) + memset(row, 0, ss->pre_scan_bytes); + if (ss->post_scan_bytes != 0) + memset(row + ss->dst_size - ss->post_scan_bytes, 0, ss->post_scan_bytes); + } + pw->ptr += ss->dst_size; + ss->dst_y++; + wleft -= ss->dst_size; + any_output = 1; + } + /* If nothing happened, nothing to be gained from calling again */ + if (ret == 0) + break; + } + + if (any_output == 0 && rleft > 0) + { + /* We've not managed to output anything, so the rescaler + * must be waiting for input data. If we had a whole line of + * data, we'd have tried to pass it in above. So we must + * have only the start of a line. */ + assert(rleft < ss->src_size && ss->dst_offset == 0); + memcpy(ss->src, pr->ptr + 1, rleft); + ss->src_offset += rleft; + pr->ptr += rleft; + return 1; + } + + return any_output; +} + +/* Release the filter's storage. */ +static void +s_IScale_cal_release(stream_state * st) +{ + stream_IScale_cal_state *const ss = (stream_IScale_cal_state *) st; + gs_memory_t *mem = ss->memory; + + if (ss->rescaler) + { + cal_rescaler_fin(ss->rescaler, mem->non_gc_memory); + ss->rescaler = NULL; + } + if (ss->context != NULL) + { + cal_fin(ss->context, mem->non_gc_memory); + ss->context = NULL; + } + gs_free_object(mem, ss->src, "image_scale src"); + ss->src = NULL; + gs_free_object(mem, ss->dst, "image_scale dst"); + ss->dst = NULL; +} + +/* Stream template */ +const stream_template s_IScale_template = { + &st_IScale_cal_state, s_IScale_cal_init, s_IScale_cal_process, 1, 1, + s_IScale_cal_release, s_IScale_cal_set_defaults +}; diff --git a/base/sisparam.h b/base/sisparam.h index 70010f72f..8082270b5 100644 --- a/base/sisparam.h +++ b/base/sisparam.h @@ -100,17 +100,17 @@ * * <--------------------EntireWidthOut----------------------> * +--------------------------------------------------------+ ^ - * | Conceptual Destination Image ^ | | - * | | | | - * | DY | | - * | | | | - * |<-DX-><---------------WidthOut--------------> v | | - * | +-------------------------------------+ ^ | | - * | | ^ | | | EntireHeightOut - * | | | | | | | - * | | TopMarginOut | | | | - * | | | | | | | - * | | v | | | | + * | Conceptual Destination Image ^ ^ | | + * | | | | | + * | | DY | | + * | | | | | + * |<-DX-><---------------WidthOut------|-------> v | | + * | +-----------------------------|-------+ ^ | | + * | | ^ | | | | EntireHeightOut + * | | | | | | | | + * | | TopMarginOut TopMarginOut2 | | | | + * | | | | | | | | + * | | v v | | | | * | | +-penum->rrect*--+ | | | | * | | | ^ | | HeightOut | | * | | | | | | | | | @@ -160,6 +160,9 @@ typedef struct stream_image_scale_params_s { int LeftMarginOut; int TopMarginIn; int TopMarginOut; + int TopMarginOut2; + int PatchHeightOut2; + int pad_y; int Active; gx_dda_fixed_point scale_dda; /* used to scale limited interpolation up to actual size */ } stream_image_scale_params_t; diff --git a/base/unix-gcc.mak b/base/unix-gcc.mak index 933bd7750..a316038f2 100644 --- a/base/unix-gcc.mak +++ b/base/unix-gcc.mak @@ -666,6 +666,7 @@ include $(GLSRCDIR)/jbig2.mak include $(GLSRCDIR)/ldf_jb2.mak include $(GLSRCDIR)/lwf_jp2.mak include $(GLSRCDIR)/openjpeg.mak +include $(GLSRCDIR)/cal.mak include $(GLSRCDIR)/jpegxr.mak include $(GLSRCDIR)/expat.mak diff --git a/base/winlib.mak b/base/winlib.mak index 1e65b6db2..7767b6337 100644 --- a/base/winlib.mak +++ b/base/winlib.mak @@ -149,6 +149,7 @@ BEGINFILES=$(GLGENDIR)\ccf32.tr\ !include $(GLSRCDIR)\ldf_jb2.mak !include $(GLSRCDIR)\lwf_jp2.mak !include $(GLSRCDIR)\openjpeg.mak +!include $(GLSRCDIR)\cal.mak !include $(GLSRCDIR)\expat.mak !include $(GLSRCDIR)\jpegxr.mak |