Created
December 21, 2022 08:32
-
-
Save iamnotacoder-djs/5663a5ac2e501fdcb540fdf19a73e768 to your computer and use it in GitHub Desktop.
Add overlay to GIF file
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const gifFrames = require('gif-frames'); // @1.0.1 | |
const { createCanvas, loadImage } = require('canvas'); // @2.10.2 | |
const GifEncoder = require('gif-encoder'); // 0.4.3 | |
const fs = require("fs"); | |
convertBanner(); | |
async function convertBanner() { | |
const originalFrames = await gifFrames({ url: 'source.gif', frames: "all" }).catch(console.error); | |
if (!originalFrames) return; | |
// console.log(originalFrames[0]); // { getImage: [Function: getImage], frameIndex: 0, frameInfo: { x: 0, y: 0, width: 900, height: 540, has_local_palette: false, palette_offset: 13, palette_size: 256, data_offset: 890, data_length: 287127, transparent_index: null, interlaced: false, delay: 1, disposal: 0 } } | |
// return; | |
const canvasOverlay = createCanvas(originalFrames[0].frameInfo.width, originalFrames[0].frameInfo.height); | |
const contextOverlay = canvasOverlay.getContext('2d'); | |
const date = new Date(); | |
const targetDate = new Date(date.getFullYear(), 11, 31); | |
const remainingDays = Math.ceil( (targetDate.getTime() - date.getTime()) / (1000 * 60 * 60 * 24) ); | |
const message = `До Нового Года ${remainingDays} ${dayPlural(remainingDays)}`; | |
contextOverlay.textAlign = 'left'; | |
contextOverlay.font = `bold ${originalFrames[0].frameInfo.height * 0.1}px serif`; | |
contextOverlay.fillStyle = '#000'; | |
contextOverlay.fillText(message, 52, originalFrames[0].frameInfo.height * 0.9+2); | |
contextOverlay.fillStyle = '#fff'; | |
contextOverlay.fillText(message, 50, originalFrames[0].frameInfo.height * 0.9); | |
let frames = []; | |
for(let frame of originalFrames) { | |
const canvas = createCanvas(frame.frameInfo.width, frame.frameInfo.height); | |
const context = canvas.getContext('2d'); | |
const frameImage = await loadImage(frame.getImage()._obj).catch(console.error); | |
if (frameImage) { | |
context.drawImage(frameImage, 0, 0, frame.frameInfo.width, frame.frameInfo.height); | |
context.drawImage(canvasOverlay, 0, 0, frame.frameInfo.width, frame.frameInfo.height); | |
frames.push(context.getImageData(0, 0, frame.frameInfo.width, frame.frameInfo.height).data); | |
} | |
} | |
const gif = new GifEncoder(originalFrames[0].frameInfo.width, originalFrames[0].frameInfo.height, { highWaterMark: 50 * 1024 * 1024 }); // highWaterMark устанавливает лимит нашего внутреннего буфера для нашего потока GIFEncoder. Также есть метод read() — это один из способов вывода содержимого из внутреннего буфера, что освобождает место для большего количества кадров. | |
const buffers = []; | |
gif.on('data', data => buffers.push(data)); | |
gif.on('end', () => { | |
let file = Buffer.concat(buffers); | |
fs.writeFileSync('destination.gif', file); | |
// <Guild>.setBanner('./destination.gif').catch(console.error); | |
}) | |
gif.writeHeader(); | |
gif.setRepeat(0); | |
for(let frame of frames) { | |
gif.read(1024 * 1024 * 5); | |
gif.addFrame(frame); | |
} | |
gif.finish(); | |
} | |
function dayPlural(number) { | |
if (number > 10 && [11, 12, 13, 14].includes(number%100)) return 'дней'; | |
last_num = number%10; | |
if (last_num == 1) return 'день'; | |
if ([2,3,4].includes(last_num)) return 'дня'; | |
if ([5,6,7,8,9, 0].includes(last_num)) return 'дней'; | |
} |
Author
iamnotacoder-djs
commented
Dec 21, 2022
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment