python 标准库处理png图片 简单案例

import zlib  # 数据解压和压缩的库
import binascii  # 进制转换函数的库

# python 标准库处理png图片 简单案例
"""
png图片包括以下的数据块,都是比较重要的一些数据块
# 文件头数据块 IHDR
# 调色板数据块 PLTE
# 图像数据块 IDAT
# 图像结束数据 IEND
"""


# 采用字节流读取,然后转码成十六进制便于处理
def photo_HEX(address):
    with open(address, 'rb') as f:
        data = f.read().hex()
        print("图片十六进制数据为:", data)
    return data


# 识别png的IHDR文件头数据块,获取对应信息
def photo_IHDR(data, step):
    # 查看是否为png
    if data[0:16] == "89504e470d0a1a0a":
        print("是png图片")
        step += 16
    else:
        print("错误不是png图片")

    # 文件头数据块 IHDR的内容字符长度,转换十进制输出字符长度
    number = int(data[step:step + 8], 16)
    print("IHDR的内容字符长度为:", number)
    # step步数更新
    step += 8

    # 识别文件头数据块 IHDR
    if data[step:step + 8] == "49484452":
        print("IHDR 识别成功")
    else:
        print("IHDR 识别失败")
    # step步数更新
    step += 8

    # 读取图片width信息
    width = int(data[step:step + 8], 16)
    print("图像宽度为:", width)
    # step步数更新
    step += 8

    # 读取图片height信息
    height = int(data[step:step + 8], 16)
    print("图像高度为:", height)
    # step步数更新
    step += 8

    """
    图像深度:
    索引彩色图像:1,2,4或8
    灰度图像:1,2,4,8或16
    真彩色图像:8或16
    """
    # 读取图片深度信息
    bit_depth = int(data[step:step + 2], 16)
    print("图像深度为:", bit_depth)
    # step步数更新
    step += 2

    """
    颜色类型:
    0:灰度图像, 1,2,4,8或16
    2:真彩色图像,8或16
    3:索引彩色图像,1,2,4或8
    4:带α通道数据的灰度图像,8或16
    6:带α通道数据的真彩色图像,8或16
    """
    # 读取图片颜色类型信息
    color_type = int(data[step:step + 2], 16)
    print("图片颜色类型为:", color_type)
    # step步数更新
    step += 2

    # 读取图片压缩方法信息
    comdivssion_method = int(data[step:step + 2], 16)
    print("图片压缩方法为:", comdivssion_method)
    # step步数更新
    step += 2

    # 读取图片滤波器方法信息
    filter_method = int(data[step:step + 2], 16)
    print("图片滤波器方法为:", filter_method)
    # step步数更新
    step += 2

    """
    扫描类型:
    0:非隔行扫描
    1:隔行扫描方法
    """
    # 读取图片扫描类型信息
    scan_type = int(data[step:step + 2], 16)
    print("图片扫描类型为:", scan_type)
    # step步数更新
    step += 2

    return step, width, height


# 图像数据块 IDAT 通过step,width,height处理数据
def photo_IDAT(data, step, width, height):
    # 找数据块位置,设置起始位置
    step = data.find('49444154', step)
    print(step)
    # 查看数据块的长度
    number = int(data[step - 8:step], 16)
    print("数据块长度为:", number)
    # step步数更新
    step += 8

    # 提取数据块数据
    extract_data = data[step:step + number * 2]
    # 16进制字符串转换为二进制数据
    extract_data = binascii.unhexlify(extract_data)
    # zlib库解码二进制
    photo_data = zlib.decompress(extract_data)
    # 转换为list
    list_data = list(photo_data)
    # 打印长度会发现为5*5的图片彩色情况下应该为75,但打印的是80,这是设计的时候的0换行,去除就行了
    print(len(list_data))
    # 获取对应的宽度和长度,对数据做处理
    width = width
    height = height
    # 每一部分对应0 去除法:
    # 0,3*5*1,3*5*2,3*5*3,3*5*4
    for de in range(height):
        del list_data[3 * width * de]
    # 设置list作为处理图片数据
    list_all = []
    list_line = []
    # 彩色要除以3,3个一组
    for one in range(int(len(list_data) / 3)):
        list_line.append(list_data[one * 3:(one * 3 + 3)])
        # 换行
        if len(list_line) % width == 0:
            list_all.append(list_line)
            list_line = []
    # 现在和其他库处理的多维数组是差不多的
    print(list_all)
    # 更新这一个数据块后的步数
    step += number * 2

    print("CRC循环冗余检测:", data[step:step + 8])
    step += 8

    return step, list_all


"""
5×5的图片数据 字节流为 
b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x05\x00\x00\x00\x05\x08\x02\x00\x00\x00\x02\r\xb1\xb2\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00\tpHYs\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7o\xa8d\x00\x00\x00\x1dIDAT\x18Wc\xc0\x00\x8b^\x00\xd1[\x19\x95\x997_m}&K\x12\x7f\xe6\xcdW\x00\x1aC!\xf9P\xad\ry\x00\x00\x00\x00IEND\xaeB`\x82'
"""

if __name__ == '__main__':
    print("开始解码png图片")
    # 初始解码步数
    step = 0
    # 读取图片
    data = photo_HEX("photo.png")
    # 识别png的IHDR文件头数据块,获取step,width,height
    step, width, height = photo_IHDR(data, step)
    # 图片没有调色板数据块 PLTE 直接跳过
    # 图像数据块 IDAT 通过step,width,height处理数据
    step, list_data = photo_IDAT(data, step, width, height)
    if data[step:step + 8] == "00000000":
        if data[step + 8:] == "49454e44ae426082":
            print("图像结束数据 IEND结束")

