2012

Про Qt5 и VisualStudio 2012

Если в двух словах, то со связкой указанной в заголовке - счастья не получил, откатился на VS2010.

Если подробно:

  • Qt - собирается без проблем, работает.
  • qmake делает прекрасные работоспособные Makefiles
  • qmake -tp vc - делает .vcxproj которые зовут компилятор от 2010-й версии (нет, я не туп, пути стоят нормально, QMAKESPEC=win32-msvc2012) и проекты не собираются, линкер ругается что у меня мои объектники от 2010, а библиотеки - от 2012.
  • Предыдущую проблему поборол: QMAKESPEC=win32-msvc2010 qmake -tp vc, при первом открытии проекта его апгрейдим на 2012. Достает, но уже привык.
  • Макросы для отладчика (показ Q-types по человечески) - установились, но не заработали.
  • Последняя капля: при попытке прикрутить иконку к .exe (обычным способом: RC_FILE=resource.rc в .pro) - все сломалось с ошибкой "VTRES : fatal error CVT1100: duplicate resource. type:ICON, name:1, language:0x0409". Судя по гуглению, это привет от конверсии проекта из 2010 в 2012, этот самый .rc оказывается в двух местах прописан.
Короче, поживу с 2010-м вижуалом до Qt 5.0.1. Хотя 2012-й мне нравится больше.

О сортах RAW у Sony

Про тоновую кривую в новых камерах Sony я уже писал и повторяться не буду.

Но тут переписывался с Ллойдом Чамберсом на тему Sony RX1 (прежде всего, конечно, как щупать RawDigger-ом неподдерживаемые камеры, как уровень черного определить и т.п.) и обнаружил массу веселья в самом формате ARW, точнее в новых его версиях.

В камерах Sony используются три формата записи RAW:

  • "Старый ARW" - камеры поколения Sony A100-A290 (точный список не составлял, по ощущениям это именно "старые камеры"). Это обычное такое хаффмановское сжатие, без потерь.

    При использовании этого режима - RAW-файлы будут сильно разного размера, в зависимости от детализации и шума.

  • Нежатый 12-битный RAW. Просто пишутся 2 пикселя в 3 байта, без сжатия, без потерь, без прочих глупостей. Этот формат используется в A900 в режиме "большие файлы" (~36Mb + размер JPEG), в Minolta 5D, возможно в еще каких-то, опять же не изучал.

    При использовании этого режима размер файлов "примерно одинаковый", полтора байта на пиксель плюс размер JPEG-а и EXIF-блоков. Соответственно, с A900 получается 36-37-мегабайтный файл.

  • Формат "ARW2" (так его называет Dave Coffin, а за ним и я).

    Этот режим записи используется во всех новых камерах Sony: NEX-xx, SLT-Axx, RX1, RX100. Его можно включить и на A900 (никогда не было этой камеры, надеюсь что этот режим включился не насильно после апдейта фирмвари, а есть возможность переключения юзером).

    При использовании этого режима RAW-файл имеет размер "1 байт на пиксель" (+JPEG и EXIF, конечно). 24-мегапиксельная A99 или NEX7 (или A900 в этом режиме) выдают, соответственно, 24-мегабайтный файл.

Вот последний режим нам и интересен, потому что он (и только он?) используется в актуальных камерах.

Вот как выглядит исходный код кусочка декодера (тот кусочек, который собственно распаковывает) этого формата в библиотеке RawSpeed (в dcraw - то же самое по смыслу, но Dave Coffin - истинный хакер и всякими глупостями вроде getBits(7) не пользуется):

Опять о современных CPU

Продолжаю набирать материал к вот этой презентации

Вот такой вот код (это автобаланс белого из dcraw в моем вольном изложении, слегка сокращенный, только для 4-компонентных а не байеровских изображений):

float sum[8],dsum[8]={0,0,0,0,0,0,0,0};
for (row=0; row < bottom; row += 8)
   for (col=0; col < right; col += 8) {
      for(i=0;i<8;i++) sum[i]=0.f;
      for (y=row; y < row+8 && y < bottom; y++)
        for (x=col; x < col+8 && x < right; x++)
          for(i=0; i<4; i++) {
            val = image[y*width+x][i];
            if (val > maximum-25) goto skip_block;
            sum[i] += val;
            sum[i+4]++;
           }
       for(i=0;i<8;i++) dsum[i] += sum[i];
skip_block: ;
   }
То есть, если простыми словами: берем блоки 8x8, если в этом блоке все пиксели имеют значения меньшие (maximum-25), то значения пикселов усредняем, если хоть один пиксел вылетает за указанный лимит - блок выбрасываем.

На моей тестовой 9-Mpix картинке (Nikon D800 "интерполированный в half") этот код работает 45-50 миллисекунд. Что для автобаланса белого как-то неприлично много.

Перепишем его тупо на SSE2:

Литий в самолете

Тема лития в почте (а точнее, в самолете) получила такое вот продолжение:

Где-то в середине ноября я затарился очередной пачкой литиевых енерджайзеров с прицелом на следующий летний сезон. Сегодня они приехали. Трекинг до Москвы - вот такой вот:

