const fs = require('fs'); const path = require("path"); const moment = require('moment'); const Jimp = require("jimp"); /** * download ttf font => https://www.fontspace.com/search?q=open%20sans * load custom font on jimp => https://github.com/oliver-moran/jimp/issues/375 * convert ttf to (fnt,png) => https://github.com/oliver-moran/jimp/issues/1002 => https://ttf2fnt.com/ * neon color palette => https://icolorpalette.com/color/neon-green * reference => https://libgdx.com/wiki/graphics/2d/fonts/bitmap-fonts */ const FONT_OPEN_SANS_NEON_100 = path.resolve(__dirname, '../files/public/OpenSans-B9K8.ttf_neon_100/neon_100.fnt'); const FONT_OPEN_SANS_NEON_64 = path.resolve(__dirname, '../files/public/OpenSans-B9K8.ttf_neon_64/neon_64.fnt'); const FONT_OPEN_SANS_NEON_32 = path.resolve(__dirname, '../files/public/OpenSans-B9K8.ttf_neon_32/neon_32.fnt'); const FONT_OPEN_SANS_NEON_16 = path.resolve(__dirname, '../files/public/OpenSans-B9K8.ttf_neon_16/neon_16.fnt'); class LibImgGeotagging { static create(tempFileName = '', tempFileNamePath = '', photo = 'base64', { fulladdress, lat, lng, photo_at }) { return new Promise(async (resolve, reject) => { try { const JimpLoadedFile = await Jimp.read(Buffer.from(photo.replace(/^data:(image|application)\/(png|jpg|jpeg);base64,/, ''), 'base64')); JimpLoadedFile.quality(60); fulladdress = (fulladdress) ? decodeURIComponent(fulladdress) : null; let theAddr = fulladdress || ''; let text = moment.unix(photo_at).format('DD MMMM YYYY HH:mm:ss') + ' WIB' + ' ' + lat + ',' + lng + ' ' + theAddr; let startX = 10; let startY = 10; // example 00 // const JimpLoadFont = await Jimp.loadFont(Jimp.FONT_SANS_64_WHITE); // await JimpLoadedFile // // .print(JimpLoadFont, startX, JimpLoadedFile.bitmap.height-450, { text }, JimpLoadedFile.bitmap.width) // .print(JimpLoadFont, startX, startY, { text, alignmentX: Jimp.HORIZONTAL_ALIGN_LEFT, alignmentY: Jimp.VERTICAL_ALIGN_BOTTOM }, JimpLoadedFile.bitmap.width * 75 / 100, JimpLoadedFile.bitmap.height) // // .print(JimpLoadFont, startX, startY, { text: moment.unix(photo_at).format('YYYY-MM-DD HH:mm:ss') + ' WIB', alignmentX: Jimp.HORIZONTAL_ALIGN_LEFT, alignmentY: Jimp.VERTICAL_ALIGN_BOTTOM }, JimpLoadedFile.bitmap.width, JimpLoadedFile.bitmap.height) // // .print(JimpLoadFont, startX, startY, { text: '' + lat + ',' + lng, alignmentX: Jimp.HORIZONTAL_ALIGN_LEFT, alignmentY: Jimp.VERTICAL_ALIGN_BOTTOM }, JimpLoadedFile.bitmap.width, JimpLoadedFile.bitmap.height) // // .print(JimpLoadFont, startX, startY, { text: `${theAddr}`, alignmentX: Jimp.HORIZONTAL_ALIGN_LEFT, alignmentY: Jimp.VERTICAL_ALIGN_BOTTOM }, JimpLoadedFile.bitmap.width, JimpLoadedFile.bitmap.height) // .writeAsync(tempFileNamePath); // example with set background with opacity 01 // const imgBg = Buffer.from(fs.readFileSync(path.resolve(__dirname, '../files/public/img_white_bg.png'))).toString('base64'); // const JimpImgBg = await Jimp.read(Buffer.from(imgBg.replace(/^data:(image|application)\/(png|jpg|jpeg);base64,/, ''), 'base64')); // const JimpLoadFont = (JimpLoadedFile.bitmap.height > 1000) ? await Jimp.loadFont(Jimp.FONT_SANS_32_BLACK) : await Jimp.loadFont(Jimp.FONT_SANS_32_BLACK); // await JimpLoadedFile // .composite(JimpImgBg, 0, JimpLoadedFile.bitmap.height-200, { mode: Jimp.BLEND_SOURCE_OVER, opacitySource: 0.5, opacityDest: 1 }) // .print(JimpLoadFont, startX, startY, { text, alignmentX: Jimp.HORIZONTAL_ALIGN_LEFT, alignmentY: Jimp.VERTICAL_ALIGN_BOTTOM }, JimpLoadedFile.bitmap.width * percent / 100, JimpLoadedFile.bitmap.height) // .writeAsync(tempFileNamePath); // write geotagging based on size // https://www.pixel.web.id/ukuran-foto-sesuai-standar/ // font color => https://www.fontspace.com/search?q=open%20sans /** * kalo height <= 600px maka metode maka jadikan satu baru menggunakan alignmentX dan Y * kalo height > 600px maka metode print pecah jadi 3 baris dan pake minus(-) di startY, misal -300 -200 -100 */ console.log('image width => ', JimpLoadedFile.bitmap.width, ' || ', 'image height => ', JimpLoadedFile.bitmap.height); const percent = (JimpLoadedFile.bitmap.height > 1000) ? 75 : 50; if (JimpLoadedFile.bitmap.width > 3000) { startY = -10; const JimpLoadFont = (JimpLoadedFile.bitmap.height > 1000) ? await Jimp.loadFont(FONT_OPEN_SANS_NEON_100) : await Jimp.loadFont(FONT_OPEN_SANS_NEON_64); await JimpLoadedFile .print(JimpLoadFont, startX, startY, { text, alignmentX: Jimp.HORIZONTAL_ALIGN_LEFT, alignmentY: Jimp.VERTICAL_ALIGN_BOTTOM }, JimpLoadedFile.bitmap.width * percent / 100, JimpLoadedFile.bitmap.height) .writeAsync(tempFileNamePath); } else if (JimpLoadedFile.bitmap.width > 2400) { startY = -10; const JimpLoadFont = (JimpLoadedFile.bitmap.height > 1000) ? await Jimp.loadFont(FONT_OPEN_SANS_NEON_64) : await Jimp.loadFont(FONT_OPEN_SANS_NEON_64); await JimpLoadedFile .print(JimpLoadFont, startX, startY, { text, alignmentX: Jimp.HORIZONTAL_ALIGN_LEFT, alignmentY: Jimp.VERTICAL_ALIGN_BOTTOM }, JimpLoadedFile.bitmap.width * percent / 100, JimpLoadedFile.bitmap.height) .writeAsync(tempFileNamePath); } else if (JimpLoadedFile.bitmap.width > 2100) { startY = -10; const JimpLoadFont = (JimpLoadedFile.bitmap.height > 1000) ? await Jimp.loadFont(FONT_OPEN_SANS_NEON_64) : await Jimp.loadFont(FONT_OPEN_SANS_NEON_64); await JimpLoadedFile .print(JimpLoadFont, startX, startY, { text, alignmentX: Jimp.HORIZONTAL_ALIGN_LEFT, alignmentY: Jimp.VERTICAL_ALIGN_BOTTOM }, JimpLoadedFile.bitmap.width * percent / 100, JimpLoadedFile.bitmap.height) .writeAsync(tempFileNamePath); } else if (JimpLoadedFile.bitmap.width > 1800) { // done testing startY = -10; const JimpLoadFont = (JimpLoadedFile.bitmap.height > 1000) ? await Jimp.loadFont(FONT_OPEN_SANS_NEON_64) : await Jimp.loadFont(FONT_OPEN_SANS_NEON_32); await JimpLoadedFile .print(JimpLoadFont, startX, startY, { text, alignmentX: Jimp.HORIZONTAL_ALIGN_LEFT, alignmentY: Jimp.VERTICAL_ALIGN_BOTTOM }, JimpLoadedFile.bitmap.width * percent / 100, JimpLoadedFile.bitmap.height) .writeAsync(tempFileNamePath); } else if (JimpLoadedFile.bitmap.width > 1650) { startY = -10; const JimpLoadFont = (JimpLoadedFile.bitmap.height > 1000) ? await Jimp.loadFont(FONT_OPEN_SANS_NEON_32) : await Jimp.loadFont(FONT_OPEN_SANS_NEON_32); await JimpLoadedFile .print(JimpLoadFont, startX, startY, { text, alignmentX: Jimp.HORIZONTAL_ALIGN_LEFT, alignmentY: Jimp.VERTICAL_ALIGN_BOTTOM }, JimpLoadedFile.bitmap.width * percent / 100, JimpLoadedFile.bitmap.height) .writeAsync(tempFileNamePath); } else if (JimpLoadedFile.bitmap.width > 1500) { startY = -10; const JimpLoadFont = (JimpLoadedFile.bitmap.height > 1000) ? await Jimp.loadFont(FONT_OPEN_SANS_NEON_32) : await Jimp.loadFont(FONT_OPEN_SANS_NEON_32); await JimpLoadedFile .print(JimpLoadFont, startX, startY, { text, alignmentX: Jimp.HORIZONTAL_ALIGN_LEFT, alignmentY: Jimp.VERTICAL_ALIGN_BOTTOM }, JimpLoadedFile.bitmap.width * percent / 100, JimpLoadedFile.bitmap.height) .writeAsync(tempFileNamePath); } else if (JimpLoadedFile.bitmap.width > 1200) { startY = -10; const JimpLoadFont = (JimpLoadedFile.bitmap.height > 1000) ? await Jimp.loadFont(FONT_OPEN_SANS_NEON_32) : await Jimp.loadFont(FONT_OPEN_SANS_NEON_32); await JimpLoadedFile .print(JimpLoadFont, startX, startY, { text, alignmentX: Jimp.HORIZONTAL_ALIGN_LEFT, alignmentY: Jimp.VERTICAL_ALIGN_BOTTOM }, JimpLoadedFile.bitmap.width * percent / 100, JimpLoadedFile.bitmap.height) .writeAsync(tempFileNamePath); } else if (JimpLoadedFile.bitmap.width > 900) { // done testing startY = -10; const JimpLoadFont = (JimpLoadedFile.bitmap.height > 1000) ? await Jimp.loadFont(FONT_OPEN_SANS_NEON_32) : await Jimp.loadFont(FONT_OPEN_SANS_NEON_32); await JimpLoadedFile .print(JimpLoadFont, startX, startY, { text, alignmentX: Jimp.HORIZONTAL_ALIGN_LEFT, alignmentY: Jimp.VERTICAL_ALIGN_BOTTOM }, JimpLoadedFile.bitmap.width * percent / 100, JimpLoadedFile.bitmap.height) .writeAsync(tempFileNamePath); } else if (JimpLoadedFile.bitmap.width > 750) { // done testing startX = 8; startY = -8; const JimpLoadFont = (JimpLoadedFile.bitmap.height > 1000) ? await Jimp.loadFont(FONT_OPEN_SANS_NEON_32) : await Jimp.loadFont(FONT_OPEN_SANS_NEON_16); await JimpLoadedFile .print(JimpLoadFont, startX, startY, { text, alignmentX: Jimp.HORIZONTAL_ALIGN_LEFT, alignmentY: Jimp.VERTICAL_ALIGN_BOTTOM }, JimpLoadedFile.bitmap.width * percent / 100, JimpLoadedFile.bitmap.height) .writeAsync(tempFileNamePath); } else if (JimpLoadedFile.bitmap.width > 400) { startX = 5; startY = -5; const JimpLoadFont = (JimpLoadedFile.bitmap.height > 1000) ? await Jimp.loadFont(FONT_OPEN_SANS_NEON_16) : await Jimp.loadFont(FONT_OPEN_SANS_NEON_16); await JimpLoadedFile .print(JimpLoadFont, startX, startY, { text, alignmentX: Jimp.HORIZONTAL_ALIGN_LEFT, alignmentY: Jimp.VERTICAL_ALIGN_BOTTOM }, JimpLoadedFile.bitmap.width * percent / 100, JimpLoadedFile.bitmap.height) .writeAsync(tempFileNamePath); } else { startX = 5; startY = -5; const JimpLoadFont = (JimpLoadedFile.bitmap.height > 1000) ? await Jimp.loadFont(FONT_OPEN_SANS_NEON_16) : await Jimp.loadFont(FONT_OPEN_SANS_NEON_16); await JimpLoadedFile .print(JimpLoadFont, startX, startY, { text, alignmentX: Jimp.HORIZONTAL_ALIGN_LEFT, alignmentY: Jimp.VERTICAL_ALIGN_BOTTOM }, JimpLoadedFile.bitmap.width * percent / 100, JimpLoadedFile.bitmap.height) .writeAsync(tempFileNamePath); } resolve({type: 'sc'}); } catch (e) { reject({type: 'err', e}); } }); } } module.exports = LibImgGeotagging;