--- a/devices/vector/gdevpx.c
+++ b/devices/vector/gdevpx.c
@@ -38,6 +38,7 @@
 #include "gxlum.h"
 #include "gdevpcl.h" /* for gdev_pcl_mode3compress() */
 #include "gsicc_manage.h"
+#include "gsicc_cache.h"
 #include <stdlib.h> /* abs() */
 
 /* ---------------- Device definition ---------------- */
@@ -108,6 +109,7 @@
     floatp y_scale;
     bool pen_null;
     bool brush_null;
+    bool iccTransform;
 } gx_device_pclxl;
 
 gs_public_st_suffix_add0_final(st_device_pclxl, gx_device_pclxl,
@@ -349,6 +351,22 @@
              index == gs_color_space_index_ICC);
 }
 
+/* Test whether we can icclink-transform an image. */
+static bool
+pclxl_can_icctransform(const gs_image_t * pim)
+{
+    const gs_color_space *pcs = pim->ColorSpace;
+    int bits_per_pixel =
+	(pim->ImageMask ? 1 :
+	 pim->BitsPerComponent * gs_color_space_num_components(pcs));
+
+    if ((gs_color_space_get_index(pcs) == gs_color_space_index_ICC)
+	&& (bits_per_pixel == 24))
+	return true;
+
+    return false;
+}
+
 /* Set brush, pen, and mode for painting a path. */
 static void
 pclxl_set_paints(gx_device_pclxl * xdev, gx_path_type_t type)
@@ -1533,6 +1551,7 @@
     xdev->MediaPosition = eAutoSelect;
     xdev->MediaType_old[0] = '\0';
     xdev->MediaType[0] = '\0';
+    /* xdev->iccTransform = false; */ /* set true/false here to ignore command line */
     return 0;
 }
 
@@ -1893,6 +1912,7 @@
         uint raster;
     } rows;
     bool flipped;
+  gsicc_link_t *icclink;
 } pclxl_image_enum_t;
 gs_private_st_suffix_add1(st_pclxl_image_enum, pclxl_image_enum_t,
                           "pclxl_image_enum_t", pclxl_image_enum_enum_ptrs,
@@ -1939,9 +1959,10 @@
          !((mat.xx == 0) && (mat.yy == 0) && (mat.xy * mat.yx != 0))) ||
         (pim->ImageMask ?
          (!gx_dc_is_pure(pdcolor) || pim->CombineWithColor) :
-         (!pclxl_can_handle_color_space(pim->ColorSpace) ||
-          (bits_per_pixel != 1 && bits_per_pixel != 4 &&
-           bits_per_pixel != 8 && bits_per_pixel !=24))) ||
+         ((!pclxl_can_handle_color_space(pcs) ||
+           (bits_per_pixel != 1 && bits_per_pixel != 4 &&
+            bits_per_pixel != 8 && bits_per_pixel !=24))
+          && !(pclxl_can_icctransform(pim) && xdev->iccTransform) )) ||
         format != gs_image_format_chunky || pim->Interpolate ||
         prect
         )
@@ -2047,6 +2068,17 @@
     pie->rows.num_rows = num_rows;
     pie->rows.first_y = 0;
     pie->rows.raster = row_raster;
+    if (!pclxl_can_handle_color_space(pcs)
+	&& pclxl_can_icctransform(pim) && pcs->cmm_icc_profile_data) {
+	gsicc_rendering_param_t rendering_params;
+
+	rendering_params.black_point_comp = pis->blackptcomp;
+	rendering_params.graphics_type_tag = GS_IMAGE_TAG;
+	rendering_params.rendering_intent = pis->renderingintent;
+	pie->icclink = gsicc_get_link(pis, dev, pcs, NULL /*des */ ,
+				      &rendering_params, pis->memory);
+    } else
+	pie->icclink = NULL;
     *pinfo = (gx_image_enum_common_t *) pie;
     {
         gs_logical_operation_t lop = pis->log_op;
@@ -2188,11 +2220,12 @@
         px_put_ub(s, eBit_values[8]);
         PX_PUT_LIT(s, ci_);
         if (xdev->color_info.depth==8) {
+          rows_raster/=3;
+          if (!pie->icclink) {
           byte *in=pie->rows.data + offset_lastflippedstrip;
           byte *out=pie->rows.data + offset_lastflippedstrip;
           int i;
           int j;
-          rows_raster/=3;
           for (j=0;  j<h;  j++) {
             for (i=0;  i<rows_raster;  i++) {
               *out = (byte)( ((*(in+0) * (ulong) lum_red_weight) +
@@ -2203,6 +2236,7 @@
               out++;
             }
           }
+          }
         }
     } else {
         static const byte ii_[] = {
@@ -2245,10 +2279,32 @@
                 return code;
             pie->rows.first_y = pie->y;
         }
+        if (!pie->icclink)
         memcpy(pie->rows.data +
                  pie->rows.raster * (pie->flipped ? (pie->rows.num_rows - (pie->y - pie->rows.first_y) -1) :(pie->y - pie->rows.first_y)),
                planes[0].data + planes[0].raster * i + (data_bit >> 3),
                pie->rows.raster);
+        else {
+          gsicc_bufferdesc_t input_buff_desc;
+          gsicc_bufferdesc_t output_buff_desc;
+          int pixels_per_row = pie->rows.raster / 3 ;
+          int out_raster_stride = pixels_per_row * info->dev->color_info.num_components;
+          gsicc_init_buffer(&input_buff_desc, 3 /*num_chan*/, 1 /*bytes_per_chan*/,
+                            false/*has_alpha*/, false/*alpha_first*/, false /*is_planar*/,
+                            0 /*plane_stride*/, pie->rows.raster /*row_stride*/,
+                            1/*num_rows*/, pixels_per_row /*pixels_per_row*/);
+          gsicc_init_buffer(&output_buff_desc, info->dev->color_info.num_components, 1,
+                            false, false, false,
+                            0, out_raster_stride,
+                            1, pixels_per_row);
+          gscms_transform_color_buffer(info->dev, pie->icclink,
+                                       &input_buff_desc,
+                                       &output_buff_desc,
+                                       (void *)(planes[0].data + planes[0].raster * i + (data_bit >> 3)), /*src*/
+                                       pie->rows.data +
+                                       out_raster_stride * (pie->flipped ? (pie->rows.num_rows - (pie->y - pie->rows.first_y) -1) : (pie->y - pie->rows.first_y)) /*des*/
+                                       );
+        }
     }
     *rows_used = height;
     return pie->y >= pie->height;
@@ -2341,6 +2397,9 @@
                               &(xdev->CompressMode))) < 0)
     return (code);
 
+  if ((code = param_write_bool(plist, "iccTransform", &(xdev->iccTransform))) < 0)
+    return (code);
+
   return (0);
 }
 
@@ -2446,6 +2505,7 @@
   }
   booloption(Tumble, "Tumble")
   intoption(CompressMode, "CompressMode", int)
+  booloption(iccTransform, "iccTransform")
 
  /*
   * Then process standard page device parameters...
