Current File : /home/users/barii/public_html/finansenl.com.pl/wodki/admin/plugins/png_support.js |
/**@preserve
* ====================================================================
* jsPDF PNG PlugIn
* Copyright (c) 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'
/*
* @see http://www.w3.org/TR/PNG-Chunks.html
*
Color Allowed Interpretation
Type Bit Depths
0 1,2,4,8,16 Each pixel is a grayscale sample.
2 8,16 Each pixel is an R,G,B triple.
3 1,2,4,8 Each pixel is a palette index;
a PLTE chunk must appear.
4 8,16 Each pixel is a grayscale sample,
followed by an alpha sample.
6 8,16 Each pixel is an R,G,B triple,
followed by an alpha sample.
*/
/*
* PNG filter method types
*
* @see http://www.w3.org/TR/PNG-Filters.html
* @see http://www.libpng.org/pub/png/book/chapter09.html
*
* This is what the value 'Predictor' in decode params relates to
*
* 15 is "optimal prediction", which means the prediction algorithm can change from line to line.
* In that case, you actually have to read the first byte off each line for the prediction algorthim (which should be 0-4, corresponding to PDF 10-14) and select the appropriate unprediction algorithm based on that byte.
*
0 None
1 Sub
2 Up
3 Average
4 Paeth
*/
var doesNotHavePngJS = function() {
return typeof PNG !== 'function' || typeof FlateStream !== 'function';
}
, canCompress = function(value) {
return value !== jsPDFAPI.image_compression.NONE && hasCompressionJS();
}
, hasCompressionJS = function() {
var inst = typeof Deflater === 'function';
if(!inst)
throw new Error("requires deflate.js for compression")
return inst;
}
, compressBytes = function(bytes, lineLength, colorsPerPixel, compression) {
var level = 5,
filter_method = filterUp;
switch(compression) {
case jsPDFAPI.image_compression.FAST:
level = 3;
filter_method = filterSub;
break;
case jsPDFAPI.image_compression.MEDIUM:
level = 6;
filter_method = filterAverage;
break;
case jsPDFAPI.image_compression.SLOW:
level = 9;
filter_method = filterPaeth;//uses to sum to choose best filter for each line
break;
}
bytes = applyPngFilterMethod(bytes, lineLength, colorsPerPixel, filter_method);
var header = new Uint8Array(createZlibHeader(level));
var checksum = adler32(bytes);
var deflate = new Deflater(level);
var a = deflate.append(bytes);
var cBytes = deflate.flush();
var len = header.length + a.length + cBytes.length;
var cmpd = new Uint8Array(len + 4);
cmpd.set(header);
cmpd.set(a, header.length);
cmpd.set(cBytes, header.length + a.length);
cmpd[len++] = (checksum >>> 24) & 0xff;
cmpd[len++] = (checksum >>> 16) & 0xff;
cmpd[len++] = (checksum >>> 8) & 0xff;
cmpd[len++] = checksum & 0xff;
return jsPDFAPI.arrayBufferToBinaryString(cmpd);
}
, createZlibHeader = function(bytes, level){
/*
* @see http://www.ietf.org/rfc/rfc1950.txt for zlib header
*/
var cm = 8;
var cinfo = Math.LOG2E * Math.log(0x8000) - 8;
var cmf = (cinfo << 4) | cm;
var hdr = cmf << 8;
var flevel = Math.min(3, ((level - 1) & 0xff) >> 1);
hdr |= (flevel << 6);
hdr |= 0;//FDICT
hdr += 31 - (hdr % 31);
return [cmf, (hdr & 0xff) & 0xff];
}
, adler32 = function(array, param) {
var adler = 1;
var s1 = adler & 0xffff,
s2 = (adler >>> 16) & 0xffff;
var len = array.length;
var tlen;
var i = 0;
while (len > 0) {
tlen = len > param ? param : len;
len -= tlen;
do {
s1 += array[i++];
s2 += s1;
} while (--tlen);
s1 %= 65521;
s2 %= 65521;
}
return ((s2 << 16) | s1) >>> 0;
}
, applyPngFilterMethod = function(bytes, lineLength, colorsPerPixel, filter_method) {
var lines = bytes.length / lineLength,
result = new Uint8Array(bytes.length + lines),
filter_methods = getFilterMethods(),
i = 0, line, prevLine, offset;
for(; i < lines; i++) {
offset = i * lineLength;
line = bytes.subarray(offset, offset + lineLength);
if(filter_method) {
result.set(filter_method(line, colorsPerPixel, prevLine), offset + i);
}else{
var j = 0,
len = filter_methods.length,
results = [];
for(; j < len; j++)
results[j] = filter_methods[j](line, colorsPerPixel, prevLine);
var ind = getIndexOfSmallestSum(results.concat());
result.set(results[ind], offset + i);
}
prevLine = line;
}
return result;
}
, filterNone = function(line, colorsPerPixel, prevLine) {
/*var result = new Uint8Array(line.length + 1);
result[0] = 0;
result.set(line, 1);*/
var result = Array.apply([], line);
result.unshift(0);
return result;
}
, filterSub = function(line, colorsPerPixel, prevLine) {
var result = [],
i = 0,
len = line.length,
left;
result[0] = 1;
for(; i < len; i++) {
left = line[i - colorsPerPixel] || 0;
result[i + 1] = (line[i] - left + 0x0100) & 0xff;
}
return result;
}
, filterUp = function(line, colorsPerPixel, prevLine) {
var result = [],
i = 0,
len = line.length,
up;
result[0] = 2;
for(; i < len; i++) {
up = prevLine && prevLine[i] || 0;
result[i + 1] = (line[i] - up + 0x0100) & 0xff;
}
return result;
}
, filterAverage = function(line, colorsPerPixel, prevLine) {
var result = [],
i = 0,
len = line.length,
left,
up;
result[0] = 3;
for(; i < len; i++) {
left = line[i - colorsPerPixel] || 0;
up = prevLine && prevLine[i] || 0;
result[i + 1] = (line[i] + 0x0100 - ((left + up) >>> 1)) & 0xff;
}
return result;
}
, filterPaeth = function(line, colorsPerPixel, prevLine) {
var result = [],
i = 0,
len = line.length,
left,
up,
upLeft,
paeth;
result[0] = 4;
for(; i < len; i++) {
left = line[i - colorsPerPixel] || 0;
up = prevLine && prevLine[i] || 0;
upLeft = prevLine && prevLine[i - colorsPerPixel] || 0;
paeth = paethPredictor(left, up, upLeft);
result[i + 1] = (line[i] - paeth + 0x0100) & 0xff;
}
return result;
}
,paethPredictor = function(left, up, upLeft) {
var p = left + up - upLeft,
pLeft = Math.abs(p - left),
pUp = Math.abs(p - up),
pUpLeft = Math.abs(p - upLeft);
return (pLeft <= pUp && pLeft <= pUpLeft) ? left : (pUp <= pUpLeft) ? up : upLeft;
}
, getFilterMethods = function() {
return [filterNone, filterSub, filterUp, filterAverage, filterPaeth];
}
,getIndexOfSmallestSum = function(arrays) {
var i = 0,
len = arrays.length,
sum, min, ind;
while(i < len) {
sum = absSum(arrays[i].slice(1));
if(sum < min || !min) {
min = sum;
ind = i;
}
i++;
}
return ind;
}
, absSum = function(array) {
var i = 0,
len = array.length,
sum = 0;
while(i < len)
sum += Math.abs(array[i++]);
return sum;
}
, getPredictorFromCompression = function (compression) {
var predictor;
switch (compression) {
case jsPDFAPI.image_compression.FAST:
predictor = 11;
break;
case jsPDFAPI.image_compression.MEDIUM:
predictor = 13;
break;
case jsPDFAPI.image_compression.SLOW:
predictor = 14;
break;
default:
predictor = 12;
break;
}
return predictor;
}
, logImg = function(img) {
console.log("width: " + img.width);
console.log("height: " + img.height);
console.log("bits: " + img.bits);
console.log("colorType: " + img.colorType);
console.log("transparency:");
console.log(img.transparency);
console.log("text:");
console.log(img.text);
console.log("compressionMethod: " + img.compressionMethod);
console.log("filterMethod: " + img.filterMethod);
console.log("interlaceMethod: " + img.interlaceMethod);
console.log("imgData:");
console.log(img.imgData);
console.log("palette:");
console.log(img.palette);
console.log("colors: " + img.colors);
console.log("colorSpace: " + img.colorSpace);
console.log("pixelBitlength: " + img.pixelBitlength);
console.log("hasAlphaChannel: " + img.hasAlphaChannel);
};
jsPDFAPI.processPNG = function(imageData, imageIndex, alias, compression, dataAsBinaryString) {
'use strict'
var colorSpace = this.color_spaces.DEVICE_RGB,
decode = this.decode.FLATE_DECODE,
bpc = 8,
img, dp, trns,
colors, pal, smask;
/* if(this.isString(imageData)) {
}*/
if(this.isArrayBuffer(imageData))
imageData = new Uint8Array(imageData);
if(this.isArrayBufferView(imageData)) {
if(doesNotHavePngJS())
throw new Error("PNG support requires png.js and zlib.js");
img = new PNG(imageData);
imageData = img.imgData;
bpc = img.bits;
colorSpace = img.colorSpace;
colors = img.colors;
//logImg(img);
/*
* colorType 6 - Each pixel is an R,G,B triple, followed by an alpha sample.
*
* colorType 4 - Each pixel is a grayscale sample, followed by an alpha sample.
*
* Extract alpha to create two separate images, using the alpha as a sMask
*/
if([4,6].indexOf(img.colorType) !== -1) {
/*
* processes 8 bit RGBA and grayscale + alpha images
*/
if(img.bits === 8) {
var pixels = img.pixelBitlength == 32 ? new Uint32Array(img.decodePixels().buffer) : img.pixelBitlength == 16 ? new Uint16Array(img.decodePixels().buffer) : new Uint8Array(img.decodePixels().buffer),
len = pixels.length,
imgData = new Uint8Array(len * img.colors),
alphaData = new Uint8Array(len),
pDiff = img.pixelBitlength - img.bits,
i = 0, n = 0, pixel, pbl;
for(; i < len; i++) {
pixel = pixels[i];
pbl = 0;
while(pbl < pDiff) {
imgData[n++] = ( pixel >>> pbl ) & 0xff;
pbl = pbl + img.bits;
}
alphaData[i] = ( pixel >>> pbl ) & 0xff;
}
}
/*
* processes 16 bit RGBA and grayscale + alpha images
*/
if(img.bits === 16) {
var pixels = new Uint32Array(img.decodePixels().buffer),
len = pixels.length,
imgData = new Uint8Array((len * (32 / img.pixelBitlength) ) * img.colors),
alphaData = new Uint8Array(len * (32 / img.pixelBitlength) ),
hasColors = img.colors > 1,
i = 0, n = 0, a = 0, pixel;
while(i < len) {
pixel = pixels[i++];
imgData[n++] = (pixel >>> 0) & 0xFF;
if(hasColors) {
imgData[n++] = (pixel >>> 16) & 0xFF;
pixel = pixels[i++];
imgData[n++] = (pixel >>> 0) & 0xFF;
}
alphaData[a++] = (pixel >>> 16) & 0xFF;
}
bpc = 8;
}
if(canCompress(compression)) {
imageData = compressBytes(imgData, img.width * img.colors, img.colors, compression);
smask = compressBytes(alphaData, img.width, 1, compression);
}else{
imageData = imgData;
smask = alphaData;
decode = null;
}
}
/*
* Indexed png. Each pixel is a palette index.
*/
if(img.colorType === 3) {
colorSpace = this.color_spaces.INDEXED;
pal = img.palette;
if(img.transparency.indexed) {
var trans = img.transparency.indexed;
var total = 0,
i = 0,
len = trans.length;
for(; i<len; ++i)
total += trans[i];
total = total / 255;
/*
* a single color is specified as 100% transparent (0),
* so we set trns to use a /Mask with that index
*/
if(total === len - 1 && trans.indexOf(0) !== -1) {
trns = [trans.indexOf(0)];
/*
* there's more than one colour within the palette that specifies
* a transparency value less than 255, so we unroll the pixels to create an image sMask
*/
}else if(total !== len){
var pixels = img.decodePixels(),
alphaData = new Uint8Array(pixels.length),
i = 0,
len = pixels.length;
for(; i < len; i++)
alphaData[i] = trans[pixels[i]];
smask = compressBytes(alphaData, img.width, 1);
}
}
}
var predictor = getPredictorFromCompression(compression);
if(decode === this.decode.FLATE_DECODE)
dp = '/Predictor '+ predictor +' /Colors '+ colors +' /BitsPerComponent '+ bpc +' /Columns '+ img.width;
else
//remove 'Predictor' as it applies to the type of png filter applied to its IDAT - we only apply with compression
dp = '/Colors '+ colors +' /BitsPerComponent '+ bpc +' /Columns '+ img.width;
if(this.isArrayBuffer(imageData) || this.isArrayBufferView(imageData))
imageData = this.arrayBufferToBinaryString(imageData);
if(smask && this.isArrayBuffer(smask) || this.isArrayBufferView(smask))
smask = this.arrayBufferToBinaryString(smask);
return this.createImageInfo(imageData, img.width, img.height, colorSpace,
bpc, decode, imageIndex, alias, dp, trns, pal, smask, predictor);
}
throw new Error("Unsupported PNG image data, try using JPEG instead.");
}
})(jsPDF.API);