Encode images with DCTDecode (JPEG) in PDFs if it makes sense. Fallback to FlateDecode (zip) if it makes sense. Otherewise include uncompressed stream.
This change will reduce the size of PDFs to 50% (in the case of the existing SKPs, we reduce the total size of PDFs from 105MB to 50MB) 
Review URL: https://codereview.appspot.com/7068055

git-svn-id: http://skia.googlecode.com/svn/trunk@8835 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gm/gmmain.cpp b/gm/gmmain.cpp
index 65058d6..d513a0e 100644
--- a/gm/gmmain.cpp
+++ b/gm/gmmain.cpp
@@ -174,6 +174,8 @@
         | SkGPipeWriter::kSharedAddressSpace_Flag }
 };
 
+static bool encode_to_dct_stream(SkWStream* stream, const SkBitmap& bitmap, const SkIRect& rect);
+
 const static ErrorCombination kDefaultIgnorableErrorTypes = ErrorCombination()
     .plus(kMissingExpectations_ErrorType)
     .plus(kIntentionallySkipped_ErrorType);
@@ -556,6 +558,7 @@
                               SkScalarRoundToInt(content.height()));
             dev = new SkPDFDevice(pageSize, contentSize, initialTransform);
         }
+        dev->setDCTEncoder(encode_to_dct_stream);
         SkAutoUnref aur(dev);
 
         SkCanvas c(dev);
@@ -1246,6 +1249,37 @@
              "each test).");
 DEFINE_string2(writePath, w, "",  "Write rendered images into this directory.");
 DEFINE_string2(writePicturePath, p, "", "Write .skp files into this directory.");
+DEFINE_int32(pdfJpegQuality, -1, "Encodes images in JPEG at quality level N, "
+             "which can be in range 0-100). N = -1 will disable JPEG compression. "
+             "Default is N = 100, maximum quality.");
+
+static bool encode_to_dct_stream(SkWStream* stream, const SkBitmap& bitmap, const SkIRect& rect) {
+    // Filter output of warnings that JPEG is not available for the image.
+    if (bitmap.width() >= 65500 || bitmap.height() >= 65500) return false;
+    if (FLAGS_pdfJpegQuality == -1) return false;
+
+    SkIRect bitmapBounds;
+    SkBitmap subset;
+    const SkBitmap* bitmapToUse = &bitmap;
+    bitmap.getBounds(&bitmapBounds);
+    if (rect != bitmapBounds) {
+        SkAssertResult(bitmap.extractSubset(&subset, rect));
+        bitmapToUse = ⊂
+    }
+
+#if defined(SK_BUILD_FOR_MAC)
+    // Workaround bug #1043 where bitmaps with referenced pixels cause
+    // CGImageDestinationFinalize to crash
+    SkBitmap copy;
+    bitmapToUse->deepCopyTo(&copy, bitmapToUse->config());
+    bitmapToUse = ©
+#endif
+
+    return SkImageEncoder::EncodeStream(stream,
+                                        *bitmapToUse,
+                                        SkImageEncoder::kJPEG_Type,
+                                        FLAGS_pdfJpegQuality);
+}
 
 static int findConfig(const char config[]) {
     for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); i++) {
@@ -1804,6 +1838,10 @@
         }
     }
 
+    if (FLAGS_pdfJpegQuality < -1 || FLAGS_pdfJpegQuality > 100) {
+        gm_fprintf(stderr, "%s\n", "pdfJpegQuality must be in [-1 .. 100] range.");
+    }
+
     Iter iter;
     GM* gm;
     while ((gm = iter.next()) != NULL) {