var fs = require('fs'), PDFDocument = require('pdfkit'), async = require('async'), ColorThief = require('color-thief'), colorThief = new ColorThief(); var bookWidth = 430; var bookHeight = 343; var doc = new PDFDocument({ size: [bookWidth, bookHeight], margins: [0,0,0,0] }); doc.pipe(fs.createWriteStream('output.pdf')); var pageNumber = 1; var totalPages = 0; // Request json from cooper-hewitt api to ./json // Download images to ./images // Download the Cooper Hewitt font from // http://www.cooperhewitt.org/open-source-at-cooper-hewitt/cooper-hewitt-the-typeface-by-chester-jenkins/ // http://chfonts.s3.amazonaws.com/CooHew-TTF-v1p1-public.zip // Count the total number of pages for (i = 1; i <= 9; i++) { var myData = require('./json/'+i+'.json'); for (j = 0; j < myData.objects.length; j++) { if (typeof myData.objects[j].images !== 'undefined') { if (typeof myData.objects[j].images[0] !== 'undefined') { totalPages = totalPages + 1; } } } } // format total for cover page var totalPagesComma = totalPages.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); // Make cover page doc.lineWidth(25); doc.rect(0,0,bookWidth,bookHeight).fillAndStroke("black", "white").stroke(); doc.fillColor('white').font('./font/CooHew-Bold.ttf').fontSize(52).text('MATCHSAFE', 30, 30, { width: bookWidth, align: 'left' }); doc.fillColor('white').font('./font/CooHew-Bold.ttf').fontSize(18).text(totalPagesComma + ' OBJECTS FROM THE', 30, 100, { width: bookWidth, align: 'left' }); doc.fillColor('white').font('./font/CooHew-Bold.ttf').fontSize(18).text('COOPER-HEWITT COLLECTION', 30, 121, { width: bookWidth, align: 'left' }); // Make colophon doc.addPage(); doc.lineWidth(25); doc.rect(0,0,bookWidth,bookHeight).fillAndStroke("#eeeeee", "white").stroke(); doc.fillColor('black').font('./font/CooHew-Roman.ttf').fontSize(10).text('Compiled by John Emerson\nhttp://backspace.com\n\nfrom The Cooper-Hewitt API\nhttps://collection.cooperhewitt.org/api\n\nInspired by Irma Boom\nhttps://youtu.be/oHcEKNoDajk\n\nBook source code at\nhttps://gist.github.com/bcks/dd609677c6a6ffc426e9', 30, bookHeight / 2, { width: bookWidth, align: 'left' }); // Make object pages for (var i = 1; i <= 9; i++) { var myData = require('./json/'+i+'.json'); async.forEach(myData.objects, function(object, callback) { if (typeof object.images !== 'undefined') { if (typeof object.images[0] !== 'undefined') { var parts = object.images[0].b.url.split('/'); var popped = parts.pop(); console.log(pageNumber + ' ' + popped); var imagePath = 'images/' + popped; var img_width = object.images[0].b.width; var img_height = object.images[0].b.height; var xpad = 0; var ypad = 0; var dimension; var hex = '#000000'; // some images get padding, but if they are close to the page ratio, just fit to page and crop a little var ratioDifference = (bookWidth / bookHeight) - (img_width / img_height); if (ratioDifference < .3 && ratioDifference > -.3) { if ( ( bookWidth / bookHeight ) >= ( img_width / img_height ) ) { xpad = 0; ypad = ( bookHeight / 2 ) - ( img_height * ( bookWidth / img_width ) / 2 ); dimension = { width: bookWidth }; } else { var new_width = img_width / img_height * bookHeight; xpad = ( bookWidth / 2 ) - ( img_width * ( bookHeight / img_height ) / 2 ); ypad = 0; dimension = { width: new_width }; } } else { if ( ( bookWidth / bookHeight ) >= ( img_width / img_height ) ) { xpad = ( bookWidth / 2 ) - ( img_width * ( bookHeight / img_height ) / 2 ); dimension = { height: bookHeight }; } else { ypad = ( bookHeight / 2 ) - ( img_height * ( bookWidth / img_width ) / 2 ); dimension = { width: bookWidth }; } var image = fs.readFileSync(imagePath); var rgb = colorThief.getColor(image); var onecolor = require('onecolor'); var rgbCode = 'rgb( ' + rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ')'; // 'rgb(r, g, b)' hex = onecolor(rgbCode).hex(); } doc.addPage().rect(0,0,bookWidth,bookHeight).fill(hex).image(imagePath, xpad, ypad, dimension); // add URL for debugging // doc.fillColor("#000000").font('./font/CooHew-Roman.ttf').fontSize(7).text(popped, 0, 320, { width: (bookWidth - 20), align: 'left' }); // add page number doc.fillColor("#dddddd").font('./font/CooHew-Roman.ttf').fontSize(7).text(pageNumber, 0, 320, { width: (bookWidth - 20), align: 'right' }); pageNumber = pageNumber + 1; callback; } } }, function (err) { console.log(err); }); } // make Index doc.addPage(); var indexPageNumber = 1; var creditHeight = 40; var creditMargin = 20; var creditX = creditMargin; var numberPerPage = 16; doc.fillColor("#000000").font('./font/CooHew-Bold.ttf').fontSize(28).text('INDEX', creditX, creditMargin, { width: bookWidth / 2, align: 'left' }); for (var i = 1; i <= 9; i++) { var myData = require('./json/'+i+'.json'); async.forEach(myData.objects, function(object, callback) { if (typeof object.images !== 'undefined') { if (typeof object.images[0] !== 'undefined') { if (indexPageNumber % numberPerPage == 0) { // add page number doc.fillColor("#dddddd").font('./font/CooHew-Roman.ttf').fontSize(7).text(pageNumber, 0, 320, { width: (bookWidth - 20), align: 'right' }); pageNumber = pageNumber + 1; doc.addPage(); } if (indexPageNumber % numberPerPage < ( numberPerPage / 2) ) { creditX = creditMargin; } else { creditX = ( bookWidth / 2 ) + ( creditMargin / 2 ); } var creditY = ( ( indexPageNumber % ( numberPerPage / 2) ) * creditHeight ) + creditMargin; var credit = ''; credit += object.title + '. '; if (object.medium !== null) { credit += object.medium + '. '; } if (object.creditline !== null) { credit += object.creditline + '. '; } if (object.accession_number !== null) { credit += object.accession_number + '. '; } credit += "\n\n"; // Add page number doc.fillColor("#333333").font('./font/CooHew-Roman.ttf').fontSize(7).text(indexPageNumber, creditX, creditY, { width: 100, height: creditHeight, align: 'left' }); doc.fillColor("#333333").font('./font/CooHew-Roman.ttf').fontSize(7).text(credit, creditX + 24, creditY, { width: ( bookWidth / 2 ) - 50, height: creditHeight, align: 'left' }); indexPageNumber = indexPageNumber + 1; callback; } } }, function (err) { console.log(err); }); } // add last page number doc.fillColor("#dddddd").font('./font/CooHew-Roman.ttf').fontSize(7).text(pageNumber, 0, 320, { width: (bookWidth - 20), align: 'right' }); pageNumber = pageNumber + 1; // and print! doc.end();