【问题标题】:Creating a PNG file in Python在 Python 中创建 PNG 文件
【发布时间】:2012-01-23 04:00:46
【问题描述】:

我有一个应用程序,我希望能够从 Python 中的数据生成 PNG 图像。我做了一些搜索,发现“PIL”看起来已经过时了。有没有其他图书馆可以更好地解决这个问题?

谢谢,

【问题讨论】:

  • 您使用的是旧 PIL(如果您尚未开发 py3.2 之后的版本)

标签: python image png


【解决方案1】:

有没有其他库可以更好地解决这个问题?

png 包将是一个合理的常见选择。

这是项目描述:

PyPNG 允许使用纯 Python 读取和写入 PNG 图像文件。

【讨论】:

    【解决方案2】:

    简单的PNG文件可以很容易地从纯Python代码生成——你只需要标准的zlib模块和一些字节编码来编写块。这是一个完整的示例,普通读者可以将其用作他们自己的 png 生成器的入门:

    #! /usr/bin/python
    """ Converts a list of list into gray-scale PNG image. """
    __copyright__ = "Copyright (C) 2014 Guido Draheim"
    __licence__ = "Public Domain"
    
    import zlib
    import struct
    
    def makeGrayPNG(data, height = None, width = None):
        def I1(value):
            return struct.pack("!B", value & (2**8-1))
        def I4(value):
            return struct.pack("!I", value & (2**32-1))
        # compute width&height from data if not explicit
        if height is None:
            height = len(data) # rows
        if width is None:
            width = 0
            for row in data:
                if width < len(row):
                    width = len(row)
        # generate these chunks depending on image type
        makeIHDR = True
        makeIDAT = True
        makeIEND = True
        png = b"\x89" + "PNG\r\n\x1A\n".encode('ascii')
        if makeIHDR:
            colortype = 0 # true gray image (no palette)
            bitdepth = 8 # with one byte per pixel (0..255)
            compression = 0 # zlib (no choice here)
            filtertype = 0 # adaptive (each scanline seperately)
            interlaced = 0 # no
            IHDR = I4(width) + I4(height) + I1(bitdepth)
            IHDR += I1(colortype) + I1(compression)
            IHDR += I1(filtertype) + I1(interlaced)
            block = "IHDR".encode('ascii') + IHDR
            png += I4(len(IHDR)) + block + I4(zlib.crc32(block))
        if makeIDAT:
            raw = b""
            for y in xrange(height):
                raw += b"\0" # no filter for this scanline
                for x in xrange(width):
                    c = b"\0" # default black pixel
                    if y < len(data) and x < len(data[y]):
                        c = I1(data[y][x])
                    raw += c
            compressor = zlib.compressobj()
            compressed = compressor.compress(raw)
            compressed += compressor.flush() #!!
            block = "IDAT".encode('ascii') + compressed
            png += I4(len(compressed)) + block + I4(zlib.crc32(block))
        if makeIEND:
            block = "IEND".encode('ascii')
            png += I4(0) + block + I4(zlib.crc32(block))
        return png
    
    def _example():
        with open("cross3x3.png","wb") as f:
            f.write(makeGrayPNG([[0,255,0],[255,255,255],[0,255,0]]))
    

    【讨论】:

    • 比我们大多数人(可能包括 OP)正在寻找的深度要多一点,但 +1 是为了分享这么多信息。如果我想深入了解 png,这是很好的参考资料。
    • 这个例子很棒。您可以进行任何更改以显示如何添加调色板(对于一些基本的红色/绿色/等颜色并具有 Alpha 通道)?
    • 我想提供一个非常简短的答案。显然,有很多选项可以构建和编码图片。幸运的是,PNG 标准非常清楚每个块的内容(w3.org/TR/PNG)。为了避免位填充,只需寻找始终将值编码为一个字节的选项。 ///// 对于一个非常简单的 RGBA:PLTE 块没有编码选项 => 每个颜色通道总是正好 8 位,不多也不少。所以每个条目是 4 个字节(R,G,B,A)。 IHDR 位深度指的是 IDAT - 使用 8 位可以再次写入索引字节。
    【解决方案3】:

    这是一个 Python3 示例:

    import png
    
    width = 255
    height = 255
    img = []
    for y in range(height):
        row = ()
        for x in range(width):
            row = row + (x, max(0, 255 - x - y), y)
        img.append(row)
    with open('gradient.png', 'wb') as f:
        w = png.Writer(width, height, greyscale=False)
        w.write(f, img)
    

    【讨论】:

      【解决方案4】:

      经过一番搜索,我找到了这个网站:https://www.daniweb.com/programming/software-development/code/454765/save-a-pygame-drawing。它只是使用了旧的 pygame。

      第 37 行将 pygame 表面上绘制的任何内容保存为文件。

      编辑

      下面是实际代码:

          """pg_draw_circle_save101.py
          draw a blue solid circle on a white background
          save the drawing to an image file
          for result see http://prntscr.com/156wxi
          tested with Python 2.7 and PyGame 1.9.2 by vegaseat  16may2013
          """
      
          import pygame as pg
      
          # pygame uses (r, g, b) color tuples
          white = (255, 255, 255)
          blue = (0, 0, 255)
      
          width = 300
          height = 300
      
          # create the display window
          win = pg.display.set_mode((width, height))
          # optional title bar caption
          pg.display.set_caption("Pygame draw circle and save")
          # default background is black, so make it white
          win.fill(white)
      
          # draw a blue circle
          # center coordinates (x, y)
          center = (width//2, height//2)
          radius = min(center)
          # width of 0 (default) fills the circle
          # otherwise it is thickness of outline
          width = 0
          # draw.circle(Surface, color, pos, radius, width)
          pg.draw.circle(win, blue, center, radius, width)
      
          # now save the drawing
          # can save as .bmp .tga .png or .jpg
          fname = "circle_blue.png"
          pg.image.save(win, fname)
          print("file {} has been saved".format(fname))
      
          # update the display window to show the drawing
          pg.display.flip()
      
          
          # (press escape key or click window title bar x to exit)
          while True:
          for event in pg.event.get():
              if event.type == pg.QUIT:
                  # most reliable exit on x click
                  pg.quit()
                  raise SystemExit
              elif event.type == pg.KEYDOWN:
                  # optional exit with escape key
                  if event.key == pg.K_ESCAPE:
                      pg.quit()
                      raise SystemExit
      

      【讨论】:

      • @DanielM 感谢您的提示,我将对其进行更改以包含实际代码。
      【解决方案5】:

      我知道这个问题是在 9 年前提出的,但在 Python 3.8 时代,您可以在“Writing Binary”模式下打开文件:

      f = open("filename.png", 'wb')
      # data being whatever data you wanted to write
      f.write(data)
      

      【讨论】:

      • 它并没有解决实际问题。
      猜你喜欢
      • 1970-01-01
      • 2018-01-18
      • 2022-01-07
      • 2011-08-07
      • 1970-01-01
      • 2022-11-15
      • 2018-08-25
      • 2014-04-24
      • 1970-01-01
      相关资源
      最近更新 更多