【问题标题】:Splitting APNG into png images with PHP使用 PHP 将 APNG 拆分为 png 图像
【发布时间】:2013-09-11 16:41:40
【问题描述】:

我有一个将动画 PNG 图像 (APNG) 拆分为帧的 php 代码,但出现了某种错误。该函数创建的图像无效(PHP 不会在 PHP imagecreatefrompng() 函数中返回图像资源(在 Firefox 浏览器中也不显示)。

James Holderness 引用 How can I split animated PNG with PHP? 中的函数

function splitapng($data) {
  $parts = array();

  // Save the PNG signature   
  $signature = substr($data, 0, 8);
  $offset = 8;
  $size = strlen($data);
  while ($offset < $size) {
    // Read the chunk length
    $length = substr($data, $offset, 4);
    $offset += 4;

    // Read the chunk type
    $type = substr($data, $offset, 4);
    $offset += 4;

    // Unpack the length and read the chunk data including 4 byte CRC
    $ilength = unpack('Nlength', $length);
    $ilength = $ilength['length'];
    $chunk = substr($data, $offset, $ilength+4); 
    $offset += $ilength+4;

    if ($type == 'IHDR')
      $header = $length . $type . $chunk;  // save the header chunk
    else if ($type == 'IEND')
      $end = $length . $type . $chunk;     // save the end chunk
    else if ($type == 'IDAT') 
      $parts[] = $length . $type . $chunk; // save the first frame
    else if ($type == 'fdAT') {
      // Animation frames need a bit of tweaking.
      // We need to drop the first 4 bytes and set the correct type.
      $length = pack('N', $ilength-4);
      $type = 'IDAT';
      $chunk = substr($chunk,4);
      $parts[] = $length . $type . $chunk;
    }
  }

  // Now we just add the signature, header, and end chunks to every part.
  for ($i = 0; $i < count($parts); $i++) {
    $parts[$i] = $signature . $header . $parts[$i] . $end;
  }

  return $parts;
}

零件的保存如下进行

$filename = 'example.png';

$handle = fopen($filename, 'rb');
$filesize = filesize($filename);
$data = fread($handle, $filesize);
fclose($handle);

$parts = splitapng($data);

for ($i = 0; $i < count($parts); $i++) {
  $handle = fopen("part-$i.png",'wb');
  fwrite($handle,$parts[$i]);
  fclose($handle);
}

我尝试修改标题但没有成功。请帮忙!

【问题讨论】:

    标签: php gd apng


    【解决方案1】:

    当您将块名称从 fdAT 更改为 IDAT 时,需要重新计算 CRC,并删除 4 个数据字节,以说明新的块名称和数据。

    【讨论】:

      【解决方案2】:

      我重写了splitapng(),因为必须重新计算 crc32。 现在可以使用了。

      function splitapng($data) {
        $parts = array();
      
        // Save the PNG signature   
        $signature = substr($data, 0, 8); 
        $offset = 8;
        $size = strlen($data);
        while ($offset < $size) {
          // Read the chunk length
          $length = substr($data, $offset, 4); 
          $offset += 4;
      
          // Read the chunk type
          $type = substr($data, $offset, 4); 
          $offset += 4;
      
          // Unpack the length and read the chunk data including 4 byte CRC
          $ilength = unpack('Nlength', $length);
          $ilength = $ilength['length'];
          $chunk = substr($data, $offset, $ilength+4); 
          $offset += $ilength+4;
      
          if ($type == 'IHDR')
            $header = $length . $type . $chunk;  // save the header chunk
          else if ($type == 'IEND')
            $end = $length . $type . $chunk;     // save the end chunk
          else if ($type == 'IDAT') 
            $parts[] = $length . $type . $chunk; // save the first frame
          else if ($type == 'fdAT') {
            // Animation frames need a bit of tweaking.
            // We need to drop the first 4 bytes and set the correct type.
            $length = pack('N', $ilength-4);
            $type = 'IDAT';
            // re-calc crc
            $chunk = substr($chunk,4,-4);
            $chunk .= hash('crc32b',$type.$chunk,true);
            $parts[] = $length . $type . $chunk;
          }   
        }
      
        // Now we just add the signature, header, and end chunks to every part.
        for ($i = 0; $i < count($parts); $i++) {
          $parts[$i] = $signature . $header . $parts[$i] . $end;
        }
      
        return $parts;
      }
      
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-08-20
        • 2019-01-12
        • 2018-04-16
        • 2011-06-16
        • 1970-01-01
        • 2013-11-14
        • 2010-10-18
        相关资源
        最近更新 更多