2013-12-12 5 views
2

Python, PIL библиотека имеет Image.getdata() метод, который возвращать необработанные данные изображения, письма:В Python, как преобразовать массив бит в массив байтов?

list(im.convert("1").getdata()) 

будет возвращать массив битов. Каждый бит соответствует одному пикселю изображения - пиксель может быть только черным или белым из-за режима «1».

Я хотел бы иметь массив, размер которого в 8 раз меньше. Каждый элемент массива содержит один байт.

Мои вопросы:

  • 1. Могу ли я получить такой массив байтов непосредственно из PIL?
  • 2. Если нет, то как преобразовать массив бит, возвращаемых PIL, в меньший массив байтов?

ответ

2

Я не знаю ничего о PIL, и я не использовал Python в течение некоторого времени, но вот мой подход к этой проблеме преобразования битов в байты.

import itertools 
# assuming that `bits` is your array of bits (0 or 1) 
# ordered from LSB to MSB in consecutive bytes they represent 
# e.g. bits = [0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1] will give you bytes = [128,255] 
bytes = [sum([byte[b] << b for b in range(0,8)]) 
      for byte in zip(*(iter(bits),) * 8) 
     ] 
# warning! if len(bits) % 8 != 0, then these last bits will be lost 

Этот код должен быть в основном сам по себе.

+0

В случае массива бит, который использует значения, отличные от 0 и 1, исправить 'byte [b]' соответственно, например. вместо этого используйте '[0,1] [byte [b]> 0 ]'. – przemoc

+0

Это то, что вы получаете, когда становитесь неактуальным пользователем языка ... Весь zip (* [itertools.islice (bits, i, None, 8) для i в диапазоне (0,8)]) может быть явно упрощается в 'zip (* (iter (bits),) * 8)'. Я также исправлю это в ответе. – przemoc

+0

После изменения порядка бит работает как шарм! Большое спасибо! – mnowotka

0

PIL-х ImagingCore легко могут быть преобразованы в байты:

from PIL import Image 


img = Image.open("python.jpg", "r") 
data = img.convert("1").getdata() 
bytes = bytearray(data) 

Это дает вам bytearray() список байтов, которые затем можно манипулировать или записываются в файл. Вы можете написать это в файл, выполнив:

with open("filename", "w") as f: 
    f.write(b"".join(map(bytes, data))) 

Надеюсь, это поможет!

Возможно, стоит отметить, что на самом деле у Python нет есть тип данных для бит. А что list(data) возвращает список из int (s), а не «bits» as you думал?

Пример:

>>> list(data)[:10] 
[255, 255, 255, 255, 255, 255, 255, 255, 255, 255] 
>>> set(list(data)) 
set([0, 255]) 
>>> set(map(type, list(data))) 
set([<type 'int'>]) 

Так что в реальности вы не сохранения каких-либо данных, делая это.

См.: http://docs.python.org/2/library/stdtypes.html для типов и операций типа Python. Вы можете выполнять операции «бит», но нет «бит» данных.

+0

Нет, это совсем не помогает. Ты просто не понял вопроса. Примечание: len (list (img.convert ("1"). Getdata())) == len (bytearray (img.convert ("1"). Getdata())) – mnowotka

+0

Прошу прощения? Это выражение имеет значение True. В чем именно заключается ваша точка зрения? –

+0

Точно - это выражение оценивается как True. Это проблема. Я хочу получить массив, такой как len (theArray) = len (bytearray (img.convert ("1"). Getdata()))/8. Я хочу массив байтов - то, что getdata дает мне, - это массив бит , Они могут быть упакованы. – mnowotka

Смежные вопросы