← Back to team overview

simple-scan-team team mailing list archive

[Merge] lp:~soliloque/simple-scan/fastpdf into lp:simple-scan

 

soliloque has proposed merging lp:~soliloque/simple-scan/fastpdf into lp:simple-scan.

Commit message:
Hasten the save_pdf method

Requested reviews:
  Robert Ancell (robert-ancell)

For more details, see:
https://code.launchpad.net/~soliloque/simple-scan/fastpdf/+merge/322610

Sorry, the diff is pretty hard to read.

Saving pdf currently take a long time, in part because it currently encode each page two times: one time with zlib, then with jpeg, and finally discard the biggest version. However this is mostly useless because in all test I did, the ZLIB compression was choosen when using the "Text" setting and JPEG compression when using the "Photo" setting.

I modified save_pdf so when using "Text" setting, it directly encode with zlib and when using "Photo" setting, it directly encode with jpeg. As the zlib algorithm take longer when not compressing effectively, the speedup can be very high: with only one page and an empty flatbed using "Photo" setting, the book.save method take right now 26 seconds on my computer, vs 0,1 seconds with this change.


-- 
Your team Simple Scan Development Team is subscribed to branch lp:simple-scan.
=== modified file 'src/book.vala'
--- src/book.vala	2017-03-29 09:40:01 +0000
+++ src/book.vala	2017-04-16 15:04:24 +0000
@@ -341,152 +341,119 @@
             unowned uint8[] pixels = image.get_pixels ();
             var page_width = width * 72.0 / page.dpi;
             var page_height = height * 72.0 / page.dpi;
-
-            int depth = 8;
-            string color_space = "DeviceRGB";
-            string? filter = null;
+            int depth;
+            string color_space;
+            string filter;
             char[] width_buffer = new char[double.DTOSTR_BUF_SIZE];
             char[] height_buffer = new char[double.DTOSTR_BUF_SIZE];
             uint8[] data;
+
             if (page.is_color)
             {
                 depth = 8;
                 color_space = "DeviceRGB";
-                var data_length = height * width * 3;
-                data = new uint8[data_length];
-                for (var row = 0; row < height; row++)
-                {
-                    var in_offset = row * image.rowstride;
-                    var out_offset = row * width * 3;
-                    for (var x = 0; x < width; x++)
-                    {
-                        var in_o = in_offset + x*3;
-                        var out_o = out_offset + x*3;
-
-                        data[out_o] = pixels[in_o];
-                        data[out_o+1] = pixels[in_o+1];
-                        data[out_o+2] = pixels[in_o+2];
-                    }
-                }
+                data = compress_jpeg (image, quality, page.dpi);
+                filter = "DCTDecode"; /* JPEG compression applied to color image data */
             }
