[gs-commits] ghostpdl branch, master, updated. jbig2dec-0.14-1904-g69bdf79

[email protected] (Robin Watts) Tue, 19 Nov 2019 19:19:29 +0000 (UTC)
Newsgroups gmane.comp.printing.ghostscript.cvs
Message-ID <[email protected]>
The ghostpdl branch, master has been updated
       via  69bdf79e10370ed16a17a346690fd630272f7346 (commit)
       via  b5956ac8be8c923ad9e9fd3045724a5579cf4dce (commit)
       via  0329372164611fdff22f8c02201ff1fbbf94aae7 (commit)
       via  cd8747382f47393efd0f0013700a8294c0ded15c (commit)
      from  e1b7dbc95945ef2afa38faeebfda56830f2762ab (commit)

----------------------------------------------------------------------
commit 69bdf79e10370ed16a17a346690fd630272f7346
Author: Robin Watts <[email protected]>
Date:   Tue Nov 19 18:13:08 2019 +0000

    gpdl: Add tiff "interpreter" to gpdl.

diff --git a/Makefile.in b/Makefile.in
index 83d1735..b980120 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -274,6 +274,7 @@ TIFFPLATFORM=unix
 TIFFCONFIG_SUFFIX=
 LIBTIFF_NAME=tiff
 TIFF_CFLAGS=@TIFFCFLAGS@
+ENABLE_TIFF=@ENABLETIFF@
 
 # Define the directory where the zlib sources are stored.
 # See zlib.mak for more information.
diff --git a/configure.ac b/configure.ac
index 71826fe..d5bb393 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1234,6 +1234,7 @@ case "x$with_system_libtiff" in
             LIBTIFFCONFDIR=tiff-config
             HAVE_LOCAL_LIBTIFF=1
             SHARE_LIBTIFF=0
+            ENABLETIFF="\$(D_)TIFF_INCLUDED\$(_D)"
         else
             # We MUST NOT use PKG_CHECK_MODULES since it is a) not a standard
             # autoconf macro and b) requires pkg-config on the system, which is
@@ -1259,6 +1260,7 @@ case "x$with_system_libtiff" in
             TIFFDEVS="$TIFFDEVS_ALL"
             FAX_DEVS="$FAX_DEVS_ALL"
             XPSWRITEDEVICE='xpswrite'
+            ENABLETIFF="\$(D_)TIFF_INCLUDED\$(_D)"
         fi
         ;;
     xyes)
@@ -1284,6 +1286,7 @@ case "x$with_system_libtiff" in
             TIFFDEVS="$TIFFDEVS_ALL"
             FAX_DEVS="$FAX_DEVS_ALL"
             XPSWRITEDEVICE='xpswrite'
+            ENABLETIFF="\$(D_)TIFF_INCLUDED\$(_D)"
        else
             AC_MSG_NOTICE([Could not find a copy of libtiff on your system. Disabling tiff and xps output devices.])
         fi
@@ -1298,6 +1301,7 @@ case "x$with_system_libtiff" in
             TIFFDEVS="$TIFFDEVS_ALL"
             FAX_DEVS="$FAX_DEVS_ALL"
             XPSWRITEDEVICE='xpswrite'
+            ENABLETIFF="\$(D_)TIFF_INCLUDED\$(_D)"
         else
             AC_MSG_RESULT([no])
             AC_MSG_NOTICE([Could not find local copy of libtiff. Disabling tiff and xps output devices.])
@@ -1343,6 +1347,8 @@ AC_SUBST(SHARE_LIBTIFF)
 AC_SUBST(LIBTIFFDIR)
 AC_SUBST(LIBTIFFCONFDIR)
 AC_SUBST(TIFFCFLAGS)
+AC_SUBST(ENABLETIFF)
+
 
 SHARE_EXPAT=0
 EXPATDIR=src
@@ -1861,7 +1867,7 @@ if test x$with_urf != xno; then
   AC_MSG_CHECKING([for URF support])
   if test -d $srcdir/urf; then
     AC_MSG_RESULT([yes])
-    ENABLEURF="$(D_)URF_INCLUDED$(_D)"
+    ENABLEURF="\$(D_)URF_INCLUDED\$(_D)"
     URF_DEVS='urfgray urfrgb urfcmyk'
     GPDL_URF_TOP_OBJ=$(GPDLOBJ)/$(GPDL_URF_TOP_OBJ_FILE)
     URF_INCLUDE=$(I_)$(URFSRCDIR)$(_I)
diff --git a/gpdl/gpdl.mak b/gpdl/gpdl.mak
index afc2be9..7c674b7 100644
--- a/gpdl/gpdl.mak
+++ b/gpdl/gpdl.mak
@@ -35,7 +35,11 @@ GPDL_JPG_TOP_OBJ=$(GPDLOBJ)/$(GPDL_JPG_TOP_OBJ_FILE)
 GPDL_PWG_TOP_OBJ_FILE=pwgtop.$(OBJ)
 GPDL_PWG_TOP_OBJ=$(GPDLOBJ)/$(GPDL_PWG_TOP_OBJ_FILE)
 
+GPDL_TIFF_TOP_OBJ_FILE=tifftop.$(OBJ)
+GPDL_TIFF_TOP_OBJ=$(GPDLOBJ)/$(GPDL_TIFF_TOP_OBJ_FILE)
+
 GPDL_PSI_TOP_OBJS=\
+	$(GPDL_TIFF_TOP_OBJ)\
 	$(GPDL_PWG_TOP_OBJ)\
 	$(GPDL_JPG_TOP_OBJ)\
 	$(GPDL_URF_TOP_OBJ)\
@@ -48,7 +52,8 @@ LANG_CFLAGS=\
 	$(D_)XPS_INCLUDED$(_D)\
 	$(ENABLE_URF)\
 	$(D_)JPG_INCLUDED$(_D)\
-	$(D_)PWG_INCLUDED$(_D)
+	$(D_)PWG_INCLUDED$(_D)\
+	$(ENABLE_TIFF)
 
 GPDLCC=$(CC_) $(LANG_CFLAGS) $(I_)$(PSSRCDIR)$(_I) $(I_)$(PLSRCDIR)$(_I) $(I_)$(GLSRCDIR)$(_I) $(I_)$(DEVSRCDIR)$(_I) $(I_)$(GLGENDIR)$(_I) $(C_)
 
@@ -88,3 +93,8 @@ $(GPDL_PWG_TOP_OBJ): $(GPDLSRC)pwgtop.c $(AK)\
  $(gxdevice_h) $(gserrors_h) $(gsstate_h) $(strimpl_h) $(gscoord_h)\
  $(spwgx_h) $(pltop_h)
 	$(GPDLCC) $(GPDLSRC)pwgtop.c $(GPDLO_)$(GPDL_PWG_TOP_OBJ_FILE)
