python rgb在pc端显示问题

怎么用python将8位的rgb图片信息转成bmp并显示出来呢

实现这个很容易,但是感觉题主的概念似乎有点问题。rgb是颜色模式,bmp是图像文件格式,二者分处于完全不同的层面,并没有“转换”的关系。

>>> import numpy as np
>>> from PIL import Image
>>> im = Image.open(r'D:\res\girl.jpg') # 打开图片文件
>>> im.mode # 查看模式
'RGB'
>>> im.save(r'D:\res\girl.bmp') # 另存为bmp文件
>>> import os # 导入os模块
>>> os.system(r"explorer D:\res\girl.bmp") # 显示bmp文件
1

img

对于PNG、BMP和JPG彩色图像格式之间的互相转换都可以通过Image模块的open()和save()函数来完成。具体说就是,在打开这些图像时,PIL会将它们解码为三通道的“RGB”图像。用户可以基于这个“RGB”图像,对其进行处理。处理完毕,使用函数save(),可以将处理结果保存成PNG、BMP和JPG中任何格式。这样也就完成了几种格式之间的转换。同理,其他格式的彩色图像也可以通过这种方式完成转换。
Image模块的convert()函数,用于不同模式图像之间的转换。

Convert()函数有三种形式的定义,它们定义形式如下:

im.convert(mode) ⇒ image

im.convert(“P”, **options) ⇒ image

im.convert(mode, matrix) ⇒ image

使用不同的参数,将当前的图像转换为新的模式,并产生新的图像作为返回值。
PIL中有九种不同模式。分别为1,L,P,RGB,RGBA,CMYK,YCbCr,I,F。

PIL中所涉及的基本概念有如下几个:通道(bands)、模式(mode)、尺寸(size)、坐标系统(coordinate system)、调色板(palette)、信息(info)和滤波器(filters)。

1、 通道

每张图片都是由一个或者多个数据通道构成。PIL允许在单张图片中合成相同维数和深度的多个通道。

以RGB图像为例,每张图片都是由三个数据通道构成,分别为R、G和B通道。而对于灰度图像,则只有一个通道。

对于一张图片的通道数量和名称,可以通过方法getbands()来获取。方法getbands()是Image模块的方法,它会返回一个字符串元组(tuple)。该元组将包括每一个通道的名称。

Python的元组与列表类似,不同之处在于元组的元素不能修改,元组使用小括号,列表使用方括号,元组创建很简单,只需要在括号中添加元素,并使用逗号隔开即可。

方法getbands()的使用如下:

from PIL import Image

im= Image.open('D:\Code\Python\test\img\1.jpg')

im.getbands()

('R', 'G', 'B')

im_bands = im.getbands()

len(im_bands)

3

print im_bands[0]

R

print im_bands[1]

G

print im_bands[2]

B

2、 模式

图像的模式定义了图像的类型和像素的位宽。当前支持如下模式:

1:1位像素,表示黑和白,但是存储的时候每个像素存储为8bit。

L:8位像素,表示黑和白。

P:8位像素,使用调色板映射到其他模式。

RGB:3x8位像素,为真彩色。

RGBA:4x8位像素,有透明通道的真彩色。

CMYK:4x8位像素,颜色分离。

YCbCr:3x8位像素,彩色视频格式。

I:32位整型像素。

F:32位浮点型像素。

PIL也支持一些特殊的模式,包括RGBX(有padding的真彩色)和RGBa(有自左乘alpha的真彩色)。

可以通过mode属性读取图像的模式。其返回值是包括上述模式的字符串。

属性mode的使用如下:

from PIL importImage

im =Image.open('D:\Code\Python\test\img\1.jpg')

im.mode

'RGB'

md = im.mode

print md

RGB

3、 尺寸

通过size属性可以获取图片的尺寸。这是一个二元组,包含水平和垂直方向上的像素数。

属性mode的使用如下:

from PIL importImage

im =Image.open('D:\Code\Python\test\img\1.jpg')

im.size

(800, 450)

im_size = im.size

print im_size[0]

800

print im_size[1]

450

4、 坐标系统

PIL使用笛卡尔像素坐标系统,坐标(0,0)位于左上角。注意:坐标值表示像素的角;位于坐标(0,0)处的像素的中心实际上位于(0.5,0.5)。

坐标经常用于二元组(x,y)。长方形则表示为四元组,前面是左上角坐标。例如,一个覆盖800x600的像素图像的长方形表示为(0,0,800,600)。

