@Dogrtt
Qt/Python разработчик

Непонятное замедление конкатенации в цикле?

Всем добра.

Приходит строка байт `buffered_img` длинной 786'432 байта (`Grayscale 8bit` изображение `1024x768`). Запускается поток-обработчик (Если считать в основном потоке, то просто виснет окно). Алгоритм такой - берется 0-вой пиксель из оригнального изображения (первый байт из строки `buffered_img`), проверяется его 7-ой бит, если он равен 0, то к строке `nine['img_7']` дописывается байт `'\x00'`, если 1, то `'\xff'`, затем берется 6-ой бит 0-го пикселя, также проверяется и дописывается к `nine['img_6']` и т.д. до 0 бита. Эта операция повторяется для всех пикселей. В итоге получаем 9 изображений, оригинальное + 8 генерированных.

Так вот, проблема в том, что с каждой операцией конкатенации, процесс замедляется, ползунок `QProgressBar`, который завязан на сигнал `generating`, ползет все медленнее и медленнее с каждым процентом, хотя поначалу все идет бодро. Если бы проценты капали с самого начала медленно, претензий бы не возникло, но на лицо явное замедление процесса конкатенации, и моего скудного опыта в программировании не хватает, для того, чтобы объяснить это явление. Кто подскажет, в чем проблема? Вот кусочки кода:
# Глобальный список с байт-строками генерированных картинок
    nine = {'img_7': b'', 'img_6': b'', 'img_5': b'', 'img_4': b'',
        'img_3': b'', 'img_2': b'', 'img_1': b'', 'img_0': b''}
    b0 = pack('B', 0)
    b255 = pack('B', 255)

  # Метод run() QThread в котором buffered_img - байт строка с оригинальным изображением
    def run(self):
        global nine, img_str
        self.start_gen.emit(len(buffered_img))
        pb_val = 0
        for img in nine:
            nine[img] = b''
        for byte_ in buffered_img:
            pb_val += 1
            self.generating.emit(pb_val)
            bit_str = self.by2bi(byte_)
            for i in range(8):
                if bit_str[i] == '0':
                    nine['img_' + str(i)] += b0
                else:
                    nine['img_' + str(i)] += b255
        self.stop_gen.emit()
    
    # Подсмотренный где-то код, на выходе выдает строку типа ('10110100' для
    # входного байта '\xb4'
    def by2bi(self, bytestring):
        try:
            bits = bin(int(hexlify(bytestring), 16))[2:]
            data = bits.zfill(8 * ((len(bits) + 7) // 8))
            del bits
            return data
        except ValueError:
            print 'Error bytes2bits decode!'
  • Вопрос задан
  • 167 просмотров
Решения вопроса 1
longclaps
@longclaps
Вместо nine[img] = b'' объяви nine[img] = bytearray(какой_там_тебе_нужен_размер) и пиши в него по индексу, конкатенация тебя тормозит.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы