проблемы с загрузкой изображений с помощью python и gobject

У меня есть сценарий с интерфейсом GTK (GObject), который я использую для публикации в моем фото блоге.

Я пытаюсь улучшить его отзывчивость, загружая изображения в фоновый поток.

Мне не удавалось пытаться заполнить объекты GdkPixbuf из фонового потока, все, что я пробовал, просто пробки.

Поэтому, как альтернатива, я думал, что прочитаю файлы в фоновом потоке, а затем подталкиваю их в GdkPixbuf по запросу. Этот подход дал некоторые неожиданные и довольно удручающие результаты, которые заставляют меня задаться вопросом, не делаю ли я что-то очень плохое.

Я играю со слегка сжатыми jpegs с моей камеры, они, как правило, около 3,8 мб.

Вот исходная загрузка блокирующего изображения:

pb = GdkPixbuf.Pixbuf.new_from_file(image_file) 

Это в среднем около 550 мс, но не огромная, но довольно утомительная, если вы хотите просмотреть десятки изображений.

Затем я разделил его, вот файл:

 data = bytearray(open(self.image_file).read()) 

Это составляет в среднем 15 мс, это действительно приятно, но также вызывает беспокойство, если мы можем прочитать файл в 15 мс, на что потрачены остальные 535 мс?

Кстати, вызов bytearray существует, потому что PixBufLoader не принимает данные в противном случае.

И тогда загрузка Pixbuf:

 pbl = GdkPixbuf.PixbufLoader() pbl.write(data, len(data)) pbl.close() pb = pbl.get_pixbuf() 

Это составляет около 1400 мс, что почти в 3 раза дольше, чем позволяет Gtk сделать все это.

Я здесь что-то не так?

2 Solutions collect form web for “проблемы с загрузкой изображений с помощью python и gobject”

Мое предположение: вы делаете что-то неправильно. Я только что сравнил libjpeg-turbo с gdk.PixbufLoader и практически не обнаружил различий в скорости. Код, который я использовал, приведен ниже.

Для libjpeg-turbo (jpegload.c):

 #include <assert.h> #include <stdio.h> #include <stdlib.h> #include <sys/time.h> #include <jpeglib.h> void decompress(FILE* fd) { JSAMPARRAY buffer; int row_stride; struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); jpeg_stdio_src(&cinfo, fd); jpeg_read_header(&cinfo, TRUE); jpeg_start_decompress(&cinfo); row_stride = cinfo.output_width * cinfo.output_components; buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); while (cinfo.output_scanline < cinfo.output_height) { (void) jpeg_read_scanlines(&cinfo, buffer, 1); } jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); } int main(int argc, char** argv) { long len; FILE *fd; unsigned char *buf; struct timeval start, end; int i; const int N = 100; int delta; /* read file to cache it in memory */ assert(argc == 2); fd = fopen(argv[1], "rb"); fseek(fd, 0, SEEK_END); len = ftell(fd); rewind(fd); buf = malloc(len); assert(buf != NULL); assert(fread(buf, 1, len, fd) == len); gettimeofday(&start, NULL); for(i = 0; i < N; i++) { rewind(fd); decompress(fd); } gettimeofday(&end, NULL); if(end.tv_sec > start.tv_sec) { delta = (end.tv_sec - start.tv_sec - 1) * 1000; end.tv_usec += 1000000; } delta += (end.tv_usec - start.tv_usec) / 1000; printf("time spent in decompression: %d msec\n", delta/N); } 

Для python gdk (gdk_load.py):

 import sys import gtk import time def decompress(data): pbl = gtk.gdk.PixbufLoader() pbl.write(data, len(data)) pbl.close() return pbl.get_pixbuf() data = open(sys.argv[1]).read() N = 100 start = time.time() for i in xrange(N): decompress(data) end = time.time() print "time spent in decompression: %d msec" % int((end - start) * 1000 / N) 

Результаты тестового запуска:

 $ gcc jpegload.c -ljpeg $ ./a.out DSC_8450.JPG time spent in decompression: 75 msec $ python gdk_load.py DSC_8450.JPG time spent in decompression: 75 msec $ identify DSC_8450.JPG DSC_8450.JPG JPEG 3008x2000 3008x2000+0+0 8-bit DirectClass 2.626MB 0.000u 0:00.019 

EDIT: и еще один тест, используя gi.repostiroy этот раз:

 import sys import time from gi.repository import GdkPixbuf def decompress(filename): pb = GdkPixbuf.Pixbuf.new_from_file(filename) return pb N = 100 start = time.time() for i in xrange(N): decompress(sys.argv[1]) end = time.time() print "time spent in decompression: %d msec" % int((end - start) * 1000 / N) 

И результаты:

 $ python gi_load.py DSC_8450.JPG time spent in decompression: 74 msec 

GdkPixbuf.PixbufLoader с использованием gi.repository действительно намного МНОГО медленнее, чем «чистый» gtk.gdk . Код:

 import sys import time from gi.repository import GdkPixbuf def decompress(data): pbl = GdkPixbuf.PixbufLoader() pbl.write(data, len(data)) pbl.close() return pbl.get_pixbuf() data = bytearray(open(sys.argv[1]).read()) N = 100 start = time.time() for i in xrange(N): decompress(data) end = time.time() print "time spent in decompression: %d msec" % int((end - start) * 1000 / N) 

Результаты:

 $ python gi_load.py DSC_8450.JPG time spent in decompression: 412 msec 

Но GdkPixbuf.Pixbuf.new_from_file работает так же быстро, как и чистая версия C, даже используя gi.repository , так что вы все еще либо делаете что-то неправильно, либо ожидаете слишком многого.

Я разработал небольшой просмотрщик изображений с pygtk. Я использую PixbufLoader, но я подаю только N байтов на запись (). В сочетании с idle_add () я могу загрузить изображение в фоновом режиме, в то время как приложение по-прежнему реагирует на ввод пользователя.

Вот источник: http://guettli.sourceforge.net/gthumpy/src/ImageCache.py

  • Быстрая библиотека ГИС-библиотеки python, которая поддерживает большое окружение и многоугольник
  • Ускорить сравнение поплавков между списками
  • Обертка np.arrays __pow__ метод
  • Почему numpy медленнее, чем python? Как сделать код более эффективным
  • Массовая строка заменяется на python?
  • Как заменить первые n элементов в каждой строке кадра данных, которые превышают определенный порог
  • Производительность: Python pandas DataFrame.to_csv добавляется постепенно медленнее
  • While-loop с if-statement быстрее, чем while-loop
  • Python - лучший язык программирования в мире.