2013-08-18 38 views
6

Có thể bằng cách nào đó để kết hợp hình ảnh PNG với hình ảnh động APNG bằng cách sử dụng nút jj không?Tham gia hình ảnh PNG lên hình ảnh động APNG

tôi đã tìm thấy PHP chỉ thư viện: link

+0

Tôi nghĩ rằng bạn sẽ tìm thấy những gì bạn cần trên wikipedia dưới phần Hỗ trợ ứng dụng: http://en.wikipedia.org/wiki/APNG#Application_support –

Trả lời

2

Tôi không chắc chắn về nodejs, nhưng bạn có thể thử APNG-canvas. APNG sử dụng HTML5 (-webkit-canvas), JavaScript (jQuery).

"APNG-canvas là thư viện để chuyển các tệp PNG hoạt ảnh trong trình duyệt bằng hỗ trợ canvas (Google Chrome, Internet Explorer 9, Apple Safari)."

Làm việc demo có tại đây.

+1

Thư viện này không hỗ trợ tạo file APNG. – 1j01

3

Currently, không giống như vậy. Wikipedia lists the available software và bạn có thể thấy không có hỗ trợ cho ImageMagick có trình bao bọc nút. Tuy nhiên, bạn có thể thấy rằng bạn có thể tải xuống command line tool apngasm và loại bỏ nó, nếu bạn thấy nó đáng giá trong khi có các trình bao bọc dòng lệnh Nút để móc ứng dụng này vào ứng dụng hiện có bằng cách sử dụng child_process (http://nodejs.org/api/child_process.html).

2

Không có thư viện cho điều đó, nhưng thực hiện khá đơn giản. Thuật toán cho việc sáp nhập nhiều file PNG vào đơn APNG được mô tả trong Wikipedia:

  1. Mang tất cả những phần của tệp PNG đầu tiên làm cơ sở xây dựng.
  2. Chèn đoạn điều khiển hoạt ảnh (acTL) sau đoạn tiêu đề hình ảnh (IHDR).
  3. Nếu PNG đầu tiên là một phần của hoạt ảnh, hãy chèn đoạn điều khiển khung (fcTL) trước đoạn dữ liệu hình ảnh (IDAT).
  4. Đối với mỗi khung còn lại, thêm đoạn điều khiển khung (fcTL) và khung dữ liệu khung (fdAT). Sau đó, thêm đoạn cuối hình ảnh (IEND). Nội dung cho các khối dữ liệu khung (fdAT) được lấy từ các khối dữ liệu hình ảnh (IDAT) của các hình ảnh nguồn tương ứng của chúng.

Đây là một thực hiện ví dụ:

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 có thể phân tích và xây dựng các file APNG - https://github.com/photopea/UPNG.js

Từ readme -

UPNG. js hỗ trợ APNG và giao diện mong đợi "khung".

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 có thể làm một việc rút gọn lossy các tập tin PNG, tương tự như TinyPNG và các công cụ khác. Nó thực hiện lượng tử hóa màu bằng cách sử dụng thuật toán k-means .

Nén tổn hao được phép bởi thông số cnum cuối cùng. Đặt nó thành 0 để nén không mất dữ liệu hoặc ghi số màu được phép vào hình ảnh. Giá trị nhỏ hơn tạo ra các tệp nhỏ hơn.Hoặc chỉ cần sử dụng 0 cho lossless/256 cho lossy.

Các vấn đề liên quan