将多个 png 转换为 bmp,从 stdin 到 stdout

convert multiple pngs to bmps from stdin to stdout

我需要将来自 chrome-headless 的 PNG 转换为 BMP 才能使用它们,我还需要 通过管道而不将这些图像保存在某处。

Chrome 设置为仅将图像截屏到标准输出,工作正常,但我似乎无法使用 imagemagick 转换工具来执行我需要的操作。

在使用

进行测试时
cat foo.png | convert PNG:- BMP:-

似乎对一张输入图像有效(输出以'BM'开头,表示BMP二进制垃圾),

cat foo.png bar.png | convert PNG:- BMP:-

也returns只有一张图,好像是第一张。

如何将它通过标准输入读取的每个文件的输出转换为 "overwrite"?


编辑:猫的例子只是为了演示输入。最终的想法更像是

chrome-headless | *solution* | bmpreader

正如 fmw42 和 Mark 所指出的,开箱即用的 imagemagick 似乎无法做到这一点。

我认为您无法同时使用包含多个图像的管道来做到这一点。您可以遍历每个 png 图像并使用您的管道。管道将保留显示 png 后缀的图像,但实际上将是 bmp 文件。但这让我感到困惑。

在 Imagemagick 中,如果您想将一个文件夹的文件从一种格式转换为另一种格式,那么您应该只使用 mogrify。假设您的图像在 folder1 中,您希望将它们保存到已存在的 folder2 中。然后你可以将目录更改为 folder1 然后执行:

mogrify -format bmp -path path2/folder2 *.png

这将保留输入名称,但在转换为该后缀类型时更改后缀。

Convert 只能有一个输出名称,可能与您的输入之一相同。它不能写入多个输出名称。如果输出格式支持图层或页面,则输出的名称将包含 layers/pages,否则将为 XXX-1.bmp ... XXX-n.bmp,其中 XXX 是输出名称通过

convert image1.png image2.png ... imageN.png newimage.suffix

但是,您可以在脚本循环中执行此操作。但是 mogrify 更容易。

正如 Fred (@fmw42) 所说,你不能单独使用 ImageMagick 来做到这一点,但是应该可以用一个小的 C/C++ 来做一些事情, Perl,PHP 或 Python 脚本。

基本上,PNG 文件很好 "chunked",参见 Wikipedia PNG Specification,每个块都有一个类型 - 例如 IHDR(header)、PLTE(调色板)、IDAT(图像数据)、IEND(文件结束标记)以及至关重要的字节长度。

因此,您可以编写一个 script/program 从您的管道中读取数据,获取块并将它们附加到 in-memory 字符串并继续这样做直到它到达 IEND块。那时它会使用 ImageMagickGDPillow 来转换 in-memory将字符串写入 BMP 并将其写入另一个管道,或者将字符串写入 ImageMagick 正在读取的管道并让 ImageMagick 转换文件.然后,您会将累积的 (PNG) 字符串清零并开始读取下一个文件。

我不想为了 15 分而编写和调试所有这些内容,但它看起来像这样:

chrome-cast | demultiplex

其中 demultiplex 会像:

while not error
   clear accumulated string of PNG data
   done = false
   while not done
      read chunk type and length of chunk
      read whole chunk and append to accumulated string of PNG data
      if chunk = IEND
         pass accumulated PNG string to ImageMagick to make BMP
         done = true
      endif
   end
end

请注意,您的程序不必 "understand" 所有块类型或其内容 - 只需识别块长度和 IEND 块它到了。


请注意,您可能希望 运行 pngcheckpngsplit 开始了解 PNG 文件的块结构 - 它们是 here。事实上,pngsplit可能会如你所愿。

这里是 pngcheck 的一个例子:

pngcheck -v file.png

File: file.png (462308 bytes)
  chunk IHDR at offset 0x0000c, length 13
    800 x 468 image, 32-bit RGB+alpha, non-interlaced
  chunk gAMA at offset 0x00025, length 4: 0.45455
  chunk cHRM at offset 0x00035, length 32
    White x = 0.3127 y = 0.329,  Red x = 0.64 y = 0.33
    Green x = 0.3 y = 0.6,  Blue x = 0.15 y = 0.06
  chunk bKGD at offset 0x00061, length 6
    red = 0x00ff, green = 0x00ff, blue = 0x00ff
  chunk pHYs at offset 0x00073, length 9: 3779x3779 pixels/meter (96 dpi)
  chunk tIME at offset 0x00088, length 7:  2 Oct 2017 21:34:26 UTC
  chunk IDAT at offset 0x0009b, length 32768
    zlib: deflated, 32K window, maximum compression
  chunk IDAT at offset 0x080a7, length 32768
  chunk IDAT at offset 0x100b3, length 32768
  chunk IDAT at offset 0x180bf, length 32768
  chunk IDAT at offset 0x200cb, length 32768
  chunk IDAT at offset 0x280d7, length 32768
  chunk IDAT at offset 0x300e3, length 32768
  chunk IDAT at offset 0x380ef, length 32768
  chunk IDAT at offset 0x400fb, length 32768
  chunk IDAT at offset 0x48107, length 32768
  chunk IDAT at offset 0x50113, length 32768
  chunk IDAT at offset 0x5811f, length 32768
  chunk IDAT at offset 0x6012b, length 32768
  chunk IDAT at offset 0x68137, length 32768
  chunk IDAT at offset 0x70143, length 3115
  chunk tEXt at offset 0x70d7a, length 37, keyword: date:create
  chunk tEXt at offset 0x70dab, length 37, keyword: date:modify
  chunk IEND at offset 0x70ddc, length 0
No errors detected in file.png (24 chunks, 69.1% compression).

我在 Perl 中做了一个基本版本的 PNG 分块以获得另一个答案,所以快速看一下 here