+
+$(GPDL_TIFF_TOP_OBJ): $(GPDLSRC)tifftop.c $(AK)\
+ $(gxdevice_h) $(gserrors_h) $(gsstate_h) $(strimpl_h) $(gscoord_h)\
+ $(pltop_h)
+	$(GPDLCC) $(II)$(TI_)$(_I) $(GPDLSRC)tifftop.c $(GPDLO_)$(GPDL_TIFF_TOP_OBJ_FILE)
diff --git a/gpdl/tifftop.c b/gpdl/tifftop.c
new file mode 100644
index 0000000..e0e88a0
--- /dev/null
+++ b/gpdl/tifftop.c
@@ -0,0 +1,829 @@
+/* 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.,  1305 Grant Avenue - Suite 200, Novato,
+   CA 94945, U.S.A., +1(415)492-9861, for further information.
+*/
+
+/* tifftop.c */
+/* Top-level API implementation of "TIF" Language Interface */
+
+#include "pltop.h"
+#include "gserrors.h"
+#include "gxdevice.h"
+#include "gsstate.h"
+#include "strimpl.h"
+#include "gscoord.h"
+#include "tiffio.h"
+
+/* Forward decls */
+
+/************************************************************/
+/******** Language wrapper implementation (see pltop.h) *****/
+/************************************************************/
+
+typedef enum
+{
+    ii_state_identifying = 0,
+    ii_state_tiff,
+    ii_state_tiff_header,
+    ii_state_tiff_decode,
+    ii_state_flush
+} ii_state;
+
+/*
+ * Tiff interpreter instance
+ */
+typedef struct tiff_interp_instance_s {
+    gs_memory_t       *memory;
+    gs_memory_t       *cmemory;
+    gx_device         *dev;
+    gx_device         *nulldev;
+
+    gs_color_space    *gray;
+    gs_color_space    *rgb;
+    gs_color_space    *cmyk;
+
+    /* Tiff parser state machine */
+    ii_state           state;
+
+    int                pages;
+
+    uint32_t           bpp;
+    uint32_t           bpc;
+    uint32_t           cs;
+    uint32_t           width;
+    uint32_t           height;
+    uint32_t           xresolution;
+    uint32_t           yresolution;
+    uint32_t           tile_height;
+    uint32_t           tile_width;
+
+    uint32_t           num_comps;
+    uint32_t           byte_width;
+    uint32_t           y;
+
+    uint32_t           bytes_available_on_entry;
+
+    gs_image_t         image;
+    gs_image_enum     *penum;
+    gs_gstate         *pgs;
+
+    size_t             buffer_full;
+    size_t             buffer_max;
+    byte              *tiff_buffer;
+    size_t             file_pos;
+    TIFF              *handle;
+
+    byte              *samples;
+
+} tiff_interp_instance_t;
+
+static int
+tiff_detect_language(const char *s, int len)
+{
+    const byte *hdr = (const byte *)s;
+    if (len >= 4) {
+        if (hdr[0] == 'I' && hdr[1] == 'I' && hdr[2] == 42 && hdr[3] == 0)
+            return 100; /* Intel (LSB) order */
+        if (hdr[0] == 'M' && hdr[1] == 'M' && hdr[2] == 0 && hdr[3] == 42)
+            return 100; /* Motorola (MSB) order */
+    }
+
+    return 0;
+}
+
+static const pl_interp_characteristics_t tiff_characteristics = {
+    "TIFF",
+    tiff_detect_language,
+    "Artifex",
+    "0.01",
+    "18 Nov 2019",
+    1 /* minimum input size */
+};
+
+/* Get implementation's characteristics */
+static const pl_interp_characteristics_t * /* always returns a descriptor */
+tiff_impl_characteristics(const pl_interp_implementation_t *impl)     /* implementation of interpreter to alloc */
+{
+  return &tiff_characteristics;
+}
+
+static void
+tiff_deallocate(tiff_interp_instance_t *tiff)
+{
+    if (tiff == NULL)
+        return;
+
+    rc_decrement_cs(tiff->gray, "tiff_deallocate");
+    rc_decrement_cs(tiff->rgb, "tiff_deallocate");
+    rc_decrement_cs(tiff->cmyk, "tiff_deallocate");
+
+    if (tiff->pgs != NULL)
+        gs_gstate_free_chain(tiff->pgs);
+    gs_free_object(tiff->memory, tiff, "tiff_impl_allocate_interp_instance");
+}
+
+/* Deallocate a interpreter instance */
+static int
+tiff_impl_deallocate_interp_instance(pl_interp_implementation_t *impl)
+{
+    tiff_interp_instance_t *tiff = (tiff_interp_instance_t *)impl->interp_client_data;
+
+    tiff_deallocate(tiff);
+    impl->interp_client_data = NULL;
+
+    return 0;
+}
+
+/* Do per-instance interpreter allocation/init. */
+static int
+tiff_impl_allocate_interp_instance(pl_interp_implementation_t *impl, gs_memory_t *mem)
+{
+    int code;
+    tiff_interp_instance_t *tiff
+        = (tiff_interp_instance_t *)gs_alloc_bytes(mem,
+                                                  sizeof(tiff_interp_instance_t),
+                                                  "tiff_impl_allocate_interp_instance");
+    if (!tiff)
+        return_error(gs_error_VMerror);
+    memset(tiff, 0, sizeof(*tiff));
+
+    tiff->memory = mem;
+    tiff->pgs = gs_gstate_alloc(mem);
+    if (tiff->pgs == NULL)
+        goto failVM;
+
+    /* Push one save level onto the stack to assuage the memory handling */
+    code = gs_gsave(tiff->pgs);
+    if (code < 0)
+        goto fail;
+
+    code = gsicc_init_iccmanager(tiff->pgs);
+    if (code < 0)
+        goto fail;
+
+    tiff->gray = gs_cspace_new_ICC(mem, tiff->pgs, 1);
+    tiff->rgb  = gs_cspace_new_ICC(mem, tiff->pgs, 3);
+    tiff->cmyk = gs_cspace_new_ICC(mem, tiff->pgs, 4);
+
+    impl->interp_client_data = tiff;
+
+    return 0;
+
+failVM:
+    code = gs_note_error(gs_error_VMerror);
+fail:
+    (void)tiff_deallocate(tiff);
+    return code;
+}
+
+/*
+ * Get the allocator with which to allocate a device
+ */
+static gs_memory_t *
+tiff_impl_get_device_memory(pl_interp_implementation_t *impl)
+{
+    tiff_interp_instance_t *tiff = (tiff_interp_instance_t *)impl->interp_client_data;
+
+    return tiff->dev ? tiff->dev->memory : NULL;
+}
+
+#if 0 /* UNUSED */
+static int
+tiff_impl_set_param(pl_interp_implementation_t *impl,
+                   pl_set_param_type           type,
+                   const char                 *param,
+                   const void                 *val)
+{
+    tiff_interp_instance_t *tiff = (tiff_interp_instance_t *)impl->interp_client_data;
+
+    /* No params set here */
+    return 0;
+}
+
+static int
+tiff_impl_add_path(pl_interp_implementation_t *impl,
+                  const char                 *path)
+{
+    tiff_interp_instance_t *tiff = (tiff_interp_instance_t *)impl->interp_client_data;
+
+    /* No paths to add */
+    return 0;
+}
+
+static int
+tiff_impl_post_args_init(pl_interp_implementation_t *impl)
+{
+    tiff_interp_instance_t *tiff = (jpg_interp_instance_t *)impl->interp_client_data;
+
+    /* No post args processing */
+    return 0;
+}
+#endif
+
+/* Prepare interp instance for the next "job" */
+static int
+tiff_impl_init_job(pl_interp_implementation_t *impl,
+                  gx_device                  *device)
+{
+    tiff_interp_instance_t *tiff = (tiff_interp_instance_t *)impl->interp_client_data;
+
+    tiff->dev = device;
+    tiff->state = ii_state_identifying;
+
+    return 0;
+}
+
+#if 0 /* UNUSED */
+static int
+tiff_impl_run_prefix_commands(pl_interp_implementation_t *impl,
+                             const char                 *prefix)
+{
+    tiff_interp_instance_t *tiff = (tiff_interp_instance_t *)impl->interp_client_data;
+
+    return 0;
+}
+
+static int
+tiff_impl_process_file(pl_interp_implementation_t *impl, const char *filename)
+{
+    tiff_interp_instance_t *tiff = (tiff_interp_instance_t *)impl->interp_client_data;
+
+    return 0;
+}
+#endif
+
+/* Do any setup for parser per-cursor */
+static int                      /* ret 0 or +ve if ok, else -ve error code */
+tiff_impl_process_begin(pl_interp_implementation_t * impl)
+{
+    tiff_interp_instance_t *tiff = (tiff_interp_instance_t *)impl->interp_client_data;
+
+    return 0;
+}
+
+/* Ensure we have 'required' bytes to read, and further ensure
+ * that we have no UEL's within those bytes. */
+static int
+ensure_bytes(tiff_interp_instance_t *jpg, stream_cursor_read *pr, int required)
+{
+    int n;
+    const uint8_t *p = pr->ptr+1;
+    const uint8_t *q;
+    int avail;
+
+    /* Find out how many bytes we need to check */
+    n = pr->limit - pr->ptr;
+    if (n > required)
+        n = required;
+
+    /* Make sure there are no UELs in that block */
+    q = p + n;
+    while (p != q) {
+        while (p != q && *p != '\033')
+            p++;
+        if (p == q)
+            break;
+        avail = pr->limit - pr->ptr;
+        if (memcmp(p, "\033%-12345X", min(avail, 9)) == 0) {
+            /* At least a partial match to a UEL */
+            return avail < 9 ? gs_error_NeedInput : gs_error_InterpreterExit;
+        }
+        p++;
+    }
+
+    /* If we have enough bytes, great, if not, get some more */
+    return (n < required) ? gs_error_NeedInput : 0;
+}
+
+static int
+flush_to_uel(stream_cursor_read *pr)
+{
+    const uint8_t *p = pr->ptr+1;
+    const uint8_t *q = pr->limit+1;
+    int avail;
+
+    while (p != q) {
+        while (p != q && *p != '\033')
+            p++;
+        if (p == q)
+            break;
+        avail = pr->limit - pr->ptr;
+        if (memcmp(p, "\033%-12345X", min(avail, 9)) == 0) {
+            /* At least a partial match to a UEL. Bin everything to
+             * the start of the match. */
+            pr->ptr = p-1;
+            if (avail == 9) /* Complete match. Exit! */
+                return gs_error_InterpreterExit;
+            /* Partial match. Get more data. */
+            return gs_error_NeedInput;
+        }
+        p++;
+    }
+
+    pr->ptr = pr->limit;
+
+    return 0;
+}
+
+static int
+bytes_until_uel(const stream_cursor_read *pr)
+{
+    const uint8_t *p = pr->ptr+1;
+    const uint8_t *q = pr->limit+1;
+    int avail;
+
+    while (p != q) {
+        while (p != q && *p != '\033')
+            p++;
+        if (p == q)
+            break;
+        avail = pr->limit - pr->ptr;
+        if (memcmp(p, "\033%-12345X", min(avail, 9)) == 0) {
+            /* At least a partial match to a UEL. Everything up to
+             * the start of the match is up for grabs. */
+            return p - (pr->ptr+1);
+        }
+        p++;
+    }
+
+    return pr->limit - pr->ptr;
+}
+
+static int
+get32be(stream_cursor_read *pr)
+{
+    int v = pr->ptr[1] << 24;
+    v |= pr->ptr[2] << 16;
+    v |= pr->ptr[3] << 8;
+    v |= pr->ptr[4];
+    pr->ptr += 4;
+
+    return v;
+}
+
+static int
+get8(stream_cursor_read *pr)
+{
+    return *++(pr->ptr);
+}
+
+static tmsize_t tifsReadProc(thandle_t  tiff_,
+                             void      *buf,
+                             tmsize_t   size)
+{
+    tiff_interp_instance_t *tiff = (tiff_interp_instance_t *)tiff_;
+    tmsize_t available = tiff->buffer_full - tiff->file_pos;
+    if (available > size)
+        available = size;
+
+    memcpy(buf, &tiff->tiff_buffer[tiff->file_pos], available);
+    tiff->file_pos += available;
+
+    return available;
+}
+
+static tmsize_t tifsWriteProc(thandle_t  tiff_,
+                              void      *buf,
+                              tmsize_t   size)
+{
+    return 0;
+}
+
+static toff_t tifsSeekProc(thandle_t tiff_, toff_t offset, int whence)
+{
+    tiff_interp_instance_t *tiff = (tiff_interp_instance_t *)tiff_;
+    size_t pos = tiff->file_pos;
+
+    if (whence == 1) { /* SEEK_CURR */
+        offset += pos;
+    } else if (whence == 2) { /* SEEK_END */
+        offset += tiff->buffer_full;
+    }
+    /* else assume SEEK_SET */
+
+    /* Clamp */
+    if (offset < 0)
+        offset = 0;
+    else if (offset > tiff->buffer_full)
+        offset = tiff->buffer_full;
+
+    tiff->file_pos = offset;
+
+    return offset;
+}
+
+static tifsCloseProc(thandle_t tiff_)
+{
+    return 0;
+}
+
+static toff_t tifsSizeProc(thandle_t tiff_)
+{
+    tiff_interp_instance_t *tiff = (tiff_interp_instance_t *)tiff_;
+
+    return tiff->buffer_full;
+}
+
+static int
+do_impl_process(pl_interp_implementation_t * impl, stream_cursor_read * pr, int eof)
+{
+    tiff_interp_instance_t *tiff = (tiff_interp_instance_t *)impl->interp_client_data;
+    int code = 0;
+    ii_state ostate = (ii_state)-1;
+    int bytes_left = 0;
+
+    while (tiff->state != ostate || pr->limit - pr->ptr != bytes_left)
+    {
+        ostate = tiff->state;
+        bytes_left = pr->limit - pr->ptr;
+        switch(tiff->state)
+        {
+        case ii_state_identifying:
+        {
+            const byte *hdr;
+            /* Try and get us 4 bytes */
+            code = ensure_bytes(tiff, pr, 4);
+            if (code < 0)
+                return code;
+            hdr = pr->ptr+1;
+            if (hdr[0] == 'I' && hdr[1] == 'I' && hdr[2] == 42 && hdr[3] == 0) {
+                tiff->state = ii_state_tiff;
+                break;
+            }
+            if (hdr[0] == 'M' && hdr[1] == 'M' && hdr[2] == 0 && hdr[3] == 42) {
+                tiff->state = ii_state_tiff;
+                break;
+            }
+            tiff->state = ii_state_flush;
+            break;
+        }
+        case ii_state_tiff:
+        {
+            /* Gather data into a buffer */
+            int bytes = bytes_until_uel(pr);
+
+            if (bytes == 0 && pr->limit - pr->ptr > 9) {
+                /* No bytes until UEL, and there is space for a UEL in the buffer */
+                tiff->state = ii_state_tiff_decode;
+                tiff->file_pos = 0;
+                break;
+            }
+            if (bytes == 0 && eof) {
+                /* No bytes until UEL, and we are at eof */
+                tiff->state = ii_state_tiff_decode;
+                tiff->file_pos = 0;
+                break;
+            }
+
+            if (tiff->buffer_full + bytes > tiff->buffer_max) {
+                /* Need to expand our buffer */
+                size_t proposed = tiff->buffer_full*2;
+                if (proposed == 0)
+                    proposed = 32768;
+                while (proposed < tiff->buffer_full + bytes)
+                    proposed *= 2;
+
+                if (tiff->tiff_buffer == NULL) {
+                    tiff->tiff_buffer = gs_alloc_bytes(tiff->memory, proposed, "tiff_buffer");
+                    if (tiff->tiff_buffer == NULL) {
+                        tiff->state = ii_state_flush;
+                        break;
+                    }
+                } else {
+                    void *new_buf = gs_resize_object(tiff->memory, tiff->tiff_buffer, proposed, "tiff_buffer");
+                    if (new_buf == NULL) {
+                        tiff->state = ii_state_flush;
+                        break;
+                    }
+                    tiff->tiff_buffer = new_buf;
+                }
+                tiff->buffer_max = proposed;
+            }
+
+            memcpy(&tiff->tiff_buffer[tiff->buffer_full], pr->ptr+1, bytes);
+            tiff->buffer_full += bytes;
+            pr->ptr += bytes;
+            break;
+        }
+        case ii_state_tiff_decode:
+        {
+            int tx, ty;
+            short planar;
+            float f, scale;
+            gs_color_space *cs;
+            unsigned int used;
+
+            tiff->handle = TIFFClientOpen("dummy", "rm",
+                                          (thandle_t)tiff,
+                                          tifsReadProc,
+                                          tifsWriteProc,
+                                          tifsSeekProc,
+                                          tifsCloseProc,
+                                          tifsSizeProc,
+                                          NULL,
+                                          NULL);
+            if (tiff->handle == NULL) {
+                tiff->state = ii_state_flush;
+                break;
+            }
+
+            TIFFGetField(tiff->handle, TIFFTAG_IMAGEWIDTH, &tiff->width);
+            TIFFGetField(tiff->handle, TIFFTAG_IMAGELENGTH, &tiff->height);
+            TIFFGetField(tiff->handle, TIFFTAG_TILEWIDTH, &tiff->tile_width);
+            TIFFGetField(tiff->handle, TIFFTAG_TILELENGTH, &tiff->tile_height);
+            TIFFGetField(tiff->handle, TIFFTAG_BITSPERSAMPLE, &tiff->bpc);
+            TIFFGetField(tiff->handle, TIFFTAG_SAMPLESPERPIXEL, &tiff->num_comps);
+            TIFFGetField(tiff->handle, TIFFTAG_PLANARCONFIG, &planar);
+            TIFFGetField(tiff->handle, TIFFTAG_XRESOLUTION, &f);
+            tiff->xresolution = (uint32_t)(f+0.5);
+            TIFFGetField(tiff->handle, TIFFTAG_YRESOLUTION, &f);
+            tiff->yresolution = (uint32_t)(f+0.5);
+            
+            if (TIFFIsTiled(tiff->handle)) {
+                int x, y;
+                tiff->samples = gs_alloc_bytes(tiff->memory, TIFFTileSize(tiff->handle), "tiff_tile");
+            } else {
+                tiff->tile_width = tiff->width;
+                tiff->tile_height = tiff->height;
+                tiff->samples = gs_alloc_bytes(tiff->memory, TIFFScanlineSize(tiff->handle), "tiff_scan");
+            }
+            if (tiff->samples == NULL) {
+                TIFFClose(tiff->handle);
+                tiff->state = ii_state_flush;
+                break;
+            }
+
+            /* FIXME: Need to allow for LAB, YUV etc too */
+            tiff->bpp = tiff->bpc * tiff->num_comps;
+            switch(tiff->num_comps) {
+            default:
+            case 1:
+                cs = tiff->gray;
+                break;
+            case 3:
+                cs = tiff->rgb;
+                break;
+            case 4:
+                cs = tiff->cmyk;
+                break;
+            }
+
+            /* Scale to fit, if too large. */
+            scale = 1.0f;
+            if (tiff->width * tiff->dev->HWResolution[0] > tiff->dev->width * tiff->xresolution)
+                scale = ((float)tiff->dev->width * tiff->xresolution) / (tiff->width * tiff->dev->HWResolution[0]);
+            if (scale * tiff->height * tiff->dev->HWResolution[1] > tiff->dev->height * tiff->yresolution)
+                scale = ((float)tiff->dev->height * tiff->yresolution) / (tiff->height * tiff->dev->HWResolution[1]);
+
+            tiff->nulldev = gs_currentdevice(tiff->pgs);
+            rc_increment(tiff->nulldev);
+            code = gs_setdevice_no_erase(tiff->pgs, tiff->dev);
+            if (code < 0) {
+                tiff->state = ii_state_flush;
+                break;
+            }
+
+            if (TIFFIsTiled(tiff->handle) || planar == PLANARCONFIG_CONTIG) {
+                tiff->byte_width = ((tiff->bpc * tiff->num_comps * tiff->tile_width + 7)>>3);
+            } else {
+                tiff->byte_width = ((tiff->bpc * tiff->tile_width + 7)>>3) * tiff->num_comps;
+            }
+            code = gs_erasepage(tiff->pgs);
+            if (code < 0) {
+                tiff->state = ii_state_flush;
+                return code;
+            }
+            for (ty = 0; ty < tiff->height; ty += tiff->tile_height)
+                for (tx = 0; tx < tiff->width; tx += tiff->tile_width) {
+                    int y, s;
+                    byte *row;
+                    float xext, xoffset, yext, yoffset;
+
+                    tiff->penum = gs_image_enum_alloc(tiff->memory, "tiff_impl_process(penum)");
+                    if (tiff->penum == NULL) {
+                        code = gs_note_error(gs_error_VMerror);
+                        tiff->state = ii_state_flush;
+                        return code;
+                    }
+
+                    /* Centre - Extents and offsets are all calculated in points (1/72 of an inch) */
+                    xext = (((float)tiff->width - tx * 2) * 72 * scale / tiff->xresolution);
+                    xoffset = (tiff->dev->width * 72 / tiff->dev->HWResolution[0] - xext)/2;
+                    yext = (((float)tiff->height - ty * 2) * 72 * scale / tiff->yresolution);
+                    yoffset = (tiff->dev->height * 72 / tiff->dev->HWResolution[1] - yext)/2;
+
+                    gs_initmatrix(tiff->pgs);
+
+                    /* By default the ctm is set to:
+                     *   xres/72   0
+                     *   0         -yres/72
+                     *   0         dev->height * yres/72
+                     * i.e. it moves the origin from being top right to being bottom left.
+                     * We want to move it back, as without this, the image will be displayed
+                     * upside down.
+                     */
+                    code = gs_translate(tiff->pgs, 0.0, tiff->dev->height * 72 / tiff->dev->HWResolution[1]);
+                    if (code >= 0)
+                        code = gs_translate(tiff->pgs, xoffset, -yoffset);
+                    if (code >= 0)
+                        code = gs_scale(tiff->pgs, scale, -scale);
+                    if (code < 0) {
+                        tiff->state = ii_state_flush;
+                        break;
+                    }
+
+                    memset(&tiff->image, 0, sizeof(tiff->image));
+                    gs_image_t_init(&tiff->image, cs);
+                    tiff->image.BitsPerComponent = tiff->bpp/tiff->num_comps;
+                    tiff->image.Width = tiff->tile_width;
+                    tiff->image.Height = tiff->tile_height;
+
+                    tiff->image.ImageMatrix.xx = tiff->xresolution / 72.0f;
+                    tiff->image.ImageMatrix.yy = tiff->yresolution / 72.0f;
+
+                    code = gs_image_init(tiff->penum,
+                                         &tiff->image,
+                                         false,
+                                         false,
+                                         tiff->pgs);
+                    if (code < 0) {
+                        tiff->state = ii_state_flush;
+                        return code;
+                    }
+
+                    if (TIFFIsTiled(tiff->handle)) {
+                        TIFFReadTile(tiff->handle, tiff->samples, tx, ty, 0, 0);
+                    }
+
+                    for (y = 0; y < tiff->tile_height; y++) {
+                        if (TIFFIsTiled(tiff->handle)) {
+                            row = tiff->samples + tiff->byte_width * y;
+                        } else if (planar == PLANARCONFIG_CONTIG) {
+                            row = tiff->samples;
+                            TIFFReadScanline(tiff->handle, tiff->samples, ty+y, 0);
+                        } else {
+                            int span = tiff->byte_width / tiff->num_comps; /* FIXME: Avoid division */
+                            row = tiff->samples;
+                            for (s = 0; s < tiff->num_comps; s++)
+                                TIFFReadScanline(tiff->handle, tiff->samples + span*s, ty+y, s);
+                        }
+
+                        code = gs_image_next(tiff->penum, row, tiff->byte_width, &used);
+                        if (code < 0) {
+                            tiff->state = ii_state_flush;
+                            break;
+                        }
+                    }
+                    code = gs_image_cleanup_and_free_enum(tiff->penum, tiff->pgs);
+                    tiff->penum = NULL;
+                    if (code < 0) {
+                        tiff->state = ii_state_flush;
+                        break;
+                    }
+            }
+            tiff->state = ii_state_flush;
+            (void)pl_finish_page(tiff->memory->gs_lib_ctx->top_of_system,
+                                 tiff->pgs, 1, true);
+            break;
+        }
+        default:
+        case ii_state_flush:
+
+            if (tiff->handle) {
+                TIFFClose(tiff->handle);
+                tiff->handle = NULL;
+            }
+
+            if (tiff->penum) {
+                (void)gs_image_cleanup_and_free_enum(tiff->penum, tiff->pgs);
+                tiff->penum = NULL;
+            }
+
+            if (tiff->samples) {
+                gs_free_object(tiff->memory, tiff->samples, "tiff_impl_process(samples)");
+                tiff->samples = NULL;
+            }
+
+            if (tiff->tiff_buffer) {
+                gs_free_object(tiff->memory, tiff->tiff_buffer, "tiff_impl_process(tiff_buffer)");
+                tiff->tiff_buffer = NULL;
+            }
+            /* We want to bin any data we get up to, but not including
+             * a UEL. */
+            return flush_to_uel(pr);
+        }
+    }
+
+    return code;
+}
+
+static int
+tiff_impl_process(pl_interp_implementation_t * impl, stream_cursor_read * pr) {
+    return do_impl_process(impl, pr, 0);
+}
+
+static int
+tiff_impl_process_end(pl_interp_implementation_t * impl)
+{
+    tiff_interp_instance_t *tiff = (tiff_interp_instance_t *)impl->interp_client_data;
+    int code = 0;
+
+    /* FIXME: */
+    if (code == gs_error_InterpreterExit || code == gs_error_NeedInput)
+        code = 0;
+
+    return code;
+}
+
+/* Not implemented */
+static int
+tiff_impl_flush_to_eoj(pl_interp_implementation_t *impl, stream_cursor_read *cursor)
+{
+    const byte *p = cursor->ptr;
+    const byte *rlimit = cursor->limit;
+
+    /* Skip to, but leave UEL in buffer for PJL to find later */
+    for (; p < rlimit; ++p)
+        if (p[1] == '\033') {
+            uint avail = rlimit - p;
+
+            if (memcmp(p + 1, "\033%-12345X", min(avail, 9)))
+                continue;
+            if (avail < 9)
+                break;
+            cursor->ptr = p;
+            return 1;           /* found eoj */
+        }
+    cursor->ptr = p;
+    return 0;                   /* need more */
+}
+
+/* Parser action for end-of-file */
+static int
+tiff_impl_process_eof(pl_interp_implementation_t *impl)
+{
+    stream_cursor_read r;
+
+    r.ptr = NULL;
+    r.limit = NULL;
+    return do_impl_process(impl, &r, 1);
+}
+
+/* Report any errors after running a job */
+static int
+tiff_impl_report_errors(pl_interp_implementation_t *impl,          /* interp instance to wrap up job in */
+                        int                         code,          /* prev termination status */
+                        long                        file_position, /* file position of error, -1 if unknown */
+                        bool                        force_to_cout  /* force errors to cout */
+)
+{
+    return 0;
+}
+
+/* Wrap up interp instance after a "job" */
+static int
+tiff_impl_dnit_job(pl_interp_implementation_t *impl)
+{
+    tiff_interp_instance_t *tiff = (tiff_interp_instance_t *)impl->interp_client_data;
+
+    if (tiff->nulldev) {
+        int code = gs_setdevice(tiff->pgs, tiff->nulldev);
+        tiff->dev = NULL;
+        rc_decrement(tiff->nulldev, "tiff_impl_dnit_job(nulldevice)");
+        tiff->nulldev = NULL;
+        return code;
+    }
+    return 0;
+}
+
+/* Parser implementation descriptor */
+const pl_interp_implementation_t tiff_implementation = {
+  tiff_impl_characteristics,
+  tiff_impl_allocate_interp_instance,
+  tiff_impl_get_device_memory,
+  NULL, /* tiff_impl_set_param */
+  NULL, /* tiff_impl_add_path */
+  NULL, /* tiff_impl_post_args_init */
+  tiff_impl_init_job,
+  NULL, /* tiff_impl_run_prefix_commands */
+  NULL, /* tiff_impl_process_file */
+  tiff_impl_process_begin,
+  tiff_impl_process,
+  tiff_impl_process_end,
+  tiff_impl_flush_to_eoj,
+  tiff_impl_process_eof,
+  tiff_impl_report_errors,
+  tiff_impl_dnit_job,
+  tiff_impl_deallocate_interp_instance,
+  NULL
+};
diff --git a/pcl/pl/plimpl.c b/pcl/pl/plimpl.c
index d4c0f40..fdbf8e9 100644
--- a/pcl/pl/plimpl.c
+++ b/pcl/pl/plimpl.c
@@ -41,6 +41,8 @@ extern pl_interp_implementation_t jpg_implementation;
 
 extern pl_interp_implementation_t pwg_implementation;
 
