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

时间:2023-01-04 00:25:16

I have a raw image where each pixel corresponds to a 16 bits unsigned integer. I am trying to read using the PIL Image.fromstring() function as in the following code:

我有一个原始图像,每个像素对应一个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')

The PIL documentation informs that the first argument of the fromstring() function is 'mode'. However, looking at the documentation and googling I wasn't able to find details about what that argument really means (I believe that it is related to the color space or something like that). Does anyone knows where I can find a more detailed reference about the fromstring() function and what the mode argument means?

PIL文档告知fromstring()函数的第一个参数是“mode”。然而,看着文档和google搜索,我无法找到关于这个参数真正含义的细节(我相信它与颜色空间或类似的东西有关)。有谁知道我可以从哪里找到关于fromstring()函数的更详细的引用以及模式参数的含义吗?

4 个解决方案

#1


18  

The specific documentation is at http://effbot.org/imagingbook/concepts.htm:

具体的文档是http://effbot.org/imagingbook/concepts.htm:

Mode

The mode of an image defines the type and depth of a pixel in the image. The current release supports the following standard modes:

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

  • 1 (1-bit pixels, black and white, stored with one pixel per byte)
  • 1(1位像素,黑白,每字节存储1个像素)
  • L (8-bit pixels, black and white)
  • L(8位像素,黑白)
  • P (8-bit pixels, mapped to any other mode using a colour palette)
  • P(8位像素,使用调色板映射到任何其他模式)
  • RGB (3x8-bit pixels, true colour)
  • RGB (3x8位像素,真色)
  • RGBA (4x8-bit pixels, true colour with transparency mask)
  • RGBA (4x8位像素,带有透明遮罩的真彩色)
  • CMYK (4x8-bit pixels, colour separation)
  • CMYK (4x8位像素,分色)
  • YCbCr (3x8-bit pixels, colour video format)
  • YCbCr (3x8位像素,彩色视频格式)
  • I (32-bit signed integer pixels)
  • I(32位符号整数像素)
  • F (32-bit floating point pixels)
  • F(32位浮点像素)

PIL also provides limited support for a few special modes, including LA (L with alpha), RGBX (true colour with padding) and RGBa (true colour with premultiplied alpha).

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

#2


8  

Image.frombuffer(mode, size, data) => image

图像。frombuffer(模式,大小,数据)=>图像。

(New in PIL 1.1.4). Creates an image memory from pixel data in a string or buffer object, using the standard "raw" decoder. For some modes, the image memory will share memory with the original buffer (this means that changes to the original buffer object are reflected in the image). Not all modes can share memory; supported modes include "L", "RGBX", "RGBA", and "CMYK". For other modes, this function behaves like a corresponding call to the fromstring function.

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

I'm not sure what "L" stands for, but "RGBA" stands for Red-Green-Blue-Alpha, so I presume RGBX is equivalent to RGB (edit: upon testing this isn't the case)? CMYK is Cyan-Magenta-Yellow-Kelvin, which is another type of colorspace. Of course I assume that if you know about PIL you also know about colorspaces. If not, Wikipedia has a great article.

我不确定“L”代表什么,但是“RGBA”代表红-绿-蓝- alpha,所以我认为RGBX等同于RGB(编辑:在测试中不是这样)?CMYK是Cyan-Magenta-Yellow-Kelvin,这是另一种颜色空间。当然,我认为如果你知道PIL,你也知道colorspace。如果没有,*有一篇很棒的文章。

