Attached is a patch (against PIL 1.1.6) to provide control over the
chroma subsampling done by the JPEG encoder.  This is often useful for
reducing compression artifacts around edges of clipart and text.

Comments appreciated!

--Justin
diff -ur Imaging-1.1.6-orig/PIL/JpegImagePlugin.py 
Imaging-1.1.6/PIL/JpegImagePlugin.py
--- Imaging-1.1.6-orig/PIL/JpegImagePlugin.py   2006-12-03 03:37:15.000000000 
-0800
+++ Imaging-1.1.6/PIL/JpegImagePlugin.py        2008-01-30 08:48:28.707703071 
-0800
@@ -403,7 +403,8 @@
         info.get("smooth", 0),
         info.has_key("optimize"),
         info.get("streamtype", 0),
-        dpi[0], dpi[1]
+        dpi[0], dpi[1],
+        info.get("subsampling", -1)
         )
 
     ImageFile._save(im, fp, [("jpeg", (0,0)+im.size, 0, rawmode)])
diff -ur Imaging-1.1.6-orig/encode.c Imaging-1.1.6/encode.c
--- Imaging-1.1.6-orig/encode.c 2006-12-03 03:51:25.000000000 -0800
+++ Imaging-1.1.6/encode.c      2008-01-31 11:35:48.124779643 -0800
@@ -503,9 +503,10 @@
     int optimize = 0;
     int streamtype = 0; /* 0=interchange, 1=tables only, 2=image only */
     int xdpi = 0, ydpi = 0;
-    if (!PyArg_ParseTuple(args, "ss|iiiiiii", &mode, &rawmode, &quality,
+       int subsampling = -1; /* -1=default, 0=none, 1=medium, 2=high */
+    if (!PyArg_ParseTuple(args, "ss|iiiiiiii", &mode, &rawmode, &quality,
                          &progressive, &smooth, &optimize, &streamtype,
-                          &xdpi, &ydpi))
+                          &xdpi, &ydpi, &subsampling))
        return NULL;
 
     encoder = PyImaging_EncoderNew(sizeof(JPEGENCODERSTATE));
@@ -518,6 +519,7 @@
     encoder->encode = ImagingJpegEncode;
 
     ((JPEGENCODERSTATE*)encoder->state.context)->quality = quality;
+    ((JPEGENCODERSTATE*)encoder->state.context)->subsampling = subsampling;
     ((JPEGENCODERSTATE*)encoder->state.context)->progressive = progressive;
     ((JPEGENCODERSTATE*)encoder->state.context)->smooth = smooth;
     ((JPEGENCODERSTATE*)encoder->state.context)->optimize = optimize;
diff -ur Imaging-1.1.6-orig/libImaging/Jpeg.h Imaging-1.1.6/libImaging/Jpeg.h
--- Imaging-1.1.6-orig/libImaging/Jpeg.h        2006-12-03 03:37:25.000000000 
-0800
+++ Imaging-1.1.6/libImaging/Jpeg.h     2008-01-30 08:48:19.611543368 -0800
@@ -85,6 +85,9 @@
     /* DPI setting (0=square pixels, otherwide DPI) */
     int xdpi, ydpi;
 
+       /*Chroma Subsampling (-1=default, 0=none, 1=medium, 2=high) */
+       int subsampling;
+
     /* PRIVATE CONTEXT (set by encoder) */
 
     struct jpeg_compress_struct cinfo;
diff -ur Imaging-1.1.6-orig/libImaging/JpegEncode.c 
Imaging-1.1.6/libImaging/JpegEncode.c
--- Imaging-1.1.6-orig/libImaging/JpegEncode.c  2006-12-03 03:37:25.000000000 
-0800
+++ Imaging-1.1.6/libImaging/JpegEncode.c       2008-01-31 11:39:40.763673088 
-0800
@@ -143,6 +143,46 @@
        jpeg_set_defaults(&context->cinfo);
        if (context->quality > 0)
            jpeg_set_quality(&context->cinfo, context->quality, 1);
+       
+       /* Set subsampling options */
+       switch (context->subsampling)
+       {
+               case 0:  /* 1x1 1x1 1x1 (4:4:4) : None */
+               {
+                       context->cinfo.comp_info[0].h_samp_factor = 1;
+                       context->cinfo.comp_info[0].v_samp_factor = 1;
+                       context->cinfo.comp_info[1].h_samp_factor = 1;
+                       context->cinfo.comp_info[1].v_samp_factor = 1;
+                       context->cinfo.comp_info[2].h_samp_factor = 1;
+                       context->cinfo.comp_info[2].v_samp_factor = 1;
+                       break;
+               }
+               case 1:  /* 2x1, 1x1, 1x1 (4:2:2) : Medium */
+               {
+                       context->cinfo.comp_info[0].h_samp_factor = 2;
+                       context->cinfo.comp_info[0].v_samp_factor = 1;
+                       context->cinfo.comp_info[1].h_samp_factor = 1;
+                       context->cinfo.comp_info[1].v_samp_factor = 1;
+                       context->cinfo.comp_info[2].h_samp_factor = 1;
+                       context->cinfo.comp_info[2].v_samp_factor = 1;
+                       break;
+               }
+               case 2:  /* 2x2, 1x1, 1x1 (4:1:1) : High */
+               {
+                       context->cinfo.comp_info[0].h_samp_factor = 2;
+                       context->cinfo.comp_info[0].v_samp_factor = 2;
+                       context->cinfo.comp_info[1].h_samp_factor = 1;
+                       context->cinfo.comp_info[1].v_samp_factor = 1;
+                       context->cinfo.comp_info[2].h_samp_factor = 1;
+                       context->cinfo.comp_info[2].v_samp_factor = 1;
+                       break;
+               }
+               default:
+               {
+                       /* Use the lib's default */
+                       break;
+               }
+       }
        if (context->progressive)
            jpeg_simple_progression(&context->cinfo);
        context->cinfo.smoothing_factor = context->smooth;
_______________________________________________
Image-SIG maillist  -  Image-SIG@python.org
http://mail.python.org/mailman/listinfo/image-sig

Reply via email to