123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790 |
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="utf-8">
- <title>plugins/addimage.js - Documentation</title>
- <script src="scripts/prettify/prettify.js"></script>
- <script src="scripts/prettify/lang-css.js"></script>
- <!--[if lt IE 9]>
- <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
- <![endif]-->
- <link type="text/css" rel="stylesheet" href="styles/prettify.css">
- <link type="text/css" rel="stylesheet" href="styles/jsdoc.css">
- </head>
- <body>
- <input type="checkbox" id="nav-trigger" class="nav-trigger" />
- <label for="nav-trigger" class="navicon-button x">
- <div class="navicon"></div>
- </label>
- <label for="nav-trigger" class="overlay"></label>
- <nav>
- <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="jsPDF.html">jsPDF</a></li></ul><h3>Global</h3><ul><li><a href="global.html#addFont">addFont</a></li><li><a href="global.html#addHTML">addHTML</a></li><li><a href="global.html#addMetadata">addMetadata</a></li><li><a href="global.html#addPage">addPage</a></li><li><a href="global.html#autoPrint">autoPrint</a></li><li><a href="global.html#CapJoinStyles">CapJoinStyles</a></li><li><a href="global.html#circle">circle</a></li><li><a href="global.html#ellipse">ellipse</a></li><li><a href="global.html#getFontList">getFontList</a></li><li><a href="global.html#lines">lines</a></li><li><a href="global.html#lstext">lstext</a></li><li><a href="global.html#output">output</a></li><li><a href="global.html#rect">rect</a></li><li><a href="global.html#roundedRect">roundedRect</a></li><li><a href="global.html#save">save</a></li><li><a href="global.html#setDisplayMode">setDisplayMode</a></li><li><a href="global.html#setDrawColor">setDrawColor</a></li><li><a href="global.html#setFillColor">setFillColor</a></li><li><a href="global.html#setFont">setFont</a></li><li><a href="global.html#setFontSize">setFontSize</a></li><li><a href="global.html#setFontStyle">setFontStyle</a></li><li><a href="global.html#setLineCap">setLineCap</a></li><li><a href="global.html#setLineJoin">setLineJoin</a></li><li><a href="global.html#setLineWidth">setLineWidth</a></li><li><a href="global.html#setPage">setPage</a></li><li><a href="global.html#setProperties">setProperties</a></li><li><a href="global.html#setTextColor">setTextColor</a></li><li><a href="global.html#text">text</a></li><li><a href="global.html#triangle">triangle</a></li></ul>
- </nav>
- <div id="main">
-
- <h1 class="page-title">plugins/addimage.js</h1>
-
-
-
- <section>
- <article>
- <pre class="prettyprint source linenums"><code>/** @preserve
- * jsPDF addImage plugin
- * Copyright (c) 2012 Jason Siefken, https://github.com/siefkenj/
- * 2013 Chris Dowling, https://github.com/gingerchris
- * 2013 Trinh Ho, https://github.com/ineedfat
- * 2013 Edwin Alejandro Perez, https://github.com/eaparango
- * 2013 Norah Smith, https://github.com/burnburnrocket
- * 2014 Diego Casorran, https://github.com/diegocr
- * 2014 James Robb, https://github.com/jamesbrobb
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
- ;(function(jsPDFAPI) {
- 'use strict'
- var namespace = 'addImage_',
- supported_image_types = ['jpeg', 'jpg', 'png'];
- // Image functionality ported from pdf.js
- var putImage = function(img) {
- var objectNumber = this.internal.newObject()
- , out = this.internal.write
- , putStream = this.internal.putStream
- img['n'] = objectNumber
- out('<</Type /XObject')
- out('/Subtype /Image')
- out('/Width ' + img['w'])
- out('/Height ' + img['h'])
- if (img['cs'] === this.color_spaces.INDEXED) {
- out('/ColorSpace [/Indexed /DeviceRGB '
- // if an indexed png defines more than one colour with transparency, we've created a smask
- + (img['pal'].length / 3 - 1) + ' ' + ('smask' in img ? objectNumber + 2 : objectNumber + 1)
- + ' 0 R]');
- } else {
- out('/ColorSpace /' + img['cs']);
- if (img['cs'] === this.color_spaces.DEVICE_CMYK) {
- out('/Decode [1 0 1 0 1 0 1 0]');
- }
- }
- out('/BitsPerComponent ' + img['bpc']);
- if ('f' in img) {
- out('/Filter /' + img['f']);
- }
- if ('dp' in img) {
- out('/DecodeParms <<' + img['dp'] + '>>');
- }
- if ('trns' in img && img['trns'].constructor == Array) {
- var trns = '',
- i = 0,
- len = img['trns'].length;
- for (; i < len; i++)
- trns += (img['trns'][i] + ' ' + img['trns'][i] + ' ');
- out('/Mask [' + trns + ']');
- }
- if ('smask' in img) {
- out('/SMask ' + (objectNumber + 1) + ' 0 R');
- }
- out('/Length ' + img['data'].length + '>>');
- putStream(img['data']);
- out('endobj');
- // Soft mask
- if ('smask' in img) {
- var dp = '/Predictor '+ img['p'] +' /Colors 1 /BitsPerComponent ' + img['bpc'] + ' /Columns ' + img['w'];
- var smask = {'w': img['w'], 'h': img['h'], 'cs': 'DeviceGray', 'bpc': img['bpc'], 'dp': dp, 'data': img['smask']};
- if ('f' in img)
- smask.f = img['f'];
- putImage.call(this, smask);
- }
- //Palette
- if (img['cs'] === this.color_spaces.INDEXED) {
- this.internal.newObject();
- //out('<< /Filter / ' + img['f'] +' /Length ' + img['pal'].length + '>>');
- //putStream(zlib.compress(img['pal']));
- out('<< /Length ' + img['pal'].length + '>>');
- putStream(this.arrayBufferToBinaryString(new Uint8Array(img['pal'])));
- out('endobj');
- }
- }
- , putResourcesCallback = function() {
- var images = this.internal.collections[namespace + 'images']
- for ( var i in images ) {
- putImage.call(this, images[i])
- }
- }
- , putXObjectsDictCallback = function(){
- var images = this.internal.collections[namespace + 'images']
- , out = this.internal.write
- , image
- for (var i in images) {
- image = images[i]
- out(
- '/I' + image['i']
- , image['n']
- , '0'
- , 'R'
- )
- }
- }
- , checkCompressValue = function(value) {
- if(value && typeof value === 'string')
- value = value.toUpperCase();
- return value in jsPDFAPI.image_compression ? value : jsPDFAPI.image_compression.NONE;
- }
- , getImages = function() {
- var images = this.internal.collections[namespace + 'images'];
- //first run, so initialise stuff
- if(!images) {
- this.internal.collections[namespace + 'images'] = images = {};
- this.internal.events.subscribe('putResources', putResourcesCallback);
- this.internal.events.subscribe('putXobjectDict', putXObjectsDictCallback);
- }
- return images;
- }
- , getImageIndex = function(images) {
- var imageIndex = 0;
- if (images){
- // this is NOT the first time this method is ran on this instance of jsPDF object.
- imageIndex = Object.keys ?
- Object.keys(images).length :
- (function(o){
- var i = 0
- for (var e in o){if(o.hasOwnProperty(e)){ i++ }}
- return i
- })(images)
- }
- return imageIndex;
- }
- , notDefined = function(value) {
- return typeof value === 'undefined' || value === null;
- }
- , generateAliasFromData = function(data) {
- return typeof data === 'string' && jsPDFAPI.sHashCode(data);
- }
- , doesNotSupportImageType = function(type) {
- return supported_image_types.indexOf(type) === -1;
- }
- , processMethodNotEnabled = function(type) {
- return typeof jsPDFAPI['process' + type.toUpperCase()] !== 'function';
- }
- , isDOMElement = function(object) {
- return typeof object === 'object' && object.nodeType === 1;
- }
- , createDataURIFromElement = function(element, format, angle) {
- //if element is an image which uses data url definition, just return the dataurl
- if (element.nodeName === 'IMG' && element.hasAttribute('src')) {
- var src = ''+element.getAttribute('src');
- if (!angle && src.indexOf('data:image/') === 0) return src;
- // only if the user doesn't care about a format
- if (!format && /\.png(?:[?#].*)?$/i.test(src)) format = 'png';
- }
- if(element.nodeName === 'CANVAS') {
- var canvas = element;
- } else {
- var canvas = document.createElement('canvas');
- canvas.width = element.clientWidth || element.width;
- canvas.height = element.clientHeight || element.height;
- var ctx = canvas.getContext('2d');
- if (!ctx) {
- throw ('addImage requires canvas to be supported by browser.');
- }
- if (angle) {
- var x, y, b, c, s, w, h, to_radians = Math.PI/180, angleInRadians;
- if (typeof angle === 'object') {
- x = angle.x;
- y = angle.y;
- b = angle.bg;
- angle = angle.angle;
- }
- angleInRadians = angle*to_radians;
- c = Math.abs(Math.cos(angleInRadians));
- s = Math.abs(Math.sin(angleInRadians));
- w = canvas.width;
- h = canvas.height;
- canvas.width = h * s + w * c;
- canvas.height = h * c + w * s;
- if (isNaN(x)) x = canvas.width / 2;
- if (isNaN(y)) y = canvas.height / 2;
- ctx.clearRect(0,0,canvas.width, canvas.height);
- ctx.fillStyle = b || 'white';
- ctx.fillRect(0, 0, canvas.width, canvas.height);
- ctx.save();
- ctx.translate(x, y);
- ctx.rotate(angleInRadians);
- ctx.drawImage(element, -(w/2), -(h/2));
- ctx.rotate(-angleInRadians);
- ctx.translate(-x, -y);
- ctx.restore();
- } else {
- ctx.drawImage(element, 0, 0, canvas.width, canvas.height);
- }
- }
- return canvas.toDataURL((''+format).toLowerCase() == 'png' ? 'image/png' : 'image/jpeg');
- }
- ,checkImagesForAlias = function(alias, images) {
- var cached_info;
- if(images) {
- for(var e in images) {
- if(alias === images[e].alias) {
- cached_info = images[e];
- break;
- }
- }
- }
- return cached_info;
- }
- ,determineWidthAndHeight = function(w, h, info) {
- if (!w && !h) {
- w = -96;
- h = -96;
- }
- if (w < 0) {
- w = (-1) * info['w'] * 72 / w / this.internal.scaleFactor;
- }
- if (h < 0) {
- h = (-1) * info['h'] * 72 / h / this.internal.scaleFactor;
- }
- if (w === 0) {
- w = h * info['w'] / info['h'];
- }
- if (h === 0) {
- h = w * info['h'] / info['w'];
- }
- return [w, h];
- }
- , writeImageToPDF = function(x, y, w, h, info, index, images) {
- var dims = determineWidthAndHeight.call(this, w, h, info),
- coord = this.internal.getCoordinateString,
- vcoord = this.internal.getVerticalCoordinateString;
- w = dims[0];
- h = dims[1];
- images[index] = info;
- this.internal.write(
- 'q'
- , coord(w)
- , '0 0'
- , coord(h) // TODO: check if this should be shifted by vcoord
- , coord(x)
- , vcoord(y + h)
- , 'cm /I'+info['i']
- , 'Do Q'
- )
- };
- /**
- * COLOR SPACES
- */
- jsPDFAPI.color_spaces = {
- DEVICE_RGB:'DeviceRGB',
- DEVICE_GRAY:'DeviceGray',
- DEVICE_CMYK:'DeviceCMYK',
- CAL_GREY:'CalGray',
- CAL_RGB:'CalRGB',
- LAB:'Lab',
- ICC_BASED:'ICCBased',
- INDEXED:'Indexed',
- PATTERN:'Pattern',
- SEPARATION:'Separation',
- DEVICE_N:'DeviceN'
- };
- /**
- * DECODE METHODS
- */
- jsPDFAPI.decode = {
- DCT_DECODE:'DCTDecode',
- FLATE_DECODE:'FlateDecode',
- LZW_DECODE:'LZWDecode',
- JPX_DECODE:'JPXDecode',
- JBIG2_DECODE:'JBIG2Decode',
- ASCII85_DECODE:'ASCII85Decode',
- ASCII_HEX_DECODE:'ASCIIHexDecode',
- RUN_LENGTH_DECODE:'RunLengthDecode',
- CCITT_FAX_DECODE:'CCITTFaxDecode'
- };
- /**
- * IMAGE COMPRESSION TYPES
- */
- jsPDFAPI.image_compression = {
- NONE: 'NONE',
- FAST: 'FAST',
- MEDIUM: 'MEDIUM',
- SLOW: 'SLOW'
- };
- jsPDFAPI.sHashCode = function(str) {
- return Array.prototype.reduce && str.split("").reduce(function(a,b){a=((a<<5)-a)+b.charCodeAt(0);return a&a},0);
- };
- jsPDFAPI.isString = function(object) {
- return typeof object === 'string';
- };
- /**
- * Strips out and returns info from a valid base64 data URI
- * @param {String[dataURI]} a valid data URI of format 'data:[<MIME-type>][;base64],<data>'
- * @returns an Array containing the following
- * [0] the complete data URI
- * [1] <MIME-type>
- * [2] format - the second part of the mime-type i.e 'png' in 'image/png'
- * [4] <data>
- */
- jsPDFAPI.extractInfoFromBase64DataURI = function(dataURI) {
- return /^data:([\w]+?\/([\w]+?));base64,(.+?)$/g.exec(dataURI);
- };
- /**
- * Check to see if ArrayBuffer is supported
- */
- jsPDFAPI.supportsArrayBuffer = function() {
- return typeof ArrayBuffer !== 'undefined' && typeof Uint8Array !== 'undefined';
- };
- /**
- * Tests supplied object to determine if ArrayBuffer
- * @param {Object[object]}
- */
- jsPDFAPI.isArrayBuffer = function(object) {
- if(!this.supportsArrayBuffer())
- return false;
- return object instanceof ArrayBuffer;
- };
- /**
- * Tests supplied object to determine if it implements the ArrayBufferView (TypedArray) interface
- * @param {Object[object]}
- */
- jsPDFAPI.isArrayBufferView = function(object) {
- if(!this.supportsArrayBuffer())
- return false;
- if(typeof Uint32Array === 'undefined')
- return false;
- return (object instanceof Int8Array ||
- object instanceof Uint8Array ||
- (typeof Uint8ClampedArray !== 'undefined' && object instanceof Uint8ClampedArray) ||
- object instanceof Int16Array ||
- object instanceof Uint16Array ||
- object instanceof Int32Array ||
- object instanceof Uint32Array ||
- object instanceof Float32Array ||
- object instanceof Float64Array );
- };
- /**
- * Exactly what it says on the tin
- */
- jsPDFAPI.binaryStringToUint8Array = function(binary_string) {
- /*
- * not sure how efficient this will be will bigger files. Is there a native method?
- */
- var len = binary_string.length;
- var bytes = new Uint8Array( len );
- for (var i = 0; i < len; i++) {
- bytes[i] = binary_string.charCodeAt(i);
- }
- return bytes;
- };
- /**
- * @see this discussion
- * http://stackoverflow.com/questions/6965107/converting-between-strings-and-arraybuffers
- *
- * As stated, i imagine the method below is highly inefficent for large files.
- *
- * Also of note from Mozilla,
- *
- * "However, this is slow and error-prone, due to the need for multiple conversions (especially if the binary data is not actually byte-format data, but, for example, 32-bit integers or floats)."
- *
- * https://developer.mozilla.org/en-US/Add-ons/Code_snippets/StringView
- *
- * Although i'm strugglig to see how StringView solves this issue? Doesn't appear to be a direct method for conversion?
- *
- * Async method using Blob and FileReader could be best, but i'm not sure how to fit it into the flow?
- */
- jsPDFAPI.arrayBufferToBinaryString = function(buffer) {
- /*if('TextDecoder' in window){
- var decoder = new TextDecoder('ascii');
- return decoder.decode(buffer);
- }*/
- if(this.isArrayBuffer(buffer))
- buffer = new Uint8Array(buffer);
- var binary_string = '';
- var len = buffer.byteLength;
- for (var i = 0; i < len; i++) {
- binary_string += String.fromCharCode(buffer[i]);
- }
- return binary_string;
- /*
- * Another solution is the method below - convert array buffer straight to base64 and then use atob
- */
- //return atob(this.arrayBufferToBase64(buffer));
- };
- /**
- * Converts an ArrayBuffer directly to base64
- *
- * Taken from here
- *
- * http://jsperf.com/encoding-xhr-image-data/31
- *
- * Need to test if this is a better solution for larger files
- *
- */
- jsPDFAPI.arrayBufferToBase64 = function(arrayBuffer) {
- var base64 = ''
- var encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
- var bytes = new Uint8Array(arrayBuffer)
- var byteLength = bytes.byteLength
- var byteRemainder = byteLength % 3
- var mainLength = byteLength - byteRemainder
- var a, b, c, d
- var chunk
- // Main loop deals with bytes in chunks of 3
- for (var i = 0; i < mainLength; i = i + 3) {
- // Combine the three bytes into a single integer
- chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2]
- // Use bitmasks to extract 6-bit segments from the triplet
- a = (chunk & 16515072) >> 18 // 16515072 = (2^6 - 1) << 18
- b = (chunk & 258048) >> 12 // 258048 = (2^6 - 1) << 12
- c = (chunk & 4032) >> 6 // 4032 = (2^6 - 1) << 6
- d = chunk & 63 // 63 = 2^6 - 1
- // Convert the raw binary segments to the appropriate ASCII encoding
- base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d]
- }
- // Deal with the remaining bytes and padding
- if (byteRemainder == 1) {
- chunk = bytes[mainLength]
- a = (chunk & 252) >> 2 // 252 = (2^6 - 1) << 2
- // Set the 4 least significant bits to zero
- b = (chunk & 3) << 4 // 3 = 2^2 - 1
- base64 += encodings[a] + encodings[b] + '=='
- } else if (byteRemainder == 2) {
- chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1]
- a = (chunk & 64512) >> 10 // 64512 = (2^6 - 1) << 10
- b = (chunk & 1008) >> 4 // 1008 = (2^6 - 1) << 4
- // Set the 2 least significant bits to zero
- c = (chunk & 15) << 2 // 15 = 2^4 - 1
- base64 += encodings[a] + encodings[b] + encodings[c] + '='
- }
- return base64
- };
- jsPDFAPI.createImageInfo = function(data, wd, ht, cs, bpc, f, imageIndex, alias, dp, trns, pal, smask, p) {
- var info = {
- alias:alias,
- w : wd,
- h : ht,
- cs : cs,
- bpc : bpc,
- i : imageIndex,
- data : data
- // n: objectNumber will be added by putImage code
- };
- if(f) info.f = f;
- if(dp) info.dp = dp;
- if(trns) info.trns = trns;
- if(pal) info.pal = pal;
- if(smask) info.smask = smask;
- if(p) info.p = p;// predictor parameter for PNG compression
- return info;
- };
- jsPDFAPI.addImage = function(imageData, format, x, y, w, h, alias, compression, rotation) {
- 'use strict'
- if(typeof format !== 'string') {
- var tmp = h;
- h = w;
- w = y;
- y = x;
- x = format;
- format = tmp;
- }
- if (typeof imageData === 'object' && !isDOMElement(imageData) && "imageData" in imageData) {
- var options = imageData;
- imageData = options.imageData;
- format = options.format || format;
- x = options.x || x || 0;
- y = options.y || y || 0;
- w = options.w || w;
- h = options.h || h;
- alias = options.alias || alias;
- compression = options.compression || compression;
- rotation = options.rotation || options.angle || rotation;
- }
- if (isNaN(x) || isNaN(y))
- {
- console.error('jsPDF.addImage: Invalid coordinates', arguments);
- throw new Error('Invalid coordinates passed to jsPDF.addImage');
- }
- var images = getImages.call(this), info;
- if (!(info = checkImagesForAlias(imageData, images))) {
- var dataAsBinaryString;
- if(isDOMElement(imageData))
- imageData = createDataURIFromElement(imageData, format, rotation);
- if(notDefined(alias))
- alias = generateAliasFromData(imageData);
- if (!(info = checkImagesForAlias(alias, images))) {
- if(this.isString(imageData)) {
- var base64Info = this.extractInfoFromBase64DataURI(imageData);
- if(base64Info) {
- format = base64Info[2];
- imageData = atob(base64Info[3]);//convert to binary string
- } else {
- if (imageData.charCodeAt(0) === 0x89 &&
- imageData.charCodeAt(1) === 0x50 &&
- imageData.charCodeAt(2) === 0x4e &&
- imageData.charCodeAt(3) === 0x47 ) format = 'png';
- }
- }
- format = (format || 'JPEG').toLowerCase();
- if(doesNotSupportImageType(format))
- throw new Error('addImage currently only supports formats ' + supported_image_types + ', not \''+format+'\'');
- if(processMethodNotEnabled(format))
- throw new Error('please ensure that the plugin for \''+format+'\' support is added');
- /**
- * need to test if it's more efficient to convert all binary strings
- * to TypedArray - or should we just leave and process as string?
- */
- if(this.supportsArrayBuffer()) {
- // no need to convert if imageData is already uint8array
- if(!(imageData instanceof Uint8Array)){
- dataAsBinaryString = imageData;
- imageData = this.binaryStringToUint8Array(imageData);
- }
- }
- info = this['process' + format.toUpperCase()](
- imageData,
- getImageIndex(images),
- alias,
- checkCompressValue(compression),
- dataAsBinaryString
- );
- if(!info)
- throw new Error('An unkwown error occurred whilst processing the image');
- }
- }
- writeImageToPDF.call(this, x, y, w, h, info, info.i, images);
- return this
- };
- /**
- * JPEG SUPPORT
- **/
- //takes a string imgData containing the raw bytes of
- //a jpeg image and returns [width, height]
- //Algorithm from: http://www.64lines.com/jpeg-width-height
- var getJpegSize = function(imgData) {
- 'use strict'
- var width, height, numcomponents;
- // Verify we have a valid jpeg header 0xff,0xd8,0xff,0xe0,?,?,'J','F','I','F',0x00
- if (!imgData.charCodeAt(0) === 0xff ||
- !imgData.charCodeAt(1) === 0xd8 ||
- !imgData.charCodeAt(2) === 0xff ||
- !imgData.charCodeAt(3) === 0xe0 ||
- !imgData.charCodeAt(6) === 'J'.charCodeAt(0) ||
- !imgData.charCodeAt(7) === 'F'.charCodeAt(0) ||
- !imgData.charCodeAt(8) === 'I'.charCodeAt(0) ||
- !imgData.charCodeAt(9) === 'F'.charCodeAt(0) ||
- !imgData.charCodeAt(10) === 0x00) {
- throw new Error('getJpegSize requires a binary string jpeg file')
- }
- var blockLength = imgData.charCodeAt(4)*256 + imgData.charCodeAt(5);
- var i = 4, len = imgData.length;
- while ( i < len ) {
- i += blockLength;
- if (imgData.charCodeAt(i) !== 0xff) {
- throw new Error('getJpegSize could not find the size of the image');
- }
- if (imgData.charCodeAt(i+1) === 0xc0 || //(SOF) Huffman - Baseline DCT
- imgData.charCodeAt(i+1) === 0xc1 || //(SOF) Huffman - Extended sequential DCT
- imgData.charCodeAt(i+1) === 0xc2 || // Progressive DCT (SOF2)
- imgData.charCodeAt(i+1) === 0xc3 || // Spatial (sequential) lossless (SOF3)
- imgData.charCodeAt(i+1) === 0xc4 || // Differential sequential DCT (SOF5)
- imgData.charCodeAt(i+1) === 0xc5 || // Differential progressive DCT (SOF6)
- imgData.charCodeAt(i+1) === 0xc6 || // Differential spatial (SOF7)
- imgData.charCodeAt(i+1) === 0xc7) {
- height = imgData.charCodeAt(i+5)*256 + imgData.charCodeAt(i+6);
- width = imgData.charCodeAt(i+7)*256 + imgData.charCodeAt(i+8);
- numcomponents = imgData.charCodeAt(i+9);
- return [width, height, numcomponents];
- } else {
- i += 2;
- blockLength = imgData.charCodeAt(i)*256 + imgData.charCodeAt(i+1)
- }
- }
- }
- , getJpegSizeFromBytes = function(data) {
- var hdr = (data[0] << 8) | data[1];
- if(hdr !== 0xFFD8)
- throw new Error('Supplied data is not a JPEG');
- var len = data.length,
- block = (data[4] << 8) + data[5],
- pos = 4,
- bytes, width, height, numcomponents;
- while(pos < len) {
- pos += block;
- bytes = readBytes(data, pos);
- block = (bytes[2] << 8) + bytes[3];
- if((bytes[1] === 0xC0 || bytes[1] === 0xC2) && bytes[0] === 0xFF && block > 7) {
- bytes = readBytes(data, pos + 5);
- width = (bytes[2] << 8) + bytes[3];
- height = (bytes[0] << 8) + bytes[1];
- numcomponents = bytes[4];
- return {width:width, height:height, numcomponents: numcomponents};
- }
- pos+=2;
- }
- throw new Error('getJpegSizeFromBytes could not find the size of the image');
- }
- , readBytes = function(data, offset) {
- return data.subarray(offset, offset+ 5);
- };
- jsPDFAPI.processJPEG = function(data, index, alias, compression, dataAsBinaryString) {
- 'use strict'
- var colorSpace = this.color_spaces.DEVICE_RGB,
- filter = this.decode.DCT_DECODE,
- bpc = 8,
- dims;
- if(this.isString(data)) {
- dims = getJpegSize(data);
- return this.createImageInfo(data, dims[0], dims[1], dims[3] == 1 ? this.color_spaces.DEVICE_GRAY:colorSpace, bpc, filter, index, alias);
- }
- if(this.isArrayBuffer(data))
- data = new Uint8Array(data);
- if(this.isArrayBufferView(data)) {
- dims = getJpegSizeFromBytes(data);
- // if we already have a stored binary string rep use that
- data = dataAsBinaryString || this.arrayBufferToBinaryString(data);
- return this.createImageInfo(data, dims.width, dims.height, dims.numcomponents == 1 ? this.color_spaces.DEVICE_GRAY:colorSpace, bpc, filter, index, alias);
- }
- return null;
- };
- jsPDFAPI.processJPG = function(/*data, index, alias, compression, dataAsBinaryString*/) {
- return this.processJPEG.apply(this, arguments);
- }
- })(jsPDF.API);
- </code></pre>
- </article>
- </section>
- </div>
- <br class="clear">
- <footer>
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.2</a> on Sun Oct 09 2016 11:08:27 GMT+0100 (BST) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
- </footer>
- <script>prettyPrint();</script>
- <script src="scripts/linenumber.js"></script>
- </body>
- </html>
|