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