Skip to content

Commit 43722d0

Browse files
committed
all 8 bit colour types now supported
8 bit colour types supported and 16 bit for type 1, 2, 4 and 6 Recompression added using Deflator - now recompresses images and masks Colour type 3 key masks and smack support added for multi pixel alpha example updated
1 parent e735966 commit 43722d0

13 files changed

+552
-589
lines changed

examples/images.html

Lines changed: 117 additions & 87 deletions
Large diffs are not rendered by default.

examples/images/RGBA_16bpc.png

74.3 KB
Loading

examples/images/RGB_16bpc.png

59.7 KB
Loading
22.3 KB
Loading

examples/images/grayscale_8bpc.png

13.4 KB
Loading
37 KB
Loading
22.4 KB
Loading

examples/images/png8_flat.png

13.7 KB
Loading
10.8 KB
Loading

jspdf.plugin.addimage.js

Lines changed: 66 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/** @preserve
2-
* jsPDF addImage plugin (JPEG only at this time)
2+
* jsPDF addImage plugin
33
* Copyright (c) 2012 Jason Siefken, https://github.com/siefkenj/
44
* 2013 Chris Dowling, https://github.com/gingerchris
55
* 2013 Trinh Ho, https://github.com/ineedfat
@@ -47,13 +47,14 @@
4747
out('/Subtype /Image')
4848
out('/Width ' + img['w'])
4949
out('/Height ' + img['h'])
50-
if (img['cs'] === 'Indexed') {
50+
if (img['cs'] === this.color_spaces.INDEXED) {
5151
out('/ColorSpace [/Indexed /DeviceRGB '
52-
+ (img['pal'].length / 3 - 1) + ' ' + (objectNumber + 1)
52+
// if an indexed png defines more than one colour with transparency, we've created a smask
53+
+ (img['pal'].length / 3 - 1) + ' ' + ('smask' in img ? objectNumber + 2 : objectNumber + 1)
5354
+ ' 0 R]');
5455
} else {
5556
out('/ColorSpace /' + img['cs']);
56-
if (img['cs'] === 'DeviceCMYK') {
57+
if (img['cs'] === this.color_spaces.DEVICE_CMYK) {
5758
out('/Decode [1 0 1 0 1 0 1 0]');
5859
}
5960
}
@@ -65,8 +66,10 @@
6566
out('/DecodeParms <<' + img['dp'] + '>>');
6667
}
6768
if ('trns' in img && img['trns'].constructor == Array) {
68-
var trns = '';
69-
for ( var i = 0; i < img['trns'].length; i++)
69+
var trns = '',
70+
i = 0,
71+
len = img['trns'].length;
72+
for (; i < len; i++)
7073
trns += (img['trns'][i] + ' ' + img['trns'][i] + ' ');
7174
out('/Mask [' + trns + ']');
7275
}
@@ -81,15 +84,15 @@
8184

8285
// Soft mask
8386
if ('smask' in img) {
84-
var dp = '/Predictor 15 /Colors 1 /BitsPerComponent 8 /Columns ' + img['w'];
85-
var smask = {'w': img['w'], 'h': img['h'], 'cs': 'DeviceGray', 'bpc': 8, 'dp': dp, 'data': img['smask']};
86-
//if ('f' in img)
87-
//smask.f = img['f'];
87+
var dp = '/Predictor 15 /Colors 1 /BitsPerComponent ' + img['bpc'] + ' /Columns ' + img['w'];
88+
var smask = {'w': img['w'], 'h': img['h'], 'cs': 'DeviceGray', 'bpc': img['bpc'], 'dp': dp, 'data': img['smask']};
89+
if ('f' in img)
90+
smask.f = img['f'];
8891
putImage.call(this, smask);
8992
}
9093

9194
//Palette
92-
if (img['cs'] === 'Indexed') {
95+
if (img['cs'] === this.color_spaces.INDEXED) {
9396

9497
this.internal.newObject();
9598
//out('<< /Filter / ' + img['f'] +' /Length ' + img['pal'].length + '>>');
@@ -119,6 +122,11 @@
119122
)
120123
}
121124
}
125+
, checkCompressValue = function(value) {
126+
if(value && typeof value === 'string')
127+
value = value.toUpperCase();
128+
return value in jsPDFAPI.image_compression ? value : jsPDFAPI.image_compression.NONE;
129+
}
122130
, getImages = function() {
123131
var images = this.internal.collections[namespace + 'images'];
124132
//first run, so initialise stuff
@@ -232,19 +240,46 @@
232240

233241

234242
/**
235-
* COLOR SPACE
243+
* COLOR SPACES
244+
*/
245+
jsPDFAPI.color_spaces = {
246+
DEVICE_RGB:'DeviceRGB',
247+
DEVICE_GRAY:'DeviceGray',
248+
DEVICE_CMYK:'DeviceCMYK',
249+
CAL_GREY:'CalGray',
250+
CAL_RGB:'CalRGB',
251+
LAB:'Lab',
252+
ICC_BASED:'ICCBased',
253+
INDEXED:'Indexed',
254+
PATTERN:'Pattern',
255+
SEPERATION:'Seperation',
256+
DEVICE_N:'DeviceN'
257+
};
258+
259+
/**
260+
* DECODE METHODS
236261
*/
237-
jsPDFAPI.DEVICE_RGB = 'DeviceRGB';
238-
jsPDFAPI.DEVICE_GRAY = 'DeviceGray';
239-
jsPDFAPI.DEVICE_CMYK = 'DeviceCMYK';
240-
jsPDFAPI.INDEXED = 'Indexed';
262+
jsPDFAPI.decode = {
263+
DCT_DECODE:'DCTDecode',
264+
FLATE_DECODE:'FlateDecode',
265+
LZW_DECODE:'LZWDecode',
266+
JPX_DECODE:'JPXDecode',
267+
JBIG2_DECODE:'JBIG2Decode',
268+
ASCII85_DECODE:'ASCII85Decode',
269+
ASCII_HEX_DECODE:'ASCIIHexDecode',
270+
RUN_LENGTH_DECODE:'RunLengthDecode',
271+
CCITT_FAX_DECODE:'CCITTFaxDecode'
272+
};
241273