5、 调色板

调色板模式 ("P")使用一个颜色调色板为每个像素定义具体的颜色值

6、 信息

使用info属性可以为一张图片添加一些辅助信息。这个是字典对象。加载和保存图像文件时,多少信息需要处理取决于文件格式。

属性info的使用如下:

from PIL import Image

im =Image.open('D:\Code\Python\test\img\1.jpg')

im.info

{'jfif_version':(1, 1), 'jfif': 257, 'jfif_unit': 1, 'jfif_density': (96, 96), 'dpi': (96, 96)}

im_info = im.info

im_info

{'jfif_version':(1, 1), 'jfif': 257, 'jfif_unit': 1, 'jfif_density': (96, 96), 'dpi': (96, 96)}

print im_info['jfif_version']

(1, 1)

print im_info['jfif']

257

7、 滤波器

对于将多个输入像素映射为一个输出像素的几何操作,PIL提供了4个不同的采样滤波器:

NEAREST:最近滤波。从输入图像中选取最近的像素作为输出像素。它忽略了所有其他的像素。

BILINEAR:双线性滤波。在输入图像的2x2矩阵上进行线性插值。注意:PIL的当前版本,做下采样时该滤波器使用了固定输入模板。

BICUBIC:双立方滤波。在输入图像的4x4矩阵上进行立方插值。注意:PIL的当前版本,做下采样时该滤波器使用了固定输入模板。

ANTIALIAS:平滑滤波。这是PIL 1.1.3版本中新的滤波器。对所有可以影响输出像素的输入像素进行高质量的重采样滤波,以计算输出像素值。在当前的PIL版本中,这个滤波器只用于改变尺寸和缩略图方法。

注意:在当前的PIL版本中,ANTIALIAS滤波器是下采样(例如,将一个大的图像转换为小图)时唯一正确的滤波器。BILIEAR和BICUBIC滤波器使用固定的输入模板,用于固定比例的几何变换和上采样是最好的。

Image模块中的方法resize()和thumbnail()用到了滤波器。

方法resize()的使用如下:

方法resize()的定义为:resize(size, filter=None)=> image

from PIL import Image

im= Image.open('D:\Code\Python\test\img\1.jpg')

im.size

(800, 450)

im_resize = im.resize((256,256))

im_resize.size

(256, 256)

对参数filter不赋值的话,方法resize()默认使用NEAREST滤波器。如果要使用其他滤波器可以通过下面的方法来实现:

im_resize0 = im.resize((256,256), Image.BILINEAR)

im_resize0.size

(256, 256)

im_resize1 = im.resize((256,256), Image.BICUBIC)

im_resize1.size

(256, 256)

im_resize2 = im.resize((256,256), Image.ANTIALIAS)

im_resize2.size

(256, 256)

方法thumbnail ()的使用如下:

方法thumbnail ()的定义为:im.thumbnail(size, filter=None)

from PIL import Image

im= Image.open('D:\Code\Python\test\img\1.jpg')

im.size

(800, 450)

im.thumbnail((200,200))

im.size

(200,112)

这里需要说明的是,方法thumbnail()需要保持宽高比,对于size=(200,200)的输入参数,其最终的缩略图尺寸为(200, 112)。

对参数filter不赋值的话,方法thumbnail()默认使用NEAREST滤波器。如果要使用其他滤波器可以通过下面的方法来实现:

im= Image.open('D:\Code\Python\test\img\1.jpg')

im.size

(800, 450)

im.thumbnail((200,200),Image.BILINEAR)

im.size

(200, 112)

im= Image.open('D:\Code\Python\test\img\1.jpg')

im.size

(800, 450)

im.thumbnail((200,200), Image.BICUBIC)

im.size

(200, 112)

im= Image.open('D:\Code\Python\test\img\1.jpg')

im.size

(800, 450)

im.thumbnail((200,200), Image.ANTIALIAS)

im.size

(200, 112)


import os
from PIL import Image
import numpy as np
import imageio
from PIL import ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True
 
