diff --git a/src/ImageManager/Jpeg.js b/src/ImageManager/Jpeg.js index b66420e..742a754 100644 --- a/src/ImageManager/Jpeg.js +++ b/src/ImageManager/Jpeg.js @@ -1,5 +1,6 @@ const fs = require('fs'); +const customReadBuffer = require('./customReadBuffer') const MARKERS = [0xffc0, 0xffc1, 0xffc2, 0xffc3, 0xffc5, 0xffc6, 0xffc7, 0xffc8, 0xffc9, 0xffca, 0xffcb, 0xffcc, 0xffcd, 0xffce, 0xffcf]; @@ -29,11 +30,14 @@ const LoadJpeg = (src) => { } } - if (data[0] !== 0xff || data[1] !== 0xd8) { + const imageReader = new customReadBuffer(data) + + const Signature = imageReader.readChunk(2) + if (Signature[0] !== 0xff || Signature[1] !== 0xd8) { throw new Error('Unknown image format.'); } - if (data.readUInt16BE(0) !== 0xffd8) { + if (Signature.readUInt16BE(0) !== 0xffd8) { throw 'SOI not found in JPEG'; } @@ -41,14 +45,15 @@ const LoadJpeg = (src) => { let pos = 2; while (pos < data.length) { - marker = data.readUInt16BE(pos); + marker = imageReader.readUInt16dBEByPos(pos); pos += 2; if (MARKERS.includes(marker)) { break; } - pos += data.readUInt16BE(pos); + pos += imageReader.readUInt16dBEByPos(pos); + } if (!MARKERS.includes(marker)) { @@ -57,9 +62,9 @@ const LoadJpeg = (src) => { pos += 2; const bits = data[pos++]; - const height = data.readUInt16BE(pos); + const height = imageReader.readUInt16dBEByPos(pos); pos += 2; - const width = data.readUInt16BE(pos); + const width = imageReader.readUInt16dBEByPos(pos); pos += 2; const channels = data[pos++]; diff --git a/src/ImageManager/customReadBuffer.js b/src/ImageManager/customReadBuffer.js index 4c22d41..48ad3ad 100644 --- a/src/ImageManager/customReadBuffer.js +++ b/src/ImageManager/customReadBuffer.js @@ -56,6 +56,11 @@ class customReadBuffer { const readData = this.readChunk(2); return readData.readUInt16BE() } + + readUInt16dBEByPos(pos) { + return this.buffer.readUInt16BE(pos) + } + curretByte() { return this.buffer[this.bytesRead] diff --git a/src/ImageManager/png.js b/src/ImageManager/png.js index a66a06f..b986c58 100644 --- a/src/ImageManager/png.js +++ b/src/ImageManager/png.js @@ -1,8 +1,8 @@ -const { chr, ord, str_replace, substr, function_exists, gzcompress, gzuncompress } = require('../PHP_CoreFunctions') +const { chr, ord, str_replace, substr, function_exists, gzcompress, gzuncompress, strpos } = require('../PHP_CoreFunctions') const customReadBuffer = require('./customReadBuffer') const fs = require('fs') -const LoadPng = (src) => { +const LoadPng = (src, readdpi = true) => { let imagedata @@ -36,49 +36,33 @@ const LoadPng = (src) => { if (header !== 'IHDR') { throw 'Incorrect PNG file: ' + file } - + const w = imageReader.readint(); const h = imageReader.readint(); - - const bpc = ord(imageReader.readEncodeData(1)); + + const bpc = imageReader.readint8() //ord(imageReader.readEncodeData(1)); if (bpc > 8) { throw '16-bit depth not supported: ' + file } - const ct = ord(imageReader.readEncodeData(1)); - - let colspace - if (ct === 0 || ct === 4) { - colspace = 'DeviceGray'; - } else if (ct === 2 || ct === 6) { - colspace = 'DeviceRGB'; - } else if (ct === 3) { - colspace = 'Indexed'; - } else { - throw 'Unknown color type: ' + file - } - - if (ord(imageReader.readEncodeData(1)) !== 0) { - throw 'Unknown compression method: ' + file - } + const ct = imageReader.readint8() //ord(imageReader.readEncodeData(1)); + const { colorVal, colspace } = pngColorSpace(ct) - if (ord(imageReader.readEncodeData(1)) !== 0) { - throw 'Unknown filter method: ' + file - } + if (imageReader.readint8() !== 0) { throw 'Unknown compression method: ' + file } - if (ord(imageReader.readEncodeData(1)) !== 0) { - throw 'Interlacing not supported: ' + file - } + if (imageReader.readint8() !== 0) { throw 'Unknown filter method: ' + file } + if (imageReader.readint8() !== 0) { throw 'Interlacing not supported: ' + file } imageReader.skip(4) - const dp = `/Predictor 15 /Colors ${(colspace == 'DeviceRGB' ? 3 : 1)} /BitsPerComponent ${bpc} /Columns ${w}`; + const dp = `/Predictor 15 /Colors ${colorVal} /BitsPerComponent ${bpc} /Columns ${w}`; // Scan chunks looking for palette, transparency and image data let pal = ''; let trns = ''; let data = ''; let n + let dpi do { @@ -114,8 +98,25 @@ const LoadPng = (src) => { data += imageReader.readEncodeData(n); imageReader.skip(4) - } else if (type == 'IEND') { + } else if (type === 'IEND') { break; + } else if (type === "pHYs") { + + const x = imageReader.readint()//int(r.i32()) + const y = imageReader.readint()//int(r.i32()) + const units = imageReader.readint8()// r.u8() + + if (x == y && readdpi) { + switch (units) { + // if units is 1 then measurement is px/meter + case 1: + dpi = x / 39.3701 // inches per meter + default: + dpi = x + } + } + + imageReader.skip(4) } else { imageReader.skip(n + 4) //readstream(imagedata, n + 4); @@ -127,7 +128,8 @@ const LoadPng = (src) => { throw 'Missing palette in ' + file } - let info = { 'w': w, 'h': h, 'cs': colspace, 'bpc': bpc, 'f': 'FlateDecode', 'dp': dp, 'pal': pal, 'trns': trns }; + let info = { 'w': w, 'h': h, 'cs': colspace, 'bpc': bpc, 'f': 'FlateDecode', 'dp': dp, 'pal': pal, 'trns': trns, dpi }; + if (ct >= 4) { @@ -137,6 +139,7 @@ const LoadPng = (src) => { } data = gzuncompress(data); + let color = ''; let alpha = ''; @@ -172,10 +175,13 @@ const LoadPng = (src) => { data = undefined data = gzcompress(color); info['smask'] = gzcompress(alpha); - this.WithAlpha = true; info['PDFVersion'] = 1.4 + + info['WithAlpha'] = true + } else { + info['WithAlpha'] = false } info['data'] = data; @@ -185,5 +191,30 @@ const LoadPng = (src) => { } +const pngColorSpace = (ct) => { + + let colorVal = 1 + let colspace = "" + + switch (ct) { + case 0: + case 4: + colspace = "DeviceGray" + break + case 2: + case 6: + colspace = "DeviceRGB" + colorVal = 3 + break + case 3: + colspace = "Indexed" + break + default: + throw `unknown color type in PNG buffer:${ct}` + } + + return { colorVal, colspace } +} + module.exports = LoadPng \ No newline at end of file diff --git a/src/fpdf_js.js b/src/fpdf_js.js index 9b2e710..9bb1472 100644 --- a/src/fpdf_js.js +++ b/src/fpdf_js.js @@ -143,7 +143,6 @@ class FPDF { break; default: this.Error(`Incorrect unit: ${unit}`); - break; } @@ -508,19 +507,15 @@ class FPDF { */ DrawGrid() { - let spacing - - if (this.grid === true) { - spacing = 5; - } else { - spacing = this.grid; - } + const spacing = (this.grid === true) ? 5 : this.grid this.SetDrawColor(204, 255, 255); this.SetLineWidth(0.35); + for (let i = 0; i < this.w; i += spacing) { this.Line(i, 0, i, this.h); } + for (let i = 0; i < this.h; i += spacing) { this.Line(0, i, this.w, i); } @@ -529,17 +524,22 @@ class FPDF { let x = this.GetX(); let y = this.GetY(); + this.SetFont('Arial', 'I', 8); this.SetTextColor(204, 204, 204); + for (let i = 20; i < this.h; i += 20) { this.SetXY(1, i - 3); this.Write(4, `${i}`); } + for (let i = 20; i < ((this.w) - (this.rMargin) - 10); i += 20) { this.SetXY(i - 1, 1); this.Write(4, `${i}`); } + this.SetXY(x, y); + } /** @@ -1589,6 +1589,18 @@ class FPDF { h = -96; } + if (w === -1) { + // Set image width to whatever value for dpi we read + // from the image or that was set manually + w = -info.dpi + } + + if (h === -1) { + // Set image height to whatever value for dpi we read + // from the image or that was set manually + h = -info.dpi + } + if (w < 0) { w = -info['w'] * 72 / w / this.k; } if (h < 0) { h = -info['h'] * 72 / h / this.k; } if (w === 0) { w = h * info['w'] / info['h']; } @@ -2034,6 +2046,11 @@ class FPDF { delete imageData['PDFVersion'] } + //update alpha variable + this.WithAlpha = imageData['WithAlpha'] + //delete key + delete imageData['WithAlpha'] + return imageData } @@ -2504,6 +2521,7 @@ class FPDF { // Palette if (info['cs'] === 'Indexed') { + this._putstreamobject(info['pal']); } diff --git a/test/ImageReport.js b/test/ImageReport.js index f03358c..2f3b5f4 100644 --- a/test/ImageReport.js +++ b/test/ImageReport.js @@ -2,9 +2,9 @@ const FPDF = require('../index') let textColour = [0, 0, 0]; //let logoFile = `${__dirname}/test4.png`; -let logoFile = `${__dirname}/01-45-42-996_512.gif`; -let logoXPos = 0; -let logoYPos = 0; +let logoFile = `${__dirname}/horses.gif`; +let logoXPos = 50; +let logoYPos = 50; let logoWidth = 100; const pdf = new FPDF('P', 'mm', 'A4'); diff --git a/test/test4.png b/test/test4.png index cf53578..231840a 100644 Binary files a/test/test4.png and b/test/test4.png differ