from math import floor # 十六进制转十进制 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] # 输入数据 img = input("请输入图片路径:") new_width = int(input("请输入新宽度(px):")) new_height = int(input("请输入新高度(px):")) # img = 'imgs/24.bmp' # new_width = 128 # new_height = 128 # 读入图片 with open(img, 'rb') as f: imgBytes = f.read() # 文件头处理 # 检验文件头是否为 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 currentRow = 0 while (currentRow < 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 currentRow += 1 # 读入图片为像素数组完成 # 缩放图片 # 变量预处理 scale_w = new_width / width scale_h = new_height / height newpixels = [] for i in range(new_height): newpixels.append([]) # 计算新像素 currentRow = 0 while (currentRow < new_height): currentCol = 0 while (currentCol < new_width): newpixels[currentRow].append(pixels[floor(currentRow / scale_h)][floor( currentCol // scale_w)]) currentCol += 1 currentRow += 1 # 处理新文件 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))) for i in range(len(newpixels)): row = newpixels[i] for col in range(len(row)): 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) 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)