class bmp:
    """ bmp data structure """
 
    def __init__(self, w=1080, h=1920):
        self.w = w
        self.h = h
 
    def calc_data_size (self):
        if ((self.w * 3) % 4 == 0):
            self.dataSize = self.w * 3 * self.h
        else:
            self.dataSize = (((self.w * 3) // 4 + 1) * 4) * self.h
 
        self.fileSize = self.dataSize + 54
 
 
    def conv2byte(self, l, num, len):
        tmp = num
        for i in range(len):
            l.append(tmp & 0x000000ff)
            tmp >>= 8
 
    def gen_bmp_header (self):
        self.calc_data_size();
        self.bmp_header = [0x42, 0x4d]
        self.conv2byte(self.bmp_header, self.fileSize, 4) #file size
        self.conv2byte(self.bmp_header, 0, 2)
        self.conv2byte(self.bmp_header, 0, 2)
        self.conv2byte(self.bmp_header, 54, 4) #rgb data offset
        self.conv2byte(self.bmp_header, 40, 4) #info block size
        self.conv2byte(self.bmp_header, self.w, 4)
        self.conv2byte(self.bmp_header, self.h, 4)
        self.conv2byte(self.bmp_header, 1, 2)
        self.conv2byte(self.bmp_header, 24, 2) #888
        self.conv2byte(self.bmp_header, 0, 4)  #no compression
        self.conv2byte(self.bmp_header, self.dataSize, 4) #rgb data size
        self.conv2byte(self.bmp_header, 0, 4)
        self.conv2byte(self.bmp_header, 0, 4)
        self.conv2byte(self.bmp_header, 0, 4)
        self.conv2byte(self.bmp_header, 0, 4)
 
    def print_bmp_header (self):
        length = len(self.bmp_header)
        for i in range(length):
            print("{:0>2x}".format(self.bmp_header[i]), end=' ')
            if i%16 == 15:
                print('')
        print('')
 
    def paint_bgcolor(self, pixel):
        self.rgbData = []
        self.rgbData += pixel
 
    def save_image(self, name="save.bmp"):
        f = open(name, 'wb')
 
        # write bmp header
        f.write(bytes(self.bmp_header))
 
        # write rgb data
        zeroBytes = self.dataSize // self.h - self.w * 3               #计算图像的每行后面需要的补充0的个数
 
        pixel_array = np.array(self.rgbData).reshape(self.h,self.w*3)  #将像素值list转换成np.array
 
        for r in range(self.h):
            l = []
            for i in range(0,len(pixel_array[r]),3):  #索引图片每行像素
                p = pixel_array[r][i]        # b vaule; 8bit
                l.append(p & 0x00ff)
                p = pixel_array[r][i+1]      # g vaule; 8bit
                l.append(p & 0x00ff)
                p = pixel_array[r][i+2]      # r vaule; 8bit
                l.append(p & 0x00ff)
 
            f.write(bytes(l))                #写入bmp文件中
 
            for i in range(zeroBytes):       #用于每行像素后补0
                f.write(bytes([0x00]))
 
        f.close()
 
 
def convert_img_to_a8rgb565(im):
    im_bytes = list()
    for (r, g, b, a) in list(im.getdata()):
        r = r & 0xF8
        g = g & 0xFC
        b = b & 0xF8
 
        im_bytes += [b, g, r]    #bmp文件数据位BGR格式
 
    return im_bytes
 
def convert(picture_path):
    for filename in os.listdir(picture_path):
        picture = os.path.join(picture_path, filename)
        print(picture)                     #打印文件名称
        bmp_file_name = filename.split('.')[0]
 
        img = Image.open(picture).transpose(Image.FLIP_TOP_BOTTOM).convert("RGBA") #PIL获取的图片会旋转,这里将其旋转回正图
 
        img_width , img_hight = img.size
 
        img_bgr = convert_img_to_a8rgb565(img)   #获取bgr数据,list
 
        image = bmp(img_width, img_hight)        #创建bmp文件
        image.gen_bmp_header()                   #写入bmp文件头信息#
        #image.print_bmp_header()                #打印出bmp文件头部信息
 
        image.paint_bgcolor(img_bgr)
        image.save_image('./conver_pic/'+bmp_file_name+'.bmp')
 
        print('picture convert over...')
 
def scan(picture_path):
    for filename in os.listdir(picture_path):
        picture = os.path.join(picture_path, filename)
        print(picture)                           #打印文件名称
 
        src_img = Image.open(picture)
        src_img.show()                           #显示图片
 
def main(source_picture_path,convert_picture_path):  #原图路径、转换后的保存路径
    convert(source_picture_path)
    scan(convert_picture_path)        #预览转换后的bmp图片
 
 
if __name__ == "__main__":
    main("./ori_pic/",'./convert_pic/')

import os
from PIL import Image
import numpy as np
import imageio
from PIL import ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True

class bmp:
""" bmp data structure """

def __init__(self, w=1080, h=1920):
    self.w = w
    self.h = h

def calc_data_size (self):
    if ((self.w * 3) % 4 == 0):
        self.dataSize = self.w * 3 * self.h
    else:
        self.dataSize = (((self.w * 3) // 4 + 1) * 4) * self.h

    self.fileSize = self.dataSize + 54


def conv2byte(self, l, num, len):
    tmp = num
    for i in range(len):
        l.append(tmp & 0x000000ff)
        tmp >>= 8

def gen_bmp_header (self):
    self.calc_data_size();
    self.bmp_header = [0x42, 0x4d]
    self.conv2byte(self.bmp_header, self.fileSize, 4) #file size
    self.conv2byte(self.bmp_header, 0, 2)
    self.conv2byte(self.bmp_header, 0, 2)
    self.conv2byte(self.bmp_header, 54, 4) #rgb data offset
    self.conv2byte(self.bmp_header, 40, 4) #info block size
    self.conv2byte(self.bmp_header, self.w, 4)
    self.conv2byte(self.bmp_header, self.h, 4)
    self.conv2byte(self.bmp_header, 1, 2)
    self.conv2byte(self.bmp_header, 24, 2) #888
    self.conv2byte(self.bmp_header, 0, 4)  #no compression
    self.conv2byte(self.bmp_header, self.dataSize, 4) #rgb data size
    self.conv2byte(self.bmp_header, 0, 4)
    self.conv2byte(self.bmp_header, 0, 4)
    self.conv2byte(self.bmp_header, 0, 4)
    self.conv2byte(self.bmp_header, 0, 4)

def print_bmp_header (self):
    length = len(self.bmp_header)
    for i in range(length):
        print("{:0>2x}".format(self.bmp_header[i]), end=' ')
        if i%16 == 15:
            print('')
    print('')

def paint_bgcolor(self, pixel):
    self.rgbData = []
    self.rgbData += pixel

def save_image(self, name="save.bmp"):
    f = open(name, 'wb')

    # write bmp header
    f.write(bytes(self.bmp_header))

    # write rgb data
    zeroBytes = self.dataSize // self.h - self.w * 3               #计算图像的每行后面需要的补充0的个数

    pixel_array = np.array(self.rgbData).reshape(self.h,self.w*3)  #将像素值list转换成np.array

    for r in range(self.h):
        l = []
        for i in range(0,len(pixel_array[r]),3):  #索引图片每行像素
            p = pixel_array[r][i]        # b vaule; 8bit
            l.append(p & 0x00ff)
            p = pixel_array[r][i+1]      # g vaule; 8bit
            l.append(p & 0x00ff)
            p = pixel_array[r][i+2]      # r vaule; 8bit
            l.append(p & 0x00ff)

        f.write(bytes(l))                #写入bmp文件中

        for i in range(zeroBytes):       #用于每行像素后补0
            f.write(bytes([0x00]))

    f.close()

def convert_img_to_a8rgb565(im):
im_bytes = list()
for (r, g, b, a) in list(im.getdata()):
r = r & 0xF8
g = g & 0xFC
b = b & 0xF8

    im_bytes += [b, g, r]    #bmp文件数据位BGR格式

return im_bytes

def convert(picture_path):
for filename in os.listdir(picture_path):
picture = os.path.join(picture_path, filename)
print(picture) #打印文件名称
bmp_file_name = filename.split('.')[0]

    img = Image.open(picture).transpose(Image.FLIP_TOP_BOTTOM).convert("RGBA") #PIL获取的图片会旋转,这里将其旋转回正图

    img_width , img_hight = img.size

    img_bgr = convert_img_to_a8rgb565(img)   #获取bgr数据,list

    image = bmp(img_width, img_hight)        #创建bmp文件
    image.gen_bmp_header()                   #写入bmp文件头信息#
    #image.print_bmp_header()                #打印出bmp文件头部信息

    image.paint_bgcolor(img_bgr)
    image.save_image('./conver_pic/'+bmp_file_name+'.bmp')

    print('picture convert over...')

def scan(picture_path):
for filename in os.listdir(picture_path):
picture = os.path.join(picture_path, filename)
print(picture) #打印文件名称

    src_img = Image.open(picture)
    src_img.show()                           #显示图片

def main(source_picture_path,convert_picture_path): #原图路径、转换后的保存路径
convert(source_picture_path)
scan(convert_picture_path) #预览转换后的bmp图片

if name == "main":
main("./ori_pic/",'./convert_pic/')