浏览代码

Optimize SVG files

Gaël Métais 10 年之前
父节点
当前提交
c428c8ae2d
共有 3 个文件被更改,包括 726 次插入1 次删除
  1. 49 1
      lib/tools/weightChecker/imageOptimizer.js
  2. 50 0
      test/core/imageOptimizerTest.js
  3. 627 0
      test/fixtures/svg-image.svg

+ 49 - 1
lib/tools/weightChecker/imageOptimizer.js

@@ -75,6 +75,27 @@ var ImageOptimizer = function() {
                 return entry;
                 return entry;
             });
             });
 
 
+        } else if (isSVG(entry)) {
+
+            debug('File is an SVG');
+
+            // Starting softly with a lossless compression
+            return compressSvgLosslessly(entry.weightCheck.body)
+
+            .then(function(newFile) {
+                var newFileSize = newFile.contents.length;
+
+                debug('SVG lossless compression complete for %s', entry.url);
+                
+                if (newFileSize < fileSize) {
+                    entry.weightCheck.lossless = entry.weightCheck.optimized = newFileSize;
+                    entry.weightCheck.isOptimized = false;
+                    debug('Filesize is %d bytes smaller (-%d%)', fileSize - newFileSize, Math.round((fileSize - newFileSize) * 100 / fileSize));
+                }
+
+                return entry;
+            });
+
         } else {
         } else {
             debug('File type is not an optimizable image');
             debug('File type is not an optimizable image');
             deferred.resolve(entry);
             deferred.resolve(entry);
@@ -157,12 +178,39 @@ var ImageOptimizer = function() {
         return deferred.promise;
         return deferred.promise;
     }
     }
 
 
+    function isSVG(entry) {
+        return entry.isImage && entry.contentType === 'image/svg+xml';
+    }
+
+    function compressSvgLosslessly(imageBody) {
+        var deferred = Q.defer();
+        var startTime = Date.now();
+
+        debug('Starting SVG losslessly compression');
+
+        new Imagemin()
+            .src(imageBody)
+            .use(Imagemin.svgo())
+            .run(function (err, files) {
+                if (err) {
+                    deferred.reject(err);
+                } else {
+                    deferred.resolve(files[0]);
+                    var endTime = Date.now();
+                    debug('compressSvgLosslessly took %d ms', endTime - startTime);
+                }
+            });
+
+        return deferred.promise;
+    }
+
     return {
     return {
         //recompressIfImage: recompressIfImage,
         //recompressIfImage: recompressIfImage,
         optimizeImage: optimizeImage,
         optimizeImage: optimizeImage,
         compressJpegLosslessly: compressJpegLosslessly,
         compressJpegLosslessly: compressJpegLosslessly,
         compressJpegLossly: compressJpegLossly,
         compressJpegLossly: compressJpegLossly,
-        compressPngLosslessly: compressPngLosslessly
+        compressPngLosslessly: compressPngLosslessly,
+        compressSvgLosslessly: compressSvgLosslessly
     };
     };
 };
 };
 
 

+ 50 - 0
test/core/imageOptimizerTest.js

@@ -133,11 +133,61 @@ describe('imageOptimizer', function() {
     });
     });
 
 
 
 
+    it('should optimize an SVG image losslessly', function(done) {
+        var fileContent = fs.readFileSync(path.resolve(__dirname, '../fixtures/svg-image.svg'));
 
 
+        var fileSize = fileContent.length;
 
 
+        imageOptimizer.compressSvgLosslessly(fileContent).then(function(newFile) {
+            var newFileSize = newFile.contents.length;
+            newFileSize.should.be.below(fileSize);
+            done();
+        }).fail(function(err) {
+            done(err);
+        });
+    });
 
 
+    it('should optimize an SVG', function(done) {
+        var fileContent = fs.readFileSync(path.resolve(__dirname, '../fixtures/svg-image.svg'));
+        var fileSize = fileContent.length;
 
 
+        var entry = {
+            method: 'GET',
+            url: 'http://localhost:8388/an-image.svg',
+            requestHeaders: {
+                'User-Agent': 'something',
+                Referer: 'http://www.google.fr/',
+                Accept: '*/*',
+                'Accept-Encoding': 'gzip, deflate'
+            },
+            status: 200,
+            isImage: true,
+            type: 'image',
+            contentType: 'image/svg+xml',
+            contentLength: 999,
+            weightCheck: {
+                body: fileContent,
+                totalWeight: fileSize + 200,
+                headersSize: 200,
+                bodySize: fileSize,
+                isCompressed: false,
+                uncompressedSize: fileSize
+            }
+        };
 
 
+        imageOptimizer.optimizeImage(entry)
+
+        .then(function(newEntry) {
+            newEntry.weightCheck.should.have.a.property('isOptimized').that.equals(false);
+            newEntry.weightCheck.should.have.a.property('lossless').that.is.below(fileSize);
+
+            done();
+        })
+
+        .fail(function(err) {
+            done(err);
+        });
+    });
 
 
 
 
     it('shouldn\'t fail optimizing a corrupted jpeg', function(done) {
     it('shouldn\'t fail optimizing a corrupted jpeg', function(done) {

文件差异内容过多而无法显示
+ 627 - 0
test/fixtures/svg-image.svg


部分文件因为文件数量过多而无法显示