-            else if (page.depth == 2)
+            else
             {
-                int shift_count = 6;
-                depth = 2;
                 color_space = "DeviceGray";
-                var data_length = height * ((width * 2 + 7) / 8);
-                data = new uint8[data_length];
-                var offset = 0;
-                for (var row = 0; row < height; row++)
+                if (page.depth == 2)
                 {
-                    /* Pad to the next line */
-                    if (shift_count != 6)
-                    {
-                        offset++;
-                        shift_count = 6;
-                    }
-
-                    var in_offset = row * image.rowstride;
-                    for (var x = 0; x < width; x++)
-                    {
-                        /* Clear byte */
-                        if (shift_count == 6)
-                            data[offset] = 0;
-
-                        /* Set bits */
-                        var p = pixels[in_offset + x*3];
-                        if (p >= 192)
-                            data[offset] |= 3 << shift_count;
-                        else if (p >= 128)
-                            data[offset] |= 2 << shift_count;
-                        else if (p >= 64)
-                            data[offset] |= 1 << shift_count;
-
-                        /* Move to the next position */
-                        if (shift_count == 0)
+                    int shift_count = 6;
+                    depth = 2;
+                    var data_length = height * ((width * 2 + 7) / 8);
+                    data = new uint8[data_length];
+                    var offset = 0;
+                    for (var row = 0; row < height; row++)
+                    {
+                        /* Pad to the next line */
+                        if (shift_count != 6)
                         {
                             offset++;
                             shift_count = 6;
                         }
-                        else
-                            shift_count -= 2;
+
+                        var in_offset = row * image.rowstride;
+                        for (var x = 0; x < width; x++)
+                        {
+                            /* Clear byte */
+                            if (shift_count == 6)
+                                data[offset] = 0;
+
+                            /* Set bits */
+                            var p = pixels[in_offset + x*3];
+                            if (p >= 192)
+                                data[offset] |= 3 << shift_count;
+                            else if (p >= 128)
+                                data[offset] |= 2 << shift_count;
+                            else if (p >= 64)
+                                data[offset] |= 1 << shift_count;
+
+                            /* Move to the next position */
+                            if (shift_count == 0)
+                            {
+                                offset++;
+                                shift_count = 6;
+                            }
+                            else
+                                shift_count -= 2;
+                        }
                     }
                 }
-            }
-            else if (page.depth == 1)
-            {
-                int mask = 0x80;
-
-                depth = 1;
-                color_space = "DeviceGray";
-                var data_length = height * ((width + 7) / 8);
-                data = new uint8[data_length];
-                var offset = 0;
-                for (var row = 0; row < height; row++)
+                else if (page.depth == 1)
                 {
-                    /* Pad to the next line */
-                    if (mask != 0x80)
-                    {
-                        offset++;
-                        mask = 0x80;
-                    }
-
-                    var in_offset = row * image.rowstride;
-                    for (var x = 0; x < width; x++)
-                    {
-                        /* Clear byte */
-                        if (mask == 0x80)
-                            data[offset] = 0;
-
-                        /* Set bit */
-                        if (pixels[in_offset+x*3] != 0)
-                            data[offset] |= (uint8) mask;
-
-                        /* Move to the next bit */
-                        mask >>= 1;
-                        if (mask == 0)
+                    int mask = 0x80;
+
+                    depth = 1;
+                    var data_length = height * ((width + 7) / 8);
+                    data = new uint8[data_length];
+                    var offset = 0;
+                    for (var row = 0; row < height; row++)
+                    {
+                        /* Pad to the next line */
+                        if (mask != 0x80)
                         {
                             offset++;
                             mask = 0x80;
                         }
+
+                        var in_offset = row * image.rowstride;
+                        for (var x = 0; x < width; x++)
+                        {
+                            /* Clear byte */
+                            if (mask == 0x80)
+                                data[offset] = 0;
+
+                            /* Set bit */
+                            if (pixels[in_offset+x*3] != 0)
+                                data[offset] |= (uint8) mask;
+
+                            /* Move to the next bit */
+                            mask >>= 1;
+                            if (mask == 0)
+                            {
+                                offset++;
+                                mask = 0x80;
+                            }
+                        }
                     }
                 }
-            }
-            else
-            {
-                depth = 8;
-                color_space = "DeviceGray";
-                var data_length = height * width;
-                data = new uint8 [data_length];
-                for (var row = 0; row < height; row++)
-                {
-                    var in_offset = row * image.rowstride;
-                    var out_offset = row * width;
-                    for (var x = 0; x < width; x++)
-                        data[out_offset+x] = pixels[in_offset+x*3];
-                }
-            }
-
-            /* Compress data */
-            var compressed_data = compress_zlib (data);
-            if (compressed_data != null)
-            {
-                /* Try if JPEG compression is better */
-                if (depth > 1)
-                {
-                    var jpeg_data = compress_jpeg (image, quality, page.dpi);
-                    if (jpeg_data.length < compressed_data.length)
+                else
+                {
+                    depth = 8;
+                    var data_length = height * width;
+                    data = new uint8 [data_length];
+                    for (var row = 0; row < height; row++)
                     {
-                        filter = "DCTDecode";
-                        data = jpeg_data;
+                        var in_offset = row * image.rowstride;
+                        var out_offset = row * width;
+                        for (var x = 0; x < width; x++)
+                            data[out_offset+x] = pixels[in_offset+x*3];
                     }
                 }
-
-                if (filter == null)
-                {
-                    filter = "FlateDecode";
-                    data = compressed_data;
-                }
+                data = compress_zlib (data);
+                filter = "FlateDecode"; /* ZLIB compression applied to gray image data */
             }
 
             /* Page */
@@ -528,7 +495,7 @@
             writer.start_object (struct_tree_root_number);
             writer.write_string ("%u 0 obj\n".printf (struct_tree_root_number));
             writer.write_string ("<<\n");
-            writer.write_string ("/Type /StructTreeRoot\n");            
+            writer.write_string ("/Type /StructTreeRoot\n");
             writer.write_string (">>\n");
             writer.write_string ("endobj\n");
 


Follow ups