2013-08-18 7 views
6

Ist es irgendwie möglich, PNG-Bilder mit einem APNG-animierten Bild mit nodejs zu verbinden?PNG-Bilder an ein APNG-animiertes Bild anbinden

Ich habe nur PHP-Bibliothek gefunden: link

+0

Ich denke, Sie finden, was Sie auf wikipedia unter Application Support Abschnitt benötigen: http://en.wikipedia.org/wiki/APNG#Application_support –

Antwort

2

Ich bin über NodeJS nicht sicher, aber man konnte APNG-canvas versuchen. APNG verwendet HTML5 (-webkit-canvas), JavaScript (jQuery).

"APNG-Canvas ist eine Bibliothek zum Anzeigen animierter PNG-Dateien in Browsern mit Canvas-Unterstützung (Google Chrome, Internet Explorer 9, Apple Safari)."

Arbeiten demo ist hier.

+1

Diese Bibliothek nicht die Erstellung unterstützt APNG Dateien. – 1j01

3

Currently, nein, es sieht nicht so aus. Wikipedia lists the available software, und wie Sie sehen können, gibt es keine Unterstützung für ImageMagick, die einen Node-Wrapper hat. Sie können jedoch finden, dass Sie die command line tool apngasm herunterladen können und Shell, wenn Sie finden, es lohnt sich, während es Node-Befehlszeilen-Wrapper sind, um dies in eine vorhandene Anwendung mit child_process() zu haken.

2

Es gibt keine Bibliothek dafür, aber es ist ziemlich einfach zu implementieren.

  1. alle Stücke der ersten PNG-Datei als Gebäude Basis Nehmen: Algorithmus für mehr PNG-Dateien in einzelne APNG Verschmelzung wird in Wikipedia beschrieben.
  2. Fügen Sie einen Animationssteuerungsabschnitt (acTL) nach dem Bildkopfabschnitt (IHDR) ein.
  3. Wenn das erste PNG Teil der Animation sein soll, fügen Sie einen Frame Control Chunk (fcTL) vor dem Image Data Chunk (IDAT) ein.
  4. Fügen Sie für jeden der verbleibenden Rahmen einen Rahmensteuerungsabschnitt (fcTL) und einen Rahmendatenabschnitt (fdAT) hinzu. Fügen Sie dann das Bildende-Chunk (IEND) hinzu. Der Inhalt für die Rahmendatenabschnitte (fdAT) wird aus den Bilddatenabschnitten (IDAT) ihrer jeweiligen Quellbilder entnommen.

Hier eine Beispielimplementierung:

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 können APNG Dateien analysieren und bauen - https://github.com/photopea/UPNG.js

Von der Readme -

UPNG. js unterstützt APNG und die Schnittstelle erwartet "frames".

UPNG.encode (imgs, 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 kann ein verlustbehaftetes minification von PNG-Dateien tun, ähnlich wie TinyPNG und andere Werkzeuge. Es führt eine Farbquantisierung unter Verwendung des k-means Algorithmus durch.

Die verlustbehaftete Komprimierung wird vom letzten Parameter cnum zugelassen. Stellen Sie es auf Null für eine verlustfreie Komprimierung oder schreiben Sie die Anzahl der zulässigen Farben in das Bild. Kleinere Werte erzeugen kleinere Dateien.Oder verwenden Sie einfach 0 für verlustfrei/256 für verlustbehaftet.