+extern pl_interp_implementation_t tiff_implementation;
+
 /* Zero-terminated list of pointers to implementations */
 pl_interp_implementation_t *pdl_implementations[] = {
     &pjl_implementation,
@@ -63,6 +65,9 @@ pl_interp_implementation_t *pdl_implementations[] = {
 #ifdef PWG_INCLUDED
     &pwg_implementation,
 #endif
+#ifdef TIFF_INCLUDED
+    &tiff_implementation,
+#endif
     0
 };
 
diff --git a/psi/msvc.mak b/psi/msvc.mak
index f5e9258..eb997e2 100644
--- a/psi/msvc.mak
+++ b/psi/msvc.mak
@@ -660,6 +660,7 @@ TIFFCONFDIR=$(TIFFSRCDIR)
 TIFFCONFIG_SUFFIX=.vc
 TIFFPLATFORM=win32
 TIFFCFLAGS="-DJPEG_LIB_MK1_OR_12BIT=0"
+ENABLE_TIFF=$(D_)TIFF_INCLUDED$(_D)
 !endif
 
 # Define the directory where the zlib sources are stored.
diff --git a/windows/ghostpdl.vcproj b/windows/ghostpdl.vcproj
index 87f6e5a..955d375 100644
--- a/windows/ghostpdl.vcproj
+++ b/windows/ghostpdl.vcproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="UTF-8"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <VisualStudioProject
 	ProjectType="Visual C++"
 	Version="8.00"
@@ -317,6 +317,10 @@
 				RelativePath="..\gpdl\pwgtop.c"
 				>
 			</File>
+			<File
+				RelativePath="..\gpdl\tifftop.c"
+				>
+			</File>
 		</Filter>
 	</Files>
 	<Globals>

----------------------------------------------------------------------
commit b5956ac8be8c923ad9e9fd3045724a5579cf4dce
Author: Robin Watts <[email protected]>
Date:   Tue Nov 19 18:11:55 2019 +0000

    gpdl: Fix compiler flags for pwgtop.c
    
    Don't need to pass the JPEG include directory here.

diff --git a/gpdl/gpdl.mak b/gpdl/gpdl.mak
index 7be019c..afc2be9 100644
--- a/gpdl/gpdl.mak
+++ b/gpdl/gpdl.mak
@@ -87,4 +87,4 @@ $(GPDL_JPG_TOP_OBJ): $(GPDLSRC)jpgtop.c $(AK)\
 $(GPDL_PWG_TOP_OBJ): $(GPDLSRC)pwgtop.c $(AK)\
  $(gxdevice_h) $(gserrors_h) $(gsstate_h) $(strimpl_h) $(gscoord_h)\
  $(spwgx_h) $(pltop_h)
-	$(GPDLCC) $(II)$(JI_)$(_I) $(GPDLSRC)pwgtop.c $(GPDLO_)$(GPDL_PWG_TOP_OBJ_FILE)
+	$(GPDLCC) $(GPDLSRC)pwgtop.c $(GPDLO_)$(GPDL_PWG_TOP_OBJ_FILE)

----------------------------------------------------------------------
commit 0329372164611fdff22f8c02201ff1fbbf94aae7
Author: Robin Watts <[email protected]>
Date:   Tue Nov 19 18:10:54 2019 +0000

    gpdl: Fix jpeg/pwg behaviour with varying resolutions.
    
    I thought this worked before, but tests revealed that it was
    broken.

diff --git a/gpdl/jpgtop.c b/gpdl/jpgtop.c
index 9974fcc..c2b46ed 100644
--- a/gpdl/jpgtop.c
+++ b/gpdl/jpgtop.c
@@ -585,17 +585,16 @@ jpg_impl_process(pl_interp_implementation_t * impl, stream_cursor_read * pr)
 
             /* Scale to fit, if too large. */
             scale = 1.0f;
-            if (jpg->width * 72 > jpg->dev->width * jpg->xresolution)
-                scale = ((float)jpg->dev->width * jpg->xresolution) / (jpg->width * 72);
-            if (scale * jpg->height * 72 > jpg->dev->height * jpg->yresolution)
-                scale = ((float)jpg->dev->height * jpg->yresolution) / (jpg->height * 72);
+            if (jpg->width * jpg->dev->HWResolution[0] > jpg->dev->width * jpg->xresolution)
+                scale = ((float)jpg->dev->width * jpg->xresolution) / (jpg->width * jpg->dev->HWResolution[0]);
+            if (scale * jpg->height * jpg->dev->HWResolution[1] > jpg->dev->height * jpg->yresolution)
+                scale = ((float)jpg->dev->height * jpg->yresolution) / (jpg->height * jpg->dev->HWResolution[1]);
 
-            /* Centre */
+            /* Centre - Extents and offsets are all calculated in points (1/72 of an inch) */
             xext = ((float)jpg->width * 72 * scale / jpg->xresolution);
-            xoffset = (jpg->dev->width - xext)/2;
+            xoffset = (jpg->dev->width * 72 / jpg->dev->HWResolution[0] - xext)/2;
             yext = ((float)jpg->height * 72 * scale / jpg->yresolution);
-            yoffset = (jpg->dev->height - yext)/2;
-
+            yoffset = (jpg->dev->height * 72 / jpg->dev->HWResolution[1] - yext)/2;
 
             /* Now we've got the data from the image header, we can
              * make the gs image instance */
@@ -610,9 +609,24 @@ jpg_impl_process(pl_interp_implementation_t * impl, stream_cursor_read * pr)
             }
             gs_initmatrix(jpg->pgs);
 
