bmp-resize-python/main.py

236 lines
7.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from math import floor
from tqdm import tqdm
# 输入数据
img = input("请输入图片路径:")
new_width = int(input("请输入新宽度(px)"))
new_height = int(input("请输入新高度(px)"))
print("模式 0 直接缩放")
print("模式 1 高斯模糊缩放")
mode = int(input("请输入模式:"))
# img = 'imgs/bw.bmp'
# new_width = 512
# new_height = 512
# mode = 1
if (mode != 1):
mode = 0
# 读入图片
with open(img, 'rb') as f:
imgBytes = f.read()
for _ in tqdm(range(len(imgBytes)), "读入文件中"):
pass
# 十六进制转十进制
def byteSize(begin, length):
size = 0
for i in range(length):
size += imgBytes[i + begin] * 16**(2 * i)
return size
# 十进制转十六进制
def sizeByte(size, length):
b = []
while (size):
b.append(size // 16**((length - len(b) - 1) * 2))
size %= 16**((length - len(b)) * 2)
b.extend([0] * (length - len(b)))
return b[::-1]
# 文件头处理
# 检验文件头是否为 BM
if (imgBytes[0] != 66 or imgBytes[1] != 77):
print("当前文件非 BMP 格式")
exit()
fileSize = byteSize(2, 4) #文件头中的文件大小
dataStart = byteSize(10, 4) #文件头中的数据开始字节
# bmp 文件头
headerSize = byteSize(14, 4)
width = byteSize(18, 4)
height = byteSize(22, 4)
nbplan = byteSize(26, 2)
bpp = byteSize(28, 2)
compression = byteSize(30, 4)
imageSize = byteSize(34, 4)
# 调色板不做处理
# 变量预处理
pixels = []
for i in range(height):
pixels.append([])
rowLength = width
rowLength *= bpp // 8
while (rowLength % 4 != 0):
rowLength += 1
# 计算像素点
i = dataStart
for currentRow in tqdm(range(height), "读入像素点中"):
currentCol = 0
while (currentCol < width * (bpp // 8)):
if (bpp == 32):
pixels[currentRow].append({
'r':
imgBytes[dataStart + currentRow * rowLength + currentCol],
'g':
imgBytes[dataStart + currentRow * rowLength + currentCol + 1],
'b':
imgBytes[dataStart + currentRow * rowLength + currentCol + 2],
'a':
imgBytes[dataStart + currentRow * rowLength + currentCol + 3]
})
currentCol += bpp // 8
else:
pixels[currentRow].append({
'r':
imgBytes[dataStart + currentRow * rowLength + currentCol],
'g':
imgBytes[dataStart + currentRow * rowLength + currentCol + 1],
'b':
imgBytes[dataStart + currentRow * rowLength + currentCol + 2]
})
currentCol += bpp // 8
# 读入图片为像素数组完成
# 缩放图片
# 变量预处理
scale_w = new_width / width
scale_h = new_height / height
newpixels = []
for i in range(new_height):
newpixels.append([])
# 计算新像素
for currentRow in tqdm(range(new_height), "计算新像素点中"):
for currentCol in range(new_width):
ori_row = floor(currentRow / scale_h)
ori_col = floor(currentCol // scale_w)
newpixels[currentRow].append(pixels[ori_row][ori_col])
# 处理新文件
newimgArray = [66, 77]
rowLength = new_width
rowLength *= bpp // 8
while (rowLength % 4 != 0):
rowLength += 1
# 新文件头
new_fileSize = 54 + rowLength * new_height #文件头中的文件大小
newimgArray.extend(sizeByte(new_fileSize, 4))
newimgArray.extend(sizeByte(0, 4))
new_dataStart = dataStart
newimgArray.extend(sizeByte(new_dataStart, 4))
# 新 bmp 文件头
new_headerSize = headerSize
newimgArray.extend(sizeByte(headerSize, 4))
new_width_b = sizeByte(new_width, 4)
newimgArray.extend(new_width_b)
new_height_b = sizeByte(new_height, 4)
newimgArray.extend(new_height_b)
new_nbplan = nbplan
newimgArray.extend(sizeByte(new_nbplan, 2))
new_bpp = bpp
newimgArray.extend(sizeByte(bpp, 2))
new_compression = compression
newimgArray.extend(sizeByte(new_compression, 4))
new_imageSize = rowLength * new_height
newimgArray.extend(sizeByte(new_imageSize, 4))
# 调色板不做处理
newimgArray.extend(sizeByte(0, new_headerSize + 14 - len(newimgArray)))
def flur(row, col):
if (row - 1 < 0):
row = new_height + 1
if (row + 1 >= new_height):
row = 0
if (col - 1 < 0):
col = new_width + 1
if (col + 1 >= new_width):
col = 0
p = [0.0947416, 0.118318, 0.147761]
r = floor(newpixels[row - 1][col - 1]['r'] * p[0] +
newpixels[row - 1][col + 1]['r'] * p[0] +
newpixels[row + 1][col - 1]['r'] * p[0] +
newpixels[row + 1][col + 1]['r'] * p[0] +
newpixels[row][col + 1]['r'] * p[1] +
newpixels[row][col - 1]['r'] * p[1] +
newpixels[row - 1][col]['r'] * p[1] +
newpixels[row + 1][col]['r'] * p[1] +
newpixels[row][col]['r'] * p[2])
g = floor(newpixels[row - 1][col - 1]['g'] * p[0] +
newpixels[row - 1][col + 1]['g'] * p[0] +
newpixels[row + 1][col - 1]['g'] * p[0] +
newpixels[row + 1][col + 1]['g'] * p[0] +
newpixels[row][col + 1]['g'] * p[1] +
newpixels[row][col - 1]['g'] * p[1] +
newpixels[row - 1][col]['g'] * p[1] +
newpixels[row + 1][col]['g'] * p[1] +
newpixels[row][col]['g'] * p[2])
b = floor(newpixels[row - 1][col - 1]['b'] * p[0] +
newpixels[row - 1][col + 1]['b'] * p[0] +
newpixels[row + 1][col - 1]['b'] * p[0] +
newpixels[row + 1][col + 1]['b'] * p[0] +
newpixels[row][col + 1]['b'] * p[1] +
newpixels[row][col - 1]['b'] * p[1] +
newpixels[row - 1][col]['b'] * p[1] +
newpixels[row + 1][col]['b'] * p[1] +
newpixels[row][col]['b'] * p[2])
if (new_bpp // 8 == 3):
return [r, g, b]
else:
a = floor(newpixels[row - 1][col - 1]['a'] * p[0] +
newpixels[row - 1][col + 1]['a'] * p[0] +
newpixels[row + 1][col - 1]['a'] * p[0] +
newpixels[row + 1][col + 1]['a'] * p[0] +
newpixels[row][col + 1]['a'] * p[1] +
newpixels[row][col - 1]['a'] * p[1] +
newpixels[row - 1][col]['a'] * p[1] +
newpixels[row + 1][col]['a'] * p[1] +
newpixels[row][col]['a'] * p[2])
return [r, g, b, a]
for i in tqdm(range(len(newpixels)), "将像素点格式化中"):
row = newpixels[i]
for col in range(len(row)):
if (mode == 0):
if (new_bpp // 8 == 3):
pixel = [
newpixels[i][col]['r'], newpixels[i][col]['g'],
newpixels[i][col]['b']
]
else:
pixel = [
newpixels[i][col]['r'], newpixels[i][col]['g'],
newpixels[i][col]['b'], newpixels[i][col]['a']
]
newimgArray.extend(pixel)
elif (mode == 1):
newimgArray.extend(flur(i, col))
newimgArray.extend(sizeByte(0, rowLength - len(row) * (new_bpp // 8)))
# 写入新的文件
newimgBytes = bytes(newimgArray)
with open(img[:-4] + "_new" + img[-4:], 'wb') as f:
f.write(newimgBytes)
for _ in tqdm(range(len(newimgBytes)), "写出图片中"):
pass