242274
/**
243-
* COMPRESSION METHODS
275+
* IMAGE COMPRESSION TYPES
244276
*/
245-
jsPDFAPI.DCT_DECODE = 'DCTDecode';
246-
jsPDFAPI.FLATE_DECODE = 'FlateDecode';
247-
jsPDFAPI.LZW_DECODE = 'LZWDecode';
277+
jsPDFAPI.image_compression = {
278+
NONE: 'NONE',
279+
FAST: 'FAST',
280+
MEDIUM: 'MEDIUM',
281+
SLOW: 'SLOW'
282+
};
248283

249284

250285
jsPDFAPI.isString = function(object) {
@@ -333,6 +368,7 @@
333368
jsPDFAPI.arrayBufferToBinaryString = function(buffer) {
334369
if(this.isArrayBuffer(buffer))
335370
buffer = new Uint8Array(buffer);
371+
336372
var binary_string = '';
337373
var len = buffer.byteLength;
338374
for (var i = 0; i < len; i++) {
@@ -342,7 +378,7 @@
342378
/*
343379
* Another solution is the method below - convert array buffer straight to base64 and then use atob
344380
*/
345-
//return atob(arrayBufferToBase64(array_buffer));
381+
//return atob(this.arrayBufferToBase64(buffer));
346382
};
347383

348384
/**
@@ -429,7 +465,7 @@
429465
return info;
430466
};
431467

432-
jsPDFAPI.addImage = function(imageData, format, x, y, w, h, alias, compress) {
468+
jsPDFAPI.addImage = function(imageData, format, x, y, w, h, alias, compression) {
433469
'use strict'
434470

435471
if(typeof format === 'number') {
@@ -444,8 +480,8 @@
444480
var images = getImages.call(this),//initalises internals and events on first run
445481
cached_info,
446482
dataAsBinaryString;
447-
448-
compress = compress || false;
483+
484+
compression = checkCompressValue(compression);
449485
format = format.toLowerCase();
450486

451487
if(notDefined(alias))
@@ -489,7 +525,7 @@
489525
info = cached_info;
490526

491527
if(!info)
492-
info = this['process' + format.toUpperCase()](imageData, imageIndex, alias, compress, dataAsBinaryString);
528+
info = this['process' + format.toUpperCase()](imageData, imageIndex, alias, compression, dataAsBinaryString);
493529

494530
if(!info)
495531
throw new Error('An unkwown error occurred whilst processing the image');
@@ -548,10 +584,10 @@
548584
};
549585

550586

551-
jsPDFAPI.processJPEG = function(data, index, alias, compress, dataAsBinaryString) {
587+
jsPDFAPI.processJPEG = function(data, index, alias, compression, dataAsBinaryString) {
552588
'use strict'
553-
var colorSpace = this.DEVICE_RGB,
554-
filter = this.DCT_DECODE,
589+
var colorSpace = this.color_spaces.DEVICE_RGB,
590+
filter = this.decode.DCT_DECODE,
555591
bpc = 8,
556592
dims;
557593

@@ -579,8 +615,8 @@
579615
return null;
580616
};
581617

582-
jsPDFAPI.processJPG = function(data, index, alias, compress, dataAsBinaryString) {
583-
return this.processJPEG(data, index, alias, compress, dataAsBinaryString);
618+
jsPDFAPI.processJPG = function(data, index, alias, compression, dataAsBinaryString) {
619+
return this.processJPEG(data, index, alias, compression, dataAsBinaryString);
584620
}
585621

586622
})(jsPDF.API);

0 commit comments

Comments
 (0)