-            code = gs_translate(jpg->pgs, xoffset, jpg->dev->height-yoffset);
+            /* By default the ctm is set to:
+             *   xres/72   0
+             *   0         -yres/72
+             *   0         dev->height * yres/72
+             * i.e. it moves the origin from being top right to being bottom left.
+             * We want to move it back, as without this, the image will be displayed
+             * upside down.
+             */
+            code = gs_translate(jpg->pgs, 0.0, jpg->dev->height * 72 / jpg->dev->HWResolution[1]);
+            if (code >= 0)
+                code = gs_translate(jpg->pgs, xoffset, -yoffset);
             if (code >= 0)
                 code = gs_scale(jpg->pgs, scale, -scale);
+            /* At this point, the ctm is set to:
+             *   xres/72  0
+             *   0        yres/72
+             *   0        0
+             */
             if (code >= 0)
                 code = gs_erasepage(jpg->pgs);
             if (code < 0) {
@@ -632,8 +646,8 @@ jpg_impl_process(pl_interp_implementation_t * impl, stream_cursor_read * pr)
             jpg->image.Width = jpg->width;
             jpg->image.Height = jpg->height;
 
-            jpg->image.ImageMatrix.xx = jpg->xresolution / 72.0;
-            jpg->image.ImageMatrix.yy = jpg->yresolution / 72.0;
+            jpg->image.ImageMatrix.xx = jpg->xresolution / 72.0f;
+            jpg->image.ImageMatrix.yy = jpg->yresolution / 72.0f;
 
             jpg->penum = gs_image_enum_alloc(jpg->memory, "jpg_impl_process(penum)");
             if (jpg->penum == NULL) {
diff --git a/gpdl/pwgtop.c b/gpdl/pwgtop.c
index 5e7549e..1083508 100644
--- a/gpdl/pwgtop.c
+++ b/gpdl/pwgtop.c
@@ -498,9 +498,22 @@ bad_header:
                 goto early_flush;
             gs_initmatrix(pwg->pgs);
 
-            code = gs_scale(pwg->pgs, 1.0, -1.0);
+            /* By default the ctm is set to:
+             *   xres/72   0
+             *   0         -yres/72
+             *   0         dev->height * yres/72
+             * i.e. it moves the origin from being top right to being bottom left.
+             * We want to move it back, as without this, the image will be displayed
+             * upside down.
+             */
+            code = gs_translate(pwg->pgs, 0.0, -pwg->dev->height * 72 / pwg->dev->HWResolution[1]);
             if (code >= 0)
-                code = gs_translate(pwg->pgs, 0.0, -pwg->dev->height);
+                code = gs_scale(pwg->pgs, 1, -1);
+            /* At this point, the ctm is set to:
+             *   xres/72  0
+             *   0        yres/72
+             *   0        0
+             */
             if (code >= 0)
                 code = gs_erasepage(pwg->pgs);
             if (code < 0)
@@ -512,8 +525,8 @@ bad_header:
             pwg->image.Width = pwg->width;
             pwg->image.Height = pwg->height;
 
-            pwg->image.ImageMatrix.xx = pwg->xresolution / 72.0;
-            pwg->image.ImageMatrix.yy = pwg->yresolution / 72.0;
+            pwg->image.ImageMatrix.xx = pwg->xresolution / 72.0f;
+            pwg->image.ImageMatrix.yy = pwg->yresolution / 72.0f;
 
             pwg->penum = gs_image_enum_alloc(pwg->memory, "pwg_impl_process(penum)");
             if (pwg->penum == NULL) {

----------------------------------------------------------------------
commit cd8747382f47393efd0f0013700a8294c0ded15c
Author: Robin Watts <[email protected]>
Date:   Mon Nov 18 11:36:30 2019 +0000

    Slight reorganisation of gpdl interpreter files.
    
    Rather than having each different "language" have a 'top' file
    in gpdl/foo/footop.c, move them to be gpdl/foo.c. Extra directories
    seem overkill at this point, and it simplifies the Makefile
    slightly.
    
    Also, rename IMG to JPG.

diff --git a/Makefile.in b/Makefile.in
index add2f36..83d1735 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -63,10 +63,6 @@ URFSRCDIR=@srcdir@/urf
 URFGENDIR=./$(BUILDDIRPREFIX)@OBJDIR_BSDMAKE_WORKAROUND@
 URFOBJDIR=./$(BUILDDIRPREFIX)@OBJDIR_BSDMAKE_WORKAROUND@
 
-IMGSRCDIR=@srcdir@/gpdl/image
-IMGGENDIR=./$(BUILDDIRPREFIX)@OBJDIR_BSDMAKE_WORKAROUND@
-IMGOBJDIR=./$(BUILDDIRPREFIX)@OBJDIR_BSDMAKE_WORKAROUND@
-
 CONTRIBDIR=@srcdir@/contrib
 
 # Do not edit the next group of lines.
diff --git a/gpdl/gpdl.mak b/gpdl/gpdl.mak
index 3864a92..7be019c 100644
--- a/gpdl/gpdl.mak
+++ b/gpdl/gpdl.mak
@@ -18,8 +18,6 @@ GPDL_MAK=$(GPDLSRCDIR)$(D)gpdl.mak
 GPDLSRC=$(GPDLSRCDIR)$(D)
 GPDLPSISRC=$(GPDLSRCDIR)$(D)psi$(D)
 GPDLURFSRC=$(URFSRCDIR)$(D)
-GPDLIMGSRC=$(GPDLSRCDIR)$(D)image$(D)
-GPDLPWGSRC=$(GPDLSRCDIR)$(D)pwg$(D)
 
 GPDLOBJ=$(GPDLOBJDIR)$(D)
 GPDLGEN=$(GPDLGENDIR)$(D)
@@ -31,16 +29,26 @@ GPDL_PSI_TOP_OBJ=$(GPDLOBJ)/$(GPDL_PSI_TOP_OBJ_FILE)
 
 GPDL_URF_TOP_OBJ_FILE=urftop.$(OBJ)
 
-GPDL_IMG_TOP_OBJ_FILE=imagetop.$(OBJ)
-GPDL_IMG_TOP_OBJ=$(GPDLOBJ)/$(GPDL_IMG_TOP_OBJ_FILE)
+GPDL_JPG_TOP_OBJ_FILE=jpgtop.$(OBJ)
+GPDL_JPG_TOP_OBJ=$(GPDLOBJ)/$(GPDL_JPG_TOP_OBJ_FILE)
 
 GPDL_PWG_TOP_OBJ_FILE=pwgtop.$(OBJ)
 GPDL_PWG_TOP_OBJ=$(GPDLOBJ)/$(GPDL_PWG_TOP_OBJ_FILE)
 
-GPDL_PSI_TOP_OBJS=$(GPDL_PWG_TOP_OBJ) $(GPDL_IMG_TOP_OBJ) $(GPDL_URF_TOP_OBJ) $(GPDL_PSI_TOP_OBJ) $(GPDLOBJ)gpdlimpl.$(OBJ)
-
-LANG_CFLAGS=$(D_)PCL_INCLUDED$(_D) $(D_)PSI_INCLUDED$(_D) $(D_)XPS_INCLUDED$(_D) $(ENABLE_URF) $(D_)IMG_INCLUDED$(_D) $(D_)PWG_INCLUDED$(_D)
+GPDL_PSI_TOP_OBJS=\
+	$(GPDL_PWG_TOP_OBJ)\
+	$(GPDL_JPG_TOP_OBJ)\
+	$(GPDL_URF_TOP_OBJ)\
+	$(GPDL_PSI_TOP_OBJ)\
+	$(GPDLOBJ)gpdlimpl.$(OBJ)
 
+LANG_CFLAGS=\
+	$(D_)PCL_INCLUDED$(_D)\
+	$(D_)PSI_INCLUDED$(_D)\
+	$(D_)XPS_INCLUDED$(_D)\
+	$(ENABLE_URF)\
+	$(D_)JPG_INCLUDED$(_D)\
+	$(D_)PWG_INCLUDED$(_D)
 
 GPDLCC=$(CC_) $(LANG_CFLAGS) $(I_)$(PSSRCDIR)$(_I) $(I_)$(PLSRCDIR)$(_I) $(I_)$(GLSRCDIR)$(_I) $(I_)$(DEVSRCDIR)$(_I) $(I_)$(GLGENDIR)$(_I) $(C_)
 
@@ -56,12 +64,12 @@ $(GPDLOBJ)gpdlimpl.$(OBJ): $(GPDLGEN)gpdlimpl.c          \
 	$(GPDLCC) $(GPDLGEN)gpdlimpl.c $(GPDLO_)gpdlimpl.$(OBJ)
 
 
-$(GPDL_PSI_TOP_OBJ): $(GPDLPSISRC)psitop.c $(AK) $(stdio__h)\
+$(GPDL_PSI_TOP_OBJ): $(GPDLSRC)psitop.c $(AK) $(stdio__h)\
  $(string__h) $(gdebug_h) $(gp_h) $(gsdevice_h) $(gserrors_h) $(gsmemory_h)\
  $(gsstate_h) $(gsstruct_h) $(gspaint_h) $(gstypes_h) $(gxalloc_h) $(gxstate_h)\
  $(gsnogc_h) $(pltop_h) $(psitop_h) $(plparse_h) $(gsicc_manage_h)\
  $(plfont_h) $(uconfig_h)
-	$(GPDLCC) $(GPDLPSISRC)psitop.c $(GPDLO_)$(GPDL_PSI_TOP_OBJ_FILE)
+	$(GPDLCC) $(GPDLSRC)psitop.c $(GPDLO_)$(GPDL_PSI_TOP_OBJ_FILE)
 
 # Note that we don't use $(GPDL_URF_TOP_OBJ) as the target of the
 # next make rule, as this expands to "" in builds that don't use
@@ -71,12 +79,12 @@ $(GPDLOBJ)/$(GPDL_URF_TOP_OBJ_FILE): $(GPDLURFSRC)urftop.c $(AK)\
  $(gscoord_h) $(pltop_h)
 	$(GPDLCC) $(GPDLURFSRC)urftop.c $(GPDLO_)$(GPDL_URF_TOP_OBJ_FILE)
 
-$(GPDL_IMG_TOP_OBJ): $(GPDLIMGSRC)imagetop.c $(AK)\
+$(GPDL_JPG_TOP_OBJ): $(GPDLSRC)jpgtop.c $(AK)\
  $(gxdevice_h) $(gserrors_h) $(gsstate_h) $(strimpl_h) $(gscoord_h)\
  $(jpeglib_h) $(setjmp__h) $(sjpeg_h) $(pltop_h)
-	$(GPDLCC) $(II)$(JI_)$(_I) $(GPDLIMGSRC)imagetop.c $(GPDLO_)$(GPDL_IMG_TOP_OBJ_FILE)
+	$(GPDLCC) $(II)$(JI_)$(_I) $(GPDLSRC)jpgtop.c $(GPDLO_)$(GPDL_JPG_TOP_OBJ_FILE)
 
-$(GPDL_PWG_TOP_OBJ): $(GPDLPWGSRC)pwgtop.c $(AK)\
- $(gxdevice_h) $(gserrors_h) $(gsstate_h) $(spwgx_h) $(strimpl_h)\
- $(gscoord_h) $(pltop_h)
-	$(GPDLCC) $(II)$(JI_)$(_I) $(GPDLPWGSRC)pwgtop.c $(GPDLO_)$(GPDL_PWG_TOP_OBJ_FILE)
+$(GPDL_PWG_TOP_OBJ): $(GPDLSRC)pwgtop.c $(AK)\
+ $(gxdevice_h) $(gserrors_h) $(gsstate_h) $(strimpl_h) $(gscoord_h)\
+ $(spwgx_h) $(pltop_h)
+	$(GPDLCC) $(II)$(JI_)$(_I) $(GPDLSRC)pwgtop.c $(GPDLO_)$(GPDL_PWG_TOP_OBJ_FILE)
diff --git a/gpdl/image/imagetop.c b/gpdl/jpgtop.c
similarity index 53%
rename from gpdl/image/imagetop.c
rename to gpdl/jpgtop.c
index b3232dc..9974fcc 100644
--- a/gpdl/image/imagetop.c
+++ b/gpdl/jpgtop.c
@@ -13,8 +13,8 @@
    CA 94945, U.S.A., +1(415)492-9861, for further information.
 */
 
-/* imagetop.c */
-/* Top-level API implementation of "Image" Language Interface */
+/* jpgtop.c */
+/* Top-level API implementation of "JPG" Language Interface */
 
 #include "pltop.h"
 #include "gserrors.h"
@@ -46,12 +46,12 @@ typedef enum
 typedef struct {
     struct jpeg_error_mgr pub;
     jmp_buf setjmp_buffer;
-} img_error_mgr;
+} jpg_error_mgr;
 
 /*
- * Image interpreter instance
+ * Jpg interpreter instance
  */
-typedef struct img_interp_instance_s {
+typedef struct jpg_interp_instance_s {
     gs_memory_t       *memory;
     gs_memory_t       *cmemory;
     gx_device         *dev;
@@ -61,7 +61,7 @@ typedef struct img_interp_instance_s {
     gs_color_space    *rgb;
     gs_color_space    *cmyk;
 
-    /* Image parser state machine */
+    /* Jpg parser state machine */
     ii_state           state;
 
     int                pages;
@@ -86,14 +86,14 @@ typedef struct img_interp_instance_s {
     struct jpeg_decompress_struct cinfo;
     struct jpeg_source_mgr        jsrc;
     size_t             bytes_to_skip;
-    img_error_mgr      jerr;
+    jpg_error_mgr      jerr;
 
     byte              *samples;
 
-} img_interp_instance_t;
+} jpg_interp_instance_t;
 
 static int
-img_detect_language(const char *s, int len)
+jpg_detect_language(const char *s, int len)
 {
     const byte *hdr = (const byte *)s;
     if (len >= 11) {
@@ -106,9 +106,9 @@ img_detect_language(const char *s, int len)
     return 0;
 }
 
-static const pl_interp_characteristics_t img_characteristics = {
-    "IMAGE",
-    img_detect_language,
+static const pl_interp_characteristics_t jpg_characteristics = {
+    "JPG",
+    jpg_detect_language,
     "Artifex",
     "0.01",
     "11 Nov 2019",
@@ -120,39 +120,39 @@ static const pl_interp_characteristics_t img_characteristics = {
  * This is no good to find our instance from. We therefore find
  * it by offsetting back from the address of the cinfo. This is
  * a nasty bit of casting, so wrap it in a macro. */
-#define IMG_FROM_CINFO(CINFO) \
-    (img_interp_instance_t *)(((char *)(CINFO))-offsetof(img_interp_instance_t,cinfo))
+#define JPG_FROM_CINFO(CINFO) \
+    (jpg_interp_instance_t *)(((char *)(CINFO))-offsetof(jpg_interp_instance_t,cinfo))
 
 
 /* Get implementation's characteristics */
 static const pl_interp_characteristics_t * /* always returns a descriptor */
-img_impl_characteristics(const pl_interp_implementation_t *impl)     /* implementation of interpreter to alloc */
+jpg_impl_characteristics(const pl_interp_implementation_t *impl)     /* implementation of interpreter to alloc */
 {
-  return &img_characteristics;
+  return &jpg_characteristics;
 }
 
 static void
-img_deallocate(img_interp_instance_t *img)
+jpg_deallocate(jpg_interp_instance_t *jpg)
 {
-    if (img == NULL)
+    if (jpg == NULL)
         return;
 
-    rc_decrement_cs(img->gray, "img_deallocate");
-    rc_decrement_cs(img->rgb, "img_deallocate");
-    rc_decrement_cs(img->cmyk, "img_deallocate");
+    rc_decrement_cs(jpg->gray, "jpg_deallocate");
+    rc_decrement_cs(jpg->rgb, "jpg_deallocate");
+    rc_decrement_cs(jpg->cmyk, "jpg_deallocate");
 
-    if (img->pgs != NULL)
-        gs_gstate_free_chain(img->pgs);
-    gs_free_object(img->memory, img, "img_impl_allocate_interp_instance");
+    if (jpg->pgs != NULL)
+        gs_gstate_free_chain(jpg->pgs);
+    gs_free_object(jpg->memory, jpg, "jpg_impl_allocate_interp_instance");
 }
 
 /* Deallocate a interpreter instance */
 static int
-img_impl_deallocate_interp_instance(pl_interp_implementation_t *impl)
+jpg_impl_deallocate_interp_instance(pl_interp_implementation_t *impl)
 {
-    img_interp_instance_t *img = (img_interp_instance_t *)impl->interp_client_data;
+    jpg_interp_instance_t *jpg = (jpg_interp_instance_t *)impl->interp_client_data;
 
-    img_deallocate(img);
+    jpg_deallocate(jpg);
     impl->interp_client_data = NULL;
 
     return 0;
@@ -160,43 +160,43 @@ img_impl_deallocate_interp_instance(pl_interp_implementation_t *impl)
 
 /* Do per-instance interpreter allocation/init. */
 static int
-img_impl_allocate_interp_instance(pl_interp_implementation_t *impl, gs_memory_t *mem)
+jpg_impl_allocate_interp_instance(pl_interp_implementation_t *impl, gs_memory_t *mem)
 {
     int code;
-    img_interp_instance_t *img
-        = (img_interp_instance_t *)gs_alloc_bytes(mem,
-                                                  sizeof(img_interp_instance_t),
-                                                  "img_impl_allocate_interp_instance");
-    if (!img)
+    jpg_interp_instance_t *jpg
+        = (jpg_interp_instance_t *)gs_alloc_bytes(mem,
+                                                  sizeof(jpg_interp_instance_t),
+                                                  "jpg_impl_allocate_interp_instance");
+    if (!jpg)
         return_error(gs_error_VMerror);
-    memset(img, 0, sizeof(*img));
+    memset(jpg, 0, sizeof(*jpg));
 
-    img->memory = mem;
-    img->pgs = gs_gstate_alloc(mem);
-    if (img->pgs == NULL)
+    jpg->memory = mem;
+    jpg->pgs = gs_gstate_alloc(mem);
+    if (jpg->pgs == NULL)
         goto failVM;
 
     /* Push one save level onto the stack to assuage the memory handling */
-    code = gs_gsave(img->pgs);
+    code = gs_gsave(jpg->pgs);
     if (code < 0)
         goto fail;
 
-    code = gsicc_init_iccmanager(img->pgs);
+    code = gsicc_init_iccmanager(jpg->pgs);
     if (code < 0)
         goto fail;
 
-    img->gray = gs_cspace_new_ICC(mem, img->pgs, 1);
-    img->rgb  = gs_cspace_new_ICC(mem, img->pgs, 3);
-    img->cmyk = gs_cspace_new_ICC(mem, img->pgs, 4);
+    jpg->gray = gs_cspace_new_ICC(mem, jpg->pgs, 1);
+    jpg->rgb  = gs_cspace_new_ICC(mem, jpg->pgs, 3);
+    jpg->cmyk = gs_cspace_new_ICC(mem, jpg->pgs, 4);
 
-    impl->interp_client_data = img;
+    impl->interp_client_data = jpg;
 
     return 0;
 
 failVM:
     code = gs_note_error(gs_error_VMerror);
 fail:
-    (void)img_deallocate(img);
+    (void)jpg_deallocate(jpg);
     return code;
 }
 
@@ -204,40 +204,40 @@ fail:
  * Get the allocator with which to allocate a device
  */
 static gs_memory_t *
-img_impl_get_device_memory(pl_interp_implementation_t *impl)
+jpg_impl_get_device_memory(pl_interp_implementation_t *impl)
 {
-    img_interp_instance_t *img = (img_interp_instance_t *)impl->interp_client_data;
+    jpg_interp_instance_t *jpg = (jpg_interp_instance_t *)impl->interp_client_data;
 
-    return img->dev ? img->dev->memory : NULL;
+    return jpg->dev ? jpg->dev->memory : NULL;
 }
 
 #if 0 /* UNUSED */
 static int
-img_impl_set_param(pl_interp_implementation_t *impl,
+jpg_impl_set_param(pl_interp_implementation_t *impl,
                    pl_set_param_type           type,
                    const char                 *param,
                    const void                 *val)
 {
-    img_interp_instance_t *img = (img_interp_instance_t *)impl->interp_client_data;
+    jpg_interp_instance_t *jpg = (jpg_interp_instance_t *)impl->interp_client_data;
 
     /* No params set here */
     return 0;
 }
 
 static int
-img_impl_add_path(pl_interp_implementation_t *impl,
+jpg_impl_add_path(pl_interp_implementation_t *impl,
                   const char                 *path)
 {
-    img_interp_instance_t *img = (img_interp_instance_t *)impl->interp_client_data;
+    jpg_interp_instance_t *jpg = (jpg_interp_instance_t *)impl->interp_client_data;
 
     /* No paths to add */
     return 0;
 }
 
 static int
-img_impl_post_args_init(pl_interp_implementation_t *impl)
+jpg_impl_post_args_init(pl_interp_implementation_t *impl)
 {
-    img_interp_instance_t *img = (img_interp_instance_t *)impl->interp_client_data;
+    jpg_interp_instance_t *jpg = (jpg_interp_instance_t *)impl->interp_client_data;
 
     /* No post args processing */
     return 0;
@@ -246,31 +246,31 @@ img_impl_post_args_init(pl_interp_implementation_t *impl)
 
 /* Prepare interp instance for the next "job" */
 static int
-img_impl_init_job(pl_interp_implementation_t *impl,
+jpg_impl_init_job(pl_interp_implementation_t *impl,
                   gx_device                  *device)
 {
-    img_interp_instance_t *img = (img_interp_instance_t *)impl->interp_client_data;
+    jpg_interp_instance_t *jpg = (jpg_interp_instance_t *)impl->interp_client_data;
 
-    img->dev = device;
-    img->state = ii_state_identifying;
+    jpg->dev = device;
+    jpg->state = ii_state_identifying;
 
     return 0;
 }
 
 #if 0 /* UNUSED */
 static int
-img_impl_run_prefix_commands(pl_interp_implementation_t *impl,
+jpg_impl_run_prefix_commands(pl_interp_implementation_t *impl,
                              const char                 *prefix)
 {
-    img_interp_instance_t *img = (img_interp_instance_t *)impl->interp_client_data;
+    jpg_interp_instance_t *jpg = (jpg_interp_instance_t *)impl->interp_client_data;
 
     return 0;
 }
 
 static int
-img_impl_process_file(pl_interp_implementation_t *impl, const char *filename)
+jpg_impl_process_file(pl_interp_implementation_t *impl, const char *filename)
 {
-    img_interp_instance_t *img = (img_interp_instance_t *)impl->interp_client_data;
+    jpg_interp_instance_t *jpg = (jpg_interp_instance_t *)impl->interp_client_data;
 
     return 0;
 }
@@ -278,9 +278,9 @@ img_impl_process_file(pl_interp_implementation_t *impl, const char *filename)
 
 /* Do any setup for parser per-cursor */
 static int                      /* ret 0 or +ve if ok, else -ve error code */
-img_impl_process_begin(pl_interp_implementation_t * impl)
+jpg_impl_process_begin(pl_interp_implementation_t * impl)
 {
-    img_interp_instance_t *img = (img_interp_instance_t *)impl->interp_client_data;
+    jpg_interp_instance_t *jpg = (jpg_interp_instance_t *)impl->interp_client_data;
 
     return 0;
 }
@@ -288,7 +288,7 @@ img_impl_process_begin(pl_interp_implementation_t * impl)
 /* Ensure we have 'required' bytes to read, and further ensure
  * that we have no UEL's within those bytes. */
 static int
-ensure_bytes(img_interp_instance_t *img, stream_cursor_read *pr, int required)
+ensure_bytes(jpg_interp_instance_t *jpg, stream_cursor_read *pr, int required)
 {
     int n;
     const uint8_t *p = pr->ptr+1;
@@ -392,53 +392,53 @@ get8(stream_cursor_read *pr)
 }
 
 static void
-img_jpeg_init_source(j_decompress_ptr cinfo)
+jpg_jpeg_init_source(j_decompress_ptr cinfo)
 {
     /* We've already inited the source */
 }
 
 static boolean
-img_fill_input_buffer(j_decompress_ptr cinfo)
+jpg_fill_input_buffer(j_decompress_ptr cinfo)
 {
     return FALSE; /* We've filled the buffer already */
 }
 
 static void
-img_skip_input_data(j_decompress_ptr cinfo, long num_bytes)
+jpg_skip_input_data(j_decompress_ptr cinfo, long num_bytes)
 {
-    img_interp_instance_t *img = IMG_FROM_CINFO(cinfo);
+    jpg_interp_instance_t *jpg = JPG_FROM_CINFO(cinfo);
     size_t n = cinfo->src->bytes_in_buffer;
 
     if (n > num_bytes)
         n = num_bytes;
-    img->jsrc.next_input_byte += num_bytes;
-    img->jsrc.bytes_in_buffer -= n;
+    jpg->jsrc.next_input_byte += num_bytes;
+    jpg->jsrc.bytes_in_buffer -= n;
 }
 
 static boolean
-img_resync_to_restart(j_decompress_ptr cinfo, int desired)
+jpg_resync_to_restart(j_decompress_ptr cinfo, int desired)
 {
     return FALSE;
 }
 
 static void
-img_term_source(j_decompress_ptr cinfo)
+jpg_term_source(j_decompress_ptr cinfo)
 {
 }
 
 static void
-img_error_exit(j_common_ptr cinfo)
+jpg_error_exit(j_common_ptr cinfo)
 {
-    img_error_mgr *jerr = (img_error_mgr *)cinfo->err;
+    jpg_error_mgr *jerr = (jpg_error_mgr *)cinfo->err;
 
     longjmp(jerr->setjmp_buffer, 1);
 }
 
 static int
-fill_jpeg_source(img_interp_instance_t *img, stream_cursor_read * pr)
+fill_jpeg_source(jpg_interp_instance_t *jpg, stream_cursor_read * pr)
 {
     size_t n = pr->limit - pr->ptr;
-    size_t skip = img->bytes_to_skip;
+    size_t skip = jpg->bytes_to_skip;
 
     /* Skip any bytes we are supposed to be skipping. */
     if (skip > 0) {
@@ -446,23 +446,23 @@ fill_jpeg_source(img_interp_instance_t *img, stream_cursor_read * pr)
             skip = n;
         pr->ptr += skip;
         n -= skip;
-        img->bytes_to_skip -= skip;
-        if (img->bytes_to_skip != 0)
+        jpg->bytes_to_skip -= skip;
+        if (jpg->bytes_to_skip != 0)
             return 1; /* Still more to skip */
     }
 
     /* Set up for the call into the jpeg lib */
-    img->jsrc.next_input_byte = pr->ptr+1;
-    img->jsrc.bytes_in_buffer = pr->limit - pr->ptr;
-    img->bytes_available_on_entry = img->jsrc.bytes_in_buffer;
+    jpg->jsrc.next_input_byte = pr->ptr+1;
+    jpg->jsrc.bytes_in_buffer = pr->limit - pr->ptr;
+    jpg->bytes_available_on_entry = jpg->jsrc.bytes_in_buffer;
 
     return 0;
 }
 
 static int
-consume_jpeg_data(img_interp_instance_t *img, stream_cursor_read *pr)
+consume_jpeg_data(jpg_interp_instance_t *jpg, stream_cursor_read *pr)
 {
-    size_t bytes_read = img->jsrc.next_input_byte - (pr->ptr+1);
+    size_t bytes_read = jpg->jsrc.next_input_byte - (pr->ptr+1);
     size_t n = pr->limit - pr->ptr;
 
     if (n > bytes_read)
@@ -471,64 +471,64 @@ consume_jpeg_data(img_interp_instance_t *img, stream_cursor_read *pr)
     bytes_read -= n;
 
     /* We need to skip the next bytes_read bytes */
-    img->bytes_to_skip = bytes_read;
+    jpg->bytes_to_skip = bytes_read;
 
-    return (pr->limit - pr->ptr == img->bytes_available_on_entry);
+    return (pr->limit - pr->ptr == jpg->bytes_available_on_entry);
 }
 
 static int
-img_impl_process(pl_interp_implementation_t * impl, stream_cursor_read * pr)
+jpg_impl_process(pl_interp_implementation_t * impl, stream_cursor_read * pr)
 {
-    img_interp_instance_t *img = (img_interp_instance_t *)impl->interp_client_data;
+    jpg_interp_instance_t *jpg = (jpg_interp_instance_t *)impl->interp_client_data;
     int code = 0;
     int need_more_data;
 
     do
     {
         need_more_data = 0;
-        switch(img->state)
+        switch(jpg->state)
         {
         case ii_state_identifying:
         {
             const byte *hdr;
             /* Try and get us 11 bytes */
-            code = ensure_bytes(img, pr, 11);
+            code = ensure_bytes(jpg, pr, 11);
             if (code < 0)
                 return code;
             hdr = pr->ptr+1;
             if (hdr[0] == 0xFF && hdr[1] == 0xd8 && hdr[2] == 0xff && hdr[3] == 0xe0 &&
                 memcmp("JFIF", hdr+6, 5) == 0)
             {
-                img->state = ii_state_jpeg;
+                jpg->state = ii_state_jpeg;
                 break;
             }
-            img->state = ii_state_flush;
+            jpg->state = ii_state_flush;
             break;
         }
         case ii_state_jpeg:
-            code = gs_jpeg_mem_init(img->memory, (j_common_ptr)&img->cinfo);
+            code = gs_jpeg_mem_init(jpg->memory, (j_common_ptr)&jpg->cinfo);
             if (code < 0) {
-                img->state = ii_state_flush;
+                jpg->state = ii_state_flush;
                 break;
             }
 
-            img->cinfo.err = jpeg_std_error(&img->jerr.pub);
-            img->jerr.pub.error_exit = img_error_exit;
-            if (setjmp(img->jerr.setjmp_buffer)) {
-                img->state = ii_state_flush;
+            jpg->cinfo.err = jpeg_std_error(&jpg->jerr.pub);
+            jpg->jerr.pub.error_exit = jpg_error_exit;
+            if (setjmp(jpg->jerr.setjmp_buffer)) {
+                jpg->state = ii_state_flush;
                 break;
             }
 
-            jpeg_create_decompress(&img->cinfo);
+            jpeg_create_decompress(&jpg->cinfo);
 
-            img->cinfo.src = &img->jsrc;
-            img->jsrc.init_source = img_jpeg_init_source;
-            img->jsrc.fill_input_buffer = img_fill_input_buffer;
-            img->jsrc.skip_input_data = img_skip_input_data;
-            img->jsrc.resync_to_restart = img_resync_to_restart;
-            img->jsrc.term_source = img_term_source;
+            jpg->cinfo.src = &jpg->jsrc;
+            jpg->jsrc.init_source = jpg_jpeg_init_source;
+            jpg->jsrc.fill_input_buffer = jpg_fill_input_buffer;
+            jpg->jsrc.skip_input_data = jpg_skip_input_data;
+            jpg->jsrc.resync_to_restart = jpg_resync_to_restart;
+            jpg->jsrc.term_source = jpg_term_source;
 
-            img->state = ii_state_jpeg_header;
+            jpg->state = ii_state_jpeg_header;
             break;
         case ii_state_jpeg_header:
         {
@@ -536,142 +536,142 @@ img_impl_process(pl_interp_implementation_t * impl, stream_cursor_read * pr)
             gs_color_space *cs;
             float scale, xext, yext, xoffset, yoffset;
 
-            if (fill_jpeg_source(img, pr)) {
+            if (fill_jpeg_source(jpg, pr)) {
                 need_more_data = 1;
                 break; /* No bytes left after skipping */
             }
-            if (setjmp(img->jerr.setjmp_buffer)) {
-                jpeg_destroy_decompress(&img->cinfo);
-                img->state = ii_state_flush;
+            if (setjmp(jpg->jerr.setjmp_buffer)) {
+                jpeg_destroy_decompress(&jpg->cinfo);
+                jpg->state = ii_state_flush;
                 break;
             }
-            ok = jpeg_read_header(&img->cinfo, TRUE);
-            need_more_data = consume_jpeg_data(img, pr);
+            ok = jpeg_read_header(&jpg->cinfo, TRUE);
+            need_more_data = consume_jpeg_data(jpg, pr);
             if (ok == JPEG_SUSPENDED)
                 break;
             need_more_data = 0;
 
-            img->width = img->cinfo.image_width;
-            img->height = img->cinfo.image_height;
-            img->num_comps = img->cinfo.num_components;
-            img->bpp = 8 * img->num_comps;
-            switch(img->num_comps) {
+            jpg->width = jpg->cinfo.image_width;
+            jpg->height = jpg->cinfo.image_height;
+            jpg->num_comps = jpg->cinfo.num_components;
+            jpg->bpp = 8 * jpg->num_comps;
+            switch(jpg->num_comps) {
             default:
             case 1:
-                cs = img->gray;
-                img->cinfo.out_color_space = JCS_GRAYSCALE;
+                cs = jpg->gray;
+                jpg->cinfo.out_color_space = JCS_GRAYSCALE;
                 break;
             case 3:
-                cs = img->rgb;
-                img->cinfo.out_color_space = JCS_RGB;
+                cs = jpg->rgb;
+                jpg->cinfo.out_color_space = JCS_RGB;
                 break;
             case 4:
-                cs = img->cmyk;
-                img->cinfo.out_color_space = JCS_CMYK;
+                cs = jpg->cmyk;
+                jpg->cinfo.out_color_space = JCS_CMYK;
                 break;
             }
 
             /* Find us some X and Y resolutions */
-            img->xresolution = img->cinfo.X_density;
-            img->yresolution = img->cinfo.Y_density;
-            if (img->xresolution == 0)
-                img->xresolution = img->yresolution;
-            if (img->yresolution == 0)
-                img->yresolution = img->xresolution;
-            if (img->xresolution == 0)
-                img->xresolution = 72;
-            if (img->yresolution == 0)
-                img->yresolution = 72;
+            jpg->xresolution = jpg->cinfo.X_density;
+            jpg->yresolution = jpg->cinfo.Y_density;
+            if (jpg->xresolution == 0)
+                jpg->xresolution = jpg->yresolution;
+            if (jpg->yresolution == 0)
+                jpg->yresolution = jpg->xresolution;
+            if (jpg->xresolution == 0)
+                jpg->xresolution = 72;
+            if (jpg->yresolution == 0)
+                jpg->yresolution = 72;
 
             /* Scale to fit, if too large. */
             scale = 1.0f;
-            if (img->width * 72 > img->dev->width * img->xresolution)
-                scale = ((float)img->dev->width * img->xresolution) / (img->width * 72);
-            if (scale * img->height * 72 > img->dev->height * img->yresolution)
-                scale = ((float)img->dev->height * img->yresolution) / (img->height * 72);
+            if (jpg->width * 72 > jpg->dev->width * jpg->xresolution)
+                scale = ((float)jpg->dev->width * jpg->xresolution) / (jpg->width * 72);
+            if (scale * jpg->height * 72 > jpg->dev->height * jpg->yresolution)
+                scale = ((float)jpg->dev->height * jpg->yresolution) / (jpg->height * 72);
 
             /* Centre */
-            xext = ((float)img->width * 72 * scale / img->xresolution);
-            xoffset = (img->dev->width - xext)/2;
-            yext = ((float)img->height * 72 * scale / img->yresolution);
-            yoffset = (img->dev->height - yext)/2;
+            xext = ((float)jpg->width * 72 * scale / jpg->xresolution);
+            xoffset = (jpg->dev->width - xext)/2;
+            yext = ((float)jpg->height * 72 * scale / jpg->yresolution);
+            yoffset = (jpg->dev->height - yext)/2;
 
 
             /* Now we've got the data from the image header, we can
              * make the gs image instance */
-            img->byte_width = (img->bpp>>3)*img->width;
+            jpg->byte_width = (jpg->bpp>>3)*jpg->width;
 
-            img->nulldev = gs_currentdevice(img->pgs);
-            rc_increment(img->nulldev);
-            code = gs_setdevice_no_erase(img->pgs, img->dev);
+            jpg->nulldev = gs_currentdevice(jpg->pgs);
+            rc_increment(jpg->nulldev);
+            code = gs_setdevice_no_erase(jpg->pgs, jpg->dev);
             if (code < 0) {
-                img->state = ii_state_flush;
+                jpg->state = ii_state_flush;
                 break;
             }
-            gs_initmatrix(img->pgs);
+            gs_initmatrix(jpg->pgs);
 
-            code = gs_translate(img->pgs, xoffset, img->dev->height-yoffset);
+            code = gs_translate(jpg->pgs, xoffset, jpg->dev->height-yoffset);
             if (code >= 0)
-                code = gs_scale(img->pgs, scale, -scale);
+                code = gs_scale(jpg->pgs, scale, -scale);
             if (code >= 0)
-                code = gs_erasepage(img->pgs);
+                code = gs_erasepage(jpg->pgs);
             if (code < 0) {
-                img->state = ii_state_flush;
+                jpg->state = ii_state_flush;
                 break;
             }
 
-            img->samples = gs_alloc_bytes(img->memory, img->byte_width, "img_impl_process(samples)");
-            if (img->samples == NULL) {
-                img->state = ii_state_flush;
+            jpg->samples = gs_alloc_bytes(jpg->memory, jpg->byte_width, "jpg_impl_process(samples)");
+            if (jpg->samples == NULL) {
+                jpg->state = ii_state_flush;
                 break;
             }
 
-            memset(&img->image, 0, sizeof(img->image));
-            gs_image_t_init(&img->image, cs);
-            img->image.BitsPerComponent = img->bpp/img->num_comps;
-            img->image.Width = img->width;
-            img->image.Height = img->height;
+            memset(&jpg->image, 0, sizeof(jpg->image));
+            gs_image_t_init(&jpg->image, cs);
+            jpg->image.BitsPerComponent = jpg->bpp/jpg->num_comps;
+            jpg->image.Width = jpg->width;
+            jpg->image.Height = jpg->height;
 
-            img->image.ImageMatrix.xx = img->xresolution / 72.0;
-            img->image.ImageMatrix.yy = img->yresolution / 72.0;
+            jpg->image.ImageMatrix.xx = jpg->xresolution / 72.0;
+            jpg->image.ImageMatrix.yy = jpg->yresolution / 72.0;
 
-            img->penum = gs_image_enum_alloc(img->memory, "img_impl_process(penum)");
-            if (img->penum == NULL) {
+            jpg->penum = gs_image_enum_alloc(jpg->memory, "jpg_impl_process(penum)");
+            if (jpg->penum == NULL) {
                 code = gs_note_error(gs_error_VMerror);
-                img->state = ii_state_flush;
+                jpg->state = ii_state_flush;
                 return code;
             }
 
-            code = gs_image_init(img->penum,
-                                 &img->image,
+            code = gs_image_init(jpg->penum,
+                                 &jpg->image,
                                  false,
                                  false,
-                                 img->pgs);
+                                 jpg->pgs);
             if (code < 0) {
-                img->state = ii_state_flush;
+                jpg->state = ii_state_flush;
                 return code;
             }
 
-            img->state = ii_state_jpeg_start;
+            jpg->state = ii_state_jpeg_start;
             break;
         }
         case ii_state_jpeg_start:
         {
             int ok;
-            if (fill_jpeg_source(img, pr)) {
+            if (fill_jpeg_source(jpg, pr)) {
                 need_more_data = 1;
                 break; /* No bytes left after skipping */
             }
-            if (setjmp(img->jerr.setjmp_buffer)) {
-                jpeg_destroy_decompress(&img->cinfo);
-                img->state = ii_state_flush;
+            if (setjmp(jpg->jerr.setjmp_buffer)) {
+                jpeg_destroy_decompress(&jpg->cinfo);
+                jpg->state = ii_state_flush;
                 break;
             }
-            ok = jpeg_start_decompress(&img->cinfo);
-            (void)consume_jpeg_data(img, pr);
+            ok = jpeg_start_decompress(&jpg->cinfo);
+            (void)consume_jpeg_data(jpg, pr);
             if (ok == FALSE)
                 break;
-            img->state = ii_state_jpeg_rows;
+            jpg->state = ii_state_jpeg_rows;
             break;
         }
         case ii_state_jpeg_rows:
@@ -679,41 +679,41 @@ img_impl_process(pl_interp_implementation_t * impl, stream_cursor_read * pr)
             int rows_decoded;
             unsigned int used;
 
-            if (fill_jpeg_source(img, pr)) {
+            if (fill_jpeg_source(jpg, pr)) {
                 need_more_data = 1;
                 break; /* No bytes left after skipping */
             }
-            if (setjmp(img->jerr.setjmp_buffer)) {
-                jpeg_destroy_decompress(&img->cinfo);
-                img->state = ii_state_flush;
+            if (setjmp(jpg->jerr.setjmp_buffer)) {
+                jpeg_destroy_decompress(&jpg->cinfo);
+                jpg->state = ii_state_flush;
                 break;
             }
-            rows_decoded = jpeg_read_scanlines(&img->cinfo, &img->samples, 1);
-            need_more_data = consume_jpeg_data(img, pr);
+            rows_decoded = jpeg_read_scanlines(&jpg->cinfo, &jpg->samples, 1);
+            need_more_data = consume_jpeg_data(jpg, pr);
             if (rows_decoded == 0)
                 break; /* Not enough data for a scanline yet */
             need_more_data = 0;
 
-            code = gs_image_next(img->penum, img->samples, img->byte_width, &used);
+            code = gs_image_next(jpg->penum, jpg->samples, jpg->byte_width, &used);
             if (code < 0) {
-                img->state = ii_state_flush;
+                jpg->state = ii_state_flush;
                 break;
             }
-            img->y++;
-            if (img->y == img->height) {
-                code = gs_image_cleanup_and_free_enum(img->penum, img->pgs);
-                img->penum = NULL;
+            jpg->y++;
+            if (jpg->y == jpg->height) {
+                code = gs_image_cleanup_and_free_enum(jpg->penum, jpg->pgs);
+                jpg->penum = NULL;
                 if (code < 0) {
-                    img->state = ii_state_flush;
+                    jpg->state = ii_state_flush;
                     break;
                 }
-                code = pl_finish_page(img->memory->gs_lib_ctx->top_of_system,
-                                      img->pgs, 1, true);
+                code = pl_finish_page(jpg->memory->gs_lib_ctx->top_of_system,
+                                      jpg->pgs, 1, true);
                 if (code < 0) {
-                    img->state = ii_state_flush;
+                    jpg->state = ii_state_flush;
                     break;
                 }
-                img->state = ii_state_jpeg_finish;
+                jpg->state = ii_state_jpeg_finish;
             }
             break;
         }
@@ -721,38 +721,38 @@ img_impl_process(pl_interp_implementation_t * impl, stream_cursor_read * pr)
         {
             int ok;
 
-            if (fill_jpeg_source(img, pr)) {
+            if (fill_jpeg_source(jpg, pr)) {
                 need_more_data = 1;
                 break; /* No bytes left after skipping */
             }
-            if (setjmp(img->jerr.setjmp_buffer)) {
-                jpeg_destroy_decompress(&img->cinfo);
-                img->state = ii_state_flush;
+            if (setjmp(jpg->jerr.setjmp_buffer)) {
+                jpeg_destroy_decompress(&jpg->cinfo);
+                jpg->state = ii_state_flush;
                 break;
             }
-            ok = jpeg_finish_decompress(&img->cinfo);
-            need_more_data = consume_jpeg_data(img, pr);
+            ok = jpeg_finish_decompress(&jpg->cinfo);
+            need_more_data = consume_jpeg_data(jpg, pr);
             if (ok == FALSE)
                 break;
             need_more_data = 0;
-            img->state = ii_state_flush;
+            jpg->state = ii_state_flush;
             break;
         }
         default:
         case ii_state_flush:
-            if (setjmp(img->jerr.setjmp_buffer))
+            if (setjmp(jpg->jerr.setjmp_buffer))
                 break;
-            jpeg_destroy_decompress(&img->cinfo);
+            jpeg_destroy_decompress(&jpg->cinfo);
 
-            gs_jpeg_mem_term((j_common_ptr)&img->cinfo);
+            gs_jpeg_mem_term((j_common_ptr)&jpg->cinfo);
 
-            if (img->penum) {
-                (void)gs_image_cleanup_and_free_enum(img->penum, img->pgs);
-                img->penum = NULL;
+            if (jpg->penum) {
+                (void)gs_image_cleanup_and_free_enum(jpg->penum, jpg->pgs);
+                jpg->penum = NULL;
             }
 
-            gs_free_object(img->memory, img->samples, "img_impl_process(samples)");
-            img->samples = NULL;
+            gs_free_object(jpg->memory, jpg->samples, "jpg_impl_process(samples)");
+            jpg->samples = NULL;
             /* We want to bin any data we get up to, but not including
              * a UEL. */
             return flush_to_uel(pr);
@@ -763,9 +763,9 @@ img_impl_process(pl_interp_implementation_t * impl, stream_cursor_read * pr)
 }
 
 static int
-img_impl_process_end(pl_interp_implementation_t * impl)
+jpg_impl_process_end(pl_interp_implementation_t * impl)
 {
-    img_interp_instance_t *img = (img_interp_instance_t *)impl->interp_client_data;
+    jpg_interp_instance_t *jpg = (jpg_interp_instance_t *)impl->interp_client_data;
     int code = 0;
 
     /* FIXME: */
@@ -777,7 +777,7 @@ img_impl_process_end(pl_interp_implementation_t * impl)
 
 /* Not implemented */
 static int
-img_impl_flush_to_eoj(pl_interp_implementation_t *impl, stream_cursor_read *cursor)
+jpg_impl_flush_to_eoj(pl_interp_implementation_t *impl, stream_cursor_read *cursor)
 {
     const byte *p = cursor->ptr;
     const byte *rlimit = cursor->limit;
@@ -800,14 +800,14 @@ img_impl_flush_to_eoj(pl_interp_implementation_t *impl, stream_cursor_read *curs
 
 /* Parser action for end-of-file */
 static int
-img_impl_process_eof(pl_interp_implementation_t *impl)
+jpg_impl_process_eof(pl_interp_implementation_t *impl)
 {
     return 0;
 }
 
 /* Report any errors after running a job */
 static int
-img_impl_report_errors(pl_interp_implementation_t *impl,          /* interp instance to wrap up job in */
+jpg_impl_report_errors(pl_interp_implementation_t *impl,          /* interp instance to wrap up job in */
                        int                         code,          /* prev termination status */
                        long                        file_position, /* file position of error, -1 if unknown */
                        bool                        force_to_cout  /* force errors to cout */
@@ -818,38 +818,38 @@ img_impl_report_errors(pl_interp_implementation_t *impl,          /* interp inst
 
 /* Wrap up interp instance after a "job" */
 static int
-img_impl_dnit_job(pl_interp_implementation_t *impl)
+jpg_impl_dnit_job(pl_interp_implementation_t *impl)
 {
-    img_interp_instance_t *img = (img_interp_instance_t *)impl->interp_client_data;
+    jpg_interp_instance_t *jpg = (jpg_interp_instance_t *)impl->interp_client_data;
 
-    if (img->nulldev) {
-        int code = gs_setdevice(img->pgs, img->nulldev);
-        img->dev = NULL;
-        rc_decrement(img->nulldev, "img_impl_dnit_job(nulldevice)");
-        img->nulldev = NULL;
+    if (jpg->nulldev) {
+        int code = gs_setdevice(jpg->pgs, jpg->nulldev);
+        jpg->dev = NULL;
+        rc_decrement(jpg->nulldev, "jpg_impl_dnit_job(nulldevice)");
+        jpg->nulldev = NULL;
         return code;
     }
     return 0;
 }
 
 /* Parser implementation descriptor */
-const pl_interp_implementation_t img_implementation = {
-  img_impl_characteristics,
-  img_impl_allocate_interp_instance,
-  img_impl_get_device_memory,
-  NULL, /* img_impl_set_param */
-  NULL, /* img_impl_add_path */
-  NULL, /* img_impl_post_args_init */
-  img_impl_init_job,
-  NULL, /* img_impl_run_prefix_commands */
-  NULL, /* img_impl_process_file */
-  img_impl_process_begin,
-  img_impl_process,
-  img_impl_process_end,
-  img_impl_flush_to_eoj,
-  img_impl_process_eof,
-  img_impl_report_errors,
-  img_impl_dnit_job,
-  img_impl_deallocate_interp_instance,
+const pl_interp_implementation_t jpg_implementation = {
+  jpg_impl_characteristics,
+  jpg_impl_allocate_interp_instance,
+  jpg_impl_get_device_memory,
+  NULL, /* jpg_impl_set_param */
+  NULL, /* jpg_impl_add_path */
+  NULL, /* jpg_impl_post_args_init */
+  jpg_impl_init_job,
+  NULL, /* jpg_impl_run_prefix_commands */
+  NULL, /* jpg_impl_process_file */
+  jpg_impl_process_begin,
+  jpg_impl_process,
+  jpg_impl_process_end,
+  jpg_impl_flush_to_eoj,
+  jpg_impl_process_eof,
+  jpg_impl_report_errors,
+  jpg_impl_dnit_job,
+  jpg_impl_deallocate_interp_instance,
   NULL
 };
diff --git a/gpdl/psi/psitop.c b/gpdl/psitop.c
similarity index 100%
rename from gpdl/psi/psitop.c
rename to gpdl/psitop.c
diff --git a/gpdl/pwg/pwgtop.c b/gpdl/pwgtop.c
similarity index 100%
rename from gpdl/pwg/pwgtop.c
rename to gpdl/pwgtop.c
diff --git a/pcl/pl/plimpl.c b/pcl/pl/plimpl.c
index dddefee..d4c0f40 100644
--- a/pcl/pl/plimpl.c
+++ b/pcl/pl/plimpl.c
@@ -37,7 +37,7 @@ extern pl_interp_implementation_t ps_implementation;
 
 extern pl_interp_implementation_t urf_implementation;
 
-extern pl_interp_implementation_t img_implementation;
+extern pl_interp_implementation_t jpg_implementation;
 
 extern pl_interp_implementation_t pwg_implementation;
 
@@ -57,8 +57,8 @@ pl_interp_implementation_t *pdl_implementations[] = {
 #ifdef URF_INCLUDED
     &urf_implementation,
 #endif
-#ifdef IMG_INCLUDED
-    &img_implementation,
+#ifdef JPG_INCLUDED
+    &jpg_implementation,
 #endif
 #ifdef PWG_INCLUDED
     &pwg_implementation,
diff --git a/windows/ghostpdl.vcproj b/windows/ghostpdl.vcproj
index c105cc3..87f6e5a 100644
--- a/windows/ghostpdl.vcproj
+++ b/windows/ghostpdl.vcproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="UTF-8"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <VisualStudioProject
 	ProjectType="Visual C++"
 	Version="8.00"
@@ -303,34 +303,18 @@
 	</References>
 	<Files>
 		<Filter
-			Name="pdlpsi"
+			Name="gpdl"
 			>
 			<File
-				RelativePath="..\gpdl\psi\psitop.c"
+				RelativePath="..\gpdl\jpgtop.c"
 				>
 			</File>
-		</Filter>
-		<Filter
-			Name="urf"
-			>
-			<File
-				RelativePath="..\gpdl\urf\urftop.c"
-				>
-			</File>
-		</Filter>
-		<Filter
-			Name="image"
-			>
 			<File
-				RelativePath="..\gpdl\image\imagetop.c"
+				RelativePath="..\gpdl\psitop.c"
 				>
 			</File>
-		</Filter>
-		<Filter
-			Name="pwg"
-			>
 			<File
-				RelativePath="..\gpdl\pwg\pwgtop.c"
+				RelativePath="..\gpdl\pwgtop.c"
 				>
 			</File>
 		</Filter>


Summary of changes:
 Makefile.in                         |   5 +-
 configure.ac                        |   8 +-
 gpdl/gpdl.mak                       |  50 ++-
 gpdl/{image/imagetop.c => jpgtop.c} | 494 ++++++++++-----------
 gpdl/{psi => }/psitop.c             |   0
 gpdl/{pwg => }/pwgtop.c             |  21 +-
 gpdl/tifftop.c                      | 829 ++++++++++++++++++++++++++++++++++++
 pcl/pl/plimpl.c                     |  11 +-
 psi/msvc.mak                        |   1 +
 windows/ghostpdl.vcproj             |  22 +-
 10 files changed, 1156 insertions(+), 285 deletions(-)
 rename gpdl/{image/imagetop.c => jpgtop.c} (51%)
 rename gpdl/{psi => }/psitop.c (100%)
 rename gpdl/{pwg => }/pwgtop.c (96%)
 create mode 100644 gpdl/tifftop.c