如何使用PIL读取原始图像?

时间:2010-08-03 13:52:35

标签: python image image-processing python-imaging-library

我有一个原始图像,其中每个像素对应一个16位无符号整数。我试图使用PIL Image.fromstring()函数读取,如下面的代码所示:

if __name__ == "__main__":
    if (len(sys.argv) != 4):
        print 'Error: missing input argument'
        sys.exit()

    file = open(sys.argv[1], 'rb')
    rawData = file.read()
    file.close()

    imgSize = (int(sys.argv[2]), int(sys.argv[3]))

    # Use the PIL raw decoder to read the data.
    #   - the 'F;16' informs the raw decoder that we are reading a little endian, unsigned integer 16 bit data.
    img = Image.fromstring('L', imgSize, rawData, 'raw', 'F;16')

    im.save('out.png')

PIL文档通知fromstring()函数的第一个参数是'mode'。然而,看文档和谷歌搜索,我无法找到有关该论点真正意义的细节(我相信它与色彩空间或类似的东西有关)。有谁知道我在哪里可以找到关于fromstring()函数的更详细的参考以及mode参数的含义?

4 个答案:

答案 0 :(得分:20)

具体文档位于http://effbot.org/imagingbook/concepts.htm

  

模式

     

图像模式定义了类型   和图像中像素的深度。该   当前版本支持以下内容   标准模式:

     
      
  • 1(1位像素,黑白,每字节存储一个像素)
  •   
  • L(8位像素,黑白)
  •   
  • P(8位像素,使用调色板映射到任何其他模式)
  •   
  • RGB(3x8位像素,真彩色)
  •   
  • RGBA(4x8位像素,带透明蒙版的真彩色)
  •   
  • CMYK(4x8位像素,分色)
  •   
  • YCbCr(3x8位像素,彩色视频格式)
  •   
  • I(32位有符号整数像素)
  •   
  • F(32位浮点像素)
  •   
     

PIL也提供有限的支持   一些特殊模式,包括LA(L   与alpha),RGBX(真正的颜色与   填充)和RGBa(真彩色   预乘alpha)。

答案 1 :(得分:10)

  

Image.frombuffer(mode,size,data)=>图像

     

(PIL 1.1.4中的新内容)。使用标准的“原始”解码器从字符串或缓冲区对象中的像素数据创建图像存储器。对于某些模式,图像存储器将与原始缓冲区共享存储器(这意味着对原始缓冲区对象的更改将反映在图像中)。并非所有模式都可以共享内存;支持的模式包括“L”,“RGBX”,“RGBA”和“CMYK”。对于其他模式,此函数的行为类似于对fromstring函数的相应调用。

我不确定“L”代表什么,但“RGBA”代表Red-Green-Blue-Alpha,所以我认为RGBX相当于RGB(编辑:测试时不是这样)? CMYK是Cyan-Magenta-Yellow-Kelvin,是另一种颜色空间。当然我假设如果你了解PIL你也知道色彩空间。如果没有,Wikipedia有一篇很棒的文章。

至于它的真正意义(如果这还不够):对于每个颜色空间,像素值将被不同地编码。在常规RGB中,每个像素有3个字节 - 0-254,0-254,0-254。对于Alpha,您可以为每个像素添加另一个字节。如果将RGB图像解码为RGBA,则最终会将第一个像素右侧的R像素读取为alpha,这意味着您将获得G像素作为R值。这将根据您的图像大小而放大,但它会让您的色彩变得难以置信。同样,尝试将CMYK编码的图像作为RGB(或RGBA)读取将使您的图像看起来非常不像它应该的那样。例如,尝试使用图像:

i = Image.open('image.png')
imgSize = i.size
rawData = i.tostring()
img = Image.fromstring('L', imgSize, rawData)
img.save('lmode.png')
img = Image.fromstring('RGB', imgSize, rawData)
img.save('rgbmode.png')
img = Image.fromstring('RGBX', imgSize, rawData)
img.save('rgbxmode.jfif')
img = Image.fromstring('RGBA', imgSize, rawData)
img.save('rgbamode.png')
img = Image.fromstring('CMYK', imgSize, rawData)
img.save('rgbamode.tiff')

你会看到不同模式的作用 - 尝试使用各种输入图像:png with alpha,png without alpha,bmp,gif和jpeg。实际上,这是一个有趣的实验。

答案 2 :(得分:5)

如果所有其他方法都失败了,您可以随时阅读源代码。对于PIL,下载量为here

你从未说过16位无符号整数中的像素数据到底是什么格式,但我猜它有点像RRRRRGGGGGGBBBBBB,(5位红色,6位绿色,5位蓝色)或RRRRRGGGGGBBBBBA (5位红色,5位绿色,5位蓝色,1位Alpha或透明度)。在我自己快速浏览了一些来源之后,我没有看到对这些格式的支持,但是不能肯定地说一种方式。

在PIL下载的同一网页上,他们提到可以将问题发送到Python Image SIG邮件列表并为其提供链接。这可能比在这里询问更好。

希望这有帮助。

答案 3 :(得分:4)

这是一个老问题,但这可能会对将来有所帮助。原始代码段的一个问题是,在Image.fromstring('L', imgSize, rawData, 'raw', 'F;16')中,F;16部分适用于'F'模式。

这对我有用:

image = Image.fromstring('F', imgSize, rawData, 'raw', 'F;16')
image.convert('L').save('out.png')