2013-08-18 4 views
6

È possibile unire in qualche modo immagini PNG a un'immagine animata APNG utilizzando nodejs?Unisci immagini PNG a un'immagine animata APNG

ho trovato libreria PHP solo: link

+0

penso che troverete quello che vi serve su Wikipedia sotto la sezione Application Support: http://en.wikipedia.org/wiki/APNG#Application_support –

risposta

2

io non sono sicuro di nodejs, ma si potrebbe provare APNG-canvas. APNG utilizza HTML5 (-webkit-canvas), JavaScript (jQuery).

"APNG-canvas è una libreria per la visualizzazione di file PNG animati nei browser con supporto canvas (Google Chrome, Internet Explorer 9, Apple Safari)."

Lavoro demo è qui.

+1

Questa libreria non supporta la creazione di file APNG. – 1j01

2

Non esiste una libreria per questo, ma è abbastanza semplice da implementare. Algoritmo per la fusione di più file PNG in un'unica APNG è descritto in Wikipedia:

  1. adottare tutti pezzi del primo file PNG come base dell'edificio.
  2. Inserire un blocco di controllo animazione (acTL) dopo il frammento di intestazione dell'immagine (IHDR).
  3. Se il primo PNG deve far parte dell'animazione, inserire un blocco di controllo del frame (fcTL) prima del blocco dei dati di immagine (IDAT).
  4. Per ciascuno dei fotogrammi rimanenti, aggiungere un blocco di controllo del frame (fcTL) e un blocco di dati del frame (fdAT). Quindi aggiungere il pezzo finale dell'immagine (IEND). Il contenuto per i blocchi di dati del frame (fdAT) viene ricavato dai blocchi di dati di immagine (IDAT) delle rispettive immagini di origine.

Ecco un esempio di implementazione:

const fs = require('fs') 
const crc32 = require('crc').crc32 

function findChunk(buffer, type) { 
    let offset = 8 

    while (offset < buffer.length) { 
    let chunkLength = buffer.readUInt32BE(offset) 
    let chunkType = buffer.slice(offset + 4, offset + 8).toString('ascii') 

    if (chunkType === type) { 
     return buffer.slice(offset, offset + chunkLength + 12) 
    } 

    offset += 4 + 4 + chunkLength + 4 
    } 

    throw new Error(`Chunk "${type}" not found`) 
} 

const images = process.argv.slice(2).map(path => fs.readFileSync(path)) 

const actl = Buffer.alloc(20) 
actl.writeUInt32BE(8, 0)         // length of chunk 
actl.write('acTL', 4)          // type of chunk 
actl.writeUInt32BE(images.length, 8)      // number of frames 
actl.writeUInt32BE(0, 12)         // number of times to loop (0 - infinite) 
actl.writeUInt32BE(crc32(actl.slice(4, 16)), 16)   // crc 

const frames = images.map((data, idx) => { 
    const ihdr = findChunk(data, 'IHDR') 

    const fctl = Buffer.alloc(38) 
    fctl.writeUInt32BE(26, 0)         // length of chunk 
    fctl.write('fcTL', 4)          // type of chunk 
    fctl.writeUInt32BE(idx ? idx * 2 - 1 : 0, 8)    // sequence number 
    fctl.writeUInt32BE(ihdr.readUInt32BE(8), 12)    // width 
    fctl.writeUInt32BE(ihdr.readUInt32BE(12), 16)    // height 
    fctl.writeUInt32BE(0, 20)         // x offset 
    fctl.writeUInt32BE(0, 24)         // y offset 
    fctl.writeUInt16BE(1, 28)         // frame delay - fraction numerator 
    fctl.writeUInt16BE(1, 30)         // frame delay - fraction denominator 
    fctl.writeUInt8(0, 32)         // dispose mode 
    fctl.writeUInt8(0, 33)         // blend mode 
    fctl.writeUInt32BE(crc32(fctl.slice(4, 34)), 34)   // crc 

    const idat = findChunk(data, 'IDAT') 

    // All IDAT chunks except first one are converted to fdAT chunks 
    let fdat; 

    if (idx === 0) { 
    fdat = idat 
    } else { 
    const length = idat.length + 4 

    fdat = Buffer.alloc(length) 

    fdat.writeUInt32BE(length - 12, 0)      // length of chunk 
    fdat.write('fdAT', 4)         // type of chunk 
    fdat.writeUInt32BE(idx * 2, 8)       // sequence number 
    idat.copy(fdat, 12, 8)         // image data 
    fdat.writeUInt32BE(crc32(4, length - 4), length - 4) // crc 
    } 

    return Buffer.concat([ fctl, fdat ]) 
}) 

const signature = Buffer.from('\211PNG\r\n\032\n', 'ascii') 
const ihdr = findChunk(images[0], 'IHDR') 
const iend = Buffer.from('0000000049454e44ae426082', 'hex') 

const output = Buffer.concat([ signature, ihdr, actl, ...frames, iend ]) 

fs.writeFileSync('output.png', output) 
0

UPNG.js in grado di analizzare e costruire i file APNG - https://github.com/photopea/UPNG.js

Dal readme -

UPNG. js supporta APNG e l'interfaccia si aspetta "frame".

UPNG.encode (IMG, w, h, cnum, [dels])

imgs: array of frames. A frame is an ArrayBuffer containing the pixel 
     data (RGBA, 8 bits per channel) 
w, h : width and height of the image 
cnum: number of colors in the result; 0: all colors (lossless PNG) 
dels: array of delays for each frame (only when 2 or more frames) 
returns an ArrayBuffer with binary data of a PNG file 

UPNG.js può fare una minimizzazione lossy di file PNG, simili a TinyPNG e altri strumenti. Esegue la quantizzazione del colore usando l'algoritmo k-means .

La compressione loss è consentita dall'ultimo parametro cnum. Impostalo su zero per una compressione senza perdita di dati oppure scrivi il numero di colori consentiti nell'immagine. Valori più piccoli producono file più piccoli.Oppure usa 0 per senza perdita/256 per perdita.