怎么用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
对于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/')