Судя по времени от Сингапура до России и по точке входа в Россию, ехало оно наземкой через Китай и Казахстан. Тот же отправитель весной - слал нормальной авиапочтой, т.е. на попытку маленько поэкономить это не похоже.

Такие дела.

LibRaw 0.15.0-Beta3

Вышла LibRaw 0.15-Beta3, доступна в обычном месте.

Никаких серьезных внутренних изменений нет, только поддержка новых камер:

  • Canon 6D и EOS M
  • Casio EX-ZR100
  • Fujifilm X-E1
  • Leica D-LUX6 and V-LUX4
  • Nikon P7700
  • Olympus XZ-2
  • Panasonic G5
  • Samsung EX2F
  • Sony RX-1

Ёж - птица гордая

Дети притащили с благотворительного аукциона

Хозяйке на заметку: Qt, OpenGL и PBO

В режиме записок: на этой проблеме впустую потерял дня два минимум, если не больше. Вот, чтобы никогда более, запишу.

Вот есть QGraphicsView, направленный в QGLWidget. Есть еще QGraphicsScene, у которой с помощью drawBackground() рисуем нужное нам (картинку).

Этот самый drawBackground() использует текстуры, одну или много, текстуры залиты через PBO.

Дальше - пытаюсь вывести на эту Scene другие объекты. Ну, как в документации написано, к примеру так:

QLabel *label = new QLabel("Bla-Bla");
scene->addWidget(label);
(ну чуть побольше кода, потому что прозрачность, возможность двигать, но смысл именно такой)

Результат:

  • Если объекты выводятся, окно открывается и т.п. до создания "моих" текстур (которые рисуются на фоне) - то все отлично.
  • Если все разлеглось так, что свои текстуры и PBO я создал до первого показа (даже не создания) объекта на Scene, то жопа, при добавлении элемента к сцене получаем такое:
    texture upload failed, error code 0x502
    
И так пробовал, и сяк и об косяк, потерял не меньше двух дней (ну то есть - не работает, пытаемся создать свой пример, там работает, из примера переносим код к себе - не работает и так с десяток раз). И, внезапно, ответ нашелся:

Если вы работали с QOpenGLBuffer, то прежде чем отдать управление в Qt - сделайте ему release(). Иначе будет нехорошо.

И ведь натыкался я уже на подобное, но с VBO: если не отцепить их, то вообще ничего не работает.

Об эффективном использовании современных CPU

Практика вот к этой презентации:

Берем 36Mpix файлик с D800, распаковываем егонный RAW в 16-битный однокомпонентный битмеп, дальше начинаем процессить.

Процессим без "интерполяции", т.е. 4 пикселя исходного байера образуют один выходной пиксель (режим half_size у LibRaw/dcraw). Получаем такие вот времена:

  1. LibRaw::dcraw_process() плюс формирование RGBA-битмепа: 420ms.
  2. Перепишем этот самый dcraw_process() на SSE3, процессить будем в плавучке (с эмуляцией особенностей dcraw), выдаем такой же 8-битный RGBA: 110ms (и более-менее понятно где еще выиграть миллисекунд 20).
  3. Добавим в предыдущий суп еще: подсчет RAW-гистограммы и сохранение исходного float-битмепа нетронутым (и без дублирования по памяти), т.е. баланс белого и конверсию цвета делаем два раза, один раз для подсчета гистограммы результирующего файла, а второй раз - прямо на вывод. 180ms.
Это все был один поток. Распараллелим его:
  1. "распараллеленный dcraw_process": 130ms (так в RawDigger сделано, тамошний RGB render устроен именно так, но гистограммы и статистика в эти 130ms не входят, равно как и битмеп для показа там готовится иначе и потому дольше).
  2. "распаралеленный ассемблерный dcraw_process": не делал, ожидаю <50ms (потому что вариант с двойным вычислением, как следующий, но без гистограмм - 57ms).
  3. параллельная ассемблерная версия с гистограммами, сохранением float RAW: 75ms
Сравнивая последний вариант с последовательным C-шным, нужно понимать, что в C-шном варианте еще где-то 200ms придется на гистограммы и еще 200 на конверсию int16 - float. То есть реальное ускорение от SSE и параллельной обработки - раз в 10 (75ms против 800). И это оптимизированный C-шный, в LibRaw это место заметно пооптимизировано в сравнении с исходным dcraw.

Минусы: потрачено изрядно времени (несколько дней), окончательного кода 25кб, а промежуточных вариантов было в разы больше. Ну и две баги ловились достаточно мучительно.

О процессинге RAW: плавучка или целое

Обработка RAW в плавучке позволяет избавиться от артефактов вылета за диапазон, да и вообще получить более качественную картинку.

Тем интереснее обратные случаи.

Возьмем вот такой вот кадр:

Это D800 с его приколами в светах, вот на света и посмотрим.

Если обработать картинку dcraw (или LibRaw, которая дает побитово такой же процессинг, если автоматическое определение максимума отключить), то в светах в "середине верха кадра" мы увидим такое вот:

Pages