代码之家  ›  专栏  ›  技术社区  ›  Til W.

如何在ImageMagick中指定自定义频道分发?

  •  0
  • Til W.  · 技术社区  · 3 年前

    我有一堆文件,不是例如RGB16,但基本上有一个自定义格式。

    该格式有16位,通道划分如下,我希望ImageMagick将其导入,然后将其导出为可读的常规RGBA格式(或者,将每个通道导出为单独的灰度文件)。

    第0-4位:红色

    第5-9位:绿色

    第10-12位:蓝色

    第13-15位:阿尔法

    所以基本上是5-5-3-3。

    Here 是一个压缩的示例文件,还包括想要的输出(PNG)。 有人知道怎么做吗?

    我用另一种手动方式成功地做到了这一点,但我不知道如何在ImageMagick中做到这一点。

    0 回复  |  直到 3 年前
        1
  •  0
  •   Mark Setchell    3 年前

    首先要做的是将您提供的预期输出分离到其组成的RGBA通道中,并排排列,以便我们可以看到每个通道的目标:

    magick out.png -separate +smush 10 channels.png
    

    enter image description here

    下一步是检查文件大小。你说的是512x512像素的16位数据。这意味着我期待512x512x2,即524288字节,但你的文件有524290字节。快速检查显示您有一个2字节的 BOM 一开始我们需要跳过。这意味着我们的命令必须将数据视为512x512像素的16位灰度数据,并使用2字节的头进行跳过。我们也不想读取文件4次,所以我们将其放入MPR “Magick持久寄存器” (或 “命名内存块” 是我的想法)并在每次解码通道时从那里回忆原始数据。

    因此,在下面的命令中,第一行读取输入图像,跳过BOM并将其放入MPR。第二行获取MPR的副本,比特将红色通道从中旋转出来。第二行、第三行和第四行对绿色、蓝色和Alpha通道的作用相同。最后一行将处理堆栈中的4个通道合并到输出文件中。

    magick -size 512x512+2 -endian MSB -depth 16 gray:in.file -write MPR:orig +delete \
       \( MPR:orig -evaluate and 63488 \) \
       \( MPR:orig -evaluate and 1984  -evaluate leftshift 5  \) \
       \( MPR:orig -evaluate and 56    -evaluate leftshift 10 \) \
       \( MPR:orig -evaluate and 7     -evaluate leftshift 13 \) \
       -combine result.png
    

    注:

    63488 = 0xf800
    1984  = 0x07c0
    56    = 0x0038
    

    enter image description here


    在我不使用且无法测试的Windows上,该命令将如下所示:

    magick -size 512x512+2 -endian MSB -depth 16 gray:in.file -write MPR:orig +delete ^
       ( MPR:orig -evaluate and 63488 ) ^
       ( MPR:orig -evaluate and 1984  -evaluate leftshift 5  ) ^
       ( MPR:orig -evaluate and 56    -evaluate leftshift 10 ) ^
       ( MPR:orig -evaluate and 7     -evaluate leftshift 13 ) ^
       -combine result.png
    

    为了好玩,你可以用Python做同样的事情:

    #!/usr/bin/env python3
    
    import numpy as np
    from PIL import Image
    
    h, w = 512, 512
    
    # Read raw 16-bit file, skipping BOM with offset=2. Reshape.
    raw = np.fromfile('in.file', dtype=np.dtype('>u2'), offset=2).reshape((h,w))
    
    # RGBA5533 packed into uint16
    R = (np.bitwise_and(raw, 0xf800) >> 8).astype(np.uint8)
    G = (np.bitwise_and(raw, 0x07c0) >> 3).astype(np.uint8)
    B = (np.bitwise_and(raw, 0x0038) << 2).astype(np.uint8)
    A = (np.bitwise_and(raw, 0x0007) << 5).astype(np.uint8)
    
    # Stack the individual channels into RGBA
    RGBA = np.dstack((R,G,B,A))
    
    # Display or save
    Image.fromarray(RGBA).show()