From f1f9c9b18344d8d30256bfca7e68e15d3d0d3878 Mon Sep 17 00:00:00 2001 From: Andreas Kirkerud Date: Sat, 13 Jun 2015 10:39:50 +0200 Subject: [PATCH 1/3] added support for LZMA compressed swf-files --- index.js | 116 +++++++++++++++++++++++++++++++++++++++++---------- package.json | 8 ++-- 2 files changed, 100 insertions(+), 24 deletions(-) diff --git a/index.js b/index.js index f5ef1c7..a850dc4 100644 --- a/index.js +++ b/index.js @@ -57,7 +57,7 @@ function readBit(buffer, offset, bitOffset) { function readBits(buffer, offset, bitOffset, bitLen, signed) { var val = 0; - + var neg = false; if (signed) { if (readBit(buffer, offset, bitOffset) > 0) { @@ -98,7 +98,7 @@ function imageInfoPng(buffer) { format: 'PNG', mimeType: 'image/png', width: readUInt32(buffer, pos, true), - height: readUInt32(buffer, pos+4, true), + height: readUInt32(buffer, pos+4, true) }; } @@ -115,7 +115,7 @@ function imageInfoJpg(buffer) { format: 'JPG', mimeType: 'image/jpeg', width: readUInt16(buffer, pos+2, true), - height: readUInt16(buffer, pos, true), + height: readUInt16(buffer, pos, true) }; } @@ -133,20 +133,56 @@ function imageInfoGif(buffer) { format: 'GIF', mimeType: 'image/gif', width: readUInt16(buffer, pos, false), - height: readUInt16(buffer, pos+2, false), + height: readUInt16(buffer, pos+2, false) }; } -function imageInfoSwf(buffer) { - var pos = 8, +/** + * Found advice for SWF 2 7Z LZMA-Header conversion: + * https://helpx.adobe.com/flash-player/kb/exception-thrown-you-decompress-lzma-compressed.html + * + * @param buffer swf-lzma formated + * @return buffer 7z-lzma formated + */ +function convertSwfTo7zLzmaHeader(buffer) { + + var scriptlen = buffer[4] & 0xFF | (buffer[5] & 0xFF) << 8 | (buffer[6] & 0xFF) << 16 | buffer[7] << 24; + scriptlen -= 8; + + var lzmaProperties = buffer.slice(12, 17); + + var headerUnCompressedSize = new Buffer([scriptlen & 0xFF, (scriptlen >> 8) & 0xFF, (scriptlen >> 16) & 0xFF, (scriptlen >> 24) & 0xFF, 0, 0, 0, 0 ]); + + var newHeader = Buffer.concat([ lzmaProperties, headerUnCompressedSize ]); + + var sevenZipLZMAFormatedData = Buffer.concat([newHeader, buffer.slice(17)]); + + return sevenZipLZMAFormatedData; +} + + +function imageInfoSwf(buffer, cb, p, extraInfo) { + + var pos = p > -1 ? p : 8, bitPos = 0, val; + if (!extraInfo) { + extraInfo = { + flashVersion: buffer[3], + isCompressed: buffer[0] === 0x43 || buffer[0] === 0x5a, + uncompressedSize: buffer[4] & 0xFF | (buffer[5] & 0xFF) << 8 | (buffer[6] & 0xFF) << 16 | buffer[7] << 24 + } + } + if (buffer[0] === 0x43) { try { // If you have zlib available ( npm install zlib ) then we can read compressed flash files - buffer = require('zlib').inflate(buffer.slice(8, 100)); - pos = 0; + require('zlib').inflate(buffer.slice(8), function (error, buffer) { + imageInfoSwf(buffer, cb, 0, extraInfo); + }); + + return; } catch (ex) { // Can't get width/height of compressed flash files... yet (need zlib) @@ -154,15 +190,43 @@ function imageInfoSwf(buffer) { type: 'flash', format: 'SWF', mimeType: 'application/x-shockwave-flash', + version: extraInfo ? extraInfo.flashVersion : null, + isCompressed: extraInfo ? extraInfo.isCompressed : null, + uncompressedSize: extraInfo ? extraInfo.uncompressedSize : null, width: null, - height: null, + height: null } } - } + } else if (buffer[0] === 0x5a) { + + //swf file is lzma compressed + + try { + var lzmaBuffer = convertSwfTo7zLzmaHeader(buffer); + + require("lzma").decompress(lzmaBuffer, function(uncompressedBuffer) { + imageInfoSwf(uncompressedBuffer, cb, 0, extraInfo); + }); + return; + } + catch (ex) { + return { + type: 'flash', + format: 'SWF', + mimeType: 'application/x-shockwave-flash', + version: extraInfo ? extraInfo.flashVersion : null, + isCompressed: extraInfo ? extraInfo.isCompressed : null, + uncompressedSize: extraInfo ? extraInfo.uncompressedSize : null, + width: null, + height: null + } + } + + } var numBits = readBits(buffer, pos, bitPos, 5)[0]; bitPos += 5; - + val = readBits(buffer, pos, bitPos, numBits, true); var xMin = (numBits > 9 ? readUInt16(val, 0, true) : val[0]) * (val.negative ? -1 : 1); bitPos += numBits; @@ -178,13 +242,23 @@ function imageInfoSwf(buffer) { val = readBits(buffer, pos, bitPos, numBits, true); var yMax = (numBits > 9 ? readUInt16(val, 0, true) : val[0]) * (val.negative ? -1 : 1); - return { + var byteIdx = 9; + var fps = readUInt16(buffer, byteIdx, false) / 256; + byteIdx += 2; + var frameCount = readUInt16(buffer, byteIdx, false); + + cb({ type: 'flash', format: 'SWF', mimeType: 'application/x-shockwave-flash', + version: extraInfo ? extraInfo.flashVersion : null, + isCompressed: extraInfo ? extraInfo.isCompressed : null, + uncompressedSize: extraInfo ? extraInfo.uncompressedSize : null, + fps: fps, + frameCount: frameCount, width: Math.ceil((xMax - xMin) / 20), - height: Math.ceil((yMax - yMin) / 20), - }; + height: Math.ceil((yMax - yMin) / 20) + }); } function checkSig(buffer, offset, sig) { @@ -214,17 +288,17 @@ function checkSig(buffer, offset, sig) { return true; } -module.exports = function imageInfo(buffer, path) { +module.exports = function imageInfo(buffer, cb) { var pngSig = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]; var jpgSig = [0xff, 0xd8, 0xff]; var gifSig = [0x47, 0x49, 0x46, 0x38, [0x37, 0x39], 0x61]; - var swfSig = [[0x46, 0x43], 0x57, 0x53]; + var swfSig = [[0x46, 0x43, 0x5a], 0x57, 0x53]; - if (checkSig(buffer, 0, pngSig)) return imageInfoPng(buffer); - if (checkSig(buffer, 0, jpgSig)) return imageInfoJpg(buffer); - if (checkSig(buffer, 0, gifSig)) return imageInfoGif(buffer); - if (checkSig(buffer, 0, swfSig)) return imageInfoSwf(buffer); + if (checkSig(buffer, 0, pngSig)) cb(imageInfoPng(buffer)); + else if (checkSig(buffer, 0, jpgSig)) cb(imageInfoJpg(buffer)); + else if (checkSig(buffer, 0, gifSig)) cb(imageInfoGif(buffer)); + else if (checkSig(buffer, 0, swfSig)) imageInfoSwf(buffer, cb); + else cb({}); - return false; }; diff --git a/package.json b/package.json index d0ab397..7cb82b9 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "imageinfo", "description": "A node.js package that returns information about an image or flash file such as type, dimensions etc.", "homepage": "https://github.com/NorgannasAddOns/node-imageinfo", - "version": "1.0.4", + "version": "1.1.0", "author": "Norganna ", "repository": { "type": "git", @@ -13,12 +13,14 @@ }, "main": "index", "keywords": [ - "image", "info", "jpg", "jpeg", "png", "gif", "swf", "dimensions", "size", "type", "mime", "format" + "image", "info", "jpg", "jpeg", "png", "gif", "swf", "dimensions", "size", "type", "mime", "format", "lzma" ], "engines": { "node": ">=0.4" }, - "dependencies": {}, + "dependencies": { + "lzma": "2.1.5" + }, "devDependencies": {}, "directories": { "lib": ".", From ec9e87bbc10f0bb8db5be2811a2f7b7622248b16 Mon Sep 17 00:00:00 2001 From: Andreas Kirkerud Date: Sat, 13 Jun 2015 10:43:01 +0200 Subject: [PATCH 2/3] updated example in README --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 21f529f..50c20f2 100644 --- a/README.md +++ b/README.md @@ -18,10 +18,12 @@ To install imageinfo into your project, use `npm install imageinfo`, then it's s fs.readFile('testimage', function(err, data) { if (err) throw err; - info = imageinfo(data); - console.log("Data is type:", info.mimeType); - console.log(" Size:", data.length, "bytes"); - console.log(" Dimensions:", info.width, "x", info.height); + imageinfo(data, function (info) { + console.log("Data is type:", info.mimeType); + console.log("Size:", data.length, "bytes"); + console.log("Dimensions:", info.width, "x", info.height); + }); + }); ## License: From 5b9c6cbb238248d4e69922ab7295d3b7e649cd53 Mon Sep 17 00:00:00 2001 From: Andreas Kirkerud Date: Sat, 13 Jun 2015 10:53:09 +0200 Subject: [PATCH 3/3] corrected text in README --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 50c20f2..cce614a 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,9 @@ This is a small package for node.js to allow the analysis of image data in a Buffer, and return mime-type, and image dimensions for the data. -It is designed to be fast, completely written in javascript and have no dependencies on external packages or libraries. +It is designed to be fast, completely written in javascript. -Currently it supports Png, Jpeg, Gif and (uncompressed) Swf analysis. - -If you also have zlib available (`npm install zlib`) then it will support compressed Swf files. +Currently it supports Png, Jpeg, Gif and Swf(uncompressed, deflate and LZMA) analysis. ## Usage: