from math import floor from tqdm import tqdm ################## 数据输入 Start ################## # 输入数据 # img = input("请输入图片路径:") # new_width = int(input("请输入新宽度(px):")) # new_height = int(input("请输入新高度(px):")) # print("模式 0 直接缩放") # print("模式 1 高斯模糊缩放") # mode = int(input("请输入模式:")) img = 'imgs/1/2x1.bmp' new_width = 512 new_height = 512 mode = 0 if (mode != 1): mode = 0 ################## 数据输入 End ################## ################## 文件读入 Start ################## # 读入图片 with open(img, 'rb') as f: imgBytes = f.read() for _ in tqdm(range(len(imgBytes)), "读入文件中"): pass ################## 文件读入 End ################## # 十六进制转十进制 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] ################## 文件头处理 Start ################## # 位图文件头 # 检验文件头是否为 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) #该头结构的大小(40字节) width = byteSize(18, 4) #位图宽度,单位为像素(有符号整数) height = byteSize(22, 4) #位图高度,单位为像素(有符号整数) nbplan = byteSize(26, 2) #色彩平面数;只有1为有效值 bpp = byteSize(28, 2) #每个像素所占位数,即图像的色深。典型值为1、4、8、16、24和32 compression = byteSize(30, 4) #所使用的压缩方法,可取值见下表。 imageSize = byteSize(34, 4) #图像大小。指原始位图数据的大小(详见后文),与文件大小不是同一个概念。 wppm = byteSize(38, 4) #图像的横向分辨率,单位为像素每米(有符号整数) hppm = byteSize(42, 4) #图像的纵向分辨率,单位为像素每米(有符号整数) colorsNum = byteSize(46, 4) #调色板的颜色数,为0时表示颜色数为默认的2^色深个 icolorsNum = byteSize(50, 4) #重要颜色数,为0时表示所有颜色都是重要的;通常不使用本项 colorsBoard = imgBytes[54:dataStart] #调色板 colors = [] i = 0 while (i < len(colorsBoard)): colors.append({ 'r': colorsBoard[i], 'g': colorsBoard[i + 1], 'b': colorsBoard[i + 2], 'a': colorsBoard[i + 3], }) i += 4 ################## 文件头处理 End ################## ################## 像素点读入 Start ################## # 变量预处理 pixels = [] for i in range(height): pixels.append([]) rowLength = floor(width * bpp / 8) while (rowLength % 4 != 0 or rowLength == 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