Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement POC for image embedding #509

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
74 changes: 71 additions & 3 deletions xlsx.js
Expand Up @@ -1255,7 +1255,7 @@ return exports;
if(typeof require !== 'undefined' && typeof module !== 'undefined' && typeof DO_NOT_EXPORT_CFB === 'undefined') { module.exports = CFB; }
function isval(x) { return x !== undefined && x !== null; }

function keys(o) { return Object.keys(o); }
function keys(o) { return o != null ? Object.keys(o) : []; }

function evert_key(obj, key) {
var o = [], K = keys(obj);
Expand Down Expand Up @@ -2435,6 +2435,8 @@ var CTYPE_XML_ROOT = writextag('Types', null, {

var CTYPE_DEFAULTS = [
['xml', 'application/xml'],
['png', 'image/png'],
['jpg', 'image/jpeg'],
['bin', 'application/vnd.ms-excel.sheet.binary.macroEnabled.main'],
['rels', type2ct.rels[0]]
].map(function(x) {
Expand Down Expand Up @@ -2476,6 +2478,7 @@ function write_ct(ct, opts) {
f3('themes');
['strs', 'styles'].forEach(f1);
['coreprops', 'extprops', 'custprops'].forEach(f3);
o[o.length] = '<Override PartName="/xl/drawings/drawing1.xml" ContentType="application/vnd.openxmlformats-officedocument.drawing+xml"/>';
if(o.length>2){ o[o.length] = ('</Types>'); o[1]=o[1].replace("/>",">"); }
return o.join("");
}
Expand Down Expand Up @@ -2529,6 +2532,39 @@ var RELS_ROOT = writextag('Relationships', null, {
'xmlns': XMLNS.RELS
});

var DRAW_ROOT = writextag('xdr:wsDr', null, {
'xmlns:xdr': 'http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing',
'xmlns:a': 'http://schemas.openxmlformats.org/drawingml/2006/main'
//'xmlns:ns0': XMLNS.RELS,
// 'xmlns': XMLNS.RELS
});

function write_drawing(images) {
var o = [];
o[o.length] = (XML_HEADER);
o[o.length] = (DRAW_ROOT);

for (var i = 0; i < images.length; i++) {
var image = images[i];
var pos = image.position || {};
if (pos.type === 'twoCellAnchor') {
var from = pos.from || {}, to = pos.to || {},
fromCol = from.col || 0, toCol = to.col || 0,
fromRow = from.row || 0, toRow = to.row || 0;

var twoCell = '<xdr:from><xdr:col>'+fromCol+'</xdr:col><xdr:colOff>0</xdr:colOff><xdr:row>'+fromRow+'</xdr:row><xdr:rowOff>0</xdr:rowOff></xdr:from>';
twoCell += '<xdr:to><xdr:col>'+toCol+'</xdr:col><xdr:colOff>0</xdr:colOff><xdr:row>'+toRow+'</xdr:row><xdr:rowOff>99999</xdr:rowOff></xdr:to>';
twoCell += '<xdr:pic><xdr:nvPicPr><xdr:cNvPr id="'+(i+1)+'" name="'+image.name+'">'
twoCell += '</xdr:cNvPr><xdr:cNvPicPr><a:picLocks noChangeAspect="1"/></xdr:cNvPicPr></xdr:nvPicPr>';
twoCell += '<xdr:blipFill><a:blip xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" r:embed="rId'+(i+1)+'"/>';
twoCell += '<a:stretch><a:fillRect/></a:stretch></xdr:blipFill><xdr:spPr><a:prstGeom prst="rect"><a:avLst/></a:prstGeom></xdr:spPr></xdr:pic><xdr:clientData/>';
o[o.length] = (writextag('xdr:twoCellAnchor', twoCell, images[i].attrs));
}
}

if(o.length>2){ o[o.length] = ('</xdr:wsDr>'); o[1]=o[1].replace("/>",">"); }
return o.join("");
}
/* TODO */
function write_rels(rels) {
var o = [];
Expand Down Expand Up @@ -4601,6 +4637,7 @@ function rgb_tint(hex, tint) {
var DEF_MDW = 7, MAX_MDW = 15, MIN_MDW = 1, MDW = DEF_MDW;
function width2px(width) { return (( width + ((128/MDW)|0)/256 )* MDW )|0; }
function px2char(px) { return (((px - 5)/MDW * 100 + 0.5)|0)/100; }
function px2pt(px) { return px * 72 / 96; }
function char2width(chr) { return (((chr * MDW + 5)/MDW*256)|0)/256; }
function cycle_width(collw) { return char2width(px2char(width2px(collw))); }
function find_mdw(collw, coll) {
Expand Down Expand Up @@ -7534,8 +7571,20 @@ function write_ws_xml_data(ws, opts, idx, wb) {
if(ws[ref] === undefined) continue;
if((cell = write_ws_xml_cell(ws[ref], ref, ws, opts, idx, wb)) != null) r.push(cell);
}
if(r.length > 0) o[o.length] = (writextag('row', r.join(""), {r:rr}));
}
if(r.length > 0) {
// 18.3.1.73 row
var params = {r:rr};
if(typeof ws['!rows'] !== 'undefined' && ws['!rows'].length > R) {
var row = ws['!rows'][R];
if (row.hidden) params.hidden = 1;
var height = -1;
if (row.hpx) height = px2pt(row.hpx);
else if (row.hpt) height = row.hpt;
if (height > -1) { params.ht = height; params.customHeight = 1; }
};
o[o.length] = (writextag('row', r.join(""), params));
}
}
return o.join("");
}

Expand All @@ -7562,6 +7611,9 @@ function write_ws_xml(idx, opts, wb) {

if(ws['!merges'] !== undefined && ws['!merges'].length > 0) o[o.length] = (write_ws_xml_merges(ws['!merges']));

var images = ws['!images'] || [];
if (images.length) o[o.length] = '<drawing r:id="rId1"/>';

if(o.length>2) { o[o.length] = ('</worksheet>'); o[1]=o[1].replace("/>",">"); }
return o.join("");
}
Expand Down Expand Up @@ -11277,6 +11329,9 @@ function add_rels(rels, rId, f, type, relobj) {
rels[('/' + relobj.Target).replace("//","/")] = relobj;
}

RELS.IMG = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";
RELS.DRAW = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing";

function write_zip(wb, opts) {
if(wb && !wb.SSF) {
wb.SSF = SSF.get_table();
Expand Down Expand Up @@ -11324,6 +11379,19 @@ function write_zip(wb, opts) {
add_rels(opts.rels, 1, f, RELS.WB);

for(rId=1;rId <= wb.SheetNames.length; ++rId) {
var s = wb.SheetNames[rId-1], ws = wb.Sheets[s],
images = ws['!images'] || [];
var rels = ws['!rels'] = [], draw_rels = [];
for (var sId=1; sId < images.length+1; ++sId) {
var image = images[sId - 1];
f = 'xl/media/' + image.name;
zip.file(f, image.data, image.opts);
add_rels(draw_rels, sId, "../media/" + image.name, RELS.IMG);
}
zip.file("xl/drawings/drawing" + rId + "." + wbext, write_drawing(images));
add_rels(rels, rId, "../drawings/drawing" + rId + "." + wbext, RELS.DRAW);
zip.file("xl/drawings/_rels/drawing" + rId + "." + wbext + ".rels", write_rels(draw_rels));
zip.file("xl/worksheets/_rels/sheet" + rId + "." + wbext + '.rels', write_rels(rels));
f = "xl/worksheets/sheet" + rId + "." + wbext;
zip.file(f, write_ws(rId-1, f, opts, wb));
ct.sheets.push(f);
Expand Down