Сжатие битмапа не выполняется (реализация Python)

У меня есть приложение, которое использует растровые изображения для хранения изображений. В настоящее время они хранятся как несжатые растровые изображения, но поскольку количество цветов почти всегда <= 16, я должен иметь возможность использовать сжатый формат растрового изображения, что делает файлы почти в 6 раз меньше. С помощью записи в Википедии на странице https://en.wikipedia.org/wiki/BMP_file_formatЯ попытался реализовать программу сжатия в Python - ниже. Это успешно считывает входной бит bmp и выводит меньший бит, но полученный bmp не читается, поэтому я должен делать что-то неправильно. В обозревателе Windows свойства файла включают «Bit Depth: 32», что явно не является целью, но я уверен, что получил информацию о заголовке для глубины бит и сжатия. Это помогло бы, если бы я смог найти пример сжатого растрового изображения для проверки, но не смог отследить его. Этот формат обычно не поддерживается, или я делаю что-то неправильно?

import math

def rgb(r,g,b):
    return hex(256*256*256+r*256*256+g*256+b)[3:9]
def read_bmp(path):
    bm={}
    with open(path,"rb") as f:
        byte=f.read(54)
        header_size=byte[14]+byte[15]*256
        if header_size!=40: return None
        bm['w']=w=byte[18]+byte[19]*256
        bm['h']=byte[22]+byte[23]*256
        bm['color_depth']=byte[28]
        bm['compression']=byte[30]
        bm['im_size']=byte[34]+byte[35]*256+byte[36]*256*256
        if bm['compression']!=0:
            ct=f.read(4*bm['color_depth'])
            color_table=[]
            for i in range(0,bm['color_depth']):
                color_table.append((ct[i*4],ct[i*4+1],ct[i*4+2]))
        if bm['color_depth']==24:
            bmp=f.read(bm['im_size'])
            row_size=bm['im_size']//bm['h']
            col={}
            pixel=[]
            for y in range(0,bm['h']):
                s=""
                row=[]
                for x in range(0,w):
                    row.append((bmp[y*row_size+x*3],bmp[y*row_size+x*3+1],bmp[y*row_size+x*3+2]))
                    color=rgb(bmp[y*row_size+x*3],bmp[y*row_size+x*3+1],bmp[y*row_size+x*3+2])
                    if color in col:
                        col[color]+=1
                    else:
                        col[color]=1
                pixel.append(row)
            bm['pix']=pixel
            bm['color_count']=len(col)
        return bm
def putint(b,p,i):
    b[p]=i & 255
    b[p+1]=(i>>8)&255
    if i>65535:
        b[p+2]=(i>>16)&255
        b[p+3]=(i>>24)&255
def write_compressed_bmp(bm,path):
    pix=bm['pix']
    col=[]
    color_index=[]
    for row in pix:
        rowindex=[]
        for color in row:
            if not color in col: col.append(color)
            rowindex.append(col.index(color))
        color_index.append(rowindex)
    print(col)
    if len(col)>16: return
    with open(path,"wb") as f:
        row_size=math.ceil(bm['w']/8)*4
        image_size=row_size*bm['h']
        file_len=54+64+image_size
        header=bytearray(54)
        header[0]=ord('B')
        header[1]=ord('M')
        putint(header,2,file_len)
        putint(header,10,54+64)
        putint(header,14,40)
        putint(header,18,bm['w'])
        putint(header,22,bm['h'])
        putint(header,26,1)
        putint(header,28,4)
        putint(header,34,image_size)
        f.write(header)
        color_map=bytearray(64)
        for i in range(0,len(col)):
            color_map[i*4]=col[i][0]
            color_map[i*4+1]=col[i][1]
            color_map[i*4+2]=col[i][2]
        f.write(color_map)
        for row in pix:
            row_bytes=bytearray(row_size)
            i=0
            for color in row:
                ci=col.index(color)
                if i&1:
                    row_bytes[i>>1]|=ci
                else:
                    row_bytes[i>>1]|=ci<<4
                i+=1
            f.write(row_bytes)

bm=read_bmp("bitmap.bmp")
if bm['color_count']<=16:
    write_compressed_bmp(bm,"bitmap2.bmp")

python,bitmap,bmp,

0

Ответов: 1


0

Я узнал, что не так - я забыл, что метод range () в Python занимает больше, чем самое большое желаемое значение, как его второй параметр, поэтому было написано слишком мало строк. Исправляя это и оставляя бит «сжатия» на 0, исправил проблему - я соответствующим образом отредактировал код. Если все в порядке, я оставлю это здесь для возможного использования другими.

Python, растровые, BMP,
Похожие вопросы
Яндекс.Метрика