import zlib  # 数据解压和压缩的库
import binascii  # 进制转换函数的库

# python 标准库处理png图片 简单案例
"""
png图片包括以下的数据块,都是比较重要的一些数据块
# 文件头数据块 IHDR
# 调色板数据块 PLTE
# 图像数据块 IDAT
# 图像结束数据 IEND
"""


# 采用字节流读取,然后转码成十六进制便于处理
def photo_HEX(address):
    with open(address, 'rb') as f:
        data = f.read().hex()
        print("图片十六进制数据为:", data)
    return data


# 识别png的IHDR文件头数据块,获取对应信息
def photo_IHDR(data, step):
    # 查看是否为png
    if data[0:16] == "89504e470d0a1a0a":
        print("是png图片")
        step += 16
    else:
        print("错误不是png图片")

    # 文件头数据块 IHDR的内容字符长度,转换十进制输出字符长度
    number = int(data[step:step + 8], 16)
    print("IHDR的内容字符长度为:", number)
    # step步数更新
    step += 8

    # 识别文件头数据块 IHDR
    if data[step:step + 8] == "49484452":
        print("IHDR 识别成功")
    else:
        print("IHDR 识别失败")
    # step步数更新
    step += 8

    # 读取图片width信息
    width = int(data[step:step + 8], 16)
    print("图像宽度为:", width)
    # step步数更新
    step += 8

    # 读取图片height信息
    height = int(data[step:step + 8], 16)
    print("图像高度为:", height)
    # step步数更新
    step += 8

    """
    图像深度:
    索引彩色图像:1,2,4或8
    灰度图像:1,2,4,8或16
    真彩色图像:8或16
    """
    # 读取图片深度信息
    bit_depth = int(data[step:step + 2], 16)
    print("图像深度为:", bit_depth)
    # step步数更新
    step += 2

    """
    颜色类型:
    0:灰度图像, 1,2,4,8或16
    2:真彩色图像,8或16
    3:索引彩色图像,1,2,4或8
    4:带α通道数据的灰度图像,8或16
    6:带α通道数据的真彩色图像,8或16
    """
    # 读取图片颜色类型信息
    color_type = int(data[step:step + 2], 16)
    print("图片颜色类型为:", color_type)
    # step步数更新
    step += 2

    # 读取图片压缩方法信息
    comdivssion_method = int(data[step:step + 2], 16)
    print("图片压缩方法为:", comdivssion_method)
    # step步数更新
    step += 2

    # 读取图片滤波器方法信息
    filter_method = int(data[step:step + 2], 16)
    print("图片滤波器方法为:", filter_method)
    # step步数更新
    step += 2

    """
    扫描类型:
    0:非隔行扫描
    1:隔行扫描方法
    """
    # 读取图片扫描类型信息
    scan_type = int(data[step:step + 2], 16)
    print("图片扫描类型为:", scan_type)
    # step步数更新
    step += 2

    return step, width, height


# 图像数据块 IDAT 通过step,width,height处理数据
def photo_IDAT(data, step, width, height):
    # 找数据块位置,设置起始位置
    step = data.find('49444154', step)
    print(step)
    # 查看数据块的长度
    number = int(data[step - 8:step], 16)
    print("数据块长度为:", number)
    # step步数更新
    step += 8

    # 提取数据块数据
    extract_data = data[step:step + number * 2]
    # 16进制字符串转换为二进制数据
    extract_data = binascii.unhexlify(extract_data)
    # zlib库解码二进制
    photo_data = zlib.decompress(extract_data)
    # 转换为list
    list_data = list(photo_data)
    # 打印长度会发现为5*5的图片彩色情况下应该为75,但打印的是80,这是设计的时候的0换行,去除就行了
    print(len(list_data))
    # 获取对应的宽度和长度,对数据做处理
    width = width
    height = height
    # 每一部分对应0 去除法:
    # 0,3*5*1,3*5*2,3*5*3,3*5*4
    for de in range(height):
        del list_data[3 * width * de]
    # 设置list作为处理图片数据
    list_all = []
    list_line = []
    # 彩色要除以3,3个一组
    for one in range(int(len(list_data) / 3)):
        list_line.append(list_data[one * 3:(one * 3 + 3)])
        # 换行
        if len(list_line) % width == 0:
            list_all.append(list_line)
            list_line = []
    # 现在和其他库处理的多维数组是差不多的
    print(list_all)
    # 更新这一个数据块后的步数
    step += number * 2

    print("CRC循环冗余检测:", data[step:step + 8])
    step += 8

    return step, list_all


"""
5×5的图片数据 字节流为 
b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x05\x00\x00\x00\x05\x08\x02\x00\x00\x00\x02\r\xb1\xb2\x00\x00\x00\x01sRGB\x00\xae\xce\x1c\xe9\x00\x00\x00\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00\tpHYs\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7o\xa8d\x00\x00\x00\x1dIDAT\x18Wc\xc0\x00\x8b^\x00\xd1[\x19\x95\x997_m}&K\x12\x7f\xe6\xcdW\x00\x1aC!\xf9P\xad\ry\x00\x00\x00\x00IEND\xaeB`\x82'
"""

if __name__ == '__main__':
    print("开始解码png图片")
    # 初始解码步数
    step = 0
    # 读取图片
    data = photo_HEX("photo.png")
    # 识别png的IHDR文件头数据块,获取step,width,height
    step, width, height = photo_IHDR(data, step)
    # 图片没有调色板数据块 PLTE 直接跳过
    # 图像数据块 IDAT 通过step,width,height处理数据
    step, list_data = photo_IDAT(data, step, width, height)
    if data[step:step + 8] == "00000000":
        if data[step + 8:] == "49454e44ae426082":
            print("图像结束数据 IEND结束")

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值