As for what it really means (if that's not enough): pixel values will be encoded differently for each colorspace. In regular RGB you have 3 bytes per pixel - 0-254, 0-254, 0-254. For Alpha you add another byte to each pixel. If you decode an RGB image as RGBA, you'll end out reading the R pixel to the right of the first pixel as your alpha, which means you'll get the G pixel as your R value. This will be magnified depending on how large your image, but it will really make your colors go wonky. Similarly, trying to read a CMYK encoded image as RGB (or RGBA) will make your image look very much not like it's supposed to. For instance, try this with an image:

至于它到底意味着什么(如果这还不够):像素值将以不同的方式对每个颜色空间进行编码。在常规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')

And you'll see what the different modes do - try it with a variety of input images: png with alpha, png without alpha, bmp, gif, and jpeg. It's kinda a fun experiment, actually.

你将会看到不同的模式是怎么做的——用不同的输入图像来尝试:png与alpha, png没有alpha, bmp, gif和jpeg。实际上,这是一个有趣的实验。

#3


5  

If all else fails, you can always read the source code. For PIL, the downloads are here.

如果其他方法都失败了,您可以始终阅读源代码。对于PIL,下载在这里。

You never said exactly what format the pixel data in the 16 bits unsigned integers was in, but I'd guess it's something like RRRRRGGGGGGBBBBBB, (5-bits Red, 6-bits Green, 5-bits Blue), or RRRRRGGGGGBBBBBA (5-bits Red, 5-bits Green, 5-bits Blue, 1-bit Alpha or Transparency). I didn't see support for those formats after a very quick peek at the some of the sources myself, but can't say one way or the other for sure.

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

On the same web page where the PIL downloads are, they mention that one can send questions to the Python Image SIG mailing list and provide a link for it. That might be a better source than asking here.

在PIL下载的同一个web页面上,他们提到可以向Python Image SIG邮件列表发送问题并提供链接。这可能是一个更好的来源。

Hope this helps.

希望这个有帮助。

#4


4  

This is an old question, but this might help someone in the future. One of the problems with the original code snippet is that in Image.fromstring('L', imgSize, rawData, 'raw', 'F;16'), the F;16 part works for 'F' mode.

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

This works for me:

这工作对我来说:

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

#1


18  

The specific documentation is at http://effbot.org/imagingbook/concepts.htm:

具体的文档是http://effbot.org/imagingbook/concepts.htm:

Mode

The mode of an image defines the type and depth of a pixel in the image. The current release supports the following standard modes:

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

  • 1 (1-bit pixels, black and white, stored with one pixel per byte)
  • 1(1位像素,黑白,每字节存储1个像素)
  • L (8-bit pixels, black and white)
  • L(8位像素,黑白)
  • P (8-bit pixels, mapped to any other mode using a colour palette)
  • P(8位像素,使用调色板映射到任何其他模式)
  • RGB (3x8-bit pixels, true colour)
  • RGB (3x8位像素,真色)
  • RGBA (4x8-bit pixels, true colour with transparency mask)
  • RGBA (4x8位像素,带有透明遮罩的真彩色)
  • CMYK (4x8-bit pixels, colour separation)
  • CMYK (4x8位像素,分色)
  • YCbCr (3x8-bit pixels, colour video format)
  • YCbCr (3x8位像素,彩色视频格式)
  • I (32-bit signed integer pixels)
  • I(32位符号整数像素)
  • F (32-bit floating point pixels)
  • F(32位浮点像素)

PIL also provides limited support for a few special modes, including LA (L with alpha), RGBX (true colour with padding) and RGBa (true colour with premultiplied alpha).

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

#2


8  

Image.frombuffer(mode, size, data) => image

图像。frombuffer(模式,大小,数据)=>图像。

(New in PIL 1.1.4). Creates an image memory from pixel data in a string or buffer object, using the standard "raw" decoder. For some modes, the image memory will share memory with the original buffer (this means that changes to the original buffer object are reflected in the image). Not all modes can share memory; supported modes include "L", "RGBX", "RGBA", and "CMYK". For other modes, this function behaves like a corresponding call to the fromstring function.

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

I'm not sure what "L" stands for, but "RGBA" stands for Red-Green-Blue-Alpha, so I presume RGBX is equivalent to RGB (edit: upon testing this isn't the case)? CMYK is Cyan-Magenta-Yellow-Kelvin, which is another type of colorspace. Of course I assume that if you know about PIL you also know about colorspaces. If not, Wikipedia has a great article.

我不确定“L”代表什么,但是“RGBA”代表红-绿-蓝- alpha,所以我认为RGBX等同于RGB(编辑:在测试中不是这样)?CMYK是Cyan-Magenta-Yellow-Kelvin,这是另一种颜色空间。当然,我认为如果你知道PIL,你也知道colorspace。如果没有,*有一篇很棒的文章。

As for what it really means (if that's not enough): pixel values will be encoded differently for each colorspace. In regular RGB you have 3 bytes per pixel - 0-254, 0-254, 0-254. For Alpha you add another byte to each pixel. If you decode an RGB image as RGBA, you'll end out reading the R pixel to the right of the first pixel as your alpha, which means you'll get the G pixel as your R value. This will be magnified depending on how large your image, but it will really make your colors go wonky. Similarly, trying to read a CMYK encoded image as RGB (or RGBA) will make your image look very much not like it's supposed to. For instance, try this with an image:

至于它到底意味着什么(如果这还不够):像素值将以不同的方式对每个颜色空间进行编码。在常规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')

And you'll see what the different modes do - try it with a variety of input images: png with alpha, png without alpha, bmp, gif, and jpeg. It's kinda a fun experiment, actually.

你将会看到不同的模式是怎么做的——用不同的输入图像来尝试:png与alpha, png没有alpha, bmp, gif和jpeg。实际上,这是一个有趣的实验。

#3


5  

If all else fails, you can always read the source code. For PIL, the downloads are here.

如果其他方法都失败了,您可以始终阅读源代码。对于PIL,下载在这里。

You never said exactly what format the pixel data in the 16 bits unsigned integers was in, but I'd guess it's something like RRRRRGGGGGGBBBBBB, (5-bits Red, 6-bits Green, 5-bits Blue), or RRRRRGGGGGBBBBBA (5-bits Red, 5-bits Green, 5-bits Blue, 1-bit Alpha or Transparency). I didn't see support for those formats after a very quick peek at the some of the sources myself, but can't say one way or the other for sure.

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

On the same web page where the PIL downloads are, they mention that one can send questions to the Python Image SIG mailing list and provide a link for it. That might be a better source than asking here.

在PIL下载的同一个web页面上,他们提到可以向Python Image SIG邮件列表发送问题并提供链接。这可能是一个更好的来源。

Hope this helps.

希望这个有帮助。

#4


4  

This is an old question, but this might help someone in the future. One of the problems with the original code snippet is that in Image.fromstring('L', imgSize, rawData, 'raw', 'F;16'), the F;16 part works for 'F' mode.

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

This works for me:

这